nx 18.1.0-canary.20240302-8bde48f → 18.1.0-canary.20240307-84d96cc

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.
Files changed (28) hide show
  1. package/package.json +12 -12
  2. package/schemas/nx-schema.json +10 -1
  3. package/schemas/project-schema.json +20 -0
  4. package/src/command-line/init/implementation/add-nx-to-nest.js +2 -2
  5. package/src/command-line/init/implementation/add-nx-to-npm-repo.js +2 -2
  6. package/src/command-line/init/implementation/utils.d.ts +1 -3
  7. package/src/command-line/init/implementation/utils.js +9 -16
  8. package/src/command-line/init/init-v2.js +3 -2
  9. package/src/command-line/release/changelog.js +2 -1
  10. package/src/command-line/release/command-object.d.ts +1 -0
  11. package/src/command-line/release/config/config.d.ts +2 -15
  12. package/src/command-line/release/config/config.js +62 -19
  13. package/src/command-line/release/publish.js +4 -3
  14. package/src/command-line/release/release.js +12 -11
  15. package/src/command-line/release/utils/git.js +30 -1
  16. package/src/command-line/release/utils/shared.d.ts +5 -1
  17. package/src/command-line/release/version.d.ts +4 -1
  18. package/src/command-line/release/version.js +70 -19
  19. package/src/config/nx-json.d.ts +6 -0
  20. package/src/core/graph/main.js +1 -1
  21. package/src/core/graph/polyfills.js +1 -1
  22. package/src/core/graph/styles.css +1 -1
  23. package/src/executors/run-commands/run-commands.impl.d.ts +4 -1
  24. package/src/executors/run-commands/run-commands.impl.js +34 -14
  25. package/src/migrations/update-17-2-0/move-default-base.js +2 -0
  26. package/src/plugins/js/lock-file/lock-file.js +13 -1
  27. package/src/project-graph/plugins/plugin-pool.js +16 -19
  28. package/src/project-graph/plugins/public-api.d.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "18.1.0-canary.20240302-8bde48f",
3
+ "version": "18.1.0-canary.20240307-84d96cc",
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": {
@@ -66,7 +66,7 @@
66
66
  "yargs-parser": "21.1.1",
67
67
  "node-machine-id": "1.1.12",
68
68
  "ora": "5.3.0",
69
- "@nrwl/tao": "18.1.0-canary.20240302-8bde48f"
69
+ "@nrwl/tao": "18.1.0-canary.20240307-84d96cc"
70
70
  },
71
71
  "peerDependencies": {
72
72
  "@swc-node/register": "^1.8.0",
@@ -81,16 +81,16 @@
81
81
  }
82
82
  },
83
83
  "optionalDependencies": {
84
- "@nx/nx-darwin-x64": "18.1.0-canary.20240302-8bde48f",
85
- "@nx/nx-darwin-arm64": "18.1.0-canary.20240302-8bde48f",
86
- "@nx/nx-linux-x64-gnu": "18.1.0-canary.20240302-8bde48f",
87
- "@nx/nx-linux-x64-musl": "18.1.0-canary.20240302-8bde48f",
88
- "@nx/nx-win32-x64-msvc": "18.1.0-canary.20240302-8bde48f",
89
- "@nx/nx-linux-arm64-gnu": "18.1.0-canary.20240302-8bde48f",
90
- "@nx/nx-linux-arm64-musl": "18.1.0-canary.20240302-8bde48f",
91
- "@nx/nx-linux-arm-gnueabihf": "18.1.0-canary.20240302-8bde48f",
92
- "@nx/nx-win32-arm64-msvc": "18.1.0-canary.20240302-8bde48f",
93
- "@nx/nx-freebsd-x64": "18.1.0-canary.20240302-8bde48f"
84
+ "@nx/nx-darwin-x64": "18.1.0-canary.20240307-84d96cc",
85
+ "@nx/nx-darwin-arm64": "18.1.0-canary.20240307-84d96cc",
86
+ "@nx/nx-linux-x64-gnu": "18.1.0-canary.20240307-84d96cc",
87
+ "@nx/nx-linux-x64-musl": "18.1.0-canary.20240307-84d96cc",
88
+ "@nx/nx-win32-x64-msvc": "18.1.0-canary.20240307-84d96cc",
89
+ "@nx/nx-linux-arm64-gnu": "18.1.0-canary.20240307-84d96cc",
90
+ "@nx/nx-linux-arm64-musl": "18.1.0-canary.20240307-84d96cc",
91
+ "@nx/nx-linux-arm-gnueabihf": "18.1.0-canary.20240307-84d96cc",
92
+ "@nx/nx-win32-arm64-msvc": "18.1.0-canary.20240307-84d96cc",
93
+ "@nx/nx-freebsd-x64": "18.1.0-canary.20240307-84d96cc"
94
94
  },
95
95
  "nx-migrations": {
96
96
  "migrations": "./migrations.json",
@@ -157,11 +157,16 @@
157
157
  "$ref": "#/definitions/NxReleaseVersionConfiguration"
158
158
  },
159
159
  {
160
- "anyOf": [
160
+ "allOf": [
161
161
  {
162
162
  "not": {
163
163
  "required": ["git"]
164
164
  }
165
+ },
166
+ {
167
+ "not": {
168
+ "required": ["preVersionCommand"]
169
+ }
165
170
  }
166
171
  ]
167
172
  }
@@ -576,6 +581,10 @@
576
581
  },
577
582
  "git": {
578
583
  "$ref": "#/definitions/NxReleaseGitConfiguration"
584
+ },
585
+ "preVersionCommand": {
586
+ "type": "string",
587
+ "description": "A command to run after validation of nx release configuration, but before versioning begins. Used for preparing build artifacts. If --dry-run is passed, the command is still executed, but with the NX_DRY_RUN environment variable set to 'true'."
579
588
  }
580
589
  }
581
590
  },
@@ -127,6 +127,26 @@
127
127
  "items": {
128
128
  "type": "string"
129
129
  }
130
+ },
131
+ "release": {
132
+ "type": "object",
133
+ "description": "Configuration for the nx release commands.",
134
+ "properties": {
135
+ "version": {
136
+ "type": "object",
137
+ "description": "Configuration for the nx release version command.",
138
+ "properties": {
139
+ "generator": {
140
+ "type": "string",
141
+ "description": "The version generator to use. Defaults to @nx/js:release-version."
142
+ },
143
+ "generatorOptions": {
144
+ "type": "object",
145
+ "description": "Options for the version generator."
146
+ }
147
+ }
148
+ }
149
+ }
130
150
  }
131
151
  },
132
152
  "definitions": {
@@ -73,12 +73,12 @@ async function addNxToNest(options, packageJson) {
73
73
  ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
74
74
  : false);
75
75
  }
76
- (0, utils_1.createNxJsonFile)(repoRoot, [], [...cacheableOperations, ...nestCacheableScripts], {});
76
+ (0, utils_1.createNxJsonFile)(repoRoot, [], [...cacheableOperations, ...nestCacheableScripts], scriptOutputs);
77
77
  const pmc = (0, package_manager_1.getPackageManagerCommand)();
78
78
  (0, utils_1.updateGitIgnore)(repoRoot);
79
79
  (0, utils_1.addDepsToPackageJson)(repoRoot);
80
80
  addNestPluginToPackageJson(repoRoot);
81
- (0, utils_1.markRootPackageJsonAsNxProject)(repoRoot, cacheableOperations, scriptOutputs, pmc);
81
+ (0, utils_1.markRootPackageJsonAsNxProject)(repoRoot, cacheableOperations, pmc);
82
82
  createProjectJson(repoRoot, packageJson, nestCLIConfiguration);
83
83
  removeFile(repoRoot, 'nest-cli.json');
84
84
  updatePackageJsonScripts(repoRoot, isJS);
@@ -48,11 +48,11 @@ async function addNxToNpmRepo(options) {
48
48
  ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
49
49
  : false);
50
50
  }
51
- (0, utils_1.createNxJsonFile)(repoRoot, [], cacheableOperations, {});
51
+ (0, utils_1.createNxJsonFile)(repoRoot, [], cacheableOperations, scriptOutputs);
52
52
  const pmc = (0, package_manager_1.getPackageManagerCommand)();
53
53
  (0, utils_1.updateGitIgnore)(repoRoot);
54
54
  (0, utils_1.addDepsToPackageJson)(repoRoot);
55
- (0, utils_1.markRootPackageJsonAsNxProject)(repoRoot, cacheableOperations, scriptOutputs, pmc);
55
+ (0, utils_1.markRootPackageJsonAsNxProject)(repoRoot, cacheableOperations, pmc);
56
56
  output_1.output.log({ title: '📦 Installing dependencies' });
57
57
  (0, utils_1.runInstall)(repoRoot, pmc);
58
58
  if (useNxCloud) {
@@ -8,9 +8,7 @@ export declare function updateGitIgnore(root: string): void;
8
8
  export declare function runInstall(repoRoot: string, pmc?: PackageManagerCommands): void;
9
9
  export declare function initCloud(repoRoot: string, installationSource: 'nx-init-angular' | 'nx-init-cra' | 'nx-init-monorepo' | 'nx-init-nest' | 'nx-init-npm-repo'): void;
10
10
  export declare function addVsCodeRecommendedExtensions(repoRoot: string, extensions: string[]): void;
11
- export declare function markRootPackageJsonAsNxProject(repoRoot: string, cacheableScripts: string[], scriptOutputs: {
12
- [script: string]: string;
13
- }, pmc: PackageManagerCommands): void;
11
+ export declare function markRootPackageJsonAsNxProject(repoRoot: string, cacheableScripts: string[], pmc: PackageManagerCommands): void;
14
12
  export declare function printFinalMessage({ learnMoreLink, bodyLines, }: {
15
13
  learnMoreLink?: string;
16
14
  bodyLines?: string[];
@@ -25,14 +25,14 @@ function createNxJsonFile(repoRoot, topologicalTargets, cacheableOperations, scr
25
25
  nxJson.targetDefaults[scriptName] ??= {};
26
26
  nxJson.targetDefaults[scriptName] = { dependsOn: [`^${scriptName}`] };
27
27
  }
28
- for (const [scriptName, output] of Object.entries(scriptOutputs)) {
29
- if (!output) {
30
- // eslint-disable-next-line no-continue
31
- continue;
32
- }
33
- nxJson.targetDefaults[scriptName] ??= {};
34
- nxJson.targetDefaults[scriptName].outputs = [`{projectRoot}/${output}`];
28
+ }
29
+ for (const [scriptName, output] of Object.entries(scriptOutputs)) {
30
+ if (!output) {
31
+ // eslint-disable-next-line no-continue
32
+ continue;
35
33
  }
34
+ nxJson.targetDefaults[scriptName] ??= {};
35
+ nxJson.targetDefaults[scriptName].outputs = [`{projectRoot}/${output}`];
36
36
  }
37
37
  for (const target of cacheableOperations) {
38
38
  nxJson.targetDefaults[target] ??= {};
@@ -134,16 +134,9 @@ function addVsCodeRecommendedExtensions(repoRoot, extensions) {
134
134
  }
135
135
  }
136
136
  exports.addVsCodeRecommendedExtensions = addVsCodeRecommendedExtensions;
137
- function markRootPackageJsonAsNxProject(repoRoot, cacheableScripts, scriptOutputs, pmc) {
137
+ function markRootPackageJsonAsNxProject(repoRoot, cacheableScripts, pmc) {
138
138
  const json = (0, fileutils_1.readJsonFile)((0, path_2.joinPathFragments)(repoRoot, `package.json`));
139
- json.nx = { targets: {} };
140
- for (let script of Object.keys(scriptOutputs)) {
141
- if (scriptOutputs[script]) {
142
- json.nx.targets[script] = {
143
- outputs: [`{projectRoot}/${scriptOutputs[script]}`],
144
- };
145
- }
146
- }
139
+ json.nx = {};
147
140
  for (let script of cacheableScripts) {
148
141
  const scriptDefinition = json.scripts[script];
149
142
  if (!scriptDefinition) {
@@ -19,6 +19,7 @@ const add_nx_to_npm_repo_1 = require("./implementation/add-nx-to-npm-repo");
19
19
  const add_nx_to_monorepo_1 = require("./implementation/add-nx-to-monorepo");
20
20
  const path_1 = require("path");
21
21
  async function initHandler(options) {
22
+ process.env.NX_RUNNING_NX_INIT = 'true';
22
23
  const version = process.env.NX_VERSION ?? ((0, semver_1.prerelease)(versions_1.nxVersion) ? 'next' : 'latest');
23
24
  if (process.env.NX_VERSION) {
24
25
  output_1.output.log({ title: `Using version ${process.env.NX_VERSION}` });
@@ -32,7 +33,7 @@ async function initHandler(options) {
32
33
  }
33
34
  (0, add_nx_scripts_1.generateDotNxSetup)(version);
34
35
  // invokes the wrapper, thus invoking the initial installation process
35
- (0, child_process_1.runNxSync)('');
36
+ (0, child_process_1.runNxSync)('--version', { stdio: 'ignore' });
36
37
  return;
37
38
  }
38
39
  // TODO(jack): Remove this Angular logic once `@nx/angular` is compatible with inferred targets.
@@ -80,7 +81,7 @@ async function initHandler(options) {
80
81
  if (!detectPluginsResponse.updatePackageScripts) {
81
82
  const rootPackageJsonPath = (0, path_1.join)(repoRoot, 'package.json');
82
83
  const json = (0, fileutils_1.readJsonFile)(rootPackageJsonPath);
83
- json.nx = {};
84
+ json.nx = { includedScripts: [] };
84
85
  (0, fileutils_1.writeJsonFile)(rootPackageJsonPath, json);
85
86
  }
86
87
  if (useNxCloud) {
@@ -9,6 +9,7 @@ const tmp_1 = require("tmp");
9
9
  const nx_json_1 = require("../../config/nx-json");
10
10
  const tree_1 = require("../../generators/tree");
11
11
  const register_1 = require("../../plugins/js/utils/register");
12
+ const file_map_utils_1 = require("../../project-graph/file-map-utils");
12
13
  const project_graph_1 = require("../../project-graph/project-graph");
13
14
  const utils_1 = require("../../tasks-runner/utils");
14
15
  const is_ci_1 = require("../../utils/is-ci");
@@ -40,7 +41,7 @@ async function releaseChangelog(args) {
40
41
  process.env.NX_VERBOSE_LOGGING = 'true';
41
42
  }
42
43
  // Apply default configuration to any optional user configuration
43
- const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, nxJson.release);
44
+ const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), nxJson.release);
44
45
  if (configError) {
45
46
  return await (0, config_1.handleNxReleaseConfigError)(configError);
46
47
  }
@@ -21,6 +21,7 @@ export type VersionOptions = NxReleaseArgs & GitCommitAndTagOptions & {
21
21
  specifier?: string;
22
22
  preid?: string;
23
23
  stageChanges?: boolean;
24
+ generatorOptionsOverrides?: Record<string, unknown>;
24
25
  };
25
26
  export type ChangelogOptions = NxReleaseArgs & GitCommitAndTagOptions & {
26
27
  version?: string | null;
@@ -1,18 +1,5 @@
1
- /**
2
- * `nx release` is a powerful feature which spans many possible use cases. The possible variations
3
- * of configuration are therefore quite complex, particularly when you consider release groups.
4
- *
5
- * We want to provide the best possible DX for users so that they can harness the power of `nx release`
6
- * most effectively, therefore we need to both provide sensible defaults for common scenarios (to avoid
7
- * verbose nx.json files wherever possible), and proactively handle potential sources of config issues
8
- * in more complex use-cases.
9
- *
10
- * This file is the source of truth for all `nx release` configuration reconciliation, including sensible
11
- * defaults and user overrides, as well as handling common errors, up front to produce a single, consistent,
12
- * and easy to consume config object for all the `nx release` command implementations.
13
- */
14
1
  import { NxJsonConfiguration } from '../../../config/nx-json';
15
- import { type ProjectGraph } from '../../../devkit-exports';
2
+ import { ProjectFileMap, ProjectGraph } from '../../../config/project-graph';
16
3
  type DeepRequired<T> = Required<{
17
4
  [K in keyof T]: T[K] extends Required<T[K]> ? T[K] : DeepRequired<T[K]>;
18
5
  }>;
@@ -48,7 +35,7 @@ export interface CreateNxReleaseConfigError {
48
35
  code: 'PROJECTS_AND_GROUPS_DEFINED' | 'RELEASE_GROUP_MATCHES_NO_PROJECTS' | 'RELEASE_GROUP_RELEASE_TAG_PATTERN_VERSION_PLACEHOLDER_MISSING_OR_EXCESSIVE' | 'PROJECT_MATCHES_MULTIPLE_GROUPS' | 'CONVENTIONAL_COMMITS_SHORTHAND_MIXED_WITH_OVERLAPPING_GENERATOR_OPTIONS' | 'GLOBAL_GIT_CONFIG_MIXED_WITH_GRANULAR_GIT_CONFIG';
49
36
  data: Record<string, string | string[]>;
50
37
  }
51
- export declare function createNxReleaseConfig(projectGraph: ProjectGraph, userConfig?: NxJsonConfiguration['release']): Promise<{
38
+ export declare function createNxReleaseConfig(projectGraph: ProjectGraph, projectFileMap: ProjectFileMap, userConfig?: NxJsonConfiguration['release']): Promise<{
52
39
  error: null | CreateNxReleaseConfigError;
53
40
  nxReleaseConfig: NxReleaseConfig | null;
54
41
  }>;
@@ -1,12 +1,28 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleNxReleaseConfigError = exports.createNxReleaseConfig = exports.IMPLICIT_DEFAULT_RELEASE_GROUP = void 0;
4
- const devkit_exports_1 = require("../../../devkit-exports");
4
+ /**
5
+ * `nx release` is a powerful feature which spans many possible use cases. The possible variations
6
+ * of configuration are therefore quite complex, particularly when you consider release groups.
7
+ *
8
+ * We want to provide the best possible DX for users so that they can harness the power of `nx release`
9
+ * most effectively, therefore we need to both provide sensible defaults for common scenarios (to avoid
10
+ * verbose nx.json files wherever possible), and proactively handle potential sources of config issues
11
+ * in more complex use-cases.
12
+ *
13
+ * This file is the source of truth for all `nx release` configuration reconciliation, including sensible
14
+ * defaults and user overrides, as well as handling common errors, up front to produce a single, consistent,
15
+ * and easy to consume config object for all the `nx release` command implementations.
16
+ */
17
+ const path_1 = require("path");
18
+ const fileutils_1 = require("../../../utils/fileutils");
5
19
  const find_matching_projects_1 = require("../../../utils/find-matching-projects");
20
+ const output_1 = require("../../../utils/output");
21
+ const workspace_root_1 = require("../../../utils/workspace-root");
6
22
  const resolve_nx_json_error_message_1 = require("../utils/resolve-nx-json-error-message");
7
23
  exports.IMPLICIT_DEFAULT_RELEASE_GROUP = '__default__';
8
24
  // Apply default configuration to any optional user configuration and handle known errors
9
- async function createNxReleaseConfig(projectGraph, userConfig = {}) {
25
+ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig = {}) {
10
26
  if (userConfig.projects && userConfig.groups) {
11
27
  return {
12
28
  error: {
@@ -76,6 +92,7 @@ async function createNxReleaseConfig(projectGraph, userConfig = {}) {
76
92
  conventionalCommits: userConfig.version?.conventionalCommits || false,
77
93
  generator: '@nx/js:release-version',
78
94
  generatorOptions: defaultGeneratorOptions,
95
+ preVersionCommand: userConfig.version?.preVersionCommand || '',
79
96
  },
80
97
  changelog: {
81
98
  git: changelogGitDefaults,
@@ -166,20 +183,22 @@ async function createNxReleaseConfig(projectGraph, userConfig = {}) {
166
183
  git: userConfig.git,
167
184
  },
168
185
  ], normalizeTrueToEmptyObject(userConfig.changelog));
169
- // git configuration is not supported at the group level, only the root/command level
170
- const rootVersionWithoutGit = { ...rootVersionConfig };
171
- delete rootVersionWithoutGit.git;
186
+ // these options are not supported at the group level, only the root/command level
187
+ const rootVersionWithoutGlobalOptions = { ...rootVersionConfig };
188
+ delete rootVersionWithoutGlobalOptions.git;
189
+ delete rootVersionWithoutGlobalOptions.preVersionCommand;
172
190
  // Apply conventionalCommits shorthand to the final group defaults if explicitly configured in the original user config
173
191
  if (userConfig.version?.conventionalCommits === true) {
174
- rootVersionWithoutGit.generatorOptions = {
175
- ...rootVersionWithoutGit.generatorOptions,
192
+ rootVersionWithoutGlobalOptions.generatorOptions = {
193
+ ...rootVersionWithoutGlobalOptions.generatorOptions,
176
194
  currentVersionResolver: 'git-tag',
177
195
  specifierSource: 'conventional-commits',
178
196
  };
179
197
  }
180
198
  if (userConfig.version?.conventionalCommits === false) {
181
- delete rootVersionWithoutGit.generatorOptions.currentVersionResolver;
182
- delete rootVersionWithoutGit.generatorOptions.specifierSource;
199
+ delete rootVersionWithoutGlobalOptions.generatorOptions
200
+ .currentVersionResolver;
201
+ delete rootVersionWithoutGlobalOptions.generatorOptions.specifierSource;
183
202
  }
184
203
  const groups = userConfig.groups && Object.keys(userConfig.groups).length
185
204
  ? ensureProjectsConfigIsArray(userConfig.groups)
@@ -193,14 +212,13 @@ async function createNxReleaseConfig(projectGraph, userConfig = {}) {
193
212
  projects: userConfig.projects
194
213
  ? // user-defined top level "projects" config takes priority if set
195
214
  (0, find_matching_projects_1.findMatchingProjects)(ensureArray(userConfig.projects), projectGraph.nodes)
196
- : // default to all library projects in the workspace
197
- (0, find_matching_projects_1.findMatchingProjects)(['*'], projectGraph.nodes).filter((project) => projectGraph.nodes[project].type === 'lib'),
215
+ : await getDefaultProjects(projectGraph, projectFileMap),
198
216
  /**
199
217
  * For properties which are overriding config at the root, we use the root level config as the
200
218
  * default values to merge with so that the group that matches a specific project will always
201
219
  * be the valid source of truth for that type of config.
202
220
  */
203
- version: deepMergeDefaults([GROUP_DEFAULTS.version], rootVersionWithoutGit),
221
+ version: deepMergeDefaults([GROUP_DEFAULTS.version], rootVersionWithoutGlobalOptions),
204
222
  // If the user has set something custom for releaseTagPattern at the top level, respect it for the implicit default group
205
223
  releaseTagPattern: userConfig.releaseTagPattern || GROUP_DEFAULTS.releaseTagPattern,
206
224
  // Directly inherit the root level config for projectChangelogs, if set
@@ -265,7 +283,7 @@ async function createNxReleaseConfig(projectGraph, userConfig = {}) {
265
283
  projects: matchingProjects,
266
284
  version: deepMergeDefaults(
267
285
  // First apply any group level defaults, then apply actual root level config, then group level config
268
- [GROUP_DEFAULTS.version, rootVersionWithoutGit], releaseGroup.version),
286
+ [GROUP_DEFAULTS.version, rootVersionWithoutGlobalOptions], releaseGroup.version),
269
287
  // If the user has set any changelog config at all, including at the root level, then use one set of defaults, otherwise default to false for the whole feature
270
288
  changelog: releaseGroup.changelog || rootChangelogConfig.projectChangelogs
271
289
  ? deepMergeDefaults(groupChangelogDefaults, releaseGroup.changelog || {})
@@ -325,7 +343,7 @@ async function handleNxReleaseConfigError(error) {
325
343
  'release',
326
344
  'projects',
327
345
  ]);
328
- devkit_exports_1.output.error({
346
+ output_1.output.error({
329
347
  title: `"projects" is not valid when explicitly defining release groups, and everything should be expressed within "groups" in that case. If you are using "groups" then you should remove the "projects" property`,
330
348
  bodyLines: [nxJsonMessage],
331
349
  });
@@ -337,7 +355,7 @@ async function handleNxReleaseConfigError(error) {
337
355
  'release',
338
356
  'groups',
339
357
  ]);
340
- devkit_exports_1.output.error({
358
+ output_1.output.error({
341
359
  title: `Release group "${error.data.releaseGroupName}" matches no projects. Please ensure all release groups match at least one project:`,
342
360
  bodyLines: [nxJsonMessage],
343
361
  });
@@ -349,7 +367,7 @@ async function handleNxReleaseConfigError(error) {
349
367
  'release',
350
368
  'groups',
351
369
  ]);
352
- devkit_exports_1.output.error({
370
+ output_1.output.error({
353
371
  title: `Project "${error.data.project}" matches multiple release groups. Please ensure all projects are part of only one release group:`,
354
372
  bodyLines: [nxJsonMessage],
355
373
  });
@@ -363,7 +381,7 @@ async function handleNxReleaseConfigError(error) {
363
381
  error.data.releaseGroupName,
364
382
  'releaseTagPattern',
365
383
  ]);
366
- devkit_exports_1.output.error({
384
+ output_1.output.error({
367
385
  title: `Release group "${error.data.releaseGroupName}" has an invalid releaseTagPattern. Please ensure the pattern contains exactly one instance of the "{version}" placeholder`,
368
386
  bodyLines: [nxJsonMessage],
369
387
  });
@@ -374,7 +392,7 @@ async function handleNxReleaseConfigError(error) {
374
392
  const nxJsonMessage = await (0, resolve_nx_json_error_message_1.resolveNxJsonConfigErrorMessage)([
375
393
  'release',
376
394
  ]);
377
- devkit_exports_1.output.error({
395
+ output_1.output.error({
378
396
  title: `You have configured both the shorthand "version.conventionalCommits" and one or more of the related "version.generatorOptions" that it sets for you. Please use one or the other:`,
379
397
  bodyLines: [nxJsonMessage],
380
398
  });
@@ -386,7 +404,7 @@ async function handleNxReleaseConfigError(error) {
386
404
  'release',
387
405
  'git',
388
406
  ]);
389
- devkit_exports_1.output.error({
407
+ output_1.output.error({
390
408
  title: `You have duplicate conflicting git configurations. If you are using the top level 'nx release' command, then remove the 'release.version.git' and 'release.changelog.git' properties in favor of 'release.git'. If you are using the subcommands or the programmatic API, then remove the 'release.git' property in favor of 'release.version.git' and 'release.changelog.git':`,
391
409
  bodyLines: [nxJsonMessage],
392
410
  });
@@ -499,3 +517,28 @@ function hasInvalidConventionalCommitsConfig(userConfig) {
499
517
  function hasInvalidGitConfig(userConfig) {
500
518
  return (!!userConfig.git && !!(userConfig.version?.git || userConfig.changelog?.git));
501
519
  }
520
+ async function getDefaultProjects(projectGraph, projectFileMap) {
521
+ // default to all library projects in the workspace with a package.json file
522
+ return (0, find_matching_projects_1.findMatchingProjects)(['*'], projectGraph.nodes).filter((project) => projectGraph.nodes[project].type === 'lib' &&
523
+ // Exclude all projects with "private": true in their package.json because this is
524
+ // a common indicator that a project is not intended for release.
525
+ // Users can override this behavior by explicitly defining the projects they want to release.
526
+ isProjectPublic(project, projectGraph, projectFileMap));
527
+ }
528
+ function isProjectPublic(project, projectGraph, projectFileMap) {
529
+ const projectNode = projectGraph.nodes[project];
530
+ const packageJsonPath = (0, path_1.join)(projectNode.data.root, 'package.json');
531
+ if (!projectFileMap[project]?.find((f) => f.file === packageJsonPath)) {
532
+ return false;
533
+ }
534
+ try {
535
+ const fullPackageJsonPath = (0, path_1.join)(workspace_root_1.workspaceRoot, packageJsonPath);
536
+ const packageJson = (0, fileutils_1.readJsonFile)(fullPackageJsonPath);
537
+ return !(packageJson.private === true);
538
+ }
539
+ catch (e) {
540
+ // do nothing and assume that the project is not public if there is a parsing issue
541
+ // this will result in it being excluded from the default projects list
542
+ return false;
543
+ }
544
+ }
@@ -2,10 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.releasePublish = exports.releasePublishCLIHandler = void 0;
4
4
  const nx_json_1 = require("../../config/nx-json");
5
- const devkit_exports_1 = require("../../devkit-exports");
5
+ const file_map_utils_1 = require("../../project-graph/file-map-utils");
6
6
  const project_graph_1 = require("../../project-graph/project-graph");
7
7
  const run_command_1 = require("../../tasks-runner/run-command");
8
8
  const command_line_utils_1 = require("../../utils/command-line-utils");
9
+ const output_1 = require("../../utils/output");
9
10
  const params_1 = require("../../utils/params");
10
11
  const project_graph_utils_1 = require("../../utils/project-graph-utils");
11
12
  const graph_1 = require("../graph/graph");
@@ -33,13 +34,13 @@ async function releasePublish(args, isCLI = false) {
33
34
  process.env.NX_VERBOSE_LOGGING = 'true';
34
35
  }
35
36
  // Apply default configuration to any optional user configuration
36
- const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, nxJson.release);
37
+ const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), nxJson.release);
37
38
  if (configError) {
38
39
  return await (0, config_1.handleNxReleaseConfigError)(configError);
39
40
  }
40
41
  const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, _args.projects, _args.groups);
41
42
  if (filterError) {
42
- devkit_exports_1.output.error(filterError);
43
+ output_1.output.error(filterError);
43
44
  process.exit(1);
44
45
  }
45
46
  /**
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.release = exports.releaseCLIHandler = void 0;
4
4
  const enquirer_1 = require("enquirer");
5
5
  const nx_json_1 = require("../../config/nx-json");
6
- const devkit_exports_1 = require("../../devkit-exports");
6
+ const file_map_utils_1 = require("../../project-graph/file-map-utils");
7
7
  const project_graph_1 = require("../../project-graph/project-graph");
8
+ const output_1 = require("../../utils/output");
8
9
  const params_1 = require("../../utils/params");
9
10
  const changelog_1 = require("./changelog");
10
11
  const config_1 = require("./config/config");
@@ -30,14 +31,14 @@ async function release(args) {
30
31
  ? ['release', 'version', 'git']
31
32
  : ['release', 'changelog', 'git'];
32
33
  const nxJsonMessage = await (0, resolve_nx_json_error_message_1.resolveNxJsonConfigErrorMessage)(jsonConfigErrorPath);
33
- devkit_exports_1.output.error({
34
+ output_1.output.error({
34
35
  title: `The "release" top level command cannot be used with granular git configuration. Instead, configure git options in the "release.git" property in nx.json, or use the version, changelog, and publish subcommands or programmatic API directly.`,
35
36
  bodyLines: [nxJsonMessage],
36
37
  });
37
38
  process.exit(1);
38
39
  }
39
40
  // Apply default configuration to any optional user configuration
40
- const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, nxJson.release);
41
+ const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), nxJson.release);
41
42
  if (configError) {
42
43
  return await (0, config_1.handleNxReleaseConfigError)(configError);
43
44
  }
@@ -63,11 +64,11 @@ async function release(args) {
63
64
  });
64
65
  const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
65
66
  if (filterError) {
66
- devkit_exports_1.output.error(filterError);
67
+ output_1.output.error(filterError);
67
68
  process.exit(1);
68
69
  }
69
70
  if (shouldCommit) {
70
- devkit_exports_1.output.logSingleLine(`Committing changes with git`);
71
+ output_1.output.logSingleLine(`Committing changes with git`);
71
72
  const commitMessage = nxReleaseConfig.git.commitMessage;
72
73
  const commitMessageValues = (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, versionResult.projectsVersionData, commitMessage);
73
74
  await (0, git_1.gitCommit)({
@@ -78,7 +79,7 @@ async function release(args) {
78
79
  });
79
80
  }
80
81
  if (shouldTag) {
81
- devkit_exports_1.output.logSingleLine(`Tagging commit with git`);
82
+ output_1.output.logSingleLine(`Tagging commit with git`);
82
83
  // Resolve any git tags as early as possible so that we can hard error in case of any duplicates before reaching the actual git command
83
84
  const gitTagValues = (0, shared_1.createGitTagValues)(releaseGroups, releaseGroupToFilteredProjects, versionResult.projectsVersionData);
84
85
  (0, shared_1.handleDuplicateGitTags)(gitTagValues);
@@ -96,14 +97,14 @@ async function release(args) {
96
97
  let hasPushedChanges = false;
97
98
  let latestCommit;
98
99
  if (shouldCreateWorkspaceRelease && changelogResult.workspaceChangelog) {
99
- devkit_exports_1.output.logSingleLine(`Pushing to git remote`);
100
+ output_1.output.logSingleLine(`Pushing to git remote`);
100
101
  // Before we can create/update the release we need to ensure the commit exists on the remote
101
102
  await (0, git_1.gitPush)({
102
103
  dryRun: args.dryRun,
103
104
  verbose: args.verbose,
104
105
  });
105
106
  hasPushedChanges = true;
106
- devkit_exports_1.output.logSingleLine(`Creating GitHub Release`);
107
+ output_1.output.logSingleLine(`Creating GitHub Release`);
107
108
  latestCommit = await (0, git_1.getCommitHash)('HEAD');
108
109
  await (0, github_1.createOrUpdateGithubRelease)(changelogResult.workspaceChangelog.releaseVersion, changelogResult.workspaceChangelog.contents, latestCommit, { dryRun: args.dryRun });
109
110
  }
@@ -122,7 +123,7 @@ async function release(args) {
122
123
  continue;
123
124
  }
124
125
  if (!hasPushedChanges) {
125
- devkit_exports_1.output.logSingleLine(`Pushing to git remote`);
126
+ output_1.output.logSingleLine(`Pushing to git remote`);
126
127
  // Before we can create/update the release we need to ensure the commit exists on the remote
127
128
  await (0, git_1.gitPush)({
128
129
  dryRun: args.dryRun,
@@ -130,7 +131,7 @@ async function release(args) {
130
131
  });
131
132
  hasPushedChanges = true;
132
133
  }
133
- devkit_exports_1.output.logSingleLine(`Creating GitHub Release`);
134
+ output_1.output.logSingleLine(`Creating GitHub Release`);
134
135
  if (!latestCommit) {
135
136
  latestCommit = await (0, git_1.getCommitHash)('HEAD');
136
137
  }
@@ -152,7 +153,7 @@ async function release(args) {
152
153
  await (0, publish_1.releasePublish)(args);
153
154
  }
154
155
  else {
155
- devkit_exports_1.output.logSingleLine('Skipped publishing packages.');
156
+ output_1.output.logSingleLine('Skipped publishing packages.');
156
157
  }
157
158
  return versionResult;
158
159
  }
@@ -92,7 +92,26 @@ async function getGitDiff(from, to = 'HEAD') {
92
92
  exports.getGitDiff = getGitDiff;
93
93
  async function gitAdd({ changedFiles, dryRun, verbose, logFn, }) {
94
94
  logFn = logFn || console.log;
95
- const commandArgs = ['add', ...changedFiles];
95
+ let ignoredFiles = [];
96
+ let filesToAdd = [];
97
+ for (const f of changedFiles) {
98
+ const isFileIgnored = await isIgnored(f);
99
+ if (isFileIgnored) {
100
+ ignoredFiles.push(f);
101
+ }
102
+ else {
103
+ filesToAdd.push(f);
104
+ }
105
+ }
106
+ if (verbose && ignoredFiles.length) {
107
+ logFn(`Will not add the following files because they are ignored by git:`);
108
+ ignoredFiles.forEach((f) => logFn(f));
109
+ }
110
+ if (!filesToAdd.length) {
111
+ logFn('\nNo files to stage. Skipping git add.');
112
+ return;
113
+ }
114
+ const commandArgs = ['add', ...filesToAdd];
96
115
  const message = dryRun
97
116
  ? `Would stage files in git with the following command, but --dry-run was set:`
98
117
  : `Staging files in git with the following command:`;
@@ -106,6 +125,16 @@ async function gitAdd({ changedFiles, dryRun, verbose, logFn, }) {
106
125
  return (0, exec_command_1.execCommand)('git', commandArgs);
107
126
  }
108
127
  exports.gitAdd = gitAdd;
128
+ async function isIgnored(filePath) {
129
+ try {
130
+ // This command will error if the file is not ignored
131
+ await (0, exec_command_1.execCommand)('git', ['check-ignore', filePath]);
132
+ return true;
133
+ }
134
+ catch {
135
+ return false;
136
+ }
137
+ }
109
138
  async function gitCommit({ messages, additionalArgs, dryRun, verbose, logFn, }) {
110
139
  logFn = logFn || console.log;
111
140
  const commandArgs = ['commit'];
@@ -12,7 +12,11 @@ export type ReleaseVersionGeneratorResult = {
12
12
  }) => Promise<string[]>;
13
13
  };
14
14
  export type VersionData = Record<string, {
15
- newVersion: string;
15
+ /**
16
+ * newVersion will be null in the case that no changes are detected for the project,
17
+ * e.g. when using conventional commits
18
+ */
19
+ newVersion: string | null;
16
20
  currentVersion: string;
17
21
  dependentProjects: any[];
18
22
  }>;