Skip to content

build: ensure status checks are passing when staging release #14340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@
"node-sass": "^4.9.3",
"parse5": "^5.0.0",
"protractor": "^5.4.0",
"request": "^2.83.0",
"resolve-bin": "^0.4.0",
"rollup": "^0.56.3",
"rollup-plugin-alias": "^1.4.0",
Expand Down
50 changes: 40 additions & 10 deletions tools/release/stage-release.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as OctokitApi from '@octokit/rest';
import {bold, cyan, green, italic, red, yellow} from 'chalk';
import {existsSync, readFileSync, writeFileSync} from 'fs';
import {prompt} from 'inquirer';
Expand Down Expand Up @@ -41,7 +42,12 @@ class StageReleaseTask {
/** Instance of a wrapper that can execute Git commands. */
git: GitClient;

constructor(public projectDir: string) {
/** Octokit API instance that can be used to make Github API calls. */
githubApi: OctokitApi;

constructor(public projectDir: string,
public repositoryOwner: string,
public repositoryName: string) {
this.packageJsonPath = join(projectDir, 'package.json');

console.log(this.projectDir);
Expand All @@ -61,7 +67,9 @@ class StageReleaseTask {
process.exit(1);
}

this.git = new GitClient(projectDir, this.packageJson.repository.url);
this.githubApi = new OctokitApi();
this.git = new GitClient(projectDir,
`https://github.com/${repositoryOwner}/${repositoryName}.git`);
}

async run() {
Expand All @@ -81,8 +89,7 @@ class StageReleaseTask {
this.verifyPublishBranch(expectedPublishBranch);
this.verifyLocalCommitsMatchUpstream(expectedPublishBranch);
this.verifyNoUncommittedChanges();

// TODO(devversion): Assert that GitHub statuses succeed for this branch.
await this.verifyPassingGithubStatus();

const newVersionName = newVersion.format();
const stagingBranch = `release-stage/${newVersionName}`;
Expand Down Expand Up @@ -136,8 +143,8 @@ class StageReleaseTask {

// Check if current branch matches the expected publish branch.
if (expectedPublishBranch !== currentBranchName) {
console.error(red(`Cannot stage release from "${italic(currentBranchName)}". Please stage ` +
`the release from "${bold(expectedPublishBranch)}".`));
console.error(red(`Cannot stage release from "${italic(currentBranchName)}". Please ` +
`stage the release from "${bold(expectedPublishBranch)}".`));
process.exit(1);
}
}
Expand All @@ -149,16 +156,17 @@ class StageReleaseTask {

// Check if the current branch is in sync with the remote branch.
if (upstreamCommitSha !== localCommitSha) {
console.error(red(`Cannot stage release. The current branch is not in sync with the remote ` +
`branch. Please make sure your local branch "${italic(publishBranch)}" is up to date.`));
console.error(red(` ✘ Cannot stage release. The current branch is not in sync with the ` +
`remote branch. Please make sure your local branch "${italic(publishBranch)}" is up ` +
`to date.`));
process.exit(1);
}
}

/** Verifies that there are no uncommitted changes in the project. */
private verifyNoUncommittedChanges() {
if (this.git.hasUncommittedChanges()) {
console.error(red(`Cannot stage release. There are changes which are not committed and ` +
console.error(red(`Cannot stage release. There are changes which are not committed and ` +
`should be stashed.`));
process.exit(1);
}
Expand All @@ -169,10 +177,32 @@ class StageReleaseTask {
const newPackageJson = {...this.packageJson, version: newVersionName};
writeFileSync(this.packageJsonPath, JSON.stringify(newPackageJson, null, 2));
}

/** Verifies that the latest commit of the current branch is passing all Github statuses. */
private async verifyPassingGithubStatus() {
const commitRef = this.git.getLocalCommitSha('HEAD');
const {state} = (await this.githubApi.repos.getCombinedStatusForRef({
owner: this.repositoryOwner,
repo: this.repositoryName,
ref: commitRef,
})).data;

if (state === 'failure') {
console.error(red(` ✘ Cannot stage release. Commit "${commitRef}" does not pass all ` +
`github status checks. Please make sure this commit passes all checks before re-running.`));
process.exit(1);
} else if (state === 'pending') {
console.error(red(` ✘ Cannot stage release yet. Commit "${commitRef}" still has ` +
`pending github statuses that need to succeed before staging a release.`));
process.exit(0);
}

console.info(green(` ✓ Upstream commit is passing all github status checks.`));
}
}

/** Entry-point for the release staging script. */
if (require.main === module) {
new StageReleaseTask(join(__dirname, '../../')).run();
new StageReleaseTask(join(__dirname, '../../'), 'angular', 'material2').run();
}

2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9918,7 +9918,7 @@ [email protected]:
tunnel-agent "^0.6.0"
uuid "^3.1.0"

request@^2.0.0, request@^2.55.0, request@^2.72.0, request@^2.74.0, request@^2.79.0, request@^2.81.0, request@^2.83.0, request@^2.85.0, request@^2.87.0:
request@^2.0.0, request@^2.55.0, request@^2.72.0, request@^2.74.0, request@^2.79.0, request@^2.81.0, request@^2.85.0, request@^2.87.0:
version "2.88.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
Expand Down