fix(dev-scripts): kill-backend no longer self-terminates dev:single (EVO-1609)#45
Merged
dpaes merged 1 commit intoJun 10, 2026
Conversation
…EVO-1609) `npm run dev:single` aborted with `Terminated` before boot: `kill-backend` ran `pkill -f 'node.*backend.*dist/main'`, and because `pkill -f` matches each process's FULL command line, the pattern text in pkill's own invoking `sh -c` argv self-matched and killed the parent npm process before the `&&` could chain into the Nest boot. (The old pattern also never matched a real backend — the prod cmdline is `node dist/main.js`, with no "backend" token.) Harden the pattern to `[n]ode .*dist/(src/)?main(\.js)?( |$)`: - the `[n]` class matches a real `node …` process but not the literal `[n]ode` in pkill's own argv, so it self-excludes without `$$`/`$PPID` bookkeeping; - evo-flow's `nest build` emits `dist/main.js` (tsc strips the src/ root); the optional `(src/)?` branch keeps the script portable to a `dist/src/main.js` layout (sibling evo-campaign scaffold / future monorepo) and matches both; - `main(\.js)?( |$)` blocks lookalikes like `dist/maintenance.js`/`main-old.js`; - `-u "$(id -u)"` scopes the blast radius to the current user's processes. Add a deterministic regression guard (`scripts/kill-backend-pattern.test.sh`, `npm run test:kill-backend`) that extracts the ERE from package.json and grep-asserts match/no-match including self-exclusion, wired into CI via `.github/workflows/dev-scripts-smoke.yml`. Document the step and its caveats in the README Run Modes section.
There was a problem hiding this comment.
Sorry @daniloleonecarneiro, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
dpaes
approved these changes
Jun 10, 2026
dpaes
left a comment
There was a problem hiding this comment.
✅ Approved — EVO-1609
Correct-repo twin fix — this addresses the earlier reject where the patch landed on evo-campaign instead of the evo-flow target named by the card.
AC coverage — all 3 met:
- AC1/AC2: the new
kill-backendpatternpkill -u "$(id -u)" -f '[n]ode .*dist/(src/)?main(\.js)?( |$)'self-excludes via the[n]char-class trick while still matching the realstart:prodsignature (node dist/main), docker, dumb-init, watch, and the altdist/src/main.jslayout. Lookalikes (maintenance.js,main-old.js,mainx,main.json) are correctly excluded by themain(\.js)?( |$)boundary anchor. I independently reproduced all 10 match/no-match cases plus the simulatedsh -cargv (old pattern self-matched → root cause; new pattern does not). - AC3: exceeds the either/or —
scripts/kill-backend-pattern.test.shguard + a dedicated path-filtered.github/workflows/dev-scripts-smoke.yml+ a READMEdev:singlerepro note.
Non-blocking (no action required):
- The guard is a deterministic grep-proxy (you can't safely spawn real
pkillin CI) — the correct choice, documented as such. [n]self-exclusion protects the immediate shell, not echoed copies (set -x, some CI log shells) — flagged honestly in the README.
Merging to develop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This is the fix on the real target named by EVO-1609 (
evo-flow/package.json). The buggykill-backendwas still live ondevelopandmainhere. A prior PR — evolution-foundation/evo-campaign#9 — fixed the same latent bug in theevo-campaignscaffold (a distinct standalone repo sharing thebackoffice@0.0.1base); that one stands on its own merit, but the card's title, Module, Suspected Area and all 3 ACs nameevo-flow, so this PR is what closes them.npm run dev:single(npm run kill-backend && RUN_MODE=single npm run dev) aborted withTerminatedbefore boot.kill-backendranpkill -f 'node.*backend.*dist/main'; sincepkill -fmatches each process's full command line, the pattern text in pkill's ownsh -cargv self-matched and killed the parent npm process before the&&could chain into the Nest boot. (The old pattern also never matched a real backend — the prod cmdline isnode dist/main.js, nobackendtoken.)Changes
package.json— hardenkill-backendtopkill -u "$(id -u)" -f '[n]ode .*dist/(src/)?main(\.js)?( |$)':[n]class matches a realnode …but not the literal[n]odein pkill's own argv → self-exclusion, no$$/$PPIDbookkeeping;nest buildemitsdist/main.js(tsc strips thesrc/root — verified against the repo'sdist/); the optional(src/)?keeps the script portable to adist/src/main.jslayout and matches both;main(\.js)?( |$)rejectsdist/maintenance.js/main-old.js;-u "$(id -u)"scopes the blast radius to the current user.scripts/kill-backend-pattern.test.sh+npm run test:kill-backend— deterministic, no-kill regression guard: extracts the ERE from package.json and grep-asserts match (prod/Docker/dev-watch + alt layout) and no-match (lookalikes + self-exclusion). Passes 10/10..github/workflows/dev-scripts-smoke.yml— runs the guard in CI on changes to package.json / the test script / the workflow.README.md— documentsdev:single, the[n]self-exclusion (immediate-shell only),-uscoping, the(src/)?rationale, the read-onlypgreppreview, and theEADDRINUSE+ Kafka caveats.Test plan
npm run test:kill-backend→ PASS (10/10) locally.dist/containsdist/main.js(nodist/src/), so the hardened pattern matches the actual runtime cmdline.dev-scripts-smokegreen on this PR.pgrep -af '[n]ode .*dist/(src/)?main(\.js)?( |$)'previews targets without killing;npm run dev:singlenow advances pastkill-backend(may still stop downstream at the out-of-scope Kafkajourney_trigger_kafka_queuetopic — EVO-1571 / EVO-1200).Notes
RUN_MODE=singleKafka-topic crash (EVO-1571 / EVO-1200) and general README/env sync (EVO-1229).