Merge pull request #86 from mikepenz/develop

develop -> main
This commit is contained in:
Mike Penz
2020-11-04 14:22:59 +01:00
committed by GitHub
10 changed files with 1752 additions and 439 deletions
+9 -1
View File
@@ -151,6 +151,9 @@ This configuration is a `.json` file in the following format.
"labels": ["test"] "labels": ["test"]
} }
], ],
"ignore_labels": [
"ignore"
],
"sort": "ASC", "sort": "ASC",
"template": "${{CHANGELOG}}\n\n<details>\n<summary>Uncategorized</summary>\n\n${{UNCATEGORIZED}}\n</details>", "template": "${{CHANGELOG}}\n\n<details>\n<summary>Uncategorized</summary>\n\n${{UNCATEGORIZED}}\n</details>",
"pr_template": "- ${{TITLE}}\n - PR: #${{NUMBER}}", "pr_template": "- ${{TITLE}}\n - PR: #${{NUMBER}}",
@@ -175,6 +178,8 @@ This configuration is a `.json` file in the following format.
Any section of the configuration can be omitted to have defaults apply. Any section of the configuration can be omitted to have defaults apply.
💡 `ignore_labels` take precedence over category labels, allowing to specifically exclude certain PRs.
Defaults for the configuration can be found in the [configuration.ts](https://github.com/mikepenz/release-changelog-builder-action/blob/develop/src/configuration.ts) Defaults for the configuration can be found in the [configuration.ts](https://github.com/mikepenz/release-changelog-builder-action/blob/develop/src/configuration.ts)
Please see the [Configuration Specification](#configuration-specification) for detailed descriptions on the offered configuration options. Please see the [Configuration Specification](#configuration-specification) for detailed descriptions on the offered configuration options.
@@ -239,12 +244,14 @@ Table of supported placeholders allowed to be used in the `template` and `empty_
|----------------------------|----------------------------------------------------------------------------------------------------|:---------:| |----------------------------|----------------------------------------------------------------------------------------------------|:---------:|
| `${{CHANGELOG}}` | The contents of the changelog, matching the labels as specified in the categories configuration | | | `${{CHANGELOG}}` | The contents of the changelog, matching the labels as specified in the categories configuration | |
| `${{UNCATEGORIZED}}` | All pull requests not matching a specified label in categories | | | `${{UNCATEGORIZED}}` | All pull requests not matching a specified label in categories | |
| `${{IGNORED}}` | All pull requests defining labels matching the `ignore_labels` configuration | |
| `${{OWNER}}` | Describes the owner of the repository the changelog was generated for | x | | `${{OWNER}}` | Describes the owner of the repository the changelog was generated for | x |
| `${{REPO}}` | The repository name of the repo the changelog was generated for | x | | `${{REPO}}` | The repository name of the repo the changelog was generated for | x |
| `${{FROM_TAG}}` | Defines the 'start' from where the changelog did consider merged pull requests | x | | `${{FROM_TAG}}` | Defines the 'start' from where the changelog did consider merged pull requests | x |
| `${{TO_TAG}}` | Defines until which tag the changelog did consider merged pull requests | x | | `${{TO_TAG}}` | Defines until which tag the changelog did consider merged pull requests | x |
| `${{CATEGORIZED_COUNT}}` | The count of PRs which were categorized | | | `${{CATEGORIZED_COUNT}}` | The count of PRs which were categorized | |
| `${{UNCATEGORIZED_COUNT}}` | The count of PRs and changes which were not categorized. No label overlapping with category labels | | | `${{UNCATEGORIZED_COUNT}}` | The count of PRs and changes which were not categorized. No label overlapping with category labels | |
| `${{IGNORED_COUNT}}` | The count of PRs and changes which were specifically ignored from the changelog. | |
### Configuration Specification ### Configuration Specification
@@ -255,7 +262,8 @@ Table of descriptions for the `configuration.json` options.
|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| categories | An array of `category` specifications, offering a flexible way to group changes into categories | | categories | An array of `category` specifications, offering a flexible way to group changes into categories |
| category.title | The display name of a category in the changelog | | category.title | The display name of a category in the changelog |
| category.labels | An array of labels, to match pull request labels against. If any PR label, matches any category label, the pull request will show up under this category | | category.labels | An array of labels, to match pull request labels against. If any PR label matches any category label, the pull request will show up under this category |
| ignore_labels | An array of labels, to match pull request labels against. If any PR label overlaps, the pull request will be ignored from the changelog. This takes precedence over category labels |
| sort | The sort order of pull requests. [ASC, DESC] | | sort | The sort order of pull requests. [ASC, DESC] |
| template | Specifies the global template to pick for creating the changelog. See [Template placeholders](#template-placeholders) for possible values | | template | Specifies the global template to pick for creating the changelog. See [Template placeholders](#template-placeholders) for possible values |
| pr_template | Defines the per pull request template. See [PR Template placeholders](#pr-template-placeholders) for possible values | | pr_template | Defines the per pull request template. See [PR Template placeholders](#pr-template-placeholders) for possible values |
+44 -1
View File
@@ -87,5 +87,48 @@ it('Should fill `template` placeholders', async () => {
const changeLog = await releaseNotesBuilder.build() const changeLog = await releaseNotesBuilder.build()
console.log(changeLog) console.log(changeLog)
expect(changeLog).toStrictEqual(`## 🧪 Tests\n\n- [CI] Specify Test Case\n - PR: #10\n\n\n\nmikepenz\nrelease-changelog-builder-action\nv0.0.1\nv0.0.3\n1\n0`) expect(changeLog).toStrictEqual(`## 🧪 Tests\n\n- [CI] Specify Test Case\n - PR: #10\n\n\n\n\nmikepenz\nrelease-changelog-builder-action\nv0.0.1\nv0.0.3\n1\n0\n0`)
})
it('Should fill `template` placeholders, ignore', async () => {
jest.setTimeout(180000)
const configuration = resolveConfiguration('', 'configs_test/configuration_empty_all_placeholders.json')
const releaseNotesBuilder = new ReleaseNotesBuilder(
null,
'.',
'mikepenz',
'release-changelog-builder-action',
'v0.9.1',
'v0.9.5',
false,
false,
configuration
)
const changeLog = await releaseNotesBuilder.build()
console.log(changeLog)
expect(changeLog).toStrictEqual(`## 🚀 Features\n\n- Enhance sorting by using proper semver\n - PR: #51\n\n## 🧪 Tests\n\n- Improve test cases\n - PR: #49\n\n\n- Bump @types/node from 14.11.8 to 14.11.10\n - PR: #47\n- Adjust code to move fromTag resolving to main.ts\n - PR: #48\n- dev -> main\n - PR: #52\n- Update package.json to updated description\n - PR: #53\n- dev -> main\n - PR: #54\n\n- New additional placeholders for \`template\` and \`empty_template\`\n - PR: #50\n\nmikepenz\nrelease-changelog-builder-action\nv0.9.1\nv0.9.5\n2\n5\n1`)
})
it('Uncategorized category', async () => {
jest.setTimeout(180000)
const configuration = resolveConfiguration('', 'configs_test/configuration_uncategorized_category.json')
const releaseNotesBuilder = new ReleaseNotesBuilder(
null,
'.',
'mikepenz',
'release-changelog-builder-action',
'v0.9.1',
'v0.9.5',
false,
false,
configuration
)
const changeLog = await releaseNotesBuilder.build()
console.log(changeLog)
expect(changeLog).toStrictEqual(`## 🚀 Features\n\n- Enhance sorting by using proper semver\n - PR: #51\n\n## 📦 Uncategorized\n\n- Bump @types/node from 14.11.8 to 14.11.10\n - PR: #47\n- Adjust code to move fromTag resolving to main.ts\n - PR: #48\n- Improve test cases\n - PR: #49\n- dev -> main\n - PR: #52\n- Update package.json to updated description\n - PR: #53\n- dev -> main\n - PR: #54\n\n\n\nUncategorized:\n- Bump @types/node from 14.11.8 to 14.11.10\n - PR: #47\n- Adjust code to move fromTag resolving to main.ts\n - PR: #48\n- Improve test cases\n - PR: #49\n- dev -> main\n - PR: #52\n- Update package.json to updated description\n - PR: #53\n- dev -> main\n - PR: #54\n\n\nIgnored:\n- New additional placeholders for \`template\` and \`empty_template\`\n - PR: #50\n\n\n6\n1`)
}) })
@@ -1,4 +1,4 @@
{ {
"template": "${{CHANGELOG}}\n${{UNCATEGORIZED}}\n${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}\n${{CATEGORIZED_COUNT}}\n${{UNCATEGORIZED_COUNT}}", "template": "${{CHANGELOG}}\n${{UNCATEGORIZED}}\n${{IGNORED}}\n${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}\n${{CATEGORIZED_COUNT}}\n${{UNCATEGORIZED_COUNT}}\n${{IGNORED_COUNT}}",
"empty_template": "${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}" "empty_template": "${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}"
} }
@@ -0,0 +1,14 @@
{
"categories": [
{
"title": "## 🚀 Features",
"labels": ["feature"]
},
{
"title": "## 📦 Uncategorized",
"labels": []
}
],
"template": "${{CHANGELOG}}\n\nUncategorized:\n${{UNCATEGORIZED}}\n\nIgnored:\n${{IGNORED}}\n\n${{UNCATEGORIZED_COUNT}}\n${{IGNORED_COUNT}}",
"empty_template": "${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}"
}
Generated Vendored
+1192 -9
View File
File diff suppressed because it is too large Load Diff
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+447 -416
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -35,7 +35,7 @@
"@actions/core": "^1.2.6", "@actions/core": "^1.2.6",
"@actions/exec": "^1.0.4", "@actions/exec": "^1.0.4",
"@actions/github": "^4.0.0", "@actions/github": "^4.0.0",
"@octokit/rest": "^18.0.6", "@octokit/rest": "^18.0.9",
"@types/semver": "^7.3.4", "@types/semver": "^7.3.4",
"moment": "^2.29.1", "moment": "^2.29.1",
"semver": "^7.3.2" "semver": "^7.3.2"
@@ -43,13 +43,13 @@
"devDependencies": { "devDependencies": {
"@types/jest": "^26.0.15", "@types/jest": "^26.0.15",
"@types/node": "^14.14.6", "@types/node": "^14.14.6",
"@typescript-eslint/parser": "^4.6.0", "@typescript-eslint/parser": "^4.6.1",
"@vercel/ncc": "^0.24.1", "@vercel/ncc": "^0.24.1",
"eslint": "^7.12.1", "eslint": "^7.12.1",
"eslint-plugin-github": "^4.1.1", "eslint-plugin-github": "^4.1.1",
"eslint-plugin-jest": "^24.1.0", "eslint-plugin-jest": "^24.1.0",
"jest": "^24.9.0", "jest": "^24.9.0",
"jest-circus": "^26.6.1", "jest-circus": "^26.6.3",
"js-yaml": "^3.14.0", "js-yaml": "^3.14.0",
"prettier": "2.1.2", "prettier": "2.1.2",
"ts-jest": "^24.3.0", "ts-jest": "^24.3.0",
+2
View File
@@ -8,6 +8,7 @@ export interface Configuration {
pr_template: string pr_template: string
empty_template: string empty_template: string
categories: Category[] categories: Category[]
ignore_labels: string[]
transformers: Transformer[] transformers: Transformer[]
tag_resolver: TagResolver tag_resolver: TagResolver
} }
@@ -49,6 +50,7 @@ export const DefaultConfiguration: Configuration = {
labels: ['test'] labels: ['test']
} }
], // the categories to support for the ordering ], // the categories to support for the ordering
ignore_labels: [ "ignore" ], // list of lables being ignored from the changelog
transformers: [], // transformers to apply on the PR description according to the `pr_template` transformers: [], // transformers to apply on the PR description according to the `pr_template`
tag_resolver: { tag_resolver: {
// defines the logic on how to resolve the previous tag, only relevant if `fromTag` is not specified // defines the logic on how to resolve the previous tag, only relevant if `fromTag` is not specified
+39 -7
View File
@@ -42,16 +42,24 @@ export function buildChangelog(
// bring PRs into the order of categories // bring PRs into the order of categories
const categorized = new Map<Category, string[]>() const categorized = new Map<Category, string[]>()
const categories = config.categories || DefaultConfiguration.categories const categories = config.categories || DefaultConfiguration.categories
const ignoredLabels = config.ignore_labels || DefaultConfiguration.ignore_labels
for (const category of categories) { for (const category of categories) {
categorized.set(category, []) categorized.set(category, [])
} }
const categorizedPrs: string[] = [] const categorizedPrs: string[] = []
const uncategorized: string[] = [] const ignoredPrs: string[] = []
const uncategorizedPrs: string[] = []
// bring elements in order // bring elements in order
for (const [pr, body] of transformedMap) { for (const [pr, body] of transformedMap) {
let matched = false if (haveCommonElements(ignoredLabels, pr.labels)) {
ignoredPrs.push(body)
continue
}
let matched = false
for (const [category, pullRequests] of categorized) { for (const [category, pullRequests] of categorized) {
if (haveCommonElements(category.labels, pr.labels)) { if (haveCommonElements(category.labels, pr.labels)) {
pullRequests.push(body) pullRequests.push(body)
@@ -60,7 +68,15 @@ export function buildChangelog(
} }
if (!matched) { if (!matched) {
uncategorized.push(body) // we allow to have pull requests included in an "uncategorized" category
for (const [category, pullRequests] of categorized) {
if (category.labels.length === 0) {
pullRequests.push(body)
break
}
}
uncategorizedPrs.push(body)
} else { } else {
categorizedPrs.push(body) categorizedPrs.push(body)
} }
@@ -81,14 +97,22 @@ export function buildChangelog(
changelog = `${changelog}\n` changelog = `${changelog}\n`
} }
} }
core.info(`✒️ Wrote ${categorized.size} categorized pull requests down`) core.info(`✒️ Wrote ${categorizedPrs.length} categorized pull requests down`)
let changelogUncategorized = '' let changelogUncategorized = ''
for (const pr of uncategorized) { for (const pr of uncategorizedPrs) {
changelogUncategorized = `${changelogUncategorized + pr}\n` changelogUncategorized = `${changelogUncategorized + pr}\n`
} }
core.info( core.info(
`✒️ Wrote ${uncategorized.length} non categorized pull requests down` `✒️ Wrote ${uncategorizedPrs.length} non categorized pull requests down`
)
let changelogIgnored = ''
for (const pr of ignoredPrs) {
changelogIgnored = `${changelogIgnored + pr}\n`
}
core.info(
`✒️ Wrote ${ignoredPrs.length} ignored pull requests down`
) )
// fill template // fill template
@@ -101,6 +125,10 @@ export function buildChangelog(
'${{UNCATEGORIZED}}', '${{UNCATEGORIZED}}',
changelogUncategorized changelogUncategorized
) )
transformedChangelog = transformedChangelog.replace(
'${{IGNORED}}',
changelogIgnored
)
// fill other placeholders // fill other placeholders
transformedChangelog = transformedChangelog.replace( transformedChangelog = transformedChangelog.replace(
@@ -109,7 +137,11 @@ export function buildChangelog(
) )
transformedChangelog = transformedChangelog.replace( transformedChangelog = transformedChangelog.replace(
'${{UNCATEGORIZED_COUNT}}', '${{UNCATEGORIZED_COUNT}}',
uncategorized.length.toString() uncategorizedPrs.length.toString()
)
transformedChangelog = transformedChangelog.replace(
'${{IGNORED_COUNT}}',
ignoredPrs.length.toString()
) )
transformedChangelog = fillAdditionalPlaceholders( transformedChangelog = fillAdditionalPlaceholders(
transformedChangelog, transformedChangelog,