- break out some functionality when transforming the pull requests into the changelog
This commit is contained in:
@@ -30,6 +30,8 @@ export interface Category {
|
|||||||
exhaustive?: boolean // requires all labels to be present in the PR
|
exhaustive?: boolean // requires all labels to be present in the PR
|
||||||
exhaustive_rules?: boolean // requires all rules to be present in the PR (if not set, defaults to exhaustive value)
|
exhaustive_rules?: boolean // requires all rules to be present in the PR (if not set, defaults to exhaustive value)
|
||||||
empty_content?: string // if the category has no matching PRs, this content will be used. If not set, the category will be skipped in the changelog.
|
empty_content?: string // if the category has no matching PRs, this content will be used. If not set, the category will be skipped in the changelog.
|
||||||
|
categories?: Category[] // allows for nested categories, items matched for a child category won't show up in the parent
|
||||||
|
consume?: boolean // defines if the matched PR will be consumed by this category. Consumed PRs won't show up in any category *after*
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+76
-67
@@ -111,7 +111,6 @@ export function buildChangelog(diffInfo: DiffInfo, origPrs: PullRequestInfo[], o
|
|||||||
for (const label of extracted) {
|
for (const label of extracted) {
|
||||||
pr.labels.push(label)
|
pr.labels.push(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
core.debug(` Extracted the following labels (${JSON.stringify(extracted)}) for PR ${pr.number}`)
|
core.debug(` Extracted the following labels (${JSON.stringify(extracted)}) for PR ${pr.number}`)
|
||||||
}
|
}
|
||||||
@@ -167,57 +166,7 @@ export function buildChangelog(diffInfo: DiffInfo, origPrs: PullRequestInfo[], o
|
|||||||
|
|
||||||
let matchedOnce = false // in case we matched once at least, the PR can't be uncategorized
|
let matchedOnce = false // in case we matched once at least, the PR can't be uncategorized
|
||||||
for (const [category, pullRequests] of categorized) {
|
for (const [category, pullRequests] of categorized) {
|
||||||
let matched = false // check if we matched within the given category
|
const matched = categorizePr(category, pr)
|
||||||
// check if any exclude label matches
|
|
||||||
if (category.exclude_labels !== undefined) {
|
|
||||||
if (
|
|
||||||
haveCommonElementsArr(
|
|
||||||
category.exclude_labels.map(lbl => lbl.toLocaleLowerCase('en')),
|
|
||||||
pr.labels
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if (core.isDebug()) {
|
|
||||||
const excludeLabels = JSON.stringify(category.exclude_labels)
|
|
||||||
core.debug(` PR ${pr.number} with labels: ${pr.labels} excluded from category via exclude label: ${excludeLabels}`)
|
|
||||||
}
|
|
||||||
continue // one of the exclude labels matched, skip the PR for this category
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// in case we have exhaustive matching enabled, and have labels and/or rules
|
|
||||||
// validate for an exhaustive match (e.g. every provided rule applies)
|
|
||||||
if (category.exhaustive === true && (category.labels !== undefined || category.rules !== undefined)) {
|
|
||||||
if (category.labels !== undefined) {
|
|
||||||
matched = haveEveryElementsArr(
|
|
||||||
category.labels.map(lbl => lbl.toLocaleLowerCase('en')),
|
|
||||||
pr.labels
|
|
||||||
)
|
|
||||||
}
|
|
||||||
let exhaustive_rules = true
|
|
||||||
if (category.exhaustive_rules !== undefined) {
|
|
||||||
exhaustive_rules = category.exhaustive_rules
|
|
||||||
}
|
|
||||||
if ((matched || category.labels === undefined) && category.rules !== undefined) {
|
|
||||||
matched = matchesRules(category.rules, pr, exhaustive_rules)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// if not exhaustive, do individual matches
|
|
||||||
if (category.labels !== undefined) {
|
|
||||||
// check if either any of the labels applies
|
|
||||||
matched = haveCommonElementsArr(
|
|
||||||
category.labels.map(lbl => lbl.toLocaleLowerCase('en')),
|
|
||||||
pr.labels
|
|
||||||
)
|
|
||||||
}
|
|
||||||
let exhaustive_rules = false
|
|
||||||
if (category.exhaustive_rules !== undefined) {
|
|
||||||
exhaustive_rules = category.exhaustive_rules
|
|
||||||
}
|
|
||||||
if (!matched && category.rules !== undefined) {
|
|
||||||
// if no label did apply, check if any rule applies
|
|
||||||
matched = matchesRules(category.rules, pr, exhaustive_rules)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (matched) {
|
if (matched) {
|
||||||
pullRequests.push(body) // if matched add the PR to the list
|
pullRequests.push(body) // if matched add the PR to the list
|
||||||
}
|
}
|
||||||
@@ -269,21 +218,7 @@ export function buildChangelog(diffInfo: DiffInfo, origPrs: PullRequestInfo[], o
|
|||||||
// construct final changelog
|
// construct final changelog
|
||||||
let changelog = ''
|
let changelog = ''
|
||||||
for (const [category, pullRequests] of categorized) {
|
for (const [category, pullRequests] of categorized) {
|
||||||
if (pullRequests.length > 0) {
|
changelog = attachCategoryChangelog(changelog, category, pullRequests)
|
||||||
if (category.title) {
|
|
||||||
changelog = `${changelog + category.title}\n\n`
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const pr of pullRequests) {
|
|
||||||
changelog = `${changelog + pr}\n`
|
|
||||||
}
|
|
||||||
changelog = `${changelog}\n` // add space between sections
|
|
||||||
} else if (category.empty_content !== undefined) {
|
|
||||||
if (category.title) {
|
|
||||||
changelog = `${changelog + category.title}\n\n`
|
|
||||||
}
|
|
||||||
changelog = `${changelog + category.empty_content}\n\n`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
core.info(`✒️ Wrote ${categorizedPrs.length} categorized pull requests down`)
|
core.info(`✒️ Wrote ${categorizedPrs.length} categorized pull requests down`)
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
@@ -359,6 +294,80 @@ export function buildChangelog(diffInfo: DiffInfo, origPrs: PullRequestInfo[], o
|
|||||||
return transformedChangelog
|
return transformedChangelog
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function categorizePr(category: Category, pr: PullRequestInfo): boolean {
|
||||||
|
let matched = false // check if we matched within the given category
|
||||||
|
// check if any exclude label matches
|
||||||
|
if (category.exclude_labels !== undefined) {
|
||||||
|
if (
|
||||||
|
haveCommonElementsArr(
|
||||||
|
category.exclude_labels.map(lbl => lbl.toLocaleLowerCase('en')),
|
||||||
|
pr.labels
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (core.isDebug()) {
|
||||||
|
const excludeLabels = JSON.stringify(category.exclude_labels)
|
||||||
|
core.debug(` PR ${pr.number} with labels: ${pr.labels} excluded from category via exclude label: ${excludeLabels}`)
|
||||||
|
}
|
||||||
|
return false // one of the exclude labels matched, skip the PR for this category
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// in case we have exhaustive matching enabled, and have labels and/or rules
|
||||||
|
// validate for an exhaustive match (e.g. every provided rule applies)
|
||||||
|
if (category.exhaustive === true && (category.labels !== undefined || category.rules !== undefined)) {
|
||||||
|
if (category.labels !== undefined) {
|
||||||
|
matched = haveEveryElementsArr(
|
||||||
|
category.labels.map(lbl => lbl.toLocaleLowerCase('en')),
|
||||||
|
pr.labels
|
||||||
|
)
|
||||||
|
}
|
||||||
|
let exhaustive_rules = true
|
||||||
|
if (category.exhaustive_rules !== undefined) {
|
||||||
|
exhaustive_rules = category.exhaustive_rules
|
||||||
|
}
|
||||||
|
if ((matched || category.labels === undefined) && category.rules !== undefined) {
|
||||||
|
matched = matchesRules(category.rules, pr, exhaustive_rules)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if not exhaustive, do individual matches
|
||||||
|
if (category.labels !== undefined) {
|
||||||
|
// check if either any of the labels applies
|
||||||
|
matched = haveCommonElementsArr(
|
||||||
|
category.labels.map(lbl => lbl.toLocaleLowerCase('en')),
|
||||||
|
pr.labels
|
||||||
|
)
|
||||||
|
}
|
||||||
|
let exhaustive_rules = false
|
||||||
|
if (category.exhaustive_rules !== undefined) {
|
||||||
|
exhaustive_rules = category.exhaustive_rules
|
||||||
|
}
|
||||||
|
if (!matched && category.rules !== undefined) {
|
||||||
|
// if no label did apply, check if any rule applies
|
||||||
|
matched = matchesRules(category.rules, pr, exhaustive_rules)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matched
|
||||||
|
}
|
||||||
|
|
||||||
|
function attachCategoryChangelog(changelog: string, category: Category, pullRequests: string[]): string {
|
||||||
|
if (pullRequests.length > 0) {
|
||||||
|
if (category.title) {
|
||||||
|
changelog = `${changelog + category.title}\n\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const pr of pullRequests) {
|
||||||
|
changelog = `${changelog + pr}\n`
|
||||||
|
}
|
||||||
|
changelog = `${changelog}\n` // add space between sections
|
||||||
|
} else if (category.empty_content !== undefined) {
|
||||||
|
if (category.title) {
|
||||||
|
changelog = `${changelog + category.title}\n\n`
|
||||||
|
}
|
||||||
|
changelog = `${changelog + category.empty_content}\n\n`
|
||||||
|
}
|
||||||
|
return changelog
|
||||||
|
}
|
||||||
|
|
||||||
export function replaceEmptyTemplate(template: string, options: ReleaseNotesOptions): string {
|
export function replaceEmptyTemplate(template: string, options: ReleaseNotesOptions): string {
|
||||||
const placeholders = new Map<string, Placeholder[]>()
|
const placeholders = new Map<string, Placeholder[]>()
|
||||||
for (const ph of options.configuration.custom_placeholders || []) {
|
for (const ph of options.configuration.custom_placeholders || []) {
|
||||||
|
|||||||
Reference in New Issue
Block a user