Skip to content

Conversation

@fengmk2
Copy link
Member

@fengmk2 fengmk2 commented Sep 27, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Improved reliability of inter-process messaging across cluster forks, child processes, and test-runner environments.
    • Clarified runtime-specific log messages for better diagnostics.
    • Maintains fallback behavior and warnings when no messaging channel is available.
  • Chores

    • CI: Added Node.js 24 to the test matrix.
    • Release workflow: Updated permissions, switched to an NPM release flow, and simplified token handling.

@fengmk2 fengmk2 requested a review from Copilot September 27, 2025 14:07
@coderabbitai
Copy link

coderabbitai bot commented Sep 27, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds Node.js v24 to the CI test matrix, updates release workflow permissions and switches to an npm-release workflow, and refactors IPC send logic in src/index.ts to branch explicitly for cluster forks, child processes, and Vitest workers while preserving fallback and warnings.

Changes

Cohort / File(s) Summary of Changes
CI matrix update
.github/workflows/nodejs.yml
Added Node.js v24 to the test matrix.
Release workflow adjustments
.github/workflows/release.yml
Added explicit permissions (contents, deployments, issues, pull-requests, id-token) with write access. Switched job to use npm-release.yml@master and renamed job to "NPM Release". Removed NPM_TOKEN secret mapping; retained GIT_TOKEN.
IPC send path refactor
src/index.ts
Imported node:cluster and reworked send logic to detect runtime: handle cluster forks via child.process?.connectedchild.send; child processes via child.connectedchild.send; Vitest workers when VITEST and VITEST_WORKER_ID present → emit sendmessage-to-self via setImmediate(child.emit(...)) and return. Added debug logs for contexts and preserved fallback send/warning when no channel exists.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller
  participant Sender as MessageSender
  participant Child as Child/Worker
  note over Sender,Child: Route message by runtime context

  Caller->>Sender: send(message, child)
  alt Cluster fork (child.process?.connected)
    Sender->>Child: child.send(message)
    note right of Child: Logged as cluster fork (cluster.isWorker)
  else Child process (child.connected)
    Sender->>Child: child.send(message)
    note right of Child: Logged as child process
  else Vitest worker (env VITEST & VITEST_WORKER_ID)
    Sender-)Child: setImmediate(child.emit('sendmessage-to-self', message))
    note right of Child: Vitest self-dispatch, then return
  else No channel
    Sender-->>Caller: warn("no channel available")
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I tap my paws on CI logs, hop-two-four,
Permissions pruned, releases soar.
Forks go send, and children too—
Vitest whispers, loop-back queue.
Carrots committed, pipelines green. 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the main feature added—support for the Vitest worker process— which aligns with the core changes in src/index.ts, and it remains concise and clear without extraneous details.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch support-vitest

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dcd4dcf and 107d83a.

📒 Files selected for processing (1)
  • src/index.ts (2 hunks)
🔇 Additional comments (1)
src/index.ts (1)

71-75: Restore the standard 'message' emission for Vitest workers.

As previously flagged, switching the Vitest path to emit 'sendmessage-to-self' breaks every existing process.on('message', …) listener—including the ones this helper exists to support—so Vitest workers still never receive the payload. We must keep emitting the canonical 'message' event (or add symmetrical listeners elsewhere) to avoid this regression.

-    if (process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID) {
-      debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit sendmessage-to-self: %j',
-        process.env.VITEST_WORKER_ID, message);
-      // use `sendmessage-to-self` event to send message to self, avoid vitest worker use the `message` event
-      return setImmediate(child.emit.bind(child, 'sendmessage-to-self', message));
+    if (process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID) {
+      debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit message: %j',
+        process.env.VITEST_WORKER_ID, message);
+      return setImmediate(child.emit.bind(child, 'message', message));
     }

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

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 adds support for Vitest worker processes by detecting the Vitest environment and using event emission instead of the standard IPC send method. It also updates the CI configuration to include Node.js 24 testing and modernizes the release workflow.

  • Add Vitest worker process detection and handling using environment variables
  • Update CI to test against Node.js 24 and modernize release workflow
  • Restructure child process communication logic for better separation of concerns

Reviewed Changes

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

File Description
src/index.ts Add Vitest worker process detection and emit-based message handling
.github/workflows/release.yml Update release workflow permissions and use npm-release action
.github/workflows/nodejs.yml Add Node.js 24 to test matrix

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

src/index.ts Outdated
if (process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID) {
debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit message: %j',
process.env.VITEST_WORKER_ID, message);
return setImmediate(child.emit.bind(child, 'message', message));
Copy link

Copilot AI Sep 27, 2025

Choose a reason for hiding this comment

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

The setImmediate call doesn't return a meaningful value. Since other branches return the result of child.send!(), this should either return a Promise or consistent value, or the function's return type should be updated to accommodate both synchronous and asynchronous returns.

Copilot uses AI. Check for mistakes.
uses: node-modules/github-actions/.github/workflows/npm-release.yml@master
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
Copy link

Copilot AI Sep 27, 2025

Choose a reason for hiding this comment

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

The NPM_TOKEN secret was removed but may still be required by the npm-release workflow. Verify that the new workflow doesn't need NPM authentication or ensure the token is passed through a different mechanism.

Suggested change
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Copilot uses AI. Check for mistakes.
@codecov
Copy link

codecov bot commented Sep 27, 2025

Codecov Report

❌ Patch coverage is 73.68421% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.04%. Comparing base (34ad0d0) to head (107d83a).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/index.ts 73.68% 5 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (34ad0d0) and HEAD (107d83a). Click for more details.

HEAD has 5 uploads less than BASE
Flag BASE (34ad0d0) HEAD (107d83a)
15 10
Additional details and impacted files
@@            Coverage Diff             @@
##           master       #8      +/-   ##
==========================================
- Coverage   97.22%   92.04%   -5.18%     
==========================================
  Files           1        1              
  Lines          72       88      +16     
  Branches       16       20       +4     
==========================================
+ Hits           70       81      +11     
- Misses          2        7       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gemini-code-assist
Copy link

Summary of Changes

Hello @fengmk2, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the message sending utility to properly interact with Vitest worker processes. It introduces a specialized communication method for these workers, ensuring that messages are delivered correctly within a Vitest testing environment, thereby improving compatibility and functionality.

Highlights

  • Vitest Worker Process Support: Implemented specific logic to correctly handle message sending to child processes that are identified as Vitest workers.
  • Message Emission for Vitest: For Vitest worker processes, messages are now emitted using child.emit('message', message) via setImmediate instead of the standard child.send() method.
  • Refined Process Type Detection: The message sending function now more explicitly distinguishes between cluster.fork() processes, childprocess.fork() processes, and vitest worker processes to apply the appropriate communication method.
Ignored Files
  • Ignored by pattern: .github/workflows/** (2)
    • .github/workflows/nodejs.yml
    • .github/workflows/release.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for vitest worker processes by detecting them via environment variables and using emit for messaging. The implementation refactors the process-sending logic, separating cluster.fork() and child_process.fork() cases, which improves code clarity and debuggability. The changes are logical and well-implemented. I've provided one suggestion to further enhance readability by extracting a condition into a named variable.

Comment on lines 64 to 68
if (process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID) {
debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit message: %j',
process.env.VITEST_WORKER_ID, message);
return setImmediate(child.emit.bind(child, 'message', message));
}

Choose a reason for hiding this comment

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

medium

To improve readability, consider extracting the condition for detecting a vitest worker into a named constant. This makes the code's intent more explicit and the if statement cleaner.

Suggested change
if (process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID) {
debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit message: %j',
process.env.VITEST_WORKER_ID, message);
return setImmediate(child.emit.bind(child, 'message', message));
}
const isVitestWorker = process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID;
if (isVitestWorker) {
debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit message: %j',
process.env.VITEST_WORKER_ID, message);
return setImmediate(child.emit.bind(child, 'message', message));
}

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 06c422d and 6d43f95.

📒 Files selected for processing (3)
  • .github/workflows/nodejs.yml (1 hunks)
  • .github/workflows/release.yml (1 hunks)
  • src/index.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Node.js / Test (macos-latest, 18)
  • GitHub Check: Node.js / Test (windows-latest, 18.19.0)
  • GitHub Check: Node.js / Test (windows-latest, 24)
🔇 Additional comments (1)
.github/workflows/release.yml (1)

17-18: Restore the NPM token secret mapping.

Switching to npm-release.yml still requires an NPM_TOKEN; removing it will leave the reusable workflow without credentials and the publish job will fail once it tries to hit npm. Please keep passing NPM_TOKEN alongside GIT_TOKEN.

     uses: node-modules/github-actions/.github/workflows/npm-release.yml@master
     secrets:
       GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
+      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Comment on lines 63 to 70
if (child.connected) {
if (process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID) {
debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit sendmessage-to-self: %j',
process.env.VITEST_WORKER_ID, message);
return setImmediate(child.emit.bind(child, 'sendmessage-to-self', message));
}
debug('child is childprocess.fork() process, send: %j', message);
return child.send!(message);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Emit the standard message event in the Vitest branch.

All other same-process fallbacks emit 'message' so existing process.on('message') handlers fire. Switching this branch to 'sendmessage-to-self' means no listener will see the payload, so Vitest workers never receive the message—regressing the very scenario we’re trying to support. Keep emitting 'message' (or add matching listeners elsewhere).

-    if (process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID) {
-      debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit sendmessage-to-self: %j',
-        process.env.VITEST_WORKER_ID, message);
-      return setImmediate(child.emit.bind(child, 'sendmessage-to-self', message));
+    if (process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID) {
+      debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit message: %j',
+        process.env.VITEST_WORKER_ID, message);
+      return setImmediate(child.emit.bind(child, 'message', message));
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (child.connected) {
if (process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID) {
debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit sendmessage-to-self: %j',
process.env.VITEST_WORKER_ID, message);
return setImmediate(child.emit.bind(child, 'sendmessage-to-self', message));
}
debug('child is childprocess.fork() process, send: %j', message);
return child.send!(message);
if (child.connected) {
if (process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID) {
debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit message: %j',
process.env.VITEST_WORKER_ID, message);
return setImmediate(child.emit.bind(child, 'message', message));
}
debug('child is childprocess.fork() process, send: %j', message);
return child.send!(message);
🤖 Prompt for AI Agents
In src/index.ts around lines 63 to 70, the Vitest branch emits a nonstandard
'sendmessage-to-self' event which prevents existing process.on('message')
handlers from receiving the payload; change the emitted event to the standard
'message' so Vitest worker processes get the same same-process fallback as other
branches (i.e., call setImmediate(child.emit.bind(child, 'message', message))
while preserving the debug call).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/index.ts (1)

4-4: Use namespace import for cluster to avoid default-import pitfalls

Default import requires esModuleInterop. Safer to use a namespace import.

-import cluster from 'node:cluster';
+import * as cluster from 'node:cluster';
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d43f95 and dcd4dcf.

📒 Files selected for processing (1)
  • src/index.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Node.js / Test (macos-latest, 18.19.0)
  • GitHub Check: Node.js / Test (windows-latest, 18.19.0)
  • GitHub Check: Node.js / Test (windows-latest, 16)
  • GitHub Check: Node.js / Test (windows-latest, 24)
  • GitHub Check: Node.js / Test (windows-latest, 20)
🔇 Additional comments (2)
src/index.ts (2)

58-61: LGTM: correct handling for cluster.fork() workers

Checking child.process?.connected and delegating to child.send is appropriate here.


72-76: Emit the standard 'message' event for Vitest

Use 'message' to preserve existing process.on('message') handlers; the custom 'sendmessage-to-self' won’t be observed. This also aligns with other same-process fallbacks.

Run this to verify nothing depends on the custom event name:

#!/bin/bash
rg -n -C2 "sendmessage-to-self"

Comment on lines 64 to 70
if (child.connected) {
debug('child.connected: %s, cluster.isWorker: %s, cluster.isPrimary: %s',
child.connected, cluster.isWorker, cluster.isPrimary);
if (cluster.isWorker || cluster.isPrimary) {
debug('child is cluster.fork() process, send: %j', message);
return child.send!(message);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix always-true gate that makes the Vitest branch unreachable

cluster.isWorker || cluster.isPrimary is always true, so the early return prevents the Vitest handling below from ever running.

Apply this refactor to check Vitest first and fall back to childprocess send:

-  if (child.connected) {
-    debug('child.connected: %s, cluster.isWorker: %s, cluster.isPrimary: %s',
-      child.connected, cluster.isWorker, cluster.isPrimary);
-    if (cluster.isWorker || cluster.isPrimary) {
-      debug('child is cluster.fork() process, send: %j', message);
-      return child.send!(message);
-    }
-
-    if (process.env.VITEST === 'true' && process.env.VITEST_WORKER_ID) {
-      debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit sendmessage-to-self: %j',
-        process.env.VITEST_WORKER_ID, message);
-      return setImmediate(child.emit.bind(child, 'sendmessage-to-self', message));
-    }
-    debug('child is childprocess.fork() process, send: %j', message);
-    return child.send!(message);
-  }
+  if (child.connected) {
+    const isVitestWorker = process.env.VITEST === 'true' && !!process.env.VITEST_WORKER_ID;
+    if (isVitestWorker) {
+      debug('child is vitest worker process, VITEST_WORKER_ID: %s, emit message: %j',
+        process.env.VITEST_WORKER_ID, message);
+      return setImmediate(child.emit.bind(child, 'message', message));
+    }
+    debug('child is childprocess.fork() process, send: %j', message);
+    return child.send!(message);
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (child.connected) {
debug('child.connected: %s, cluster.isWorker: %s, cluster.isPrimary: %s',
child.connected, cluster.isWorker, cluster.isPrimary);
if (cluster.isWorker || cluster.isPrimary) {
debug('child is cluster.fork() process, send: %j', message);
return child.send!(message);
}
if (child.connected) {
const isVitestWorker = process.env.VITEST === 'true' && !!process.env.VITEST_WORKER_ID;
if (isVitestWorker) {
debug(
'child is vitest worker process, VITEST_WORKER_ID: %s, emit message: %j',
process.env.VITEST_WORKER_ID,
message
);
return setImmediate(child.emit.bind(child, 'message', message));
}
debug('child is childprocess.fork() process, send: %j', message);
return child.send!(message);
}
🤖 Prompt for AI Agents
In src/index.ts around lines 64-70, the current guard uses "cluster.isWorker ||
cluster.isPrimary" which is always true and causes the Vitest-specific branch
below to never execute; change the branching order to detect the Vitest worker
first (e.g., check process.env.VITEST_WORKER_ID or appropriate Vitest indicator)
and handle sending the message to the Vitest parent/process there, and only if
not running under Vitest fall back to treating the child as a cluster.fork()
process and call child.send; remove the always-true early-return so non-cluster
child processes still reach the correct Vitest or child-process send logic and
keep debug logging for both paths.

@fengmk2 fengmk2 closed this Sep 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants