- introduce ES2021.String for replaceAll
- expand Configuration with `custom_placeholders` configuration - custom placeholders allow to extract values of placeholders and then use these in templates - refactor replacing PR template values
This commit is contained in:
@@ -14,6 +14,7 @@ export interface Configuration {
|
|||||||
transformers: Transformer[]
|
transformers: Transformer[]
|
||||||
tag_resolver: TagResolver
|
tag_resolver: TagResolver
|
||||||
base_branches: string[]
|
base_branches: string[]
|
||||||
|
custom_placeholders?: Placeholder[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Category {
|
export interface Category {
|
||||||
@@ -57,6 +58,12 @@ export interface TagResolver {
|
|||||||
transformer?: Transformer // transforms the tag name using the regex, run after the filter
|
transformer?: Transformer // transforms the tag name using the regex, run after the filter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Placeholder {
|
||||||
|
name: string // the name of the new placeholder
|
||||||
|
source: string // the src placeholder which will be used to apply the transformer on
|
||||||
|
transformer: Transformer // the transformer to use to transform the original placeholder into the custom placheolder
|
||||||
|
}
|
||||||
|
|
||||||
export const DefaultConfiguration: Configuration = {
|
export const DefaultConfiguration: Configuration = {
|
||||||
max_tags_to_fetch: 200, // the amount of tags to fetch from the github API
|
max_tags_to_fetch: 200, // the amount of tags to fetch from the github API
|
||||||
max_pull_requests: 200, // the amount of pull requests to process
|
max_pull_requests: 200, // the amount of pull requests to process
|
||||||
@@ -94,5 +101,6 @@ export const DefaultConfiguration: Configuration = {
|
|||||||
filter: undefined, // filter out all tags not matching the regex
|
filter: undefined, // filter out all tags not matching the regex
|
||||||
transformer: undefined // transforms the tag name using the regex, run after the filter
|
transformer: undefined // transforms the tag name using the regex, run after the filter
|
||||||
},
|
},
|
||||||
base_branches: [] // target branches for the merged PR ignoring PRs with different target branch, by default it will get all PRs
|
base_branches: [], // target branches for the merged PR ignoring PRs with different target branch, by default it will get all PRs
|
||||||
|
custom_placeholders: []
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-20
@@ -1,5 +1,5 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import {Category, DefaultConfiguration, Extractor, Transformer} from './configuration'
|
import {Category, DefaultConfiguration, Extractor, Placeholder, Transformer} from './configuration'
|
||||||
import {PullRequestInfo, sortPullRequests} from './pullRequests'
|
import {PullRequestInfo, sortPullRequests} from './pullRequests'
|
||||||
import {ReleaseNotesOptions} from './releaseNotes'
|
import {ReleaseNotesOptions} from './releaseNotes'
|
||||||
import {DiffInfo} from './commits'
|
import {DiffInfo} from './commits'
|
||||||
@@ -51,13 +51,21 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const placeholderMap = new Map<string, Placeholder>()
|
||||||
|
for (const ph of config.custom_placeholders || []) {
|
||||||
|
placeholderMap.set(ph.source, ph)
|
||||||
|
}
|
||||||
|
|
||||||
const validatedTransformers = validateTransformers(config.transformers)
|
const validatedTransformers = validateTransformers(config.transformers)
|
||||||
const transformedMap = new Map<PullRequestInfo, string>()
|
const transformedMap = new Map<PullRequestInfo, string>()
|
||||||
// convert PRs to their text representation
|
// convert PRs to their text representation
|
||||||
for (const pr of prs) {
|
for (const pr of prs) {
|
||||||
transformedMap.set(
|
transformedMap.set(
|
||||||
pr,
|
pr,
|
||||||
transform(fillTemplate(pr, config.pr_template || DefaultConfiguration.pr_template), validatedTransformers)
|
transform(
|
||||||
|
fillTemplate(pr, config.pr_template || DefaultConfiguration.pr_template, placeholderMap),
|
||||||
|
validatedTransformers
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
core.info(`ℹ️ Used ${validatedTransformers.length} transformers to adjust message`)
|
core.info(`ℹ️ Used ${validatedTransformers.length} transformers to adjust message`)
|
||||||
@@ -269,28 +277,47 @@ function haveEveryElements(arr1: string[], arr2: Set<string>): Boolean {
|
|||||||
return arr1.every(item => arr2.has(item))
|
return arr1.every(item => arr2.has(item))
|
||||||
}
|
}
|
||||||
|
|
||||||
function fillTemplate(pr: PullRequestInfo, template: string): string {
|
function fillTemplate(pr: PullRequestInfo, template: string, customPlaceholders: Map<string, Placeholder>): string {
|
||||||
|
const placeholderMap = new Map<string, string>()
|
||||||
|
placeholderMap.set('NUMBER', pr.number.toString())
|
||||||
|
placeholderMap.set('TITLE', pr.title)
|
||||||
|
placeholderMap.set('URL', pr.htmlURL)
|
||||||
|
placeholderMap.set('STATUS', pr.status)
|
||||||
|
placeholderMap.set('CREATED_AT', pr.createdAt.toISOString())
|
||||||
|
placeholderMap.set('MERGED_AT', pr.mergedAt?.toISOString() || '')
|
||||||
|
placeholderMap.set('MERGE_SHA', pr.mergeCommitSha)
|
||||||
|
placeholderMap.set('AUTHOR', pr.author)
|
||||||
|
placeholderMap.set('LABELS', [...pr.labels]?.filter(l => !l.startsWith('--rcba-'))?.join(', ') || '')
|
||||||
|
placeholderMap.set('MILESTONE', pr.milestone || '')
|
||||||
|
placeholderMap.set('BODY', pr.body)
|
||||||
|
placeholderMap.set('ASSIGNEES', pr.assignees?.join(', ') || '')
|
||||||
|
placeholderMap.set('REVIEWERS', pr.requestedReviewers?.join(', ') || '')
|
||||||
|
placeholderMap.set('APPROVERS', pr.approvedReviewers?.join(', ') || '')
|
||||||
|
placeholderMap.set('BRANCH', pr.branch || '')
|
||||||
|
placeholderMap.set('BASE_BRANCH', pr.baseBranch)
|
||||||
|
|
||||||
let transformed = template
|
let transformed = template
|
||||||
transformed = transformed.replace(/\${{NUMBER}}/g, pr.number.toString())
|
for (const [key, value] of placeholderMap) {
|
||||||
transformed = transformed.replace(/\${{TITLE}}/g, pr.title)
|
transformed = transformed.replaceAll(`\${{${key}}}`, value)
|
||||||
transformed = transformed.replace(/\${{URL}}/g, pr.htmlURL)
|
|
||||||
transformed = transformed.replace(/\${{STATUS}}/g, pr.status)
|
// replace custom placeholders
|
||||||
transformed = transformed.replace(/\${{CREATED_AT}}/g, pr.createdAt.toISOString())
|
transformed = applyCustomPlaceholder(transformed, value, customPlaceholders.get(key))
|
||||||
transformed = transformed.replace(/\${{MERGED_AT}}/g, pr.mergedAt?.toISOString() || '')
|
}
|
||||||
transformed = transformed.replace(/\${{MERGE_SHA}}/g, pr.mergeCommitSha)
|
|
||||||
transformed = transformed.replace(/\${{AUTHOR}}/g, pr.author)
|
|
||||||
transformed = transformed.replace(
|
|
||||||
/\${{LABELS}}/g,
|
|
||||||
[...pr.labels]?.filter(l => !l.startsWith('--rcba-'))?.join(', ') || ''
|
|
||||||
)
|
|
||||||
transformed = transformed.replace(/\${{MILESTONE}}/g, pr.milestone || '')
|
|
||||||
transformed = transformed.replace(/\${{BODY}}/g, pr.body)
|
|
||||||
transformed = transformed.replace(/\${{ASSIGNEES}}/g, pr.assignees?.join(', ') || '')
|
|
||||||
transformed = transformed.replace(/\${{REVIEWERS}}/g, pr.requestedReviewers?.join(', ') || '')
|
|
||||||
transformed = transformed.replace(/\${{APPROVERS}}/g, pr.approvedReviewers?.join(', ') || '')
|
|
||||||
return transformed
|
return transformed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyCustomPlaceholder(template: string, value: string, placeholder: Placeholder | undefined) {
|
||||||
|
if (placeholder) {
|
||||||
|
const transformer = validateTransformer(placeholder.transformer)
|
||||||
|
if (transformer?.pattern) {
|
||||||
|
const extractedValue = value.replace(transformer.pattern, transformer.target)
|
||||||
|
return template.replaceAll(`\${{${placeholder.name}}}`, extractedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return template
|
||||||
|
}
|
||||||
|
|
||||||
function transform(filled: string, transformers: RegexTransformer[]): string {
|
function transform(filled: string, transformers: RegexTransformer[]): string {
|
||||||
if (transformers.length === 0) {
|
if (transformers.length === 0) {
|
||||||
return filled
|
return filled
|
||||||
|
|||||||
+2
-1
@@ -6,7 +6,8 @@
|
|||||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
"strict": true, /* Enable all strict type-checking options. */
|
"strict": true, /* Enable all strict type-checking options. */
|
||||||
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||||
|
"lib": [ "ES2021.String" ] /* Enable custom `ES2021.String` extension in typescript for `replaceAll` */
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules", "**/*.test.ts"]
|
"exclude": ["node_modules", "**/*.test.ts"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user