- introduce new additional placeholders useable for building the changelog
| **Placeholder** | **Description** | **Empty** |
|----------------------------|----------------------------------------------------------------------------------------------------|:---------:|
| `${{CHANGED_FILES}}` | The count of changed files. | |
| `${{ADDITIONS}}` | The count of code additions (lines). | |
| `${{DELETIONS}}` | The count of code deletions (lines). | |
| `${{CHANGES}}` | The count of total changes (lines). | |
| `${{COMMITS}}` | The count of commits in this release. | |
- restructure project to return additional diff related information along the individual commits
- update testcases to verify functionality of new placeholders
This commit is contained in:
@@ -86,6 +86,11 @@ A full set list of possible output values for this action.
|
||||
| `outputs.categorized_prs` | Count of PRs which were successfully categorized as part of the action. |
|
||||
| `outputs.open_prs` | Count of open PRs. Only fetched if `includeOpen` is enabled. |
|
||||
| `outputs.uncategorized_prs` | Count of PRs which were not categorized as part of the action. |
|
||||
| `outputs.changed_files` | Count of changed files in this release. |
|
||||
| `outputs.additions` | Count of code additions in this release (lines). |
|
||||
| `outputs.deletions` | Count of code deletions in this release (lines). |
|
||||
| `outputs.changes` | Total count of changes in this release (lines). |
|
||||
| `outputs.commits` | Count of commits which have been added in this release. |
|
||||
|
||||
|
||||
## Full Sample 🖥️
|
||||
@@ -309,6 +314,11 @@ Table of supported placeholders allowed to be used in the `template` and `empty_
|
||||
| `${{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 |
|
||||
| `${{RELEASE_DIFF}}` | Introduces a link to the full diff between from tag and to tag releases | x |
|
||||
| `${{CHANGED_FILES}}` | The count of changed files. | |
|
||||
| `${{ADDITIONS}}` | The count of code additions (lines). | |
|
||||
| `${{DELETIONS}}` | The count of code deletions (lines). | |
|
||||
| `${{CHANGES}}` | The count of total changes (lines). | |
|
||||
| `${{COMMITS}}` | The count of commits in this release. | |
|
||||
| `${{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 | |
|
||||
| `${{OPEN_COUNT}}` | The count of open PRs. Will only be fetched if `includeOpen` is configured. | |
|
||||
@@ -404,7 +414,7 @@ export GITHUB_TOKEN=your_personal_github_pat
|
||||
|
||||
All patches and changes applied to the original source are licensed under the Apache 2.0 license.
|
||||
|
||||
Copyright 2021 Mike Penz
|
||||
Copyright 2022 Mike Penz
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -25,7 +25,7 @@ it('Should have empty changelog (tags)', async () => {
|
||||
|
||||
const changeLog = await releaseNotes.pull()
|
||||
console.log(changeLog)
|
||||
expect(changeLog).toStrictEqual(null)
|
||||
expect(changeLog).toStrictEqual("- no changes")
|
||||
})
|
||||
|
||||
it('Should match generated changelog (tags)', async () => {
|
||||
|
||||
@@ -103,7 +103,7 @@ it('Should fill empty placeholders', async () => {
|
||||
const changeLog = await releaseNotesBuilder.build()
|
||||
console.log(changeLog)
|
||||
expect(changeLog).toStrictEqual(
|
||||
`mikepenz\nrelease-changelog-builder-action\nv0.0.2\nv0.0.3`
|
||||
`mikepenz\nrelease-changelog-builder-action\nv0.0.2\nv0.0.3\nhttps://github.com/mikepenz/release-changelog-builder-action/compare/v0.0.2...v0.0.3`
|
||||
)
|
||||
})
|
||||
|
||||
@@ -131,7 +131,7 @@ it('Should fill `template` placeholders', async () => {
|
||||
const changeLog = await releaseNotesBuilder.build()
|
||||
console.log(changeLog)
|
||||
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`
|
||||
`## 🧪 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\nhttps://github.com/mikepenz/release-changelog-builder-action/compare/v0.0.1...v0.0.3\n1\n0\n0\n19\n14827\n444\n15271\n3`
|
||||
)
|
||||
})
|
||||
|
||||
@@ -159,7 +159,7 @@ it('Should fill `template` placeholders, ignore', async () => {
|
||||
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`
|
||||
`## 🚀 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\nhttps://github.com/mikepenz/release-changelog-builder-action/compare/v0.9.1...v0.9.5\n2\n5\n1\n16\n2931\n450\n3381\n26`
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
+14
-13
@@ -2,6 +2,7 @@ import {buildChangelog} from '../src/transform'
|
||||
import {PullRequestInfo} from '../src/pullRequests'
|
||||
import moment from 'moment'
|
||||
import { DefaultConfiguration, Configuration } from '../src/configuration';
|
||||
import { DefaultDiffInfo } from '../src/commits';
|
||||
|
||||
jest.setTimeout(180000)
|
||||
|
||||
@@ -130,7 +131,7 @@ it('Extract label from title, combined regex', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, mergedPullRequests, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
@@ -159,7 +160,7 @@ it('Extract label from title and body, combined regex', async () => {
|
||||
|
||||
let prs = Array.from(mergedPullRequests)
|
||||
prs.push(pullRequestWithLabelInBody)
|
||||
const resultChangelog = buildChangelog(prs, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, prs, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
@@ -190,7 +191,7 @@ it('Extract label from title, split regex', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, mergedPullRequests, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
@@ -221,7 +222,7 @@ it('Extract label from title, match', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, mergedPullRequests, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
@@ -247,7 +248,7 @@ it('Extract label from title, match multiple', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, mergedPullRequests, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
@@ -274,7 +275,7 @@ it('Extract label from title, match multiple, custon non matching label', async
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, mergedPullRequests, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
@@ -388,7 +389,7 @@ it('Match multiple labels exhaustive for category', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
@@ -413,7 +414,7 @@ it('Deduplicate duplicated PRs', async () => {
|
||||
method: 'match'
|
||||
}
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
@@ -439,7 +440,7 @@ it('Deduplicate duplicated PRs DESC', async () => {
|
||||
method: 'match'
|
||||
}
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
@@ -471,7 +472,7 @@ it('Use empty_content for empty category', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
@@ -493,7 +494,7 @@ it('Commit SHA-1 in commitMode', async () => {
|
||||
customConfig.sort = "DESC"
|
||||
customConfig.pr_template = "${{MERGE_SHA}}"
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
@@ -514,7 +515,7 @@ it('Release Diff', async () => {
|
||||
const customConfig = Object.assign({}, DefaultConfiguration)
|
||||
customConfig.template = "${{RELEASE_DIFF}}"
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'release-changelog-builder-action',
|
||||
fromTag: 'v2.8.0',
|
||||
@@ -553,7 +554,7 @@ it('Use exclude labels to not include a PR within a category.', async () => {
|
||||
}
|
||||
]
|
||||
|
||||
const resultChangelog = buildChangelog(pullRequestsWithLabels, {
|
||||
const resultChangelog = buildChangelog(DefaultDiffInfo, pullRequestsWithLabels, {
|
||||
owner: 'mikepenz',
|
||||
repo: 'test-repo',
|
||||
fromTag: '1.0.0',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"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}}",
|
||||
"template": "${{CHANGELOG}}\n${{UNCATEGORIZED}}\n${{IGNORED}}\n${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}\n${{RELEASE_DIFF}}\n${{CATEGORIZED_COUNT}}\n${{UNCATEGORIZED_COUNT}}\n${{IGNORED_COUNT}}\n${{CHANGED_FILES}}\n${{ADDITIONS}}\n${{DELETIONS}}\n${{CHANGES}}\n${{COMMITS}}",
|
||||
"empty_template": "${{OWNER}}\n${{REPO}}\n${{FROM_TAG}}\n${{TO_TAG}}\n${{RELEASE_DIFF}}",
|
||||
"max_pull_requests": 1000,
|
||||
"max_back_track_time_days": 1000
|
||||
}
|
||||
+87
-37
@@ -42,21 +42,36 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.filterCommits = exports.Commits = void 0;
|
||||
exports.filterCommits = exports.Commits = exports.DefaultDiffInfo = void 0;
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const moment_1 = __importDefault(__nccwpck_require__(9623));
|
||||
exports.DefaultDiffInfo = {
|
||||
changedFiles: 0,
|
||||
additions: 0,
|
||||
deletions: 0,
|
||||
changes: 0,
|
||||
commits: 0,
|
||||
commitInfo: []
|
||||
};
|
||||
class Commits {
|
||||
constructor(octokit) {
|
||||
this.octokit = octokit;
|
||||
}
|
||||
getDiff(owner, repo, base, head) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const commits = yield this.getDiffRemote(owner, repo, base, head);
|
||||
return this.sortCommits(commits);
|
||||
const diff = yield this.getDiffRemote(owner, repo, base, head);
|
||||
diff.commitInfo = this.sortCommits(diff.commitInfo);
|
||||
return diff;
|
||||
});
|
||||
}
|
||||
getDiffRemote(owner, repo, base, head) {
|
||||
var _a, _b;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let changedFilesCount = 0;
|
||||
let additionCount = 0;
|
||||
let deletionCount = 0;
|
||||
let changeCount = 0;
|
||||
let commitCount = 0;
|
||||
// Fetch comparisons recursively until we don't find any commits
|
||||
// This is because the GitHub API limits the number of commits returned in a single response.
|
||||
let commits = [];
|
||||
@@ -72,23 +87,40 @@ class Commits {
|
||||
if (compareResult.data.total_commits === 0) {
|
||||
break;
|
||||
}
|
||||
changedFilesCount += (_b = (_a = compareResult.data.files) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
|
||||
const files = compareResult.data.files;
|
||||
if (files !== undefined) {
|
||||
for (const file of files) {
|
||||
additionCount += file.additions;
|
||||
deletionCount += file.deletions;
|
||||
changeCount += file.changes;
|
||||
}
|
||||
}
|
||||
commitCount += compareResult.data.commits.length;
|
||||
commits = compareResult.data.commits.concat(commits);
|
||||
compareHead = `${commits[0].sha}^`;
|
||||
}
|
||||
core.info(`ℹ️ Found ${commits.length} commits from the GitHub API for ${owner}/${repo}`);
|
||||
return commits
|
||||
.filter(commit => commit.sha)
|
||||
.map(commit => {
|
||||
var _a, _b;
|
||||
return ({
|
||||
sha: commit.sha || '',
|
||||
summary: commit.commit.message.split('\n')[0],
|
||||
message: commit.commit.message,
|
||||
date: (0, moment_1.default)((_a = commit.commit.committer) === null || _a === void 0 ? void 0 : _a.date),
|
||||
author: ((_b = commit.commit.author) === null || _b === void 0 ? void 0 : _b.name) || '',
|
||||
prNumber: undefined
|
||||
});
|
||||
});
|
||||
return {
|
||||
changedFiles: changedFilesCount,
|
||||
additions: additionCount,
|
||||
deletions: deletionCount,
|
||||
changes: changeCount,
|
||||
commits: commitCount,
|
||||
commitInfo: commits
|
||||
.filter(commit => commit.sha)
|
||||
.map(commit => {
|
||||
var _a, _b;
|
||||
return ({
|
||||
sha: commit.sha || '',
|
||||
summary: commit.commit.message.split('\n')[0],
|
||||
message: commit.commit.message,
|
||||
date: (0, moment_1.default)((_a = commit.commit.committer) === null || _a === void 0 ? void 0 : _a.date),
|
||||
author: ((_b = commit.commit.author) === null || _b === void 0 ? void 0 : _b.name) || '',
|
||||
prNumber: undefined
|
||||
});
|
||||
})
|
||||
};
|
||||
});
|
||||
}
|
||||
sortCommits(commits) {
|
||||
@@ -718,29 +750,40 @@ class ReleaseNotes {
|
||||
pull() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let mergedPullRequests;
|
||||
let diffInfo;
|
||||
if (!this.options.commitMode) {
|
||||
core.startGroup(`🚀 Load pull requests`);
|
||||
mergedPullRequests = yield this.getMergedPullRequests(this.octokit);
|
||||
const [info, prs] = yield this.getMergedPullRequests(this.octokit);
|
||||
mergedPullRequests = prs;
|
||||
diffInfo = info;
|
||||
// define the included PRs within this release as output
|
||||
core.setOutput('pull_requests', mergedPullRequests
|
||||
.map(pr => {
|
||||
return pr.number;
|
||||
})
|
||||
.join(','));
|
||||
core.setOutput('changed_files', diffInfo.changedFiles);
|
||||
core.setOutput('additions', diffInfo.additions);
|
||||
core.setOutput('deletions', diffInfo.deletions);
|
||||
core.setOutput('changes', diffInfo.changes);
|
||||
core.setOutput('commits', diffInfo.commits);
|
||||
core.endGroup();
|
||||
}
|
||||
else {
|
||||
core.startGroup(`🚀 Load commit history`);
|
||||
core.info(`⚠️ Executing experimental commit mode`);
|
||||
mergedPullRequests = yield this.generateCommitPRs(this.octokit);
|
||||
const [info, prs] = yield this.generateCommitPRs(this.octokit);
|
||||
mergedPullRequests = prs;
|
||||
diffInfo = info;
|
||||
core.endGroup();
|
||||
}
|
||||
if (mergedPullRequests.length === 0) {
|
||||
core.warning(`⚠️ No pull requests found`);
|
||||
return null;
|
||||
return (0, transform_1.fillAdditionalPlaceholders)(this.options.configuration.empty_template ||
|
||||
configuration_1.DefaultConfiguration.empty_template, this.options);
|
||||
}
|
||||
core.startGroup('📦 Build changelog');
|
||||
const resultChangelog = (0, transform_1.buildChangelog)(mergedPullRequests, this.options);
|
||||
const resultChangelog = (0, transform_1.buildChangelog)(diffInfo, mergedPullRequests, this.options);
|
||||
core.endGroup();
|
||||
return resultChangelog;
|
||||
});
|
||||
@@ -750,27 +793,28 @@ class ReleaseNotes {
|
||||
const { owner, repo, fromTag, toTag, failOnError } = this.options;
|
||||
core.info(`ℹ️ Comparing ${owner}/${repo} - '${fromTag}...${toTag}'`);
|
||||
const commitsApi = new commits_1.Commits(octokit);
|
||||
let commits;
|
||||
let diffInfo;
|
||||
try {
|
||||
commits = yield commitsApi.getDiff(owner, repo, fromTag, toTag);
|
||||
diffInfo = yield commitsApi.getDiff(owner, repo, fromTag, toTag);
|
||||
}
|
||||
catch (error) {
|
||||
(0, utils_1.failOrError)(`💥 Failed to retrieve - Invalid tag? - Because of: ${error}`, failOnError);
|
||||
return [];
|
||||
return commits_1.DefaultDiffInfo;
|
||||
}
|
||||
if (commits.length === 0) {
|
||||
if (diffInfo.commitInfo.length === 0) {
|
||||
core.warning(`⚠️ No commits found between - ${fromTag}...${toTag}`);
|
||||
return [];
|
||||
return commits_1.DefaultDiffInfo;
|
||||
}
|
||||
return commits;
|
||||
return diffInfo;
|
||||
});
|
||||
}
|
||||
getMergedPullRequests(octokit) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const { owner, repo, includeOpen, fetchReviewers, configuration } = this.options;
|
||||
const commits = yield this.getCommitHistory(octokit);
|
||||
const diffInfo = yield this.getCommitHistory(octokit);
|
||||
const commits = diffInfo.commitInfo;
|
||||
if (commits.length === 0) {
|
||||
return [];
|
||||
return [diffInfo, []];
|
||||
}
|
||||
const firstCommit = commits[0];
|
||||
const lastCommit = commits[commits.length - 1];
|
||||
@@ -832,20 +876,21 @@ class ReleaseNotes {
|
||||
}
|
||||
}
|
||||
}
|
||||
return finalPrs;
|
||||
return [diffInfo, finalPrs];
|
||||
});
|
||||
}
|
||||
generateCommitPRs(octokit) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const { owner, repo, configuration } = this.options;
|
||||
const commits = yield this.getCommitHistory(octokit);
|
||||
const diffInfo = yield this.getCommitHistory(octokit);
|
||||
const commits = diffInfo.commitInfo;
|
||||
if (commits.length === 0) {
|
||||
return [];
|
||||
return [diffInfo, []];
|
||||
}
|
||||
const prCommits = (0, commits_1.filterCommits)(commits, configuration.exclude_merge_branches ||
|
||||
configuration_1.DefaultConfiguration.exclude_merge_branches);
|
||||
core.info(`ℹ️ Retrieved ${prCommits.length} commits for ${owner}/${repo}`);
|
||||
return prCommits.map(function (commit) {
|
||||
const prs = prCommits.map(function (commit) {
|
||||
return {
|
||||
number: 0,
|
||||
title: commit.summary,
|
||||
@@ -865,6 +910,7 @@ class ReleaseNotes {
|
||||
status: 'merged'
|
||||
};
|
||||
});
|
||||
return [diffInfo, prs];
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -918,7 +964,6 @@ const rest_1 = __nccwpck_require__(5375);
|
||||
const releaseNotes_1 = __nccwpck_require__(5882);
|
||||
const tags_1 = __nccwpck_require__(7532);
|
||||
const utils_1 = __nccwpck_require__(918);
|
||||
const transform_1 = __nccwpck_require__(1644);
|
||||
class ReleaseNotesBuilder {
|
||||
constructor(baseUrl, token, repositoryPath, owner, repo, fromTag, toTag, includeOpen = false, failOnError, ignorePreReleases, fetchReviewers = false, commitMode, configuration) {
|
||||
this.baseUrl = baseUrl;
|
||||
@@ -996,9 +1041,7 @@ class ReleaseNotesBuilder {
|
||||
configuration: this.configuration
|
||||
};
|
||||
const releaseNotes = new releaseNotes_1.ReleaseNotes(octokit, options);
|
||||
return ((yield releaseNotes.pull()) ||
|
||||
(0, transform_1.fillAdditionalPlaceholders)(this.configuration.empty_template ||
|
||||
configuration_1.DefaultConfiguration.empty_template, options));
|
||||
return yield releaseNotes.pull();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1364,7 +1407,7 @@ exports.validateTransformer = exports.fillAdditionalPlaceholders = exports.build
|
||||
const core = __importStar(__nccwpck_require__(2186));
|
||||
const configuration_1 = __nccwpck_require__(5527);
|
||||
const pullRequests_1 = __nccwpck_require__(4217);
|
||||
function buildChangelog(prs, options) {
|
||||
function buildChangelog(diffInfo, prs, options) {
|
||||
// sort to target order
|
||||
const config = options.configuration;
|
||||
const sort = config.sort || configuration_1.DefaultConfiguration.sort;
|
||||
@@ -1546,6 +1589,12 @@ function buildChangelog(prs, options) {
|
||||
transformedChangelog = transformedChangelog.replace(/\${{UNCATEGORIZED_COUNT}}/g, uncategorizedPrs.length.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{OPEN_COUNT}}/g, openPrs.length.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{IGNORED_COUNT}}/g, ignoredPrs.length.toString());
|
||||
// code change placeholders
|
||||
transformedChangelog = transformedChangelog.replace(/\${{CHANGED_FILES}}/g, diffInfo.changedFiles.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{ADDITIONS}}/g, diffInfo.additions.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{DELETIONS}}/g, diffInfo.deletions.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{CHANGES}}/g, diffInfo.changes.toString());
|
||||
transformedChangelog = transformedChangelog.replace(/\${{COMMITS}}/g, diffInfo.commits.toString());
|
||||
transformedChangelog = fillAdditionalPlaceholders(transformedChangelog, options);
|
||||
core.info(`ℹ️ Filled template`);
|
||||
return transformedChangelog;
|
||||
@@ -1553,6 +1602,7 @@ function buildChangelog(prs, options) {
|
||||
exports.buildChangelog = buildChangelog;
|
||||
function fillAdditionalPlaceholders(text, options) {
|
||||
let transformed = text;
|
||||
// repository placeholders
|
||||
transformed = transformed.replace(/\${{OWNER}}/g, options.owner);
|
||||
transformed = transformed.replace(/\${{REPO}}/g, options.repo);
|
||||
transformed = transformed.replace(/\${{FROM_TAG}}/g, options.fromTag);
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+56
-19
@@ -2,6 +2,24 @@ import * as core from '@actions/core'
|
||||
import {Octokit, RestEndpointMethodTypes} from '@octokit/rest'
|
||||
import moment from 'moment'
|
||||
|
||||
export interface DiffInfo {
|
||||
changedFiles: number
|
||||
additions: number
|
||||
deletions: number
|
||||
changes: number
|
||||
commits: number
|
||||
commitInfo: CommitInfo[]
|
||||
}
|
||||
|
||||
export const DefaultDiffInfo: DiffInfo = {
|
||||
changedFiles: 0,
|
||||
additions: 0,
|
||||
deletions: 0,
|
||||
changes: 0,
|
||||
commits: 0,
|
||||
commitInfo: []
|
||||
}
|
||||
|
||||
export interface CommitInfo {
|
||||
sha: string
|
||||
summary: string
|
||||
@@ -18,14 +36,10 @@ export class Commits {
|
||||
repo: string,
|
||||
base: string,
|
||||
head: string
|
||||
): Promise<CommitInfo[]> {
|
||||
const commits: CommitInfo[] = await this.getDiffRemote(
|
||||
owner,
|
||||
repo,
|
||||
base,
|
||||
head
|
||||
)
|
||||
return this.sortCommits(commits)
|
||||
): Promise<DiffInfo> {
|
||||
const diff: DiffInfo = await this.getDiffRemote(owner, repo, base, head)
|
||||
diff.commitInfo = this.sortCommits(diff.commitInfo)
|
||||
return diff
|
||||
}
|
||||
|
||||
private async getDiffRemote(
|
||||
@@ -33,7 +47,13 @@ export class Commits {
|
||||
repo: string,
|
||||
base: string,
|
||||
head: string
|
||||
): Promise<CommitInfo[]> {
|
||||
): Promise<DiffInfo> {
|
||||
let changedFilesCount = 0
|
||||
let additionCount = 0
|
||||
let deletionCount = 0
|
||||
let changeCount = 0
|
||||
let commitCount = 0
|
||||
|
||||
// Fetch comparisons recursively until we don't find any commits
|
||||
// This is because the GitHub API limits the number of commits returned in a single response.
|
||||
let commits: RestEndpointMethodTypes['repos']['compareCommits']['response']['data']['commits'] =
|
||||
@@ -50,6 +70,16 @@ export class Commits {
|
||||
if (compareResult.data.total_commits === 0) {
|
||||
break
|
||||
}
|
||||
changedFilesCount += compareResult.data.files?.length ?? 0
|
||||
const files = compareResult.data.files
|
||||
if (files !== undefined) {
|
||||
for (const file of files) {
|
||||
additionCount += file.additions
|
||||
deletionCount += file.deletions
|
||||
changeCount += file.changes
|
||||
}
|
||||
}
|
||||
commitCount += compareResult.data.commits.length
|
||||
commits = compareResult.data.commits.concat(commits)
|
||||
compareHead = `${commits[0].sha}^`
|
||||
}
|
||||
@@ -58,16 +88,23 @@ export class Commits {
|
||||
`ℹ️ Found ${commits.length} commits from the GitHub API for ${owner}/${repo}`
|
||||
)
|
||||
|
||||
return commits
|
||||
.filter(commit => commit.sha)
|
||||
.map(commit => ({
|
||||
sha: commit.sha || '',
|
||||
summary: commit.commit.message.split('\n')[0],
|
||||
message: commit.commit.message,
|
||||
date: moment(commit.commit.committer?.date),
|
||||
author: commit.commit.author?.name || '',
|
||||
prNumber: undefined
|
||||
}))
|
||||
return {
|
||||
changedFiles: changedFilesCount,
|
||||
additions: additionCount,
|
||||
deletions: deletionCount,
|
||||
changes: changeCount,
|
||||
commits: commitCount,
|
||||
commitInfo: commits
|
||||
.filter(commit => commit.sha)
|
||||
.map(commit => ({
|
||||
sha: commit.sha || '',
|
||||
summary: commit.commit.message.split('\n')[0],
|
||||
message: commit.commit.message,
|
||||
date: moment(commit.commit.committer?.date),
|
||||
author: commit.commit.author?.name || '',
|
||||
prNumber: undefined
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
private sortCommits(commits: CommitInfo[]): CommitInfo[] {
|
||||
|
||||
+45
-22
@@ -1,9 +1,9 @@
|
||||
import * as core from '@actions/core'
|
||||
import {CommitInfo, Commits, filterCommits} from './commits'
|
||||
import {Commits, filterCommits, DiffInfo, DefaultDiffInfo} from './commits'
|
||||
import {Configuration, DefaultConfiguration} from './configuration'
|
||||
import {PullRequestInfo, PullRequests} from './pullRequests'
|
||||
import {Octokit} from '@octokit/rest'
|
||||
import {buildChangelog} from './transform'
|
||||
import {buildChangelog, fillAdditionalPlaceholders} from './transform'
|
||||
import {failOrError} from './utils'
|
||||
|
||||
export interface ReleaseNotesOptions {
|
||||
@@ -21,11 +21,15 @@ export interface ReleaseNotesOptions {
|
||||
export class ReleaseNotes {
|
||||
constructor(private octokit: Octokit, private options: ReleaseNotesOptions) {}
|
||||
|
||||
async pull(): Promise<string | null> {
|
||||
async pull(): Promise<string> {
|
||||
let mergedPullRequests: PullRequestInfo[]
|
||||
let diffInfo: DiffInfo
|
||||
if (!this.options.commitMode) {
|
||||
core.startGroup(`🚀 Load pull requests`)
|
||||
mergedPullRequests = await this.getMergedPullRequests(this.octokit)
|
||||
|
||||
const [info, prs] = await this.getMergedPullRequests(this.octokit)
|
||||
mergedPullRequests = prs
|
||||
diffInfo = info
|
||||
|
||||
// define the included PRs within this release as output
|
||||
core.setOutput(
|
||||
@@ -37,57 +41,74 @@ export class ReleaseNotes {
|
||||
.join(',')
|
||||
)
|
||||
|
||||
core.setOutput('changed_files', diffInfo.changedFiles)
|
||||
core.setOutput('additions', diffInfo.additions)
|
||||
core.setOutput('deletions', diffInfo.deletions)
|
||||
core.setOutput('changes', diffInfo.changes)
|
||||
core.setOutput('commits', diffInfo.commits)
|
||||
|
||||
core.endGroup()
|
||||
} else {
|
||||
core.startGroup(`🚀 Load commit history`)
|
||||
core.info(`⚠️ Executing experimental commit mode`)
|
||||
mergedPullRequests = await this.generateCommitPRs(this.octokit)
|
||||
const [info, prs] = await this.generateCommitPRs(this.octokit)
|
||||
mergedPullRequests = prs
|
||||
diffInfo = info
|
||||
core.endGroup()
|
||||
}
|
||||
|
||||
if (mergedPullRequests.length === 0) {
|
||||
core.warning(`⚠️ No pull requests found`)
|
||||
return null
|
||||
return fillAdditionalPlaceholders(
|
||||
this.options.configuration.empty_template ||
|
||||
DefaultConfiguration.empty_template,
|
||||
this.options
|
||||
)
|
||||
}
|
||||
|
||||
core.startGroup('📦 Build changelog')
|
||||
const resultChangelog = buildChangelog(mergedPullRequests, this.options)
|
||||
const resultChangelog = buildChangelog(
|
||||
diffInfo,
|
||||
mergedPullRequests,
|
||||
this.options
|
||||
)
|
||||
core.endGroup()
|
||||
return resultChangelog
|
||||
}
|
||||
|
||||
private async getCommitHistory(octokit: Octokit): Promise<CommitInfo[]> {
|
||||
private async getCommitHistory(octokit: Octokit): Promise<DiffInfo> {
|
||||
const {owner, repo, fromTag, toTag, failOnError} = this.options
|
||||
core.info(`ℹ️ Comparing ${owner}/${repo} - '${fromTag}...${toTag}'`)
|
||||
|
||||
const commitsApi = new Commits(octokit)
|
||||
let commits: CommitInfo[]
|
||||
let diffInfo: DiffInfo
|
||||
try {
|
||||
commits = await commitsApi.getDiff(owner, repo, fromTag, toTag)
|
||||
diffInfo = await commitsApi.getDiff(owner, repo, fromTag, toTag)
|
||||
} catch (error) {
|
||||
failOrError(
|
||||
`💥 Failed to retrieve - Invalid tag? - Because of: ${error}`,
|
||||
failOnError
|
||||
)
|
||||
return []
|
||||
return DefaultDiffInfo
|
||||
}
|
||||
if (commits.length === 0) {
|
||||
if (diffInfo.commitInfo.length === 0) {
|
||||
core.warning(`⚠️ No commits found between - ${fromTag}...${toTag}`)
|
||||
return []
|
||||
return DefaultDiffInfo
|
||||
}
|
||||
|
||||
return commits
|
||||
return diffInfo
|
||||
}
|
||||
|
||||
private async getMergedPullRequests(
|
||||
octokit: Octokit
|
||||
): Promise<PullRequestInfo[]> {
|
||||
): Promise<[DiffInfo, PullRequestInfo[]]> {
|
||||
const {owner, repo, includeOpen, fetchReviewers, configuration} =
|
||||
this.options
|
||||
|
||||
const commits = await this.getCommitHistory(octokit)
|
||||
const diffInfo = await this.getCommitHistory(octokit)
|
||||
const commits = diffInfo.commitInfo
|
||||
if (commits.length === 0) {
|
||||
return []
|
||||
return [diffInfo, []]
|
||||
}
|
||||
|
||||
const firstCommit = commits[0]
|
||||
@@ -193,17 +214,18 @@ export class ReleaseNotes {
|
||||
}
|
||||
}
|
||||
|
||||
return finalPrs
|
||||
return [diffInfo, finalPrs]
|
||||
}
|
||||
|
||||
private async generateCommitPRs(
|
||||
octokit: Octokit
|
||||
): Promise<PullRequestInfo[]> {
|
||||
): Promise<[DiffInfo, PullRequestInfo[]]> {
|
||||
const {owner, repo, configuration} = this.options
|
||||
|
||||
const commits = await this.getCommitHistory(octokit)
|
||||
const diffInfo = await this.getCommitHistory(octokit)
|
||||
const commits = diffInfo.commitInfo
|
||||
if (commits.length === 0) {
|
||||
return []
|
||||
return [diffInfo, []]
|
||||
}
|
||||
|
||||
const prCommits = filterCommits(
|
||||
@@ -214,7 +236,7 @@ export class ReleaseNotes {
|
||||
|
||||
core.info(`ℹ️ Retrieved ${prCommits.length} commits for ${owner}/${repo}`)
|
||||
|
||||
return prCommits.map(function (commit): PullRequestInfo {
|
||||
const prs = prCommits.map(function (commit): PullRequestInfo {
|
||||
return {
|
||||
number: 0,
|
||||
title: commit.summary,
|
||||
@@ -234,5 +256,6 @@ export class ReleaseNotes {
|
||||
status: 'merged'
|
||||
}
|
||||
})
|
||||
return [diffInfo, prs]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import {Octokit} from '@octokit/rest'
|
||||
import {ReleaseNotes} from './releaseNotes'
|
||||
import {Tags} from './tags'
|
||||
import {failOrError} from './utils'
|
||||
import {fillAdditionalPlaceholders} from './transform'
|
||||
|
||||
export class ReleaseNotesBuilder {
|
||||
constructor(
|
||||
@@ -98,13 +97,6 @@ export class ReleaseNotesBuilder {
|
||||
}
|
||||
const releaseNotes = new ReleaseNotes(octokit, options)
|
||||
|
||||
return (
|
||||
(await releaseNotes.pull()) ||
|
||||
fillAdditionalPlaceholders(
|
||||
this.configuration.empty_template ||
|
||||
DefaultConfiguration.empty_template,
|
||||
options
|
||||
)
|
||||
)
|
||||
return await releaseNotes.pull()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@ import {
|
||||
} from './configuration'
|
||||
import {PullRequestInfo, sortPullRequests} from './pullRequests'
|
||||
import {ReleaseNotesOptions} from './releaseNotes'
|
||||
import {DiffInfo} from './commits'
|
||||
|
||||
export function buildChangelog(
|
||||
diffInfo: DiffInfo,
|
||||
prs: PullRequestInfo[],
|
||||
options: ReleaseNotesOptions
|
||||
): string {
|
||||
@@ -272,6 +274,27 @@ export function buildChangelog(
|
||||
/\${{IGNORED_COUNT}}/g,
|
||||
ignoredPrs.length.toString()
|
||||
)
|
||||
// code change placeholders
|
||||
transformedChangelog = transformedChangelog.replace(
|
||||
/\${{CHANGED_FILES}}/g,
|
||||
diffInfo.changedFiles.toString()
|
||||
)
|
||||
transformedChangelog = transformedChangelog.replace(
|
||||
/\${{ADDITIONS}}/g,
|
||||
diffInfo.additions.toString()
|
||||
)
|
||||
transformedChangelog = transformedChangelog.replace(
|
||||
/\${{DELETIONS}}/g,
|
||||
diffInfo.deletions.toString()
|
||||
)
|
||||
transformedChangelog = transformedChangelog.replace(
|
||||
/\${{CHANGES}}/g,
|
||||
diffInfo.changes.toString()
|
||||
)
|
||||
transformedChangelog = transformedChangelog.replace(
|
||||
/\${{COMMITS}}/g,
|
||||
diffInfo.commits.toString()
|
||||
)
|
||||
transformedChangelog = fillAdditionalPlaceholders(
|
||||
transformedChangelog,
|
||||
options
|
||||
@@ -286,6 +309,7 @@ export function fillAdditionalPlaceholders(
|
||||
options: ReleaseNotesOptions
|
||||
): string {
|
||||
let transformed = text
|
||||
// repository placeholders
|
||||
transformed = transformed.replace(/\${{OWNER}}/g, options.owner)
|
||||
transformed = transformed.replace(/\${{REPO}}/g, options.repo)
|
||||
transformed = transformed.replace(/\${{FROM_TAG}}/g, options.fromTag)
|
||||
|
||||
Reference in New Issue
Block a user