nx 21.3.0-rc.0 → 21.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/nx.js CHANGED
@@ -64,14 +64,14 @@ async function main() {
64
64
  if (!workspace) {
65
65
  handleNoWorkspace(GLOBAL_NX_VERSION);
66
66
  }
67
- if (!localNx) {
67
+ if (!localNx && !isNxCloudCommand(process.argv[2])) {
68
68
  handleMissingLocalInstallation(workspace ? workspace.dir : null);
69
69
  }
70
70
  // this file is already in the local workspace
71
71
  if (isLocalInstall) {
72
72
  await (0, init_local_1.initLocal)(workspace);
73
73
  }
74
- else {
74
+ else if (localNx) {
75
75
  // Nx is being run from globally installed CLI - hand off to the local
76
76
  warnIfUsingOutdatedGlobalInstall(GLOBAL_NX_VERSION, LOCAL_NX_VERSION);
77
77
  if (localNx.includes('.nx')) {
@@ -82,6 +82,11 @@ async function main() {
82
82
  require(localNx);
83
83
  }
84
84
  }
85
+ else if (isNxCloudCommand(process.argv[2])) {
86
+ // nx-cloud commands can run without local Nx installation
87
+ process.env.NX_DAEMON = 'false';
88
+ require('nx/src/command-line/nx-commands').commandsObject.argv;
89
+ }
85
90
  }
86
91
  }
87
92
  function handleNoWorkspace(globalNxVersion) {
@@ -132,6 +137,18 @@ function resolveNx(workspace) {
132
137
  paths: [workspace ? workspace.dir : globalsRoot],
133
138
  });
134
139
  }
140
+ function isNxCloudCommand(command) {
141
+ const nxCloudCommands = [
142
+ 'start-ci-run',
143
+ 'login',
144
+ 'logout',
145
+ 'connect',
146
+ 'view-logs',
147
+ 'fix-ci',
148
+ 'record',
149
+ ];
150
+ return nxCloudCommands.includes(command);
151
+ }
135
152
  function handleMissingLocalInstallation(detectedWorkspaceRoot) {
136
153
  output_1.output.error({
137
154
  title: detectedWorkspaceRoot
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "21.3.0-rc.0",
3
+ "version": "21.3.0",
4
4
  "private": false,
5
5
  "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
6
6
  "repository": {
@@ -83,16 +83,16 @@
83
83
  }
84
84
  },
85
85
  "optionalDependencies": {
86
- "@nx/nx-darwin-arm64": "21.3.0-rc.0",
87
- "@nx/nx-darwin-x64": "21.3.0-rc.0",
88
- "@nx/nx-freebsd-x64": "21.3.0-rc.0",
89
- "@nx/nx-linux-arm-gnueabihf": "21.3.0-rc.0",
90
- "@nx/nx-linux-arm64-gnu": "21.3.0-rc.0",
91
- "@nx/nx-linux-arm64-musl": "21.3.0-rc.0",
92
- "@nx/nx-linux-x64-gnu": "21.3.0-rc.0",
93
- "@nx/nx-linux-x64-musl": "21.3.0-rc.0",
94
- "@nx/nx-win32-arm64-msvc": "21.3.0-rc.0",
95
- "@nx/nx-win32-x64-msvc": "21.3.0-rc.0"
86
+ "@nx/nx-darwin-arm64": "21.3.0",
87
+ "@nx/nx-darwin-x64": "21.3.0",
88
+ "@nx/nx-freebsd-x64": "21.3.0",
89
+ "@nx/nx-linux-arm-gnueabihf": "21.3.0",
90
+ "@nx/nx-linux-arm64-gnu": "21.3.0",
91
+ "@nx/nx-linux-arm64-musl": "21.3.0",
92
+ "@nx/nx-linux-x64-gnu": "21.3.0",
93
+ "@nx/nx-linux-x64-musl": "21.3.0",
94
+ "@nx/nx-win32-arm64-msvc": "21.3.0",
95
+ "@nx/nx-win32-x64-msvc": "21.3.0"
96
96
  },
97
97
  "nx-migrations": {
98
98
  "migrations": "./migrations.json",
@@ -207,6 +207,13 @@
207
207
  ],
208
208
  "description": "By default, we will try and resolve the latest match for the releaseTagPattern from the current branch, falling back to all branches if no match is found on the current branch. Setting this to true will cause us to ALWAYS check all branches for the latest match. Setting it to false will cause us to ONLY check the current branch for the latest match. Setting it to an array of strings will cause us to check all branches WHEN the current branch is one of the strings in the array. Glob patterns are supported."
209
209
  },
210
+ "releaseTagPatternRequireSemver": {
211
+ "type": "boolean",
212
+ "description": "Whether to require semver to be used for the release tag pattern. If set to false, the release tag pattern will not be checked for semver compliance."
213
+ },
214
+ "releaseTagPatternStrictPreid": {
215
+ "$ref": "#/definitions/NxReleaseReleaseTagPatternStrictPreidConfiguration"
216
+ },
210
217
  "versionPlans": {
211
218
  "oneOf": [
212
219
  {
@@ -295,6 +302,13 @@
295
302
  }
296
303
  ],
297
304
  "description": "By default, we will try and resolve the latest match for the releaseTagPattern from the current branch, falling back to all branches if no match is found on the current branch. Setting this to true will cause us to ALWAYS check all branches for the latest match. Setting it to false will cause us to ONLY check the current branch for the latest match. Setting it to an array of strings will cause us to check all branches WHEN the current branch is one of the strings in the array. Glob patterns are supported."
305
+ },
306
+ "releaseTagPatternRequireSemver": {
307
+ "type": "boolean",
308
+ "description": "Whether to require semver to be used for the release tag pattern. If set to false, the release tag pattern will not be checked for semver compliance."
309
+ },
310
+ "releaseTagPatternStrictPreid": {
311
+ "$ref": "#/definitions/NxReleaseReleaseTagPatternStrictPreidConfiguration"
298
312
  }
299
313
  }
300
314
  },
@@ -925,6 +939,10 @@
925
939
  }
926
940
  }
927
941
  },
942
+ "NxReleaseReleaseTagPatternStrictPreidConfiguration": {
943
+ "type": "boolean",
944
+ "description": "When set to true and multiple tags match your configured \"releaseTagPattern\", the git tag matching logic will strictly prefer the tag which contain a semver preid which matches the one given to the nx release invocation.\n\nFor example, let's say your \"releaseTagPattern\" is \"{projectName}@{version}\" and you have the following tags for project \"my-lib\", which uses semver:\n- my-lib@1.2.4-beta.1\n- my-lib@1.2.4-alpha.1\n- my-lib@1.2.3\n\nIf \"releaseTagPatternStrictPreid\" is set to true and you run:\n- `nx release --preid beta`, the git tag \"my-lib@1.2.4-beta.1\" will be resolved.\n- `nx release --preid alpha`, the git tag \"my-lib@1.2.4-alpha.1\" will be resolved.\n- `nx release` (no preid), the git tag \"my-lib@1.2.3\" will be resolved.\n\nIf \"releaseTagPatternStrictPreid\" is set to false, the git tag \"my-lib@1.2.4-beta.1\" will always be resolved as the latest tag that matches the pattern, regardless of any preid which gets passed to nx release.\n\nNOTE: This feature was added in a minor version and is therefore set to false by default, but this may change in a future major version."
945
+ },
928
946
  "ChangelogRenderOptions": {
929
947
  "type": "object",
930
948
  "additionalProperties": true
@@ -5,6 +5,7 @@ exports.createAPI = createAPI;
5
5
  const chalk = require("chalk");
6
6
  const enquirer_1 = require("enquirer");
7
7
  const node_fs_1 = require("node:fs");
8
+ const semver_1 = require("semver");
8
9
  const tmp_1 = require("tmp");
9
10
  const nx_json_1 = require("../../config/nx-json");
10
11
  const tree_1 = require("../../generators/tree");
@@ -120,6 +121,16 @@ function createAPI(overrideReleaseConfig) {
120
121
  const to = args.to || 'HEAD';
121
122
  const toSHA = await (0, git_1.getCommitHash)(to);
122
123
  const headSHA = to === 'HEAD' ? toSHA : await (0, git_1.getCommitHash)('HEAD');
124
+ /**
125
+ * Extract the preid from the workspace version and the project versions
126
+ */
127
+ const workspacePreid = workspaceChangelogVersion
128
+ ? extractPreid(workspaceChangelogVersion)
129
+ : undefined;
130
+ const projectsPreid = Object.fromEntries(Object.entries(projectsVersionData).map(([projectName, v]) => [
131
+ projectName,
132
+ v.newVersion ? extractPreid(v.newVersion) : undefined,
133
+ ]));
123
134
  /**
124
135
  * Protect the user against attempting to create a new commit when recreating an old release changelog,
125
136
  * this seems like it would always be unintentional.
@@ -191,7 +202,13 @@ function createAPI(overrideReleaseConfig) {
191
202
  }
192
203
  else {
193
204
  let workspaceChangelogFromRef = args.from ||
194
- (await (0, git_1.getLatestGitTagForPattern)(nxReleaseConfig.releaseTagPattern, {}, nxReleaseConfig.releaseTagPatternCheckAllBranchesWhen, nxReleaseConfig.releaseTagPatternRequireSemver))?.tag;
205
+ (await (0, git_1.getLatestGitTagForPattern)(nxReleaseConfig.releaseTagPattern, {}, {
206
+ checkAllBranchesWhen: nxReleaseConfig.releaseTagPatternCheckAllBranchesWhen,
207
+ preid: workspacePreid ??
208
+ projectsPreid?.[Object.keys(projectsPreid)[0]],
209
+ releaseTagPatternRequireSemver: nxReleaseConfig.releaseTagPatternRequireSemver,
210
+ releaseTagPatternStrictPreid: nxReleaseConfig.releaseTagPatternStrictPreid,
211
+ }))?.tag;
195
212
  if (!workspaceChangelogFromRef) {
196
213
  if (useAutomaticFromRef) {
197
214
  workspaceChangelogFromRef = await (0, git_1.getFirstGitCommit)();
@@ -326,7 +343,12 @@ function createAPI(overrideReleaseConfig) {
326
343
  (await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern, {
327
344
  projectName: project.name,
328
345
  releaseGroupName: releaseGroup.name,
329
- }, releaseGroup.releaseTagPatternCheckAllBranchesWhen, releaseGroup.releaseTagPatternRequireSemver))?.tag;
346
+ }, {
347
+ checkAllBranchesWhen: releaseGroup.releaseTagPatternCheckAllBranchesWhen,
348
+ preid: projectsPreid[project.name],
349
+ releaseTagPatternRequireSemver: releaseGroup.releaseTagPatternRequireSemver,
350
+ releaseTagPatternStrictPreid: releaseGroup.releaseTagPatternStrictPreid,
351
+ }))?.tag;
330
352
  if (!fromRef && useAutomaticFromRef) {
331
353
  const firstCommit = await (0, git_1.getFirstGitCommit)();
332
354
  commits = await filterProjectCommits({
@@ -436,7 +458,13 @@ function createAPI(overrideReleaseConfig) {
436
458
  }
437
459
  else {
438
460
  let fromRef = args.from ||
439
- (await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern, {}, releaseGroup.releaseTagPatternCheckAllBranchesWhen, releaseGroup.releaseTagPatternRequireSemver))?.tag;
461
+ (await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern, {}, {
462
+ checkAllBranchesWhen: releaseGroup.releaseTagPatternCheckAllBranchesWhen,
463
+ preid: workspacePreid ??
464
+ projectsPreid?.[Object.keys(projectsPreid)[0]],
465
+ releaseTagPatternRequireSemver: releaseGroup.releaseTagPatternRequireSemver,
466
+ releaseTagPatternStrictPreid: releaseGroup.releaseTagPatternStrictPreid,
467
+ }))?.tag;
440
468
  if (!fromRef) {
441
469
  if (useAutomaticFromRef) {
442
470
  fromRef = await (0, git_1.getFirstGitCommit)();
@@ -967,3 +995,19 @@ function versionPlanSemverReleaseTypeToChangelogType(bump) {
967
995
  throw new Error(`Invalid semver bump type: ${bump}`);
968
996
  }
969
997
  }
998
+ function extractPreid(version) {
999
+ if (!(0, shared_1.isPrerelease)(version)) {
1000
+ return undefined;
1001
+ }
1002
+ const preid = (0, semver_1.prerelease)(version)?.[0];
1003
+ if (typeof preid === 'string') {
1004
+ if (preid.trim() === '') {
1005
+ return undefined;
1006
+ }
1007
+ return preid;
1008
+ }
1009
+ if (typeof preid === 'number') {
1010
+ return preid.toString();
1011
+ }
1012
+ return undefined;
1013
+ }
@@ -114,11 +114,15 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
114
114
  };
115
115
  const defaultFixedReleaseTagPattern = 'v{version}';
116
116
  /**
117
- * TODO(v21): in v21, make it so that this pattern is used by default when any custom groups are used
117
+ * TODO(v22): in v22, make it so that this pattern is used by default when any custom groups are used
118
118
  */
119
119
  const defaultFixedGroupReleaseTagPattern = '{releaseGroupName}-v{version}';
120
120
  const defaultIndependentReleaseTagPattern = '{projectName}@{version}';
121
121
  const defaultReleaseTagPatternRequireSemver = true;
122
+ /**
123
+ * TODO(v22): in v22, set this to true by default
124
+ */
125
+ const defaultReleaseTagPatternStrictPreid = false;
122
126
  const workspaceProjectsRelationship = userConfig.projectsRelationship || 'fixed';
123
127
  const defaultGeneratorOptions = {};
124
128
  if (userConfig.version?.conventionalCommits) {
@@ -203,6 +207,8 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
203
207
  releaseTagPatternCheckAllBranchesWhen: userConfig.releaseTagPatternCheckAllBranchesWhen ?? undefined,
204
208
  releaseTagPatternRequireSemver: userConfig.releaseTagPatternRequireSemver ??
205
209
  defaultReleaseTagPatternRequireSemver,
210
+ releaseTagPatternStrictPreid: userConfig.releaseTagPatternStrictPreid ??
211
+ defaultReleaseTagPatternStrictPreid,
206
212
  conventionalCommits: conventional_commits_1.DEFAULT_CONVENTIONAL_COMMITS_CONFIG,
207
213
  versionPlans: (userConfig.versionPlans ||
208
214
  false),
@@ -210,6 +216,8 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
210
216
  const groupProjectsRelationship = userConfig.projectsRelationship || WORKSPACE_DEFAULTS.projectsRelationship;
211
217
  const groupReleaseTagPatternRequireSemver = userConfig.releaseTagPatternRequireSemver ??
212
218
  WORKSPACE_DEFAULTS.releaseTagPatternRequireSemver;
219
+ const groupReleaseTagPatternStrictPreid = userConfig.releaseTagPatternStrictPreid ??
220
+ defaultReleaseTagPatternStrictPreid;
213
221
  const GROUP_DEFAULTS = {
214
222
  projectsRelationship: groupProjectsRelationship,
215
223
  version: USE_LEGACY_VERSIONING
@@ -244,6 +252,7 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
244
252
  : WORKSPACE_DEFAULTS.releaseTagPattern,
245
253
  releaseTagPatternCheckAllBranchesWhen: userConfig.releaseTagPatternCheckAllBranchesWhen ?? undefined,
246
254
  releaseTagPatternRequireSemver: groupReleaseTagPatternRequireSemver,
255
+ releaseTagPatternStrictPreid: groupReleaseTagPatternStrictPreid,
247
256
  versionPlans: false,
248
257
  };
249
258
  /**
@@ -429,6 +438,9 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
429
438
  releaseTagPatternRequireSemver: releaseGroup.releaseTagPatternRequireSemver ??
430
439
  userConfig.releaseTagPatternRequireSemver ??
431
440
  defaultReleaseTagPatternRequireSemver,
441
+ releaseTagPatternStrictPreid: releaseGroup.releaseTagPatternStrictPreid ??
442
+ userConfig.releaseTagPatternStrictPreid ??
443
+ defaultReleaseTagPatternStrictPreid,
432
444
  versionPlans: releaseGroup.versionPlans ?? rootVersionPlansConfig,
433
445
  };
434
446
  const finalReleaseGroup = deepMergeDefaults([groupDefaults], {
@@ -503,6 +515,7 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
503
515
  releaseTagPattern: WORKSPACE_DEFAULTS.releaseTagPattern,
504
516
  releaseTagPatternCheckAllBranchesWhen: WORKSPACE_DEFAULTS.releaseTagPatternCheckAllBranchesWhen,
505
517
  releaseTagPatternRequireSemver: WORKSPACE_DEFAULTS.releaseTagPatternRequireSemver,
518
+ releaseTagPatternStrictPreid: WORKSPACE_DEFAULTS.releaseTagPatternStrictPreid,
506
519
  git: rootGitConfig,
507
520
  version: rootVersionConfig,
508
521
  changelog: rootChangelogConfig,
@@ -12,6 +12,10 @@ export interface Reference {
12
12
  type: 'hash' | 'issue' | 'pull-request';
13
13
  value: string;
14
14
  }
15
+ export interface GitTagAndVersion {
16
+ tag: string;
17
+ extractedVersion: string;
18
+ }
15
19
  export interface GitCommit extends RawGitCommit {
16
20
  description: string;
17
21
  type: string;
@@ -22,10 +26,37 @@ export interface GitCommit extends RawGitCommit {
22
26
  affectedFiles: string[];
23
27
  revertedHashes: string[];
24
28
  }
25
- export declare function getLatestGitTagForPattern(releaseTagPattern: string, additionalInterpolationData?: {}, checkAllBranchesWhen?: boolean | string[], releaseTagPatternRequireSemver?: boolean): Promise<{
26
- tag: string;
27
- extractedVersion: string;
28
- } | null>;
29
+ export interface GetLatestGitTagForPatternOptions {
30
+ checkAllBranchesWhen?: boolean | string[];
31
+ preid?: string;
32
+ releaseTagPatternRequireSemver: boolean;
33
+ releaseTagPatternStrictPreid: boolean;
34
+ }
35
+ /**
36
+ * Extract the tag and version from a tag string
37
+ *
38
+ * @param tag - The tag string to extract the tag and version from
39
+ * @param tagRegexp - The regex to use to extract the tag and version from the tag string
40
+ *
41
+ * @returns The tag and version
42
+ */
43
+ export declare function extractTagAndVersion(tag: string, tagRegexp: string, options: GetLatestGitTagForPatternOptions): GitTagAndVersion;
44
+ /**
45
+ * Get the latest git tag for the configured release tag pattern.
46
+ *
47
+ * This function will:
48
+ * - Get all tags from the git repo, sorted by version
49
+ * - Filter the tags into a list with SEMVER-compliant tags, matching the release tag pattern
50
+ * - If a preid is provided, prioritise tags for that preid, then semver tags without a preid
51
+ * - If no preid is provided, search only for stable semver tags (i.e. no pre-release or build metadata)
52
+ *
53
+ * @param releaseTagPattern - The pattern to filter the tags list by
54
+ * @param additionalInterpolationData - Additional data used when interpolating the release tag pattern
55
+ * @param options - The options to use when getting the latest git tag for the pattern
56
+ *
57
+ * @returns The tag and version
58
+ */
59
+ export declare function getLatestGitTagForPattern(releaseTagPattern: string, additionalInterpolationData: {}, options: GetLatestGitTagForPatternOptions): Promise<GitTagAndVersion | null>;
29
60
  export declare function getGitDiff(from: string | undefined, to?: string): Promise<RawGitCommit[]>;
30
61
  export declare function gitAdd({ changedFiles, deletedFiles, dryRun, verbose, logFn, cwd, }: {
31
62
  changedFiles?: string[];
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractTagAndVersion = extractTagAndVersion;
3
4
  exports.getLatestGitTagForPattern = getLatestGitTagForPattern;
4
5
  exports.getGitDiff = getGitDiff;
5
6
  exports.gitAdd = gitAdd;
@@ -21,12 +22,50 @@ const minimatch_1 = require("minimatch");
21
22
  const utils_1 = require("../../../tasks-runner/utils");
22
23
  const workspace_root_1 = require("../../../utils/workspace-root");
23
24
  const exec_command_1 = require("./exec-command");
25
+ const shared_1 = require("./shared");
24
26
  function escapeRegExp(string) {
25
27
  return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
26
28
  }
27
29
  // https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
28
30
  const SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/g;
29
- async function getLatestGitTagForPattern(releaseTagPattern, additionalInterpolationData = {}, checkAllBranchesWhen, releaseTagPatternRequireSemver = true) {
31
+ /**
32
+ * Extract the tag and version from a tag string
33
+ *
34
+ * @param tag - The tag string to extract the tag and version from
35
+ * @param tagRegexp - The regex to use to extract the tag and version from the tag string
36
+ *
37
+ * @returns The tag and version
38
+ */
39
+ function extractTagAndVersion(tag, tagRegexp, options) {
40
+ const { releaseTagPatternRequireSemver } = options;
41
+ const [latestMatchingTag, ...rest] = tag.match(tagRegexp);
42
+ let version = releaseTagPatternRequireSemver
43
+ ? rest.filter((r) => {
44
+ return r.match(SEMVER_REGEX);
45
+ })[0]
46
+ : rest[0];
47
+ return {
48
+ tag: latestMatchingTag,
49
+ extractedVersion: version ?? null,
50
+ };
51
+ }
52
+ /**
53
+ * Get the latest git tag for the configured release tag pattern.
54
+ *
55
+ * This function will:
56
+ * - Get all tags from the git repo, sorted by version
57
+ * - Filter the tags into a list with SEMVER-compliant tags, matching the release tag pattern
58
+ * - If a preid is provided, prioritise tags for that preid, then semver tags without a preid
59
+ * - If no preid is provided, search only for stable semver tags (i.e. no pre-release or build metadata)
60
+ *
61
+ * @param releaseTagPattern - The pattern to filter the tags list by
62
+ * @param additionalInterpolationData - Additional data used when interpolating the release tag pattern
63
+ * @param options - The options to use when getting the latest git tag for the pattern
64
+ *
65
+ * @returns The tag and version
66
+ */
67
+ async function getLatestGitTagForPattern(releaseTagPattern, additionalInterpolationData = {}, options) {
68
+ const { checkAllBranchesWhen, releaseTagPatternRequireSemver, releaseTagPatternStrictPreid, preid, } = options;
30
69
  /**
31
70
  * By default, we will try and resolve the latest match for the releaseTagPattern from the current branch,
32
71
  * falling back to all branches if no match is found on the current branch.
@@ -118,16 +157,37 @@ async function getLatestGitTagForPattern(releaseTagPattern, additionalInterpolat
118
157
  if (!matchingTags.length) {
119
158
  return null;
120
159
  }
121
- const [latestMatchingTag, ...rest] = matchingTags[0].match(tagRegexp);
122
- const version = releaseTagPatternRequireSemver
123
- ? rest.filter((r) => {
124
- return r.match(SEMVER_REGEX);
125
- })[0]
126
- : rest[0];
127
- return {
128
- tag: latestMatchingTag,
129
- extractedVersion: version,
130
- };
160
+ if (!releaseTagPatternStrictPreid) {
161
+ // If not using strict preid, we can just return the first matching tag
162
+ return extractTagAndVersion(matchingTags[0], tagRegexp, options);
163
+ }
164
+ if (preid && preid.length > 0) {
165
+ // When a preid is provided, first try to find a tag for it
166
+ const preidReleaseTags = matchingTags.filter((tag) => {
167
+ const match = tag.match(tagRegexp);
168
+ if (!match)
169
+ return false;
170
+ const version = match.find((part) => part.match(SEMVER_REGEX));
171
+ return version && version.includes(`-${preid}.`);
172
+ });
173
+ if (preidReleaseTags.length > 0) {
174
+ return extractTagAndVersion(preidReleaseTags[0], tagRegexp, options);
175
+ }
176
+ }
177
+ // Then try to find the latest stable release tag
178
+ const stableReleaseTags = matchingTags.filter((tag) => {
179
+ const matches = tag.match(tagRegexp);
180
+ if (!matches)
181
+ return false;
182
+ const [, version] = matches;
183
+ return version && !(0, shared_1.isPrerelease)(version);
184
+ });
185
+ // If there are stable release tags, use the latest one
186
+ if (stableReleaseTags.length > 0) {
187
+ return extractTagAndVersion(stableReleaseTags[0], tagRegexp, options);
188
+ }
189
+ // Otherwise return null
190
+ return null;
131
191
  }
132
192
  catch {
133
193
  return null;
@@ -21,6 +21,7 @@ export interface VersionDataEntry {
21
21
  rawVersionSpec: string;
22
22
  }[];
23
23
  }
24
+ export declare function isPrerelease(version: string): boolean;
24
25
  export declare class ReleaseVersion {
25
26
  rawVersion: string;
26
27
  gitTag: string;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ReleaseVersion = exports.noDiffInChangelogMessage = void 0;
4
+ exports.isPrerelease = isPrerelease;
4
5
  exports.commitChanges = commitChanges;
5
6
  exports.createCommitMessageValues = createCommitMessageValues;
6
7
  exports.createGitTagValues = createGitTagValues;
@@ -198,7 +198,12 @@ class ReleaseGroupProcessor {
198
198
  if (finalConfigForProject.currentVersionResolver === 'git-tag') {
199
199
  latestMatchingGitTag = await (0, git_1.getLatestGitTagForPattern)(releaseTagPattern, {
200
200
  projectName: projectGraphNode.name,
201
- }, releaseGroupNode.group.releaseTagPatternCheckAllBranchesWhen, releaseGroupNode.group.releaseTagPatternRequireSemver);
201
+ }, {
202
+ checkAllBranchesWhen: releaseGroupNode.group.releaseTagPatternCheckAllBranchesWhen,
203
+ preid: this.options.preid,
204
+ releaseTagPatternRequireSemver: releaseGroupNode.group.releaseTagPatternRequireSemver,
205
+ releaseTagPatternStrictPreid: releaseGroupNode.group.releaseTagPatternStrictPreid,
206
+ });
202
207
  this.cachedLatestMatchingGitTag.set(projectName, latestMatchingGitTag);
203
208
  }
204
209
  // Cache the current version for the project
@@ -349,6 +349,26 @@ export interface NxReleaseConfiguration {
349
349
  * - Setting this to false will cause us to not use semver to match the version allowing for non-semver versions
350
350
  */
351
351
  releaseTagPatternRequireSemver?: boolean;
352
+ /**
353
+ * When set to true and multiple tags match your configured "releaseTagPattern", the git tag matching logic will strictly prefer the tag which contain a semver preid which matches the one
354
+ * given to the nx release invocation.
355
+ *
356
+ * For example, let's say your "releaseTagPattern" is "{projectName}@{version}" and you have the following tags for project "my-lib", which uses semver:
357
+ * - my-lib@1.2.4-beta.1
358
+ * - my-lib@1.2.4-alpha.1
359
+ * - my-lib@1.2.3
360
+ *
361
+ * If "releaseTagPatternStrictPreid" is set to true and you run:
362
+ * - `nx release --preid beta`, the git tag "my-lib@1.2.4-beta.1" will be resolved.
363
+ * - `nx release --preid alpha`, the git tag "my-lib@1.2.4-alpha.1" will be resolved.
364
+ * - `nx release` (no preid), the git tag "my-lib@1.2.3" will be resolved.
365
+ *
366
+ * If "releaseTagPatternStrictPreid" is set to false, the git tag "my-lib@1.2.4-beta.1" will always be resolved as the latest tag that matches the pattern,
367
+ * regardless of any preid which gets passed to nx release.
368
+ *
369
+ * NOTE: This feature was added in a minor version and is therefore set to false by default, but this may change in a future major version.
370
+ */
371
+ releaseTagPatternStrictPreid?: boolean;
352
372
  /**
353
373
  * Enables using version plans as a specifier source for versioning and
354
374
  * to determine changes for changelog generation.
@@ -424,6 +444,26 @@ export interface NxReleaseConfiguration {
424
444
  * - Setting this to false will cause us to not use semver to match the version allowing for non-semver versions
425
445
  */
426
446
  releaseTagPatternRequireSemver?: boolean;
447
+ /**
448
+ * When set to true and multiple tags match your configured "releaseTagPattern", the git tag matching logic will strictly prefer the tag which contain a semver preid which matches the one
449
+ * given to the nx release invocation.
450
+ *
451
+ * For example, let's say your "releaseTagPattern" is "{projectName}@{version}" and you have the following tags for project "my-lib", which uses semver:
452
+ * - my-lib@1.2.4-beta.1
453
+ * - my-lib@1.2.4-alpha.1
454
+ * - my-lib@1.2.3
455
+ *
456
+ * If "releaseTagPatternStrictPreid" is set to true and you run:
457
+ * - `nx release --preid beta`, the git tag "my-lib@1.2.4-beta.1" will be resolved.
458
+ * - `nx release --preid alpha`, the git tag "my-lib@1.2.4-alpha.1" will be resolved.
459
+ * - `nx release` (no preid), the git tag "my-lib@1.2.3" will be resolved.
460
+ *
461
+ * If "releaseTagPatternStrictPreid" is set to false, the git tag "my-lib@1.2.4-beta.1" will always be resolved as the latest tag that matches the pattern,
462
+ * regardless of any preid which gets passed to nx release.
463
+ *
464
+ * NOTE: This feature was added in a minor version and is therefore set to false by default, but this may change in a future major version.
465
+ */
466
+ releaseTagPatternStrictPreid?: boolean;
427
467
  /**
428
468
  * Enable and configure automatic git operations as part of the release
429
469
  */