@process-engine/ci_tools
Version:
CI tools for process-engine.io
118 lines (114 loc) • 5.64 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.createReleaseAnnouncement = exports.run = void 0;
const chalk = require("chalk");
const cross_fetch_1 = require("cross-fetch");
const moment = require("moment");
const yargsParser = require("yargs-parser");
const pull_requests_1 = require("../../github/pull_requests");
const git_1 = require("../../git/git");
const git_helpers_1 = require("../../versions/git_helpers");
const package_version_1 = require("../../versions/package_version");
const COMMIT_API_URI = (0, git_1.getCurrentApiBaseUrlWithAuth)('/commits/:commit_sha');
const BADGE = '[create-release-announcement]\t';
const DEFAULT_MODE = 'node';
const CONSIDER_PULL_REQUESTS_WEEKS_BACK = 30;
/**
* Creates an announcement based on data available in Git and GitHub:
*
* - Git: latest commits and tags
* - GitHub: PRs
*/
async function run(...args) {
const argv = yargsParser(args, { alias: { help: ['h'] }, default: { mode: DEFAULT_MODE } });
const mode = argv.mode;
const text = await createReleaseAnnouncement(mode);
console.log(text);
return true;
}
exports.run = run;
async function createReleaseAnnouncement(mode) {
const startRef = await (0, git_helpers_1.getPrevVersionTag)(mode);
const nextVersion = await (0, package_version_1.getPackageVersion)(mode);
const nextVersionTag = (0, git_helpers_1.getVersionTag)(nextVersion);
const repoUrl = `http://github.com/${(0, git_1.getCurrentRepoNameWithOwner)()}`;
const releaseTagUrl = `${repoUrl}/releases/tag/${nextVersionTag}`;
const getPrUrl = (number) => `${repoUrl}/pull/${number}`;
const releaseHeadline = `*${nextVersionTag}* was released!`;
const releaseTagLinkFooter = `Please see the <${releaseTagUrl}|full CHANGELOG> for details.`;
if (startRef == null) {
const changelogText = `
${releaseHeadline}
${releaseTagLinkFooter}
`
.replace('`', "'")
.trim();
return changelogText;
}
const apiResponse = await getCommitFromApi(startRef);
if (apiResponse.commit === undefined) {
console.error(chalk.red(`${BADGE}API responded with: ${apiResponse.message}`));
process.exit(3);
}
const startCommitDate = apiResponse.commit.committer.date;
const startDate = moment(startCommitDate).subtract(CONSIDER_PULL_REQUESTS_WEEKS_BACK, 'weeks').toISOString();
const endRef = 'HEAD';
if (nextVersion == null) {
console.error(chalk.red(`${BADGE}Could not determine nextVersion!`));
process.exit(3);
}
printInfo(startRef, startDate, endRef, nextVersion, nextVersionTag);
const mergedPullRequestsSince = await (0, pull_requests_1.getMergedPullRequests)(startDate);
const mergedPullRequests = filterPullRequestsForBranch(mergedPullRequestsSince, '', startRef, startDate);
console.log(`${BADGE}Found ${mergedPullRequests.length} merged pull requests since the last stable release`);
const hasBreakingChanges = mergedPullRequests.some((pr) => pr.isBreakingChange);
const breakingChangesHint = hasBreakingChanges
? 'Please note there are *BREAKING CHANGES*:'
: 'The new version includes the following changes:';
const mergedPullRequestsText = mergedPullRequests
.map((pr) => {
let title = ensureSpaceAfterLeadingEmoji(pr.title);
if (pr.isBreakingChange) {
title = `*BREAKING CHANGE:* ${title}`;
}
return `- <${getPrUrl(pr.number)}|#${pr.number}> ${title}`;
})
.join('\n');
const changelogText = `
${releaseHeadline}
${breakingChangesHint}
${mergedPullRequestsText}
${releaseTagLinkFooter}
`
.replace('`', "'")
.trim();
return changelogText;
}
exports.createReleaseAnnouncement = createReleaseAnnouncement;
async function getCommitFromApi(ref) {
const url = COMMIT_API_URI.replace(':commit_sha', ref);
const response = await (0, cross_fetch_1.default)(url);
return response.json();
}
function printInfo(startRef, startDate, endRef, nextVersion, nextVersionTag) {
console.log(`${BADGE}startRef:`, startRef);
console.log(`${BADGE}startDate:`, startDate);
console.log(`${BADGE}endRef:`, endRef);
console.log(`${BADGE}nextVersion:`, nextVersion);
console.log(`${BADGE}nextVersionTag:`, nextVersionTag);
console.log('');
}
function ensureSpaceAfterLeadingEmoji(text) {
const emojiWithoutTrailingSpaceRegex = /([\u{1f300}-\u{1f5ff}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}\u{1f680}-\u{1f6ff}\u{2600}-\u{26ff}\u{2700}-\u{27bf}\u{1f1e6}-\u{1f1ff}\u{1f191}-\u{1f251}\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}-\u{1f17f}\u{1f18e}\u{3030}\u{2b50}\u{2b55}\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}-\u{2b1c}\u{3297}\u{3299}\u{303d}\u{00a9}\u{00ae}\u{2122}\u{23f3}\u{24c2}\u{23e9}-\u{23ef}\u{25b6}\u{23f8}-\u{23fa}])(\S)/gu;
return text.replace(emojiWithoutTrailingSpaceRegex, (substring, emojiMatch, characterAfterEmojiMatch) => {
return `${emojiMatch} ${characterAfterEmojiMatch}`;
});
}
function filterPullRequestsForBranch(prs, branchName, startRef, since) {
const allShaInCurrentBranch = (0, git_1.getGitCommitListSince)(branchName, since).split('\n');
const allShaInStartRef = (0, git_1.getGitCommitListSince)(startRef, since).split('\n');
const newShaInCurrentBranch = allShaInCurrentBranch.filter((currentSha) => allShaInStartRef.indexOf(currentSha) === -1);
const filteredPrs = prs.filter((pr) => newShaInCurrentBranch.indexOf(pr.headSha) !== -1 || newShaInCurrentBranch.indexOf(pr.mergeCommitSha) !== -1);
return filteredPrs;
}
//# sourceMappingURL=create-release-announcement.js.map
;