Skip to content

Commit 19e6404

Browse files
authored
fix(release): ensure --preid flag considers stable tags for version determination (#33703)
When using `nx release version --preid=alpha`, the version determination now correctly considers both prerelease tags AND stable release tags to determine the "latest" version. Previously, it would only look at prerelease tags matching the preid, ignoring stable releases that should have become the new baseline. For example, with tags: 1.1.0, 1.1.0-alpha.0, 1.1.0-alpha.1, 1.1.1 - Before: Would return 1.1.0-alpha.1 → bump to 1.1.0-alpha.2 - After: Returns 1.1.1 (stable >= preid base) → bump to 1.1.2-alpha.0 Fixes #33343
1 parent f025232 commit 19e6404

2 files changed

Lines changed: 61 additions & 13 deletions

File tree

packages/nx/src/command-line/release/utils/git.spec.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ [email protected]
2727
2828
2929
30+
31+
32+
33+
3034
3135
3236
@@ -385,8 +389,9 @@ See merge request nx-release-test/nx-release-test!2`,
385389
{
386390
pattern: '{projectName}@{version}',
387391
projectName: 'alpha-lib',
388-
expectedTag: '[email protected]',
389-
expectedVersion: '1.2.4-beta.1',
392+
// Alpha lib has a stable 1.2.4 release, so this should be returned regardless of preid
393+
expectedTag: '[email protected]',
394+
expectedVersion: '1.2.4',
390395
preid: 'beta',
391396
},
392397
{
@@ -421,6 +426,13 @@ See merge request nx-release-test/nx-release-test!2`,
421426
expectedVersion: undefined,
422427
preid: 'alpha',
423428
},
429+
{
430+
pattern: '{projectName}@{version}',
431+
projectName: 'my-lib-5',
432+
expectedTag: '[email protected]',
433+
expectedVersion: '1.1.1',
434+
preid: 'alpha',
435+
},
424436
];
425437

426438
it.each(releaseTagPatternTestCases)(

packages/nx/src/command-line/release/utils/git.ts

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
import { relative } from 'node:path';
66
import { minimatch } from 'minimatch';
7+
import { coerce as semverCoerce, gte as semverGte } from 'semver';
78
import { interpolate } from '../../../tasks-runner/utils';
89
import { workspaceRoot } from '../../../utils/workspace-root';
910
import { execCommand } from './exec-command';
@@ -257,8 +258,16 @@ export async function getLatestGitTagForPattern(
257258
return extractTagAndVersion(matchingTags[0], tagRegexp, options);
258259
}
259260

261+
// Find stable release tags
262+
const stableReleaseTags = matchingTags.filter((tag) => {
263+
const matches = tag.match(tagRegexp);
264+
if (!matches) return false;
265+
const [, version] = matches;
266+
return version && !isPrerelease(version);
267+
});
268+
260269
if (preid && preid.length > 0) {
261-
// When a preid is provided, first try to find a tag for it
270+
// When a preid is provided, find tags matching that preid
262271
const preidReleaseTags = matchingTags.filter((tag) => {
263272
const match = tag.match(tagRegexp);
264273
if (!match) return false;
@@ -267,20 +276,47 @@ export async function getLatestGitTagForPattern(
267276
return version && version.includes(`-${preid}.`);
268277
});
269278

279+
// If both preid and stable tags exist, compare them to determine which is truly "latest"
280+
if (preidReleaseTags.length > 0 && stableReleaseTags.length > 0) {
281+
const preidResult = extractTagAndVersion(
282+
preidReleaseTags[0],
283+
tagRegexp,
284+
options
285+
);
286+
const stableResult = extractTagAndVersion(
287+
stableReleaseTags[0],
288+
tagRegexp,
289+
options
290+
);
291+
292+
// Get the base version of the preid release (e.g., "1.2.4" from "1.2.4-alpha.1")
293+
const preidBaseVersion = semverCoerce(
294+
preidResult.extractedVersion
295+
)?.version;
296+
const stableVersion = stableResult.extractedVersion;
297+
298+
// If the stable version is >= the preid's base version, use the stable tag
299+
// This handles the case where a stable release was made after the prerelease
300+
// (e.g., 1.1.1 stable was released after 1.1.0-alpha.3)
301+
if (
302+
preidBaseVersion &&
303+
stableVersion &&
304+
semverGte(stableVersion, preidBaseVersion)
305+
) {
306+
return stableResult;
307+
}
308+
309+
// Otherwise, use the preid tag (prerelease's base is ahead of stable)
310+
return preidResult;
311+
}
312+
313+
// If only preid tags exist (no stable), use the latest preid tag
270314
if (preidReleaseTags.length > 0) {
271315
return extractTagAndVersion(preidReleaseTags[0], tagRegexp, options);
272316
}
273-
}
274-
275-
// Then try to find the latest stable release tag
276-
const stableReleaseTags = matchingTags.filter((tag) => {
277-
const matches = tag.match(tagRegexp);
278317

279-
if (!matches) return false;
280-
281-
const [, version] = matches;
282-
return version && !isPrerelease(version);
283-
});
318+
// If no matching preid tags, fall through to find stable tags below
319+
}
284320

285321
// If there are stable release tags, use the latest one
286322
if (stableReleaseTags.length > 0) {

0 commit comments

Comments
 (0)