nx 17.1.0-beta.2 → 17.1.0-beta.3

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 (32) hide show
  1. package/bin/nx-cloud.js +6 -0
  2. package/package.json +12 -12
  3. package/src/command-line/exec/command-object.js +2 -1
  4. package/src/command-line/exec/exec.d.ts +1 -1
  5. package/src/command-line/exec/exec.js +75 -35
  6. package/src/command-line/init/implementation/angular/legacy-angular-versions.js +4 -2
  7. package/src/command-line/init/implementation/angular/standalone-workspace.js +1 -1
  8. package/src/command-line/release/changelog.js +73 -67
  9. package/src/command-line/release/utils/git.d.ts +1 -0
  10. package/src/command-line/release/utils/git.js +10 -1
  11. package/src/command-line/release/utils/github.d.ts +6 -2
  12. package/src/command-line/release/utils/github.js +7 -4
  13. package/src/commands-runner/command-graph.d.ts +13 -0
  14. package/src/commands-runner/command-graph.js +2 -0
  15. package/src/commands-runner/create-command-graph.d.ts +4 -0
  16. package/src/commands-runner/create-command-graph.js +44 -0
  17. package/src/commands-runner/get-command-projects.d.ts +3 -0
  18. package/src/commands-runner/get-command-projects.js +19 -0
  19. package/src/core/graph/main.js +1 -1
  20. package/src/core/graph/polyfills.js +1 -1
  21. package/src/migrations/update-17-0-0/use-minimal-config-for-tasks-runner-options.js +49 -13
  22. package/src/plugins/js/versions.d.ts +1 -1
  23. package/src/plugins/js/versions.js +1 -1
  24. package/src/plugins/project-json/build-nodes/package-json-next-to-project-json.d.ts +2 -0
  25. package/src/plugins/project-json/build-nodes/package-json-next-to-project-json.js +45 -0
  26. package/src/plugins/project-json/build-nodes/project-json.d.ts +1 -4
  27. package/src/plugins/project-json/build-nodes/project-json.js +1 -38
  28. package/src/tasks-runner/task-graph-utils.d.ts +7 -3
  29. package/src/tasks-runner/task-graph-utils.js +15 -15
  30. package/src/tasks-runner/utils.d.ts +8 -0
  31. package/src/tasks-runner/utils.js +17 -8
  32. package/src/utils/nx-plugin.js +5 -5
package/bin/nx-cloud.js CHANGED
@@ -35,6 +35,12 @@ async function invokeCommandWithNxCloudClient(options) {
35
35
  catch (e) {
36
36
  const body = ['Cannot run commands from the `nx-cloud` CLI.'];
37
37
  if (e instanceof update_manager_1.NxCloudEnterpriseOutdatedError) {
38
+ try {
39
+ // TODO: Remove this when all enterprise customers have updated.
40
+ // Try requiring the bin from the `nx-cloud` package.
41
+ return require('nx-cloud/bin/nx-cloud');
42
+ }
43
+ catch { }
38
44
  body.push('If you are an Nx Enterprise customer, please reach out to your assigned Developer Productivity Engineer.', 'If you are NOT an Nx Enterprise customer but are seeing this message, please reach out to cloud-support@nrwl.io.');
39
45
  }
40
46
  if (e instanceof update_manager_1.NxCloudClientUnavailableError) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "17.1.0-beta.2",
3
+ "version": "17.1.0-beta.3",
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": {
@@ -67,7 +67,7 @@
67
67
  "yargs": "^17.6.2",
68
68
  "yargs-parser": "21.1.1",
69
69
  "node-machine-id": "1.1.12",
70
- "@nrwl/tao": "17.1.0-beta.2"
70
+ "@nrwl/tao": "17.1.0-beta.3"
71
71
  },
72
72
  "peerDependencies": {
73
73
  "@swc-node/register": "^1.6.7",
@@ -82,16 +82,16 @@
82
82
  }
83
83
  },
84
84
  "optionalDependencies": {
85
- "@nx/nx-darwin-x64": "17.1.0-beta.2",
86
- "@nx/nx-darwin-arm64": "17.1.0-beta.2",
87
- "@nx/nx-linux-x64-gnu": "17.1.0-beta.2",
88
- "@nx/nx-linux-x64-musl": "17.1.0-beta.2",
89
- "@nx/nx-win32-x64-msvc": "17.1.0-beta.2",
90
- "@nx/nx-linux-arm64-gnu": "17.1.0-beta.2",
91
- "@nx/nx-linux-arm64-musl": "17.1.0-beta.2",
92
- "@nx/nx-linux-arm-gnueabihf": "17.1.0-beta.2",
93
- "@nx/nx-win32-arm64-msvc": "17.1.0-beta.2",
94
- "@nx/nx-freebsd-x64": "17.1.0-beta.2"
85
+ "@nx/nx-darwin-x64": "17.1.0-beta.3",
86
+ "@nx/nx-darwin-arm64": "17.1.0-beta.3",
87
+ "@nx/nx-linux-x64-gnu": "17.1.0-beta.3",
88
+ "@nx/nx-linux-x64-musl": "17.1.0-beta.3",
89
+ "@nx/nx-win32-x64-msvc": "17.1.0-beta.3",
90
+ "@nx/nx-linux-arm64-gnu": "17.1.0-beta.3",
91
+ "@nx/nx-linux-arm64-musl": "17.1.0-beta.3",
92
+ "@nx/nx-linux-arm-gnueabihf": "17.1.0-beta.3",
93
+ "@nx/nx-win32-arm64-msvc": "17.1.0-beta.3",
94
+ "@nx/nx-freebsd-x64": "17.1.0-beta.3"
95
95
  },
96
96
  "nx-migrations": {
97
97
  "migrations": "./migrations.json",
@@ -5,13 +5,14 @@ const shared_options_1 = require("../yargs-utils/shared-options");
5
5
  exports.yargsExecCommand = {
6
6
  command: 'exec',
7
7
  describe: 'Executes any command as if it was a target on the project',
8
- builder: (yargs) => (0, shared_options_1.withRunOneOptions)(yargs),
8
+ builder: (yargs) => (0, shared_options_1.withRunManyOptions)(yargs),
9
9
  handler: async (args) => {
10
10
  try {
11
11
  await (await Promise.resolve().then(() => require('./exec'))).nxExecCommand((0, shared_options_1.withOverrides)(args));
12
12
  process.exit(0);
13
13
  }
14
14
  catch (e) {
15
+ console.error(e);
15
16
  process.exit(1);
16
17
  }
17
18
  },
@@ -1 +1 @@
1
- export declare function nxExecCommand(args: Record<string, string[]>): Promise<unknown>;
1
+ export declare function nxExecCommand(args: Record<string, string | string[] | boolean>): Promise<unknown>;
@@ -5,6 +5,8 @@ const child_process_1 = require("child_process");
5
5
  const path_1 = require("path");
6
6
  const process_1 = require("process");
7
7
  const yargs = require("yargs-parser");
8
+ const fs_1 = require("fs");
9
+ const find_matching_projects_1 = require("../../utils/find-matching-projects");
8
10
  const configuration_1 = require("../../config/configuration");
9
11
  const project_graph_1 = require("../../project-graph/project-graph");
10
12
  const command_line_utils_1 = require("../../utils/command-line-utils");
@@ -13,8 +15,15 @@ const output_1 = require("../../utils/output");
13
15
  const package_manager_1 = require("../../utils/package-manager");
14
16
  const workspace_root_1 = require("../../utils/workspace-root");
15
17
  const calculate_default_project_name_1 = require("../../config/calculate-default-project-name");
18
+ const get_command_projects_1 = require("../../commands-runner/get-command-projects");
16
19
  async function nxExecCommand(args) {
17
- const scriptArgV = readScriptArgV(args);
20
+ const nxJson = (0, configuration_1.readNxJson)();
21
+ const { nxArgs, overrides } = (0, command_line_utils_1.splitArgsIntoNxArgsAndOverrides)(args, 'run-many', { printWarnings: args.graph !== 'stdout' }, nxJson);
22
+ if (nxArgs.verbose) {
23
+ process.env.NX_VERBOSE_LOGGING = 'true';
24
+ }
25
+ const scriptArgV = readScriptArgV(overrides);
26
+ const projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true });
18
27
  // NX is already running
19
28
  if (process.env.NX_TASK_TARGET_PROJECT) {
20
29
  const command = scriptArgV
@@ -22,32 +31,56 @@ async function nxExecCommand(args) {
22
31
  .trim();
23
32
  (0, child_process_1.execSync)(command, {
24
33
  stdio: 'inherit',
25
- env: process.env,
34
+ env: {
35
+ ...process.env,
36
+ NX_PROJECT_NAME: process.env.NX_TASK_TARGET_PROJECT,
37
+ NX_PROJECT_ROOT_PATH: projectGraph.nodes?.[process.env.NX_TASK_TARGET_PROJECT]?.data?.root,
38
+ },
26
39
  });
27
40
  }
28
41
  else {
29
42
  // nx exec is being ran inside of Nx's context
30
- return runScriptAsNxTarget(scriptArgV);
43
+ return runScriptAsNxTarget(projectGraph, scriptArgV, nxArgs);
31
44
  }
32
45
  }
33
46
  exports.nxExecCommand = nxExecCommand;
34
- async function runScriptAsNxTarget(argv) {
35
- const projectGraph = await (0, project_graph_1.createProjectGraphAsync)();
36
- const { projectName, project } = getProject(projectGraph);
47
+ async function runScriptAsNxTarget(projectGraph, argv, nxArgs) {
37
48
  // NPM, Yarn, and PNPM set this to the name of the currently executing script. Lets use it if we can.
38
49
  const targetName = process.env.npm_lifecycle_event;
39
- const scriptDefinition = getScriptDefinition(project, targetName);
50
+ if (targetName) {
51
+ const defaultPorject = getDefaultProject(projectGraph);
52
+ const scriptDefinition = getScriptDefinition(targetName, defaultPorject);
53
+ if (scriptDefinition) {
54
+ runTargetOnProject(scriptDefinition, targetName, defaultPorject, defaultPorject.name, argv);
55
+ return;
56
+ }
57
+ }
58
+ const projects = getProjects(projectGraph, nxArgs);
59
+ const projectsToRun = (0, get_command_projects_1.getCommandProjects)(projectGraph, projects, nxArgs);
60
+ projectsToRun.forEach((projectName) => {
61
+ const command = argv.reduce((cmd, arg) => cmd + `"${arg}" `, '').trim();
62
+ (0, child_process_1.execSync)(command, {
63
+ stdio: 'inherit',
64
+ env: {
65
+ ...process.env,
66
+ NX_PROJECT_NAME: projectGraph.nodes?.[projectName]?.name,
67
+ NX_PROJECT_ROOT_PATH: projectGraph.nodes?.[projectName]?.data?.root,
68
+ },
69
+ cwd: projectGraph.nodes?.[projectName]?.data?.root ?? workspace_root_1.workspaceRoot,
70
+ });
71
+ });
72
+ }
73
+ function runTargetOnProject(scriptDefinition, targetName, project, projectName, argv) {
40
74
  ensureNxTarget(project, targetName);
41
75
  // Get ArgV that is provided in npm script definition
42
76
  const providedArgs = yargs(scriptDefinition)._.slice(2);
43
77
  const extraArgs = providedArgs.length === argv.length ? [] : argv.slice(providedArgs.length);
44
78
  const pm = (0, package_manager_1.getPackageManagerCommand)();
45
79
  // `targetName` might be an npm script with `:` like: `start:dev`, `start:debug`.
46
- let command = `${pm.exec} nx run ${projectName}:\\\"${targetName}\\\" ${extraArgs.join(' ')}`;
47
- return (0, child_process_1.execSync)(command, { stdio: 'inherit' });
80
+ const command = `${pm.exec} nx run ${projectName}:\\\"${targetName}\\\" ${extraArgs.join(' ')}`;
81
+ (0, child_process_1.execSync)(command, { stdio: 'inherit' });
48
82
  }
49
- function readScriptArgV(args) {
50
- const { overrides } = (0, command_line_utils_1.splitArgsIntoNxArgsAndOverrides)(args, 'run-one', { printWarnings: false }, (0, configuration_1.readNxJson)());
83
+ function readScriptArgV(overrides) {
51
84
  const scriptSeparatorIdx = process.argv.findIndex((el) => el === '--');
52
85
  if (scriptSeparatorIdx === -1) {
53
86
  output_1.output.error({
@@ -57,18 +90,15 @@ function readScriptArgV(args) {
57
90
  }
58
91
  return overrides.__overrides_unparsed__;
59
92
  }
60
- function getScriptDefinition(project, targetName) {
61
- const scriptDefinition = (0, fileutils_1.readJsonFile)((0, path_1.join)(workspace_root_1.workspaceRoot, project.data.root, 'package.json')).scripts[targetName];
62
- if (!scriptDefinition) {
63
- output_1.output.error({
64
- title: "`nx exec` is meant to be used in a project's package.json scripts",
65
- bodyLines: [
66
- `Nx was unable to find a npm script matching ${targetName} for ${project.name}`,
67
- ],
68
- });
69
- process.exit(1);
93
+ function getScriptDefinition(targetName, project) {
94
+ if (!project) {
95
+ return;
96
+ }
97
+ const packageJsonPath = (0, path_1.join)(workspace_root_1.workspaceRoot, project.data.root, 'package.json');
98
+ if ((0, fs_1.existsSync)(packageJsonPath)) {
99
+ const scriptDefinition = (0, fileutils_1.readJsonFile)(packageJsonPath).scripts?.[targetName];
100
+ return scriptDefinition;
70
101
  }
71
- return scriptDefinition;
72
102
  }
73
103
  function ensureNxTarget(project, targetName) {
74
104
  if (!project.data.targets[targetName]) {
@@ -81,18 +111,28 @@ function ensureNxTarget(project, targetName) {
81
111
  (0, process_1.exit)(1);
82
112
  }
83
113
  }
84
- function getProject(projectGraph) {
85
- const projectName = (0, calculate_default_project_name_1.calculateDefaultProjectName)(process.cwd(), workspace_root_1.workspaceRoot, (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph), (0, configuration_1.readNxJson)());
86
- if (!projectName) {
87
- output_1.output.error({
88
- title: 'Unable to determine project name for `nx exec`',
89
- bodyLines: [
90
- "`nx exec` should be ran from within an Nx project's root directory.",
91
- 'Does this package.json belong to an Nx project?',
92
- ],
93
- });
94
- process.exit(1);
114
+ function getDefaultProject(projectGraph) {
115
+ const defaultProjectName = (0, calculate_default_project_name_1.calculateDefaultProjectName)(process.cwd(), workspace_root_1.workspaceRoot, (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph), (0, configuration_1.readNxJson)());
116
+ if (defaultProjectName && projectGraph.nodes[defaultProjectName]) {
117
+ return projectGraph.nodes[defaultProjectName];
118
+ }
119
+ }
120
+ function getProjects(projectGraph, nxArgs) {
121
+ let selectedProjects = {};
122
+ // get projects matched
123
+ if (nxArgs.projects?.length) {
124
+ const matchingProjects = (0, find_matching_projects_1.findMatchingProjects)(nxArgs.projects, projectGraph.nodes);
125
+ for (const project of matchingProjects) {
126
+ selectedProjects[project] = projectGraph.nodes[project];
127
+ }
128
+ }
129
+ else {
130
+ // if no project specified, return all projects
131
+ selectedProjects = { ...projectGraph.nodes };
132
+ }
133
+ const excludedProjects = (0, find_matching_projects_1.findMatchingProjects)(nxArgs.exclude, selectedProjects);
134
+ for (const excludedProject of excludedProjects) {
135
+ delete selectedProjects[excludedProject];
95
136
  }
96
- const project = projectGraph.nodes[projectName];
97
- return { projectName, project };
137
+ return Object.values(selectedProjects);
98
138
  }
@@ -12,9 +12,11 @@ const package_manager_1 = require("../../../../utils/package-manager");
12
12
  const utils_1 = require("../utils");
13
13
  // map of Angular major versions to Nx versions to use for legacy `nx init` migrations,
14
14
  // key is major Angular version and value is Nx version to use
15
- const nxAngularLegacyVersionMap = {};
15
+ const nxAngularLegacyVersionMap = {
16
+ 14: '~17.0.0',
17
+ };
16
18
  // min major angular version supported in latest Nx
17
- const minMajorAngularVersionSupported = 14;
19
+ const minMajorAngularVersionSupported = 15;
18
20
  // version when the Nx CLI changed from @nrwl/tao & @nrwl/cli to nx
19
21
  const versionWithConsolidatedPackages = '13.9.0';
20
22
  // version when packages were rescoped from @nrwl/* to @nx/*
@@ -98,7 +98,7 @@ function createNxJson(repoRoot, angularJson, cacheableOperations, { eslintProjec
98
98
  inputs: ['default', '^production'],
99
99
  };
100
100
  }
101
- // Angular 14 workspaces support defaultProject, keep it until we drop support
101
+ // Angular 15 workspaces still support defaultProject. Support was removed in Angular 16.
102
102
  nxJson.defaultProject = angularJson.defaultProject;
103
103
  (0, fileutils_1.writeJsonFile)((0, path_1.join)(repoRoot, 'nx.json'), nxJson);
104
104
  }
@@ -22,6 +22,7 @@ const github_1 = require("./utils/github");
22
22
  const launch_editor_1 = require("./utils/launch-editor");
23
23
  const markdown_1 = require("./utils/markdown");
24
24
  const print_changes_1 = require("./utils/print-changes");
25
+ const params_1 = require("../../utils/params");
25
26
  class ReleaseVersion {
26
27
  constructor({ version, // short form version string with no prefixes or patterns, e.g. 1.0.0
27
28
  releaseTagPattern, // full pattern to interpolate, e.g. "v{version}" or "{projectName}@{version}"
@@ -36,80 +37,83 @@ class ReleaseVersion {
36
37
  }
37
38
  }
38
39
  async function changelogHandler(args) {
39
- // Right now, the given version must be valid semver in order to proceed
40
- if (!(0, semver_1.valid)(args.version)) {
41
- output_1.output.error({
42
- title: `The given version "${args.version}" is not a valid semver version. Please provide your version in the format "1.0.0", "1.0.0-beta.1" etc`,
40
+ return (0, params_1.handleErrors)(args.verbose, async () => {
41
+ // Right now, the given version must be valid semver in order to proceed
42
+ if (!(0, semver_1.valid)(args.version)) {
43
+ output_1.output.error({
44
+ title: `The given version "${args.version}" is not a valid semver version. Please provide your version in the format "1.0.0", "1.0.0-beta.1" etc`,
45
+ });
46
+ process.exit(1);
47
+ }
48
+ const projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true });
49
+ const nxJson = (0, nx_json_1.readNxJson)();
50
+ const commitHash = await (0, git_1.getCommitHash)(args.to);
51
+ if (args.verbose) {
52
+ process.env.NX_VERBOSE_LOGGING = 'true';
53
+ }
54
+ // Apply default configuration to any optional user configuration
55
+ const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, nxJson.release);
56
+ if (configError) {
57
+ return await (0, config_1.handleNxReleaseConfigError)(configError);
58
+ }
59
+ const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
60
+ if (filterError) {
61
+ output_1.output.error(filterError);
62
+ process.exit(1);
63
+ }
64
+ const releaseVersion = new ReleaseVersion({
65
+ version: args.version,
66
+ releaseTagPattern: nxReleaseConfig.releaseTagPattern,
43
67
  });
44
- process.exit(1);
45
- }
46
- const projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true });
47
- const nxJson = (0, nx_json_1.readNxJson)();
48
- if (args.verbose) {
49
- process.env.NX_VERBOSE_LOGGING = 'true';
50
- }
51
- // Apply default configuration to any optional user configuration
52
- const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, nxJson.release);
53
- if (configError) {
54
- return await (0, config_1.handleNxReleaseConfigError)(configError);
55
- }
56
- const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
57
- if (filterError) {
58
- output_1.output.error(filterError);
59
- process.exit(1);
60
- }
61
- const releaseVersion = new ReleaseVersion({
62
- version: args.version,
63
- releaseTagPattern: nxReleaseConfig.releaseTagPattern,
64
- });
65
- const from = args.from ||
66
- (await (0, git_1.getLatestGitTagForPattern)(nxReleaseConfig.releaseTagPattern))?.tag;
67
- if (!from) {
68
- output_1.output.error({
69
- title: `Unable to determine the previous git tag, please provide an explicit git reference using --from`,
68
+ const from = args.from ||
69
+ (await (0, git_1.getLatestGitTagForPattern)(nxReleaseConfig.releaseTagPattern))?.tag;
70
+ if (!from) {
71
+ output_1.output.error({
72
+ title: `Unable to determine the previous git tag, please provide an explicit git reference using --from`,
73
+ });
74
+ process.exit(1);
75
+ }
76
+ const rawCommits = await (0, git_1.getGitDiff)(from, args.to);
77
+ // Parse as conventional commits
78
+ const commits = (0, git_1.parseCommits)(rawCommits).filter((c) => {
79
+ const type = c.type;
80
+ // Always ignore non user-facing commits for now
81
+ // TODO: allow this filter to be configurable via config in a future release
82
+ if (type === 'feat' || type === 'fix' || type === 'perf') {
83
+ return true;
84
+ }
85
+ return false;
70
86
  });
71
- process.exit(1);
72
- }
73
- const rawCommits = await (0, git_1.getGitDiff)(from, args.to);
74
- // Parse as conventional commits
75
- const commits = (0, git_1.parseCommits)(rawCommits).filter((c) => {
76
- const type = c.type;
77
- // Always ignore non user-facing commits for now
78
- // TODO: allow this filter to be configurable via config in a future release
79
- if (type === 'feat' || type === 'fix' || type === 'perf') {
80
- return true;
87
+ const tree = new tree_1.FsTree(workspace_root_1.workspaceRoot, args.verbose);
88
+ await generateChangelogForWorkspace(tree, releaseVersion, !!args.dryRun,
89
+ // Only trigger interactive mode for the workspace changelog if the user explicitly requested it via "all" or "workspace"
90
+ args.interactive === 'all' || args.interactive === 'workspace', commitHash, commits, nxReleaseConfig.changelog.workspaceChangelog, args.gitRemote);
91
+ if (args.projects?.length) {
92
+ /**
93
+ * Run changelog generation for all remaining release groups and filtered projects within them
94
+ */
95
+ for (const releaseGroup of releaseGroups) {
96
+ const projectNodes = Array.from(releaseGroupToFilteredProjects.get(releaseGroup)).map((name) => projectGraph.nodes[name]);
97
+ await generateChangelogForProjects(tree, args.version, !!args.dryRun,
98
+ // Only trigger interactive mode for the workspace changelog if the user explicitly requested it via "all" or "projects"
99
+ args.interactive === 'all' || args.interactive === 'projects', commitHash, commits, releaseGroup.changelog, releaseGroup.releaseTagPattern, projectNodes, args.gitRemote);
100
+ }
101
+ return process.exit(0);
81
102
  }
82
- return false;
83
- });
84
- const tree = new tree_1.FsTree(workspace_root_1.workspaceRoot, args.verbose);
85
- await generateChangelogForWorkspace(tree, releaseVersion, !!args.dryRun,
86
- // Only trigger interactive mode for the workspace changelog if the user explicitly requested it via "all" or "workspace"
87
- args.interactive === 'all' || args.interactive === 'workspace', commits, nxReleaseConfig.changelog.workspaceChangelog, args.gitRemote);
88
- if (args.projects?.length) {
89
103
  /**
90
- * Run changelog generation for all remaining release groups and filtered projects within them
104
+ * Run changelog generation for all remaining release groups
91
105
  */
92
106
  for (const releaseGroup of releaseGroups) {
93
- const projectNodes = Array.from(releaseGroupToFilteredProjects.get(releaseGroup)).map((name) => projectGraph.nodes[name]);
107
+ const projectNodes = releaseGroup.projects.map((name) => projectGraph.nodes[name]);
94
108
  await generateChangelogForProjects(tree, args.version, !!args.dryRun,
95
109
  // Only trigger interactive mode for the workspace changelog if the user explicitly requested it via "all" or "projects"
96
- args.interactive === 'all' || args.interactive === 'projects', commits, releaseGroup.changelog, releaseGroup.releaseTagPattern, projectNodes, args.gitRemote);
110
+ args.interactive === 'all' || args.interactive === 'projects', commitHash, commits, releaseGroup.changelog, releaseGroup.releaseTagPattern, projectNodes, args.gitRemote);
97
111
  }
98
- return process.exit(0);
99
- }
100
- /**
101
- * Run changelog generation for all remaining release groups
102
- */
103
- for (const releaseGroup of releaseGroups) {
104
- const projectNodes = releaseGroup.projects.map((name) => projectGraph.nodes[name]);
105
- await generateChangelogForProjects(tree, args.version, !!args.dryRun,
106
- // Only trigger interactive mode for the workspace changelog if the user explicitly requested it via "all" or "projects"
107
- args.interactive === 'all' || args.interactive === 'projects', commits, releaseGroup.changelog, releaseGroup.releaseTagPattern, projectNodes, args.gitRemote);
108
- }
109
- if (args.dryRun) {
110
- logger_1.logger.warn(`\nNOTE: The "dryRun" flag means no changelogs were actually created.`);
111
- }
112
- process.exit(0);
112
+ if (args.dryRun) {
113
+ logger_1.logger.warn(`\nNOTE: The "dryRun" flag means no changelogs were actually created.`);
114
+ }
115
+ process.exit(0);
116
+ });
113
117
  }
114
118
  exports.changelogHandler = changelogHandler;
115
119
  function isPrerelease(version) {
@@ -135,7 +139,7 @@ function resolveChangelogRenderer(changelogRendererPath) {
135
139
  }
136
140
  return changelogRenderer;
137
141
  }
138
- async function generateChangelogForWorkspace(tree, releaseVersion, dryRun, interactive, commits, config, gitRemote) {
142
+ async function generateChangelogForWorkspace(tree, releaseVersion, dryRun, interactive, commit, commits, config, gitRemote) {
139
143
  // The entire feature is disabled at the workspace level, exit early
140
144
  if (config === false) {
141
145
  return;
@@ -276,12 +280,13 @@ async function generateChangelogForWorkspace(tree, releaseVersion, dryRun, inter
276
280
  version: releaseVersion.gitTag,
277
281
  prerelease: releaseVersion.isPrerelease,
278
282
  body: contents,
283
+ commit,
279
284
  }, existingGithubReleaseForVersion);
280
285
  }
281
286
  }
282
287
  printSummary();
283
288
  }
284
- async function generateChangelogForProjects(tree, rawVersion, dryRun, interactive, commits, config, releaseTagPattern, projects, gitRemote) {
289
+ async function generateChangelogForProjects(tree, rawVersion, dryRun, interactive, commit, commits, config, releaseTagPattern, projects, gitRemote) {
285
290
  // The entire feature is disabled at the project level, exit early
286
291
  if (config === false) {
287
292
  return;
@@ -436,6 +441,7 @@ async function generateChangelogForProjects(tree, rawVersion, dryRun, interactiv
436
441
  version: releaseVersion.gitTag,
437
442
  prerelease: releaseVersion.isPrerelease,
438
443
  body: contents,
444
+ commit,
439
445
  }, existingGithubReleaseForVersion);
440
446
  }
441
447
  }
@@ -28,3 +28,4 @@ export declare function getLatestGitTagForPattern(releaseTagPattern: string, add
28
28
  export declare function getGitDiff(from: string | undefined, to?: string): Promise<RawGitCommit[]>;
29
29
  export declare function parseCommits(commits: RawGitCommit[]): GitCommit[];
30
30
  export declare function parseGitCommit(commit: RawGitCommit): GitCommit | null;
31
+ export declare function getCommitHash(ref: string): Promise<string>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseGitCommit = exports.parseCommits = exports.getGitDiff = exports.getLatestGitTagForPattern = void 0;
3
+ exports.getCommitHash = exports.parseGitCommit = exports.parseCommits = exports.getGitDiff = exports.getLatestGitTagForPattern = void 0;
4
4
  /**
5
5
  * Special thanks to changelogen for the original inspiration for many of these utilities:
6
6
  * https://github.com/unjs/changelogen
@@ -126,3 +126,12 @@ function parseGitCommit(commit) {
126
126
  };
127
127
  }
128
128
  exports.parseGitCommit = parseGitCommit;
129
+ function getCommitHash(ref) {
130
+ try {
131
+ return (0, exec_command_1.execCommand)('git', ['rev-parse', ref]);
132
+ }
133
+ catch (e) {
134
+ throw new Error(`Unknown revision: ${ref}`);
135
+ }
136
+ }
137
+ exports.getCommitHash = getCommitHash;
@@ -7,17 +7,21 @@ export interface GithubRequestConfig {
7
7
  export interface GithubRelease {
8
8
  id?: string;
9
9
  tag_name: string;
10
+ target_commitish?: string;
10
11
  name?: string;
11
12
  body?: string;
12
13
  draft?: boolean;
13
14
  prerelease?: boolean;
14
15
  }
15
16
  export declare function getGitHubRepoSlug(remoteName?: string): RepoSlug;
16
- export declare function createOrUpdateGithubRelease(githubRequestConfig: GithubRequestConfig, release: {
17
+ interface GithubReleaseOptions {
17
18
  version: string;
18
19
  body: string;
19
20
  prerelease: boolean;
20
- }, existingGithubReleaseForVersion?: GithubRelease): Promise<void>;
21
+ commit: string;
22
+ }
23
+ export declare function createOrUpdateGithubRelease(githubRequestConfig: GithubRequestConfig, release: GithubReleaseOptions, existingGithubReleaseForVersion?: GithubRelease): Promise<void>;
21
24
  export declare function resolveGithubToken(): Promise<string | null>;
22
25
  export declare function getGithubReleaseByTag(config: GithubRequestConfig, tag: string): Promise<GithubRelease>;
23
26
  export declare function formatReferences(references: Reference[], repoSlug: RepoSlug): string;
27
+ export {};
@@ -5,7 +5,7 @@ const chalk = require("chalk");
5
5
  const node_child_process_1 = require("node:child_process");
6
6
  const node_fs_1 = require("node:fs");
7
7
  const node_os_1 = require("node:os");
8
- const devkit_exports_1 = require("../../../devkit-exports");
8
+ const path_1 = require("../../../utils/path");
9
9
  // axios types and values don't seem to match
10
10
  const _axios = require("axios");
11
11
  const axios = _axios;
@@ -16,7 +16,7 @@ function getGitHubRepoSlug(remoteName = 'origin') {
16
16
  stdio: 'pipe',
17
17
  }).trim();
18
18
  // Extract the 'user/repo' part from the URL
19
- const regex = /github\.com[/:]([\w-]+\/[\w-]+)\.git/;
19
+ const regex = /github\.com[/:]([\w-]+\/[\w-]+)/;
20
20
  const match = remoteUrl.match(regex);
21
21
  if (match && match[1]) {
22
22
  return match[1];
@@ -64,7 +64,10 @@ async function syncGithubRelease(githubRequestConfig, release, existingGithubRel
64
64
  try {
65
65
  const newGhRelease = await (existingGithubReleaseForVersion
66
66
  ? updateGithubRelease(githubRequestConfig, existingGithubReleaseForVersion.id, ghRelease)
67
- : createGithubRelease(githubRequestConfig, ghRelease));
67
+ : createGithubRelease(githubRequestConfig, {
68
+ ...ghRelease,
69
+ target_commitish: release.commit,
70
+ }));
68
71
  return {
69
72
  status: existingGithubReleaseForVersion ? 'updated' : 'created',
70
73
  id: newGhRelease.id,
@@ -86,7 +89,7 @@ async function resolveGithubToken() {
86
89
  return tokenFromEnv;
87
90
  }
88
91
  // Try and resolve from gh CLI installation
89
- const ghCLIPath = (0, devkit_exports_1.joinPathFragments)(process.env.XDG_CONFIG_HOME || (0, devkit_exports_1.joinPathFragments)((0, node_os_1.homedir)(), '.config'), 'gh', 'hosts.yml');
92
+ const ghCLIPath = (0, path_1.joinPathFragments)(process.env.XDG_CONFIG_HOME || (0, path_1.joinPathFragments)((0, node_os_1.homedir)(), '.config'), 'gh', 'hosts.yml');
90
93
  if ((0, node_fs_1.existsSync)(ghCLIPath)) {
91
94
  const yamlContents = await node_fs_1.promises.readFile(ghCLIPath, 'utf8');
92
95
  const { load } = require('@zkochan/js-yaml');
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Graph of Tasks to be executed
3
+ */
4
+ export interface CommandGraph {
5
+ /**
6
+ * Projects that do not have any dependencies and are thus ready to execute immediately
7
+ */
8
+ roots: string[];
9
+ /**
10
+ * Map of projects to projects which the task depends on
11
+ */
12
+ dependencies: Record<string, string[]>;
13
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ import { ProjectGraph } from '../config/project-graph';
2
+ import { NxArgs } from '../utils/command-line-utils';
3
+ import { CommandGraph } from './command-graph';
4
+ export declare function createCommandGraph(projectGraph: ProjectGraph, projectNames: string[], nxArgs: NxArgs): CommandGraph;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCommandGraph = void 0;
4
+ const task_graph_utils_1 = require("../tasks-runner/task-graph-utils");
5
+ const output_1 = require("../utils/output");
6
+ function createCommandGraph(projectGraph, projectNames, nxArgs) {
7
+ const dependencies = {};
8
+ for (const projectName of projectNames) {
9
+ if (projectGraph.dependencies[projectName].length >= 1) {
10
+ dependencies[projectName] = [
11
+ ...new Set(projectGraph.dependencies[projectName]
12
+ .map((projectDep) => projectDep.target)
13
+ .filter((projectDep) => projectGraph.nodes[projectDep])).values(),
14
+ ];
15
+ }
16
+ else {
17
+ dependencies[projectName] = [];
18
+ }
19
+ }
20
+ const roots = Object.keys(dependencies).filter((d) => dependencies[d].length === 0);
21
+ const commandGraph = {
22
+ dependencies,
23
+ roots,
24
+ };
25
+ const cycle = (0, task_graph_utils_1.findCycle)(commandGraph);
26
+ if (cycle) {
27
+ if (process.env.NX_IGNORE_CYCLES === 'true' || nxArgs.nxIgnoreCycles) {
28
+ output_1.output.warn({
29
+ title: `The command graph has a circular dependency`,
30
+ bodyLines: [`${cycle.join(' --> ')}`],
31
+ });
32
+ (0, task_graph_utils_1.makeAcyclic)(commandGraph);
33
+ }
34
+ else {
35
+ output_1.output.error({
36
+ title: `Could not execute command because the project graph has a circular dependency`,
37
+ bodyLines: [`${cycle.join(' --> ')}`],
38
+ });
39
+ process.exit(1);
40
+ }
41
+ }
42
+ return commandGraph;
43
+ }
44
+ exports.createCommandGraph = createCommandGraph;
@@ -0,0 +1,3 @@
1
+ import { ProjectGraph, ProjectGraphProjectNode } from '../config/project-graph';
2
+ import { NxArgs } from '../utils/command-line-utils';
3
+ export declare function getCommandProjects(projectGraph: ProjectGraph, projects: ProjectGraphProjectNode[], nxArgs: NxArgs): string[];