From dc40a86b23683a02f86558c802f9ddce4b5913df Mon Sep 17 00:00:00 2001 From: Jonathan Cammisuli Date: Thu, 7 Dec 2023 10:54:06 -0500 Subject: [PATCH] feat(core): add task plans to `--graph=file.json` argument --- packages/nx/src/command-line/graph/graph.ts | 25 +++++++++++++---- packages/nx/src/hasher/create-task-hasher.ts | 29 ++++++++++++++++++++ packages/nx/src/hasher/task-hasher.ts | 4 +-- packages/nx/src/tasks-runner/run-command.ts | 16 ++--------- 4 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 packages/nx/src/hasher/create-task-hasher.ts diff --git a/packages/nx/src/command-line/graph/graph.ts b/packages/nx/src/command-line/graph/graph.ts index e0685836487ddc..27416f08d21df1 100644 --- a/packages/nx/src/command-line/graph/graph.ts +++ b/packages/nx/src/command-line/graph/graph.ts @@ -51,6 +51,7 @@ import { readFileMapCache } from '../../project-graph/nx-deps-cache'; import { ConfigurationSourceMaps } from '../../project-graph/utils/project-configuration-utils'; import { filterUsingGlobPatterns } from '../../hasher/task-hasher'; +import { createTaskHasher } from '../../hasher/create-task-hasher'; export interface ProjectGraphClientResponse { hash: string; @@ -343,7 +344,7 @@ export async function generateGraph( if (args.file === 'stdout') { console.log( JSON.stringify( - createJsonOutput(prunedGraph, args.projects, args.targets), + await createJsonOutput(prunedGraph, args.projects, args.targets), null, 2 ) @@ -404,7 +405,11 @@ export async function generateGraph( } else if (ext === '.json') { ensureDirSync(dirname(fullFilePath)); - const json = createJsonOutput(prunedGraph, args.projects, args.targets); + const json = await createJsonOutput( + rawGraph, + args.projects, + args.targets + ); json.affectedProjects = affectedProjects; json.criticalPath = affectedProjects; @@ -1014,6 +1019,7 @@ function expandInputs( interface GraphJsonResponse { tasks?: TaskGraph; + taskPlans?: Record; graph: ProjectGraph; /** @@ -1027,11 +1033,11 @@ interface GraphJsonResponse { criticalPath?: string[]; } -function createJsonOutput( +async function createJsonOutput( graph: ProjectGraph, projects: string[], targets?: string[] -): GraphJsonResponse { +): Promise { const response: GraphJsonResponse = { graph, }; @@ -1043,7 +1049,7 @@ function createJsonOutput( nxJson.targetDefaults ); - response.tasks = createTaskGraph( + const taskGraph = createTaskGraph( graph, defaultDependencyConfigs, projects, @@ -1051,6 +1057,15 @@ function createJsonOutput( undefined, {} ); + + const hasher = createTaskHasher(graph, readNxJson()); + let tasks = Object.values(taskGraph.tasks); + const hashes = await hasher.hashTasks(tasks, taskGraph); + response.tasks = taskGraph; + response.taskPlans = tasks.reduce((acc, task, index) => { + acc[task.id] = Object.keys(hashes[index].details.nodes).sort(); + return acc; + }, {}); } return response; diff --git a/packages/nx/src/hasher/create-task-hasher.ts b/packages/nx/src/hasher/create-task-hasher.ts new file mode 100644 index 00000000000000..deda1cf4434fc0 --- /dev/null +++ b/packages/nx/src/hasher/create-task-hasher.ts @@ -0,0 +1,29 @@ +import { NxJsonConfiguration } from '../config/nx-json'; +import { ProjectGraph } from '../config/project-graph'; +import { daemonClient } from '../daemon/client/client'; +import { getFileMap } from '../project-graph/build-project-graph'; +import { + DaemonBasedTaskHasher, + InProcessTaskHasher, + TaskHasher, +} from './task-hasher'; + +export function createTaskHasher( + projectGraph: ProjectGraph, + nxJson: NxJsonConfiguration, + runnerOptions?: any +): TaskHasher { + if (daemonClient.enabled()) { + return new DaemonBasedTaskHasher(daemonClient, runnerOptions); + } else { + const { fileMap, allWorkspaceFiles, rustReferences } = getFileMap(); + return new InProcessTaskHasher( + fileMap?.projectFileMap, + allWorkspaceFiles, + projectGraph, + nxJson, + rustReferences, + runnerOptions + ); + } +} diff --git a/packages/nx/src/hasher/task-hasher.ts b/packages/nx/src/hasher/task-hasher.ts index ca0377b3127b27..fdbb094860beaa 100644 --- a/packages/nx/src/hasher/task-hasher.ts +++ b/packages/nx/src/hasher/task-hasher.ts @@ -168,7 +168,7 @@ export class InProcessTaskHasher implements TaskHasher { this.projectGraph, { selectivelyHashTsConfig: - this.options.selectivelyHashTsConfig ?? false, + this.options?.selectivelyHashTsConfig ?? false, } ) : new NativeTaskHasherImpl( @@ -178,7 +178,7 @@ export class InProcessTaskHasher implements TaskHasher { this.externalRustReferences, { selectivelyHashTsConfig: - this.options.selectivelyHashTsConfig ?? false, + this.options?.selectivelyHashTsConfig ?? false, } ); } diff --git a/packages/nx/src/tasks-runner/run-command.ts b/packages/nx/src/tasks-runner/run-command.ts index f59fbc78dfe72d..8dc50bd64d8ef1 100644 --- a/packages/nx/src/tasks-runner/run-command.ts +++ b/packages/nx/src/tasks-runner/run-command.ts @@ -34,6 +34,7 @@ import { daemonClient } from '../daemon/client/client'; import { StoreRunInformationLifeCycle } from './life-cycles/store-run-information-life-cycle'; import { getFileMap } from '../project-graph/build-project-graph'; import { performance } from 'perf_hooks'; +import { createTaskHasher } from '../hasher/create-task-hasher'; async function getTerminalOutputLifeCycle( initiatingProject: string, @@ -233,20 +234,7 @@ export async function invokeTasksRunner({ const { tasksRunner, runnerOptions } = getRunner(nxArgs, nxJson); - let hasher: TaskHasher; - if (daemonClient.enabled()) { - hasher = new DaemonBasedTaskHasher(daemonClient, runnerOptions); - } else { - const { fileMap, allWorkspaceFiles, rustReferences } = getFileMap(); - hasher = new InProcessTaskHasher( - fileMap?.projectFileMap, - allWorkspaceFiles, - projectGraph, - nxJson, - rustReferences, - runnerOptions - ); - } + let hasher = createTaskHasher(projectGraph, nxJson, runnerOptions); // this is used for two reasons: to fetch all remote cache hits AND // to submit everything that is known in advance to Nx Cloud to run in