豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 5b747aa

Browse files
committed
fix(ng-dev/release): avoid accidentally incorporating unexpected changes in release build
There is an interesting scenario where the caretaker may make unexpected non-changelog changes as part of the short prompt where we allow manual polishing to the changelog. If the caretaker modified other files there, they will NOT be part of the release cutting PR (and also shouldn't be) - but currently the changes are not discarded/or detected and WILL influence the release output building. This could cause subtle differences and confusion because the release output is different than what we committed (because the release cut commits will not incorporate the other non-changelog changes). The fix is to properly detect other modifications and abort properly. Other changes should be made beforehand, go through review process and should not be part of the release cut commit.
1 parent d3a9405 commit 5b747aa

File tree

5 files changed

+67
-5
lines changed

5 files changed

+67
-5
lines changed

ng-dev/release/publish/actions.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,21 @@ export abstract class ReleaseAction {
195195

196196
// Commit message for the release point.
197197
const commitMessage = getCommitMessageForRelease(newVersion);
198+
198199
// Create a release staging commit including changelog and version bump.
199200
await this.createCommit(commitMessage, [
200201
workspaceRelativePackageJsonPath,
201202
workspaceRelativeChangelogPath,
202203
]);
203204

205+
// The caretaker may have attempted to make additional changes. These changes would
206+
// not be captured into the release commit. The working directory should remain clean,
207+
// like we assume it being clean when we start the release actions.
208+
if (this.git.hasUncommittedChanges()) {
209+
Log.error(' ✘ Unrelated changes have been made as part of the changelog editing.');
210+
throw new FatalReleaseActionError();
211+
}
212+
204213
Log.info(green(` ✓ Created release commit for: "${newVersion}".`));
205214
}
206215

ng-dev/release/publish/test/common.spec.ts

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {readFileSync} from 'fs';
9+
import {readFileSync, writeFileSync} from 'fs';
1010
import {join} from 'path';
1111
import semver from 'semver';
1212

1313
import {CommitFromGitLog, parseCommitFromGitLog} from '../../../commit-message/parse.js';
14-
import {NgDevConfig} from '../../../utils/config.js';
1514
import {GitClient} from '../../../utils/git/git-client.js';
1615
import {Log} from '../../../utils/logging.js';
1716
import {
@@ -194,6 +193,57 @@ describe('common release action logic', () => {
194193
);
195194
});
196195

196+
it('should not allow for arbitrary edits to be made during changelog edit prompt', async () => {
197+
const {repo, fork, instance, githubConfig, promptConfirmSpy} = setupReleaseActionForTesting(
198+
DelegateTestAction,
199+
baseReleaseTrains,
200+
/* isNextPublishedToNpm */ true,
201+
{useSandboxGitClient: true},
202+
);
203+
const {version, branchName} = baseReleaseTrains.next;
204+
205+
spyOn(Log, 'error');
206+
207+
let promptResolveFn: ((value: boolean) => void) | null = null;
208+
const promptPromise = new Promise<boolean>((resolve) => (promptResolveFn = resolve));
209+
promptConfirmSpy.and.returnValue(promptPromise);
210+
211+
const testFile = join(testTmpDir, 'some-file.txt');
212+
const git =
213+
SandboxGitRepo.withInitialCommit(githubConfig).createTagForHead('0.0.0-compare-base');
214+
215+
writeFileSync(testFile, 'content');
216+
git.commit('feat(test): first commit');
217+
218+
repo
219+
.expectBranchRequest(branchName, 'STAGING_SHA')
220+
.expectCommitRequest('STAGING_SHA', `release: cut the v${version} release`)
221+
.expectCommitStatusCheck('STAGING_SHA', 'success')
222+
.expectFindForkRequest(fork)
223+
.expectPullRequestToBeCreated(branchName, fork, 'release-stage-10.1.0-next.0', 10);
224+
225+
fork.expectBranchRequest('release-stage-10.1.0-next.0', null);
226+
227+
const stagingPromise = instance.testStagingWithBuild(
228+
version,
229+
branchName,
230+
parse('0.0.0-compare-base'),
231+
);
232+
233+
// Before confirming that we are good with the changelog changes, modify
234+
// an unrelated file. This should trigger a release action fatal error.
235+
writeFileSync(testFile, 'change content');
236+
promptResolveFn!(true);
237+
238+
await expectAsync(stagingPromise).toBeRejected();
239+
240+
expect(Log.error).toHaveBeenCalledWith(
241+
jasmine.stringContaining(
242+
'Unrelated changes have been made as part of the changelog editing',
243+
),
244+
);
245+
});
246+
197247
it('should link to the changelog in the release entry if notes are too large', async () => {
198248
const {repo, instance, gitClient, builtPackagesWithInfo, releaseConfig} =
199249
setupReleaseActionForTesting(DelegateTestAction, baseReleaseTrains);

ng-dev/release/publish/test/test-utils/action-mocks.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export function setupMocksForReleaseAction<T extends boolean>(
8787
// Fake confirm any prompts. We do not want to make any changelog edits and
8888
// just proceed with the release action. Also we immediately want to confirm
8989
// when we are prompted whether the pull request should be merged.
90-
spyOn(Prompt, 'confirm').and.resolveTo(true);
90+
const promptConfirmSpy = spyOn(Prompt, 'confirm').and.resolveTo(true);
9191

9292
const builtPackagesWithInfo: BuiltPackageWithInfo[] = testReleasePackages.map((pkg) => ({
9393
...pkg,
@@ -136,5 +136,5 @@ export function setupMocksForReleaseAction<T extends boolean>(
136136
);
137137
}
138138

139-
return {gitClient, builtPackagesWithInfo};
139+
return {gitClient, builtPackagesWithInfo, promptConfirmSpy};
140140
}

ng-dev/release/publish/test/test-utils/test-action.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import {GithubConfig} from '../../../../utils/config.js';
10+
import {Prompt} from '../../../../utils/prompt.js';
1011
import {
1112
GithubTestingRepo,
1213
SandboxGitClient,
@@ -57,6 +58,7 @@ export interface TestReleaseAction<
5758
projectDir: string;
5859
githubConfig: GithubConfig;
5960
releaseConfig: ReleaseConfig;
61+
promptConfirmSpy: jasmine.Spy<typeof Prompt['confirm']>;
6062
builtPackagesWithInfo: BuiltPackageWithInfo[];
6163
gitClient: O['useSandboxGitClient'] extends true ? SandboxGitClient : VirtualGitClient;
6264
}

ng-dev/release/publish/test/test-utils/test-utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export function setupReleaseActionForTesting<
6161
});
6262

6363
// Setup mocks for release action.
64-
const {gitClient, builtPackagesWithInfo} = setupMocksForReleaseAction<
64+
const {gitClient, builtPackagesWithInfo, promptConfirmSpy} = setupMocksForReleaseAction<
6565
OptionsWithDefaults['useSandboxGitClient']
6666
>(
6767
githubConfig,
@@ -81,6 +81,7 @@ export function setupReleaseActionForTesting<
8181
githubConfig,
8282
releaseConfig,
8383
gitClient,
84+
promptConfirmSpy,
8485
builtPackagesWithInfo,
8586
};
8687
}

0 commit comments

Comments
 (0)