Skip to content

fix(core): handle run-commands targets with no commands#31364

Merged
FrozenPandaz merged 1 commit intomasterfrom
fix-no-commands
May 29, 2025
Merged

fix(core): handle run-commands targets with no commands#31364
FrozenPandaz merged 1 commit intomasterfrom
fix-no-commands

Conversation

@FrozenPandaz
Copy link
Copy Markdown
Contributor

Current Behavior

Nx hangs when here is a run-commands target with no commands.

Expected Behavior

Nx does not hang when there is a run-commands target with no commands.

Related Issue(s)

Fixes #31345

@FrozenPandaz FrozenPandaz requested a review from a team as a code owner May 28, 2025 01:12
@FrozenPandaz FrozenPandaz requested a review from xiongemi May 28, 2025 01:12
@vercel
Copy link
Copy Markdown

vercel Bot commented May 28, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Skipped Deployment
Name Status Preview Updated (UTC)
nx-dev ⬜️ Ignored (Inspect) Visit Preview May 28, 2025 7:04pm

@FrozenPandaz FrozenPandaz requested a review from Copilot May 28, 2025 01:12
@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud Bot commented May 28, 2025

View your CI Pipeline Execution ↗ for commit 622b68c.

Command Status Duration Result
nx affected --targets=lint,test,build,e2e,e2e-c... ✅ Succeeded 45m 41s View ↗
nx run-many -t check-imports check-commit check... ✅ Succeeded 20s View ↗
nx-cloud record -- nx-cloud conformance:check ✅ Succeeded 2s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 3s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded 2s View ↗
nx documentation ✅ Succeeded 1m 53s View ↗

☁️ Nx Cloud last updated this comment at 2025-05-28 19:54:35 UTC

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes an issue where Nx hangs when a run-commands target has no commands by simulating a successful process exit.

  • Modify NoopChildProcess to simulate immediate task completion
  • Update runCommands to return NoopChildProcess for empty commands arrays
  • Add a test case to validate that an empty commands array returns a successful result

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
packages/nx/src/tasks-runner/running-tasks/noop-child-process.ts Introduces exitCallbacks and outputCallbacks; simulates immediate exit in the constructor
packages/nx/src/executors/run-commands/run-commands.impl.ts Returns NoopChildProcess when commands array is empty
packages/nx/src/executors/run-commands/run-commands.impl.spec.ts Adds test for handling empty commands arrays

Comment on lines +10 to +12
for (const cb of this.exitCallbacks) {
cb(this.results.code, this.results.terminalOutput);
}
Copy link

Copilot AI May 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'exitCallbacks' and 'outputCallbacks' arrays are defined and iterated over in the constructor but are never updated when callbacks are registered via onExit or onOutput. Consider either removing these arrays or updating the implementation to store and later invoke registered callbacks consistently.

Suggested change
for (const cb of this.exitCallbacks) {
cb(this.results.code, this.results.terminalOutput);
}
setTimeout(() => {
for (const cb of this.exitCallbacks) {
cb(this.results.code, this.results.terminalOutput);
}
}, 0);

Copilot uses AI. Check for mistakes.
},
context
);
expect(result).toEqual(expect.objectContaining({ success: true }));
Copy link

Copilot AI May 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test expects a 'success' property on the result, but NoopChildProcess does not explicitly provide this. Consider adding a getter for 'success' (e.g., returning true when results.code equals 0) to align the implementation with the test expectations.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +13
constructor(private results: { code: number; terminalOutput: string }) {
// Call exit callbacks asynchronously to simulate task completion
for (const cb of this.exitCallbacks) {
cb(this.results.code, this.results.terminalOutput);
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constructor is attempting to iterate through exitCallbacks which is initialized as an empty array, so no callbacks will be executed at this point. Since callbacks are registered through the onExit method after construction, consider modifying onExit to either:

  1. Execute the callback immediately if called after construction:
onExit(cb: (code: number, terminalOutput: string) => void): void {
  this.exitCallbacks.push(cb);
  // Already completed, call immediately
  cb(this.results.code, this.results.terminalOutput);
}
  1. Or use setTimeout to ensure callbacks are executed asynchronously:
constructor(private results: { code: number; terminalOutput: string }) {
  setTimeout(() => {
    for (const cb of this.exitCallbacks) {
      cb(this.results.code, this.results.terminalOutput);
    }
  }, 0);
}

This will ensure proper simulation of an asynchronous process completion.

Suggested change
constructor(private results: { code: number; terminalOutput: string }) {
// Call exit callbacks asynchronously to simulate task completion
for (const cb of this.exitCallbacks) {
cb(this.results.code, this.results.terminalOutput);
}
}
constructor(private results: { code: number; terminalOutput: string }) {
// Defer callback execution to next event loop tick to simulate async task completion
setTimeout(() => {
for (const cb of this.exitCallbacks) {
cb(this.results.code, this.results.terminalOutput);
}
}, 0);
}

Spotted by Diamond

Is this helpful? React 👍 or 👎 to let us know.

@FrozenPandaz FrozenPandaz force-pushed the fix-no-commands branch 2 times, most recently from 80bc137 to ce49dc6 Compare May 28, 2025 01:16
@FrozenPandaz FrozenPandaz requested a review from Copilot May 28, 2025 01:21
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR ensures that run-commands targets with an empty commands array return immediately instead of hanging.

  • Adds a NoopChildProcess implementation that emits a zero exit code and empty output.
  • Introduces an early return in runCommands when there are no commands.
  • Adds a unit test to verify the empty-commands behavior.

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
packages/nx/src/tasks-runner/running-tasks/noop-child-process.ts Expanded NoopChildProcess with onExit/onOutput APIs
packages/nx/src/executors/run-commands/run-commands.impl.ts Added early-return using NoopChildProcess for empty lists
packages/nx/src/executors/run-commands/run-commands.impl.spec.ts Added test case for handling an empty commands array
Comments suppressed due to low confidence (1)

packages/nx/src/tasks-runner/running-tasks/noop-child-process.ts:18

  • The NoopChildProcess class doesn’t expose success or terminalOutput properties, but the new test asserts them directly. Add getters to forward this.results.code === 0 as success and this.results.terminalOutput as terminalOutput.
}

@nrwl nrwl deleted a comment from Copilot AI May 28, 2025
@FrozenPandaz FrozenPandaz merged commit d7106f5 into master May 29, 2025
6 checks passed
@FrozenPandaz FrozenPandaz deleted the fix-no-commands branch May 29, 2025 13:48
FrozenPandaz added a commit that referenced this pull request Jun 3, 2025
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

Nx hangs when here is a `run-commands` target with no commands.

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

Nx does not hang when there is a `run-commands` target with no commands.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #31345

(cherry picked from commit d7106f5)
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 4, 2025

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jun 4, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

When using nx:run-commands with "commands": [] (empty) TUI hangs

3 participants