Uh oh!
There was an error while loading. Please reload this page.
fix(eslint): standardize failure signaling and unsafe coercion patterns in setup/js - #47419
Conversation
…nt monster stream 3) Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
✅ Design Decision Gate 🏗️ completed the design decision gate check. No ADR enforcement needed: PR does not have the 'implementation' label and has ≤100 new lines of code in business logic directories (default_business_additions=0, file_count=18). |
✅ Test Quality Sentinel completed test quality analysis. No test files were added or modified in this PR. All 18 changed files are production code in actions/setup/js/ (ESLint fixes for standardized failure signaling and unsafe coercion patterns). Test Quality Sentinel skipped. |
✅ PR Code Quality Reviewer completed the code quality review. |
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
There was a problem hiding this comment.
Pull request overview
Standardizes ESLint-compliant error handling, numeric validation, and Git command execution in setup scripts.
Changes:
- Uses
core.setFailed()with explicit control transfer. - Replaces coercive
isNaN()checks withNumber.isNaN(). - Passes Git arguments separately to
exec.exec().
Show a summary per file
| File | Description |
|---|---|
actions/setup/js/update_project.cjs | Uses non-coercive number validation. |
actions/setup/js/update_discussion.cjs | Validates parsed discussion numbers safely. |
actions/setup/js/unified_timeline.cjs | Validates timestamps without coercion. |
actions/setup/js/temporary_id.cjs | Validates resolved issue numbers safely. |
actions/setup/js/templatable.cjs | Updates integer parsing validation. |
actions/setup/js/start_mcp_gateway.cjs | Standardizes gateway failure signaling. |
actions/setup/js/reply_to_pr_review_comment.cjs | Updates comment ID validation. |
actions/setup/js/push_to_pull_request_branch.cjs | Uses argument-array Git execution. |
actions/setup/js/push_experiment_state.cjs | Stops after terminal push failure. |
actions/setup/js/pr_helpers.cjs | Updates pull request number validation. |
actions/setup/js/parse_claude_log.cjs | Updates maximum-turn parsing validation. |
actions/setup/js/mcp_cli_bridge.cjs | Standardizes bridge failure signaling. |
actions/setup/js/mark_pull_request_as_ready_for_review.cjs | Updates pull request number validation. |
actions/setup/js/log_parser_bootstrap.cjs | Stops processing after parser failures. |
actions/setup/js/lock-issue.cjs | Adds control transfer after lock failure. |
actions/setup/js/expired_entity_cleanup_helpers.cjs | Updates date validity checking. |
actions/setup/js/create_pull_request.cjs | Uses argument-array Git execution. |
actions/setup/js/convert_gateway_config_copilot.cjs | Standardizes conversion failure signaling. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 18/18 changed files
- Comments generated: 1
- Review effort level: Medium
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Review: fix(eslint): standardize failure signaling and unsafe coercion patterns in setup/js
The changes are well-structured and consistent across all 18 files. The isNaN → Number.isNaN, require-return-after-core-setfailed, and no-exec-interpolated-command fixes look correct throughout.
One blocking issue found:assertNotSymlink in start_mcp_gateway.cjs was only half-fixed — core.error() was replaced with core.setFailed(), but process.exit(1) was not replaced with return. See inline comment.
🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 33.9 AIC · ⌖ 5.26 AIC · ⊞ 5K
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /diagnosing-bugs — requesting changes on 3 correctness issues found.
📋 Key Themes & Highlights
Issues Found
- Dead code in
lock-issue.cjs:core.setOutput("locked", "false")is now unreachable after the addedreturn. - Missed
process.exitinassertNotSymlink: The symlink-attack guard instart_mcp_gateway.cjsstill callsprocess.exit(1)and was not converted — and a simplereturnthere won't work since it's a sync helper; it needs to throw or return a sentinel. - Redundant
process.exitCode = 1inmcp_cli_bridge.cjs: Three error paths set bothprocess.exitCode = 1andcore.setFailed(). The former is inconsistent with every other converted path in this PR.
Positive Highlights
- ✅ Thorough
isNaN → Number.isNaNsweep across 11 files — no misses found. - ✅
exec.execinterpolation fixes are correct and improve injection safety. - ✅ The multi-error diagnostic-block pattern (keeping
core.error()for context beforecore.setFailed()) is consistent and intentional. - ✅
returninsertions aftercore.setFailed()are correctly placed in all asyncmain()functions.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 48.9 AIC · ⌖ 4.83 AIC · ⊞ 6.7K
Comment /matt to run again
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
REQUEST_CHANGES — Two correctness bugs introduced by the conversion, one security-path inconsistency, and one child-process lifecycle risk.
### Blocking issues (4)
lock-issue.cjs— deadsetOutputcall (high): Thereturnadded beforecore.setOutput("locked", "false")makes that call unreachable. Downstream steps reading thelockedoutput will get an empty string instead of"false"in the error path.start_mcp_gateway.cjs—assertNotSymlinkhalf-converted (high):core.setFailed()was added butprocess.exit(1)was left. This is the symlink-attack guard. The function is now inconsistent — removeprocess.exit(1)and ensure callers handle the void return, or add a comment marking it intentional.start_mcp_gateway.cjs— orphaned gateway process on late-stage failures (medium): Post-spawn failure paths nowreturninstead ofprocess.exit(1).returndoes not kill child processes. Needs verification that cleanup logic covers all new early-return paths.mcp_cli_bridge.cjs—global.coreunguarded in fatal catch (medium): Ifmain()throws beforeglobal.coreis assigned,core.setFailed()itself throws and the job gets no failure annotation. Add a null guard with stderr fallback.
🔎 Code quality review by PR Code Quality Reviewer · sonnet46 87 AIC · ⌖ 5.11 AIC · ⊞ 5.7K
Comment /review to run again
Comments that could not be inline-anchored
actions/setup/js/lock-issue.cjs:89
Dead code: core.setOutput("locked", "false") is unreachable — the return inserted on the previous line means this output is never set in the error path, so downstream steps reading locked will see an empty value instead of "false".
<details>
<summary>💡 Suggested fix</summary>
Move the setOutput call before setFailed()/return:
}catch(error){consterrorMessage=getErrorMessage(error);core.error(`Failed to lock issue: ${errorMessage}`);core.setOutpu…</details><details><summary>actions/setup/js/start_mcp_gateway.cjs:283</summary>**Incompletefixin`assertNotSymlink()`: `process.exit(1)`isstillpresentafter `core.setFailed()`**, leaving this security-critical path half-converted and fragile.<details><summary>💡 Details</summary>The original `core.error()` was replaced with `core.setFailed()`, but `process.exit(1)` was left in place. Currently only the hard-exit prevents execution from continuing past the symlink check. If a future refactor removes `process.exit(1)` (to align with the rest of the PR), execution …</details><details><summary>actions/setup/js/start_mcp_gateway.cjs:452</summary>**`setFailed()` + `return` after child process has already been spawned may orphan the gateway process** — unlike `process.exit(1)`, returning from `main()` does not kill spawned child processes.<details><summary>💡 Details</summary>Multiple late-stage failure paths in `start_mcp_gateway.cjs` now use `return` instead of `process.exit(1)`. These failures occur *after* the gateway child process was already spawned (e.g., failures to read output config, gateway returning error payload, MCP se…</details><details><summary>actions/setup/js/mcp_cli_bridge.cjs:1432</summary>**`global.core` in the fatal `.catch()` handler may be `undefined`** — if `main()` throws before `global.core` is assigned, `core.setFailed()` itself throws and the Actions step gets no failure annotation.<details><summary>💡 Suggested fix</summary>```jsmain().catch(err=>{constcore=global.core;constmessage=errinstanceofError ? err.stack||err.message : String(err);if(core){core.setFailed(`mcp_cli_bridge fatal: ${message}`);}else{process.stderr.write(`m…</details>gh-aw-bot
commented
Jul 23, 2026
@copilot please run the Unresolved review feedback:
Failed checks:
|
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Addressed in |
gh-aw-bot
commented
Jul 23, 2026
@copilot please run the Unresolved review feedback:
The PR already has follow-up replies on these items; please leave a short status update for anything still open.
|
The three linked |
| core.error("ERROR: Configuration is missing required 'gateway' section"); | ||
| core.error("Per MCP Gateway Specification v1.0.0 section 4.1.3, the gateway section is required"); | ||
| process.exit(1); | ||
| core.setFailed("ERROR: Configuration is missing required 'gateway' section"); |
There was a problem hiding this comment.
@copilot add setFailed implementation in shim.cjs
There was a problem hiding this comment.
actions/setup/js/shim.cjs already has core.setFailed() on the current head via 1a1b36c (pulled in by merge 34a0668). I verified the shim sets process.exitCode = 1 and reran npx vitest run start_mcp_gateway.test.cjs successfully, so no additional code change was needed here.
pelikhan
commented
Jul 23, 2026
@copilot ensure all the shims are added in shim.cjs so that node.js run still work |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed in |
pelikhan
commented
Jul 23, 2026
gh-aw-bot
commented
Jul 23, 2026
@copilot please run the Unresolved review feedback:
The older github-actions threads on this PR already have follow-up replies; please resolve any that are fully addressed and leave a short status update for anything still open.
|
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
No further code changes were needed on the current head. |
🎉 This pull request is included in a new release. Release: |
Three ESLint rule categories were firing across 18 files in
actions/setup/js: improper failure signaling (core.error()+ process exit instead ofcore.setFailed()), missing control transfer aftercore.setFailed(), coerciveisNaN(), and interpolatedexeccommand strings.Failure signaling (
no-core-error-then-process-exit,no-core-error-then-process-exitcode)Replace
core.error()+process.exit(1)/process.exitCode = 1withcore.setFailed():Multi-error diagnostic blocks retain preceding
core.error()calls for log output;core.setFailed()is inserted as the last statement before the control transfer.Affected:
convert_gateway_config_copilot.cjs,start_mcp_gateway.cjs,mcp_cli_bridge.cjsControl transfer after
core.setFailed()(require-return-after-core-setfailed)Added explicit
returnaftercore.setFailed()calls that had no control transfer, preventing execution fallthrough:Affected:
lock-issue.cjs,log_parser_bootstrap.cjs,push_experiment_state.cjs,mcp_cli_bridge.cjsGlobal
isNaN()→Number.isNaN()(prefer-number-isnan)Affected: 11 files including
expired_entity_cleanup_helpers.cjs,pr_helpers.cjs,unified_timeline.cjs, and others.Interpolated exec commands (
no-exec-interpolated-command)Convert template-literal exec commands to static command + args array form:
Affected:
create_pull_request.cjs(7 instances),push_to_pull_request_branch.cjs(3 instances)Run URL: https://github.com/github/gh-aw/actions/runs/29984131428