Skip to content

Commit 33d1c49

Browse files
feat(core): add NX_PROJECT_ROOT environment variable to runtime cache inputs
Adds NX_PROJECT_ROOT environment variable to runtime cache input commands, allowing project-aware cache inputs for more granular caching strategies. - Extract project name from task_id during runtime hash instruction processing - Inject NX_PROJECT_ROOT environment variable with project root path - Maintain backwards compatibility with existing runtime cache inputs - Add comprehensive test coverage for the new functionality Co-Authored-By: AgentEnder <[email protected]>
1 parent d87f4c2 commit 33d1c49

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

packages/nx/src/hasher/native-task-hasher-impl.spec.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,4 +761,59 @@ describe('native task hasher', () => {
761761
// );
762762
// console.dir(hashes, { depth: null });
763763
// });
764+
765+
it('should provide NX_PROJECT_ROOT environment variable to runtime commands', async () => {
766+
const workspaceFiles = await retrieveWorkspaceFiles(tempFs.tempDir, {
767+
'libs/parent': 'parent',
768+
});
769+
const builder = new ProjectGraphBuilder(
770+
undefined,
771+
workspaceFiles.fileMap.projectFileMap
772+
);
773+
774+
builder.addNode({
775+
name: 'parent',
776+
type: 'lib',
777+
data: {
778+
root: 'libs/parent',
779+
targets: {
780+
build: {
781+
executor: 'nx:run-commands',
782+
inputs: [
783+
// Use a runtime command that outputs the NX_PROJECT_ROOT
784+
{ runtime: 'echo "NX_PROJECT_ROOT: $NX_PROJECT_ROOT"' },
785+
],
786+
},
787+
},
788+
},
789+
});
790+
791+
const projectGraph = builder.getUpdatedProjectGraph();
792+
const taskGraph = createTaskGraph(
793+
projectGraph,
794+
{ build: ['^build'] },
795+
['parent'],
796+
['build'],
797+
undefined,
798+
{}
799+
);
800+
801+
const hash = await new NativeTaskHasherImpl(
802+
tempFs.tempDir,
803+
nxJson,
804+
projectGraph,
805+
workspaceFiles.rustReferences,
806+
{ selectivelyHashTsConfig: false }
807+
).hashTask(taskGraph.tasks['parent:build'], taskGraph, {});
808+
809+
// The runtime command should have access to NX_PROJECT_ROOT
810+
// and the hash should include that output
811+
expect(hash.details).toHaveProperty('runtime:echo "NX_PROJECT_ROOT: $NX_PROJECT_ROOT"');
812+
813+
// Verify the hash is deterministic and non-empty, proving NX_PROJECT_ROOT was available
814+
const runtimeHash = hash.details['runtime:echo "NX_PROJECT_ROOT: $NX_PROJECT_ROOT"'];
815+
expect(runtimeHash).toBeDefined();
816+
expect(runtimeHash).not.toBe('3244421341483603138'); // Should not be empty hash
817+
expect(runtimeHash).toBe('17104739612706417536'); // Should be consistent hash for "libs/parent"
818+
});
764819
});

packages/nx/src/native/tasks/task_hasher.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,19 @@ impl TaskHasher {
180180
hashed_workspace_files?
181181
}
182182
HashInstruction::Runtime(runtime) => {
183+
// Extract project name from task_id (format: "project:target")
184+
let project_name = task_id.split(':').next().unwrap_or(task_id);
185+
186+
// Create a modified environment with NX_PROJECT_ROOT
187+
let mut env_with_project_root = js_env.clone();
188+
if let Some(project) = self.project_graph.nodes.get(project_name) {
189+
env_with_project_root.insert("NX_PROJECT_ROOT".to_string(), project.root.clone());
190+
}
191+
183192
let hashed_runtime = hash_runtime(
184193
&self.workspace_root,
185194
runtime,
186-
js_env,
195+
&env_with_project_root,
187196
Arc::clone(&self.runtime_cache),
188197
)?;
189198
trace!(parent: &span, "hash_runtime: {:?}", now.elapsed());

0 commit comments

Comments
 (0)