@auto-it/released
Version:
Released plugin for auto. Comments with version + extra
170 lines • 7.69 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@auto-it/core");
const bot_list_1 = tslib_1.__importDefault(require("@auto-it/bot-list"));
const deepmerge_1 = tslib_1.__importDefault(require("deepmerge"));
const t = tslib_1.__importStar(require("io-ts"));
const pluginOptions = t.partial({
/** Message to use when posting on issues and pull requests */
message: t.string,
/** The label to add to issues and pull requests */
label: t.string,
/** The label to add to issues and pull requests that are in a prerelease */
prereleaseLabel: t.string,
/** Whether to lock the issue once the pull request has been released */
lockIssues: t.boolean,
/** Whether to lock the issue once the pull request has been released */
lockPrs: t.boolean,
/** Whether to comment on PRs made by bots */
includeBotPrs: t.boolean,
});
const TYPE = "%TYPE";
const VERSION = "%VERSION";
const defaultOptions = {
label: "released",
prereleaseLabel: "prerelease",
lockIssues: false,
lockPrs: false,
includeBotPrs: false,
message: `:rocket: ${TYPE} was released in ${VERSION} :rocket:`,
};
const closeIssue = /(?:Close|Closes|Closed|Fix|Fixes|Fixed|Resolve|Resolves|Resolved)\s((?:#\d+(?:,\s)?)+)/gi;
/** Comment on merged pull requests and issues with the new version */
class ReleasedLabelPlugin {
/** Initialize the plugin with it's options */
constructor(options = {}) {
/** The name of the plugin */
this.name = "released";
this.options = deepmerge_1.default(defaultOptions, options);
}
/** Tap into auto plugin points. */
apply(auto) {
auto.hooks.modifyConfig.tap(this.name, (config) => {
if (!config.labels.find((l) => l.name === this.options.label)) {
config.labels.push({
name: this.options.label,
description: "This issue/pull request has been released.",
releaseType: "none",
});
}
if (!config.labels.find((l) => l.name === this.options.prereleaseLabel)) {
config.labels.push({
name: this.options.prereleaseLabel,
description: "This change is available in a prerelease.",
releaseType: "none",
});
}
return config;
});
auto.hooks.validateConfig.tapPromise(this.name, async (name, options) => {
if (name === this.name || name === `@auto-it/${this.name}`) {
return core_1.validatePluginConfiguration(this.name, pluginOptions, options);
}
});
auto.hooks.afterRelease.tapPromise(this.name, async ({ newVersion, commits, response }) => {
var _a;
if (!newVersion) {
return;
}
const head = commits[0];
if (!head) {
return;
}
const skipReleaseLabels = (((_a = auto.config) === null || _a === void 0 ? void 0 : _a.labels.filter((l) => l.releaseType === "skip")) || []).map((l) => l.name);
const isSkipped = head.labels.find((label) => skipReleaseLabels.includes(label));
if (isSkipped) {
return;
}
const releases = (Array.isArray(response) && response) ||
(response && [response]) ||
[];
await Promise.all(commits.map(async (commit) => this.addReleased(auto, commit, releases)));
});
}
/** Add the release label + other stuff to a commit */
async addReleased(auto, commit, releases) {
var _a, _b;
const messages = [commit.subject];
const isPrerelease = releases.some((r) => r.data.prerelease);
if (commit.pullRequest) {
try {
const pr = await auto.git.getPullRequest(commit.pullRequest.number);
const branch = pr === null || pr === void 0 ? void 0 : pr.data.head.ref;
if (branch && ((_a = auto.config) === null || _a === void 0 ? void 0 : _a.prereleaseBranches.includes(branch))) {
return;
}
if (!this.options.includeBotPrs &&
commit.authors.some((author) => (author.name && bot_list_1.default.includes(author.name)) ||
(author.username && bot_list_1.default.includes(author.username)) ||
author.type === "Bot")) {
return;
}
await this.addCommentAndLabel({
auto,
prOrIssue: commit.pullRequest.number,
isPrerelease,
releases,
});
if (this.options.lockPrs && !isPrerelease) {
await auto.git.lockIssue(commit.pullRequest.number);
}
(_b = pr.data.body) === null || _b === void 0 ? void 0 : _b.split("\n").map((line) => messages.push(line));
const commitsInPr = await auto.git.getCommitsForPR(commit.pullRequest.number);
commitsInPr.map((c) => messages.push(c.commit.message));
}
catch (error) {
auto.logger.verbose.log(error);
}
}
const issues = messages
.map((message) => message.match(closeIssue))
.filter((r) => Boolean(r))
.reduce((all, arr) => [...all, ...arr], [])
.map((issue) => issue.match(/#(\d+)/i))
.filter((r) => Boolean(r))
.map((match) => Number(match[1]));
await Promise.all(issues.map(async (issue) => {
await this.addCommentAndLabel({
auto,
prOrIssue: issue,
isIssue: true,
isPrerelease,
releases,
});
if (this.options.lockIssues && !isPrerelease) {
await auto.git.lockIssue(issue);
}
}));
}
/** Add the templated comment to the pr and attach the "released" label */
async addCommentAndLabel({ auto, prOrIssue, isIssue = false, isPrerelease = false, releases, }) {
// leave a comment with the new version
const urls = releases.map((release) => this.options.message === defaultOptions.message
? `[\`${release.data.name || release.data.tag_name}\`](${release.data.html_url})`
: release.data.name);
const message = this.createReleasedComment(isIssue, urls.join(", "));
await auto.comment({ message, pr: prOrIssue, context: "released" });
// add a `released` label to a PR
const labels = await auto.git.getLabels(prOrIssue);
if (isPrerelease) {
if (!labels.includes(this.options.prereleaseLabel)) {
await auto.git.addLabelToPr(prOrIssue, this.options.prereleaseLabel);
}
}
else if (!labels.includes(this.options.label)) {
await auto.git.addLabelToPr(prOrIssue, this.options.label);
if (labels.includes(this.options.prereleaseLabel)) {
await auto.git.removeLabel(prOrIssue, this.options.prereleaseLabel);
}
}
}
/** Create a comment that fits the context (pr of issue) */
createReleasedComment(isIssue, version) {
return this.options.message
.replace(new RegExp(TYPE, "g"), isIssue ? "Issue" : "PR")
.replace(new RegExp(VERSION, "g"), version);
}
}
exports.default = ReleasedLabelPlugin;
//# sourceMappingURL=index.js.map