fix: report-job-failure cannot post from a node-only image, so it never posts at all #52

Closed
opened 2026-09-06 00:39:56 +00:00 by ahmad · 0 comments
Owner

Context

report-job-failure builds its comment body with jq and refuses to post without it:

command -v jq >/dev/null || {
  echo "jq is not installed, so the failure comment cannot be built." >&2
  exit 0
}

jq is absent from node:22-bookworm, and this repository already knows that. release.yml says so in a comment, and works around it deliberately:

# the commits the bump was derived from. node, not jq (jq is absent,
# and hand-built JSON breaks on a quote or newline in a subject).

Every reporter consumer on this fleet runs in exactly that image:

amtronics/platform-actions  validate  node:22-bookworm   uses ./report-job-failure   <-- migrated in #38
ahmad/portfolio             validate  node:22-bookworm   inline node reporter
ahmad/imamah                checks    node:22-bookworm   inline node reporter
ahmad/expiro                validate  node:22-bookworm   inline node reporter
ahmad/expiro                image     (host runner)      inline node reporter

So the action exits 0 and posts nothing wherever it is used, and the exit code is success — the failure mode the guard was written to make legible is invisible in practice.

This is not hypothetical: this repository's own validate has been a silent no-op since #38 merged. It has not been exercised because every pr.yml run since has passed, which is why nobody noticed. The inline reporters it was migrated away from use node, not curl+jq, precisely because of this image — the migration replaced a working reporter with one that cannot run there.

It also blocks #46: migrating the remaining three consumers as written would silently disable all of them. #46's third acceptance criterion exists to force this decision, and this is the decision it was asking for.

Scope

  • In: report-job-failure building its JSON body without requiring jq — preferring jq when present and falling back to node, the same choice release.yml already makes in this image.
  • In: keeping the curl guard as it is; curl is present in these images.
  • Out: changing the comment's wording or the tail-capture half.
  • Out: installing jq into consumer job containers, which fixes one consumer at a time and leaves the action unusable on a node-only image.

Acceptance criteria

  • Given a job on an image with node but no jq, when the action runs after a failure, then the comment is posted.
  • Given a job on an image with jq, when the action runs, then the comment is posted and its body is identical to the jq-built one.
  • Given a tail containing a double quote, a backslash and a newline, when the body is built by either path, then the posted comment renders that tail intact.
  • Given an image with neither jq nor node, when the action runs, then it says so and exits 0 without failing the job, as today.
  • Given the fix is released, when amtronics/platform-actions' own validate fails, then a comment appears on the pull request.

Notes

The third criterion is the one that matters: jq --arg was chosen over hand-built JSON because quoting is where this breaks, and any fallback has to be held to the same standard. node -e with JSON.stringify is the same guarantee, which is why release.yml uses it.

### Context `report-job-failure` builds its comment body with `jq` and refuses to post without it: ```sh command -v jq >/dev/null || { echo "jq is not installed, so the failure comment cannot be built." >&2 exit 0 } ``` **`jq` is absent from `node:22-bookworm`**, and this repository already knows that. `release.yml` says so in a comment, and works around it deliberately: ``` # the commits the bump was derived from. node, not jq (jq is absent, # and hand-built JSON breaks on a quote or newline in a subject). ``` Every reporter consumer on this fleet runs in exactly that image: ``` amtronics/platform-actions validate node:22-bookworm uses ./report-job-failure <-- migrated in #38 ahmad/portfolio validate node:22-bookworm inline node reporter ahmad/imamah checks node:22-bookworm inline node reporter ahmad/expiro validate node:22-bookworm inline node reporter ahmad/expiro image (host runner) inline node reporter ``` So the action exits 0 and posts nothing wherever it is used, and the exit code is success — the failure mode the guard was written to make legible is invisible in practice. **This is not hypothetical: this repository's own `validate` has been a silent no-op since #38 merged.** It has not been exercised because every `pr.yml` run since has passed, which is why nobody noticed. The inline reporters it was migrated away from use `node`, not `curl`+`jq`, precisely because of this image — the migration replaced a working reporter with one that cannot run there. It also blocks #46: migrating the remaining three consumers as written would silently disable all of them. #46's third acceptance criterion exists to force this decision, and this is the decision it was asking for. ### Scope - In: `report-job-failure` building its JSON body without requiring `jq` — preferring `jq` when present and falling back to `node`, the same choice `release.yml` already makes in this image. - In: keeping the `curl` guard as it is; `curl` is present in these images. - Out: changing the comment's wording or the tail-capture half. - Out: installing `jq` into consumer job containers, which fixes one consumer at a time and leaves the action unusable on a node-only image. ### Acceptance criteria - [ ] Given a job on an image with `node` but no `jq`, when the action runs after a failure, then the comment is posted. - [ ] Given a job on an image with `jq`, when the action runs, then the comment is posted and its body is identical to the `jq`-built one. - [ ] Given a tail containing a double quote, a backslash and a newline, when the body is built by either path, then the posted comment renders that tail intact. - [ ] Given an image with neither `jq` nor `node`, when the action runs, then it says so and exits 0 without failing the job, as today. - [ ] Given the fix is released, when `amtronics/platform-actions`' own `validate` fails, then a comment appears on the pull request. ### Notes The third criterion is the one that matters: `jq --arg` was chosen over hand-built JSON because quoting is where this breaks, and any fallback has to be held to the same standard. `node -e` with `JSON.stringify` is the same guarantee, which is why `release.yml` uses it.
ahmad self-assigned this 2026-09-06 00:40:38 +00:00
ahmad 2026-09-06 01:34:24 +00:00
Sign in to join this conversation.
No description provided.