Skip to content

eslint-factory: no-core-error-then-process-exit only checks adjacent statements — misses intervening statements (FN) #46993

Description

@github-actions

Rule

no-core-error-then-process-exit (eslint-factory/src/rules/no-core-error-then-process-exit.ts)

The rule flags core.error(msg); process.exit(nonzero) and steers toward core.setFailed(msg). It only inspects immediately adjacent statements (current = stmts[i], next = stmts[i+1] in checkStatements, rule lines ~139-143), so any statement between the core.error(...) and the process.exit(nonzero) defeats detection:

core.error("fatal: could not load config");
core.summary.addRaw("fatal");   // any intervening statement
process.exit(1);                 // NOT flagged today

The anti-pattern is unchanged by an intervening log/summary line — it is still core.error used to fail instead of core.setFailed, followed by a hard process.exit(nonzero).

Contrast with the sibling rule

require-return-after-core-setfailed performs cross-statement / nested continuation analysis. no-core-error-then-process-exit is adjacency-only, which is inconsistent and under-covers.

Existing tests

Only adjacent pairs are covered (core.error("..."); process.exit(1);). No test exercises an intervening statement.

Proposed refinement

Within the same statement list (block / switch-case / program body), after a core.error(...) statement, scan forward for a process.exit(nonzero) before any of:

  • a core.setFailed(...) call (that already fixes the failure signalling — do not flag), or
  • a control-transfer statement (return / throw / break / continue), or
  • a nested container that changes flow (be conservative — only scan the flat sibling list to avoid FPs).

Keep the existing autofix/suggestion behavior for the directly-adjacent case; the widened detection can report without a suggestion when the pair is non-adjacent (or extend the fixer to remove the process.exit and rewrite the core.error).

Acceptance criteria

  • core.error("x"); core.info("y"); process.exit(1); is flagged.
  • core.error("x"); core.setFailed("x"); process.exit(1); is not flagged (setFailed already present).
  • core.error("x"); process.exit(0); remains valid (clean exit).
  • All existing valid/invalid adjacency tests remain unchanged.
  • npm test passes.

Grounding

No live sites in actions/setup/js (no process.exit / core.error in non-test .cjs). This is regression-guard hardening. Confidence: medium; the scan-forward variant is a small, well-scoped change but must guard against FPs (hence the intervening-setFailed and control-transfer stops above).

Generated by 🤖 ESLint Refiner · 455.7 AIC · ⌖ 10.8 AIC · ⊞ 4.6K ·

  • expires on Jul 27, 2026, 10:19 PM UTC-08:00

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions