Merge pull request #151 from mikepenz/feature/141

Experimental commit based changelog generation mode
This commit is contained in:
Mike Penz
2021-01-07 15:38:58 +01:00
committed by GitHub
11 changed files with 11121 additions and 4265 deletions
+5
View File
@@ -17,6 +17,7 @@ it('Should have empty changelog (tags)', async () => {
fromTag: 'v0.0.1', fromTag: 'v0.0.1',
toTag: 'v0.0.2', toTag: 'v0.0.2',
failOnError: false, failOnError: false,
commitMode: false,
configuration: configuration configuration: configuration
}) })
@@ -33,6 +34,7 @@ it('Should match generated changelog (tags)', async () => {
fromTag: 'v0.0.1', fromTag: 'v0.0.1',
toTag: 'v0.0.3', toTag: 'v0.0.3',
failOnError: false, failOnError: false,
commitMode: false,
configuration: configuration configuration: configuration
}) })
@@ -57,6 +59,7 @@ it('Should match generated changelog (refs)', async () => {
fromTag: '5ec7a2d86fe9f43fdd38d5e254a1117c8a51b4c3', fromTag: '5ec7a2d86fe9f43fdd38d5e254a1117c8a51b4c3',
toTag: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa', toTag: 'fa3788c8c4b3373ef8424ce3eb008a5cd07cc5aa',
failOnError: false, failOnError: false,
commitMode: false,
configuration: configuration configuration: configuration
}) })
@@ -89,6 +92,7 @@ it('Should match ordered ASC', async () => {
fromTag: 'v0.3.0', fromTag: 'v0.3.0',
toTag: 'v0.5.0', toTag: 'v0.5.0',
failOnError: false, failOnError: false,
commitMode: false,
configuration: configuration configuration: configuration
}) })
@@ -110,6 +114,7 @@ it('Should match ordered DESC', async () => {
fromTag: 'v0.3.0', fromTag: 'v0.3.0',
toTag: 'v0.5.0', toTag: 'v0.5.0',
failOnError: false, failOnError: false,
commitMode: false,
configuration: configuration configuration: configuration
}) })
+33
View File
@@ -14,6 +14,7 @@ it('Should match generated changelog (unspecified fromTag)', async () => {
'v0.0.3', 'v0.0.3',
false, false,
false, false,
false,
configuration configuration
) )
@@ -38,6 +39,7 @@ it('Should use empty placeholder', async () => {
'v0.0.3', 'v0.0.3',
false, false,
false, false,
false,
configuration configuration
) )
@@ -60,6 +62,7 @@ it('Should fill empty placeholders', async () => {
'v0.0.3', 'v0.0.3',
false, false,
false, false,
false,
configuration configuration
) )
@@ -84,6 +87,7 @@ it('Should fill `template` placeholders', async () => {
'v0.0.3', 'v0.0.3',
false, false,
false, false,
false,
configuration configuration
) )
@@ -108,6 +112,7 @@ it('Should fill `template` placeholders, ignore', async () => {
'v0.9.5', 'v0.9.5',
false, false,
false, false,
false,
configuration configuration
) )
@@ -132,6 +137,7 @@ it('Uncategorized category', async () => {
'v0.9.5', 'v0.9.5',
false, false,
false, false,
false,
configuration configuration
) )
@@ -141,3 +147,30 @@ it('Uncategorized category', async () => {
`## 🚀 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` `## 🚀 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`
) )
}) })
it('Verify commit based changelog', async () => {
const configuration = resolveConfiguration(
'',
'configs_test/configuration_commits.json'
)
const releaseNotesBuilder = new ReleaseNotesBuilder(
null,
'.',
'mikepenz',
'release-changelog-builder-action',
'v0.0.1',
'v0.0.3',
false,
false,
true,
configuration
)
const changeLog = await releaseNotesBuilder.build()
console.log(changeLog)
expect(changeLog).toStrictEqual(
`## 📦 Uncategorized\n\n- - introduce proper approach to retrieve tag before a given tag\n\n- - configure test case\n\n- Merge pull request #10 from mikepenz/feature/specify_test\n\n\n\n\nUncategorized:\n- - introduce proper approach to retrieve tag before a given tag\n\n- - configure test case\n\n- Merge pull request #10 from mikepenz/feature/specify_test\n\n\n\nIgnored:\n\n\n3\n0`
)
})
+3
View File
@@ -23,6 +23,9 @@ inputs:
failOnError: failOnError:
description: 'Defines if the action should result in a build failure, if an error was discovered' description: 'Defines if the action should result in a build failure, if an error was discovered'
default: "false" default: "false"
commitMode:
description: 'Enables a `light` commit based mode. This mode generates changelogs based on the commits. Please note that this is not officially supported, and lacks a lot of features only possible with PRs.'
default: "false"
outputFile: outputFile:
description: 'If defined, the changelog will get written to this file. (relative to the checkout dir)' description: 'If defined, the changelog will get written to this file. (relative to the checkout dir)'
token: token:
+11
View File
@@ -0,0 +1,11 @@
{
"categories": [
{
"title": "## 📦 Uncategorized",
"labels": []
}
],
"template": "${{CHANGELOG}}\n\nUncategorized:\n${{UNCATEGORIZED}}\n\nIgnored:\n${{IGNORED}}\n\n${{UNCATEGORIZED_COUNT}}\n${{IGNORED_COUNT}}",
"pr_template": "- ${{TITLE}}\n",
"empty_template": "${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}"
}
Generated Vendored
+385 -339
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
Generated Vendored
+1 -3910
View File
File diff suppressed because one or more lines are too long
+10625 -1
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -33,6 +33,7 @@ async function run(): Promise<void> {
// read in flags // read in flags
const ignorePreReleases = core.getInput('ignorePreReleases') === 'true' const ignorePreReleases = core.getInput('ignorePreReleases') === 'true'
const failOnError = core.getInput('failOnError') === 'true' const failOnError = core.getInput('failOnError') === 'true'
const commitMode = core.getInput('commitMode') === 'true'
const result = await new ReleaseNotesBuilder( const result = await new ReleaseNotesBuilder(
token, token,
@@ -43,6 +44,7 @@ async function run(): Promise<void> {
toTag, toTag,
failOnError, failOnError,
ignorePreReleases, ignorePreReleases,
commitMode,
configuration configuration
).build() ).build()
+53 -14
View File
@@ -12,6 +12,7 @@ export interface ReleaseNotesOptions {
fromTag: string // the tag/ref to start from fromTag: string // the tag/ref to start from
toTag: string // the tag/ref up to toTag: string // the tag/ref up to
failOnError: boolean // defines if we should fail the action in case of an error failOnError: boolean // defines if we should fail the action in case of an error
commitMode: boolean // defines if we use the alternative commit based mode. note: this is only partially supported
configuration: Configuration // the configuration as defined in `configuration.ts` configuration: Configuration // the configuration as defined in `configuration.ts`
} }
@@ -21,9 +22,17 @@ export class ReleaseNotes {
async pull(): Promise<string | null> { async pull(): Promise<string | null> {
const {configuration} = this.options const {configuration} = this.options
core.startGroup(`🚀 Load pull requests`) let mergedPullRequests: PullRequestInfo[]
const mergedPullRequests = await this.getMergedPullRequests(this.octokit) if (!this.options.commitMode) {
core.endGroup() core.startGroup(`🚀 Load pull requests`)
mergedPullRequests = await this.getMergedPullRequests(this.octokit)
core.endGroup()
} else {
core.startGroup(`🚀 Load commit history`)
core.info(`⚠️ Executing experimental commit mode`)
mergedPullRequests = await this.generateCommitPRs(this.octokit)
core.endGroup()
}
if (mergedPullRequests.length === 0) { if (mergedPullRequests.length === 0) {
core.warning(`⚠️ No pull requests found`) core.warning(`⚠️ No pull requests found`)
@@ -40,17 +49,8 @@ export class ReleaseNotes {
return resultChangelog return resultChangelog
} }
private async getMergedPullRequests( private async getCommitHistory(octokit: Octokit): Promise<CommitInfo[]> {
octokit: Octokit const {owner, repo, fromTag, toTag, failOnError} = this.options
): Promise<PullRequestInfo[]> {
const {
owner,
repo,
fromTag,
toTag,
failOnError,
configuration
} = this.options
core.info(`️ Comparing ${owner}/${repo} - '${fromTag}...${toTag}'`) core.info(`️ Comparing ${owner}/${repo} - '${fromTag}...${toTag}'`)
const commitsApi = new Commits(octokit) const commitsApi = new Commits(octokit)
@@ -69,6 +69,19 @@ export class ReleaseNotes {
return [] return []
} }
return commits
}
private async getMergedPullRequests(
octokit: Octokit
): Promise<PullRequestInfo[]> {
const {owner, repo, configuration} = this.options
const commits = await this.getCommitHistory(octokit)
if (commits.length === 0) {
return []
}
const firstCommit = commits[0] const firstCommit = commits[0]
const lastCommit = commits[commits.length - 1] const lastCommit = commits[commits.length - 1]
let fromDate = firstCommit.date let fromDate = firstCommit.date
@@ -120,4 +133,30 @@ export class ReleaseNotes {
return releaseCommitHashes.includes(pr.mergeCommitSha) return releaseCommitHashes.includes(pr.mergeCommitSha)
}) })
} }
private async generateCommitPRs(
octokit: Octokit
): Promise<PullRequestInfo[]> {
const commits = await this.getCommitHistory(octokit)
if (commits.length === 0) {
return []
}
return commits.map(function (commit) {
return {
number: 0,
title: commit.summary,
htmlURL: '',
mergedAt: commit.date,
mergeCommitSha: '',
author: commit.author || '',
repoName: '',
labels: [],
milestone: '',
body: commit.message || '',
assignees: [],
requestedReviewers: []
}
})
}
} }
+2
View File
@@ -18,6 +18,7 @@ export class ReleaseNotesBuilder {
private toTag: string | null, private toTag: string | null,
private failOnError: boolean, private failOnError: boolean,
private ignorePreReleases: boolean, private ignorePreReleases: boolean,
private commitMode: boolean,
private configuration: Configuration private configuration: Configuration
) {} ) {}
@@ -104,6 +105,7 @@ export class ReleaseNotesBuilder {
fromTag: this.fromTag, fromTag: this.fromTag,
toTag: this.toTag, toTag: this.toTag,
failOnError: this.failOnError, failOnError: this.failOnError,
commitMode: this.commitMode,
configuration: this.configuration configuration: this.configuration
} }
const releaseNotes = new ReleaseNotes(octokit, options) const releaseNotes = new ReleaseNotes(octokit, options)