2019-03-11 12:00:49 -04:00
|
|
|
/**
|
|
|
|
* @license
|
|
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* **Usage:**
|
|
|
|
* ```
|
|
|
|
* node rebase-pr <github-repository> <pull-request-number>
|
|
|
|
* ```
|
|
|
|
* **Example:**
|
|
|
|
* ```
|
|
|
|
* node rebase-pr angular/angular 123
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* Rebases the current branch on top of the GitHub PR target branch.
|
|
|
|
*
|
|
|
|
* **Context:**
|
|
|
|
* Since a GitHub PR is not necessarily up to date with its target branch, it is useful to rebase
|
|
|
|
* prior to testing it on CI to ensure more up to date test results.
|
|
|
|
*
|
|
|
|
* **Implementation details:**
|
|
|
|
* This script obtains the base for a GitHub PR via the
|
|
|
|
* [GitHub PR API](https://developer.github.com/v3/pulls/#get-a-single-pull-request), then
|
|
|
|
* fetches that branch, and rebases the current branch on top of it.
|
|
|
|
*
|
|
|
|
* **NOTE:**
|
|
|
|
* This script cannot use external dependencies or be compiled because it needs to run before the
|
|
|
|
* environment is setup.
|
|
|
|
* Use only features supported by the NodeJS versions used in the environment.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// This script uses `console` to print messages to the user.
|
|
|
|
// tslint:disable:no-console
|
|
|
|
|
|
|
|
// Imports
|
|
|
|
const util = require('util');
|
|
|
|
const child_process = require('child_process');
|
|
|
|
const exec = util.promisify(child_process.exec);
|
2020-01-29 12:19:16 -05:00
|
|
|
const getRefsAndShasForTarget = require('./utils/get-refs-and-shas-for-target');
|
2019-03-11 12:00:49 -04:00
|
|
|
|
|
|
|
// CLI validation
|
|
|
|
if (process.argv.length != 4) {
|
|
|
|
console.error(`This script requires the GitHub repository and PR number as arguments.`);
|
|
|
|
console.error(`Example: node tools/rebase-pr.js angular/angular 123`);
|
|
|
|
process.exitCode = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run
|
|
|
|
_main(...process.argv.slice(2)).catch(err => {
|
|
|
|
console.log('Failed to rebase on top of target branch.\n');
|
|
|
|
console.error(err);
|
|
|
|
process.exitCode = 1;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Helpers
|
|
|
|
async function _main(repository, prNumber) {
|
2020-01-29 12:19:16 -05:00
|
|
|
const target = await getRefsAndShasForTarget(prNumber);
|
2019-11-11 13:50:53 -05:00
|
|
|
|
|
|
|
// Log known refs and shas
|
|
|
|
console.log(`--------------------------------`);
|
2020-01-29 12:19:16 -05:00
|
|
|
console.log(` Target Branch: ${target.base.ref}`);
|
|
|
|
console.log(` Latest Commit for Target Branch: ${target.latestShaOfTargetBranch}`);
|
|
|
|
console.log(` Latest Commit for PR: ${target.latestShaOfPrBranch}`);
|
|
|
|
console.log(` First Common Ancestor SHA: ${target.commonAncestorSha}`);
|
2019-11-11 13:50:53 -05:00
|
|
|
console.log(`--------------------------------`);
|
|
|
|
console.log();
|
|
|
|
|
|
|
|
|
2020-01-29 12:19:16 -05:00
|
|
|
|
2019-11-11 13:50:53 -05:00
|
|
|
// Get the count of commits between the latest commit from origin and the common ancestor SHA.
|
|
|
|
const {stdout: commitCount} =
|
2020-01-29 12:19:16 -05:00
|
|
|
await exec(`git rev-list --count origin/${target.base.ref}...${target.commonAncestorSha}`);
|
2019-11-11 13:50:53 -05:00
|
|
|
console.log(`Checking ${commitCount.trim()} commits for changes in the CircleCI config file.`);
|
|
|
|
|
|
|
|
// Check if the files changed between the latest commit from origin and the common ancestor SHA
|
|
|
|
// includes the CircleCI config.
|
2020-04-13 19:40:21 -04:00
|
|
|
const {stdout: circleCIConfigChanged} = await exec(`git diff --name-only origin/${
|
|
|
|
target.base.ref} ${target.commonAncestorSha} -- .circleci/config.yml`);
|
2019-11-11 13:50:53 -05:00
|
|
|
|
|
|
|
if (!!circleCIConfigChanged) {
|
|
|
|
throw Error(`
|
2020-04-13 19:40:21 -04:00
|
|
|
CircleCI config on ${target.base.ref} has been modified since commit ${
|
|
|
|
target.commonAncestorSha.slice(0, 7)},
|
2019-11-11 13:50:53 -05:00
|
|
|
which this PR is based on.
|
|
|
|
|
2020-01-29 12:19:16 -05:00
|
|
|
Please rebase the PR on ${target.base.ref} after fetching from upstream.
|
2019-11-11 13:50:53 -05:00
|
|
|
|
|
|
|
Rebase instructions for PR Author, please run the following commands:
|
|
|
|
|
2020-01-29 12:19:16 -05:00
|
|
|
git fetch upstream ${target.base.ref};
|
|
|
|
git checkout ${target.head.ref};
|
|
|
|
git rebase upstream/${target.base.ref};
|
2019-11-11 13:50:53 -05:00
|
|
|
git push --force-with-lease;
|
|
|
|
`);
|
|
|
|
} else {
|
|
|
|
console.log('No change found in the CircleCI config file, continuing.');
|
|
|
|
}
|
|
|
|
console.log();
|
|
|
|
|
|
|
|
// Rebase the PR.
|
2020-01-29 12:19:16 -05:00
|
|
|
console.log(`Rebasing current branch on ${target.base.ref}.`);
|
|
|
|
await exec(`git rebase origin/${target.base.ref}`);
|
2019-03-11 12:00:49 -04:00
|
|
|
console.log('Rebase successful.');
|
|
|
|
}
|