Skip to content

Commit 21fe473

Browse files
authored
fix(git-node): use stash and detached head for release operations (#1033)
1 parent 63171d7 commit 21fe473

File tree

2 files changed

+20
-10
lines changed

2 files changed

+20
-10
lines changed

components/git/release.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import ReleasePreparation from '../../lib/prepare_release.js';
44
import ReleasePromotion from '../../lib/promote_release.js';
55
import TeamInfo from '../../lib/team_info.js';
66
import Request from '../../lib/request.js';
7-
import { runPromise } from '../../lib/run.js';
7+
import { forceRunAsync, runPromise } from '../../lib/run.js';
88

99
export const command = 'release [prid..]';
1010
export const describe = 'Manage an in-progress release or start a new one.';
@@ -114,14 +114,30 @@ function release(state, argv) {
114114
cli.setAssumeYes();
115115
}
116116

117-
return runPromise(main(state, argv, cli, dir)).catch((err) => {
117+
return runPromise(wrapStash(() => main(state, argv, cli, dir))).catch((err) => {
118118
if (cli.spinner.enabled) {
119119
cli.spinner.fail();
120120
}
121121
throw err;
122122
});
123123
}
124124

125+
async function wrapStash(fn) {
126+
const stashTip = await forceRunAsync('git', ['stash', 'list', '-1', '--format="%gd"'],
127+
{ ignoreFailure: false, captureStdout: true });
128+
await forceRunAsync('git', ['stash', '--include-untracked'], { ignoreFailure: false });
129+
const newStashTip = await forceRunAsync('git', ['stash', 'list', '-1', '--format="%gd"'],
130+
{ ignoreFailure: false, captureStdout: true });
131+
const hasStashed = newStashTip !== stashTip && newStashTip.trim();
132+
try {
133+
await fn();
134+
} finally {
135+
if (hasStashed) {
136+
await forceRunAsync('git', ['stash', 'pop'], { ignoreFailure: false });
137+
}
138+
}
139+
}
140+
125141
async function main(state, argv, cli, dir) {
126142
if (state === PREPARE) {
127143
const release = new ReleasePreparation(argv, cli, dir);

lib/promote_release.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,12 @@ export default class ReleasePromotion extends Session {
5656
cli.warn('Current HEAD is not the release commit');
5757
localCloneIsClean = false;
5858
}
59-
try {
60-
await forceRunAsync('git', ['--no-pager', 'diff', '--exit-code'], { ignoreFailure: false });
61-
} catch {
62-
cli.warn('Some local changes have not been committed');
63-
localCloneIsClean = false;
64-
}
6559
if (!localCloneIsClean) {
66-
if (await cli.prompt('Should we reset the local HEAD to be the release proposal?')) {
60+
if (await cli.prompt('Should we checkout the release proposal?')) {
6761
cli.startSpinner('Fetching the proposal upstream...');
6862
await forceRunAsync('git', ['fetch', proposalUpstreamRemote, releaseCommitSha],
6963
{ ignoreFailure: false });
70-
await forceRunAsync('git', ['reset', releaseCommitSha, '--hard'], { ignoreFailure: false });
64+
await forceRunAsync('git', ['checkout', releaseCommitSha], { ignoreFailure: false });
7165
cli.stopSpinner('Local HEAD is now in sync with the proposal');
7266
} else {
7367
cli.error('Local clone is not ready');

0 commit comments

Comments
 (0)