diff --git a/scripts/get-release-version.js b/scripts/get-release-version.js index cce8b092a81..fdf8eb29e30 100644 --- a/scripts/get-release-version.js +++ b/scripts/get-release-version.js @@ -348,6 +348,14 @@ function bumpPastPublishedLatest(baseVersion, label, target, refBase) { `Published latest ${latestStable} is ahead of the checked-out package.json version ${refBase}. Refusing a stale or cross-line stable release.`, ); } + // When the preview base already leads `latest`, no bump is computed below, + // so the bumped-version check cannot fire; compare the derived base with + // the checked-out ref directly. + if (refBase && semver.valid(baseVersion) && semver.lt(refBase, baseVersion)) { + throw new Error( + `Derived base ${baseVersion} is ahead of the checked-out package.json version ${refBase}. Refusing a stale or cross-line stable release.`, + ); + } if ( !semver.valid(latestStable) || !semver.valid(baseVersion) || diff --git a/scripts/tests/get-release-version.test.js b/scripts/tests/get-release-version.test.js index 27415cf19c1..0a949480e26 100644 --- a/scripts/tests/get-release-version.test.js +++ b/scripts/tests/get-release-version.test.js @@ -842,6 +842,37 @@ describe('getVersion', () => { ); }); + it('should refuse a stale ref when the preview base is ahead and no bump happens', () => { + // release/v0.26 at 0.26.8 with `latest` also 0.26.8: the preview tag + // already carries 0.27.0, so no bump is computed and only a direct + // base-vs-ref comparison can refuse publishing 0.26 content as 0.27.0. + vi.mocked(readFileSync).mockReturnValue( + JSON.stringify({ version: '0.26.8' }), + ); + const mockWithAheadPreviewAtLatest = (command) => { + if ( + command.includes('npm view') && + command.includes('--tag=preview') && + !command.includes('versions --json') + ) + return '0.27.0-preview.0'; + if ( + command.includes('npm view') && + command.includes('--tag=latest') && + !command.includes('versions --json') + ) + return '0.26.8'; + if (command.includes('npm view') && command.includes('versions --json')) + return JSON.stringify(['0.26.8', '0.27.0-preview.0']); + return mockExecSync(command); + }; + vi.mocked(execSync).mockImplementation(mockWithAheadPreviewAtLatest); + + expect(() => getVersion({ type: 'stable' })).toThrow( + 'Derived base 0.27.0 is ahead of the checked-out package.json version 0.26.8', + ); + }); + it('should refuse a stable release when the ref is behind latest on the same line', () => { // release/0.26.5 predates the 0.26.8 stable. Bumping it to 0.26.9 // would publish older content over a newer stable.