UNPKG

@auto-it/released

Version:

Released plugin for auto. Comments with version + extra

170 lines • 7.69 kB
"use strict"; 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