Skip to content

build: staging script should switch to publish branch #14448

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
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
5 changes: 5 additions & 0 deletions tools/release/git/git-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export class GitClient {
return spawnSync('git', ['diff-index', '--quiet', 'HEAD'], {cwd: this.projectDir}).status !== 0;
}

/** Checks out an existing branch with the specified name. */
checkoutBranch(branchName: string): boolean {
return spawnSync('git', ['checkout', branchName], {cwd: this.projectDir}).status === 0;
}

/** Creates a new branch which is based on the previous active branch. */
checkoutNewBranch(branchName: string): boolean {
return spawnSync('git', ['checkout', '-b', branchName], {cwd: this.projectDir}).status === 0;
Expand Down
50 changes: 33 additions & 17 deletions tools/release/stage-release.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ const CHANGELOG_FILE_NAME = 'CHANGELOG.md';
*
* 1) Prompt for release type (with version suggestion)
* 2) Prompt for version name if no suggestions has been selected
* 3) Assert that the proper publish branch is checked out (e.g. 6.4.x for patches)
* 4) Assert that there are no local changes which are uncommitted.
* 5) Assert that the local branch is up to date with the remote branch.
* 6) Creates a new branch for the release staging (release-stage/{VERSION})
* 7) Switches to the staging branch and updates the package.json
* 8) Waits for the user to continue (users can generate the changelog in the meanwhile)
* 9) Create a commit that includes all changes in the staging branch.
* 3) Assert that there are no local changes which are uncommitted.
* 4) Assert that the proper publish branch is checked out. (e.g. 6.4.x for patches)
* If a different branch is used, try switching to the publish branch automatically
* 5) Assert that the Github status checks pass for the publish branch.
* 6) Assert that the local branch is up to date with the remote branch.
* 7) Creates a new branch for the release staging (release-stage/{VERSION})
* 8) Switches to the staging branch and updates the package.json
* 9) Prompt for release name and generate changelog
* 10) Wait for the user to continue (users can customize generated changelog)
* 11) Create a commit that includes all changes in the staging branch.
*/
class StageReleaseTask {

Expand Down Expand Up @@ -86,9 +89,10 @@ class StageReleaseTask {
// new log messages to be more in the foreground.
console.log();

this.verifyPublishBranch(expectedPublishBranch);
this.verifyLocalCommitsMatchUpstream(expectedPublishBranch);
this.verifyNoUncommittedChanges();
this.switchToPublishBranch(expectedPublishBranch);

this.verifyLocalCommitsMatchUpstream(expectedPublishBranch);
await this.verifyPassingGithubStatus();

const newVersionName = newVersion.format();
Expand Down Expand Up @@ -137,16 +141,28 @@ class StageReleaseTask {
// TODO(devversion): automatic push and PR open URL shortcut.
}

/** Verifies that the user is on the specified publish branch. */
private verifyPublishBranch(expectedPublishBranch: string) {
/**
* Checks if the user is on the expected publish branch. If the user is on a different branch,
* this function automatically tries to checkout the publish branch.
*/
private switchToPublishBranch(expectedPublishBranch: string): boolean {
const currentBranchName = this.git.getCurrentBranch();

// 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)}".`));
// If current branch already matches the expected publish branch, just continue
// by exiting this function.
if (expectedPublishBranch === currentBranchName) {
return;
}

if (!this.git.checkoutBranch(expectedPublishBranch)) {
console.error(red(` ✘ Could not switch to the "${italic(expectedPublishBranch)}" ` +
`branch.`));
console.error(red(` Please ensure that the branch exists or manually switch to the ` +
`branch.`));
process.exit(1);
}

console.log(green(` ✓ Switched to the "${italic(expectedPublishBranch)}" branch.`));
}

/** Verifies that the local branch is up to date with the given publish branch. */
Expand All @@ -166,8 +182,8 @@ class StageReleaseTask {
/** 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 ` +
`should be stashed.`));
console.error(red(` ✘ Cannot stage release. There are changes which are not committed ` +
`and should be discarded.`));
process.exit(1);
}
}
Expand Down