UNPKG

@salesforce/plugin-release-management

Version:
122 lines 5.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /* * Copyright (c) 2020, salesforce.com, inc. * All rights reserved. * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, camelcase*/ const os = require("os"); const command_1 = require("@salesforce/command"); const core_1 = require("@octokit/core"); const kit_1 = require("@salesforce/kit"); const ts_types_1 = require("@salesforce/ts-types"); const core_2 = require("@salesforce/core"); const dependabot_1 = require("../../dependabot"); core_2.Messages.importMessagesDirectory(__dirname); const messages = core_2.Messages.loadMessages('@salesforce/plugin-release-management', 'dependabot.automerge'); const messagesFromConsolidate = core_2.Messages.loadMessages('@salesforce/plugin-release-management', 'dependabot.consolidate'); class AutoMerge extends command_1.SfdxCommand { async run() { const auth = (0, ts_types_1.ensureString)(new kit_1.Env().getString('GH_TOKEN') ?? new kit_1.Env().getString('GITHUB_TOKEN'), 'GH_TOKEN is required to be set in the environment'); const { owner, repo } = await (0, dependabot_1.getOwnerAndRepo)(this.flags.owner, this.flags.repo); this.octokit = new core_1.Octokit({ auth }); this.baseRepoObject = { owner, repo, }; this.ux.log(`owner: ${this.baseRepoObject.owner}, scope: ${this.baseRepoObject.repo}`); const eligiblePRs = (await this.octokit.request('GET /repos/{owner}/{repo}/pulls', this.baseRepoObject)).data.filter((pr) => pr.state === 'open' && pr.user.login === 'dependabot[bot]'); const greenPRs = (await Promise.all(eligiblePRs.map((pr) => this.isGreen(pr)))).filter((pr) => pr !== undefined); const mergeablePRs = (await Promise.all(greenPRs.map((pr) => this.isMergeable(pr)))).filter((pr) => pr !== undefined); this.ux.table(mergeablePRs, { title: { header: 'Green, Mergeable PR' }, html_url: { header: 'Link' }, }); this.ux.log(''); if (mergeablePRs.length === 0) { this.ux.log('No PRs can be automerged'); return; } const prToMerge = mergeablePRs[0]; if (this.flags.dryrun === false) { this.ux.log(`merging ${prToMerge.number.toString()} | ${prToMerge.title}`); const opts = { ...this.baseRepoObject, merge_method: this.flags['merge-method'], pull_number: prToMerge.number, }; if (this.flags['skip-ci']) { opts.commit_title = `Merge pull request #${prToMerge.number} from ${prToMerge.head.ref} [skip ci]`; } const mergeResult = await this.octokit.request('PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge', opts); this.ux.logJson(mergeResult); } else { this.ux.log(`dry run ${prToMerge.number.toString()} | ${prToMerge.title}`); } } async isGreen(pr) { const statusResponse = await this.octokit.request('GET /repos/{owner}/{repo}/commits/{ref}/status', { ...this.baseRepoObject, ref: pr.head.sha, }); // no point looking at check runs if the commit status is not green if (statusResponse.data.state !== 'success') { return undefined; } const checkRunResponse = await this.octokit.request('GET /repos/{owner}/{repo}/commits/{ref}/check-runs', { ...this.baseRepoObject, ref: pr.head.sha, }); this.ux.logJson(checkRunResponse.data); if (checkRunResponse.data.check_runs.every((cr) => cr.status === 'completed' && ['success', 'skipped'].includes(cr.conclusion))) { return pr; } } async isMergeable(pr) { const statusResponse = await this.octokit.request('GET /repos/{owner}/{repo}/pulls/{pull_number}', { ...this.baseRepoObject, pull_number: pr.number, }); // mergeable_state of 'blocked' is ok because that's just missing an approval. // We're screening out 'behind' which might be merge conflicts. // Dependabot should rebase this PR eventually if (statusResponse.data.mergeable === true && statusResponse.data.mergeable_state !== 'behind') { return pr; } } } exports.default = AutoMerge; AutoMerge.description = messages.getMessage('description'); AutoMerge.examples = messages.getMessage('examples').split(os.EOL); AutoMerge.flagsConfig = { owner: command_1.flags.string({ char: 'o', description: messagesFromConsolidate.getMessage('owner'), dependsOn: ['repo'], }), repo: command_1.flags.string({ char: 'r', description: messagesFromConsolidate.getMessage('repo'), dependsOn: ['owner'], }), 'max-version-bump': dependabot_1.maxVersionBumpFlag, dryrun: command_1.flags.boolean({ description: messagesFromConsolidate.getMessage('dryrun'), char: 'd', default: false, }), 'skip-ci': command_1.flags.boolean({ description: messages.getMessage('skipCi'), char: 's', default: false, }), 'merge-method': command_1.flags.enum({ description: messages.getMessage('mergeMethod'), options: ['merge', 'squash', 'rebase'], default: 'merge', }), }; //# sourceMappingURL=automerge.js.map