fix(webhooks): stop reporting a cancelled CI run as a failure #433

Merged
gmackie merged 1 commit from fix/cancelled-run-commit-status into main 2026-08-25 05:30:33 +00:00
Owner

forgegraph/ci published failure for any workflow run that did not pass:

state: status === "passed" ? "success" : "failure"

mapConclusion folds Forgejo's cancelled and skipped into "cancelled", so a run that was stopped — and therefore reached no verdict — stamped the commit red.

Two statements further down, the attestation engine already handled this correctly and emitted nothing for the same conclusion. The handler contradicted itself inside one function.

How it surfaced

gmackie/bob #161, 2026-08-24: a docs-only PR adding a single HTML file showed forgegraph/ci red while the real CI / ci job was still running. Fetching that run's logs returned log file not found — because a cancelled run produces none.

It cost a diagnosis and a re-run. More importantly, the commit status is what humans and the merge flow read, so a false red there is worse than no update at all.

Approach

Extracted the decision into a pure commitStatusForConclusion rather than adding an inline guard. The rule is what was wrong, and testing it through the handler would have needed a ~60-line database mock harness to assert one branch.

An unrecognised conclusion still reports failure — an unknown terminal state is a real signal, unlike a run that was deliberately stopped.

Verification

Tests cover pass, genuine failure, cancelled, skipped, and unknown/null. Proved they actually catch the regression by restoring the old expression and watching the cancelled and skipped cases fail.

Webhook suite 43 passed across 8 files; @forgegraph/web typecheck clean.

`forgegraph/ci` published `failure` for any workflow run that did not pass: ```ts state: status === "passed" ? "success" : "failure" ``` `mapConclusion` folds Forgejo's `cancelled` **and `skipped`** into `"cancelled"`, so a run that was stopped — and therefore reached no verdict — stamped the commit red. Two statements further down, the attestation engine already handled this correctly and emitted nothing for the same conclusion. The handler contradicted itself inside one function. ## How it surfaced gmackie/bob #161, 2026-08-24: a **docs-only PR adding a single HTML file** showed `forgegraph/ci` red while the real `CI / ci` job was still running. Fetching that run's logs returned `log file not found` — because a cancelled run produces none. It cost a diagnosis and a re-run. More importantly, the commit status is what humans and the merge flow read, so a false red there is worse than no update at all. ## Approach Extracted the decision into a pure `commitStatusForConclusion` rather than adding an inline guard. The *rule* is what was wrong, and testing it through the handler would have needed a ~60-line database mock harness to assert one branch. An unrecognised conclusion still reports failure — an unknown terminal state is a real signal, unlike a run that was deliberately stopped. ## Verification Tests cover pass, genuine failure, cancelled, skipped, and unknown/null. Proved they actually catch the regression by restoring the old expression and watching the cancelled and skipped cases fail. Webhook suite 43 passed across 8 files; `@forgegraph/web` typecheck clean.
fix(webhooks): stop reporting a cancelled CI run as a failure
All checks were successful
CI / gitleaks (pull_request) Successful in 6s
CI / storybook (pull_request) Successful in 1m23s
forgegraph/ci CI passed
CI / ci (pull_request) Successful in 9m58s
87f6fd0921
`forgegraph/ci` published `failure` for any workflow run that did not pass:

    state: status === "passed" ? "success" : "failure"

`mapConclusion` folds Forgejo's "cancelled" AND "skipped" into "cancelled",
so a run that was stopped — and therefore reached no verdict — stamped the
commit red. Two statements further down, the attestation engine already
handled this correctly and emitted nothing for the same conclusion, so the
handler contradicted itself within one function.

Observed on gmackie/bob #161 (2026-08-24): a docs-only PR adding a single
HTML file showed `forgegraph/ci` red while the real `CI / ci` job was still
running, and fetching that run's logs returned "log file not found" —
because a cancelled run produces none. It cost a diagnosis and a re-run,
and the commit status is what humans and the merge flow read, so a false
red there is worse than no update at all.

Extracted the decision into `commitStatusForConclusion` rather than adding
an inline guard: the rule is what was wrong, and testing it through the
handler would have needed a sixty-line database mock harness to assert one
branch.

Tests cover pass, genuine failure, cancelled, skipped, and unknown/null
conclusions. An unrecognised conclusion still reports failure — an unknown
terminal state is a real signal, unlike a run that was stopped. Verified by
restoring the old expression and watching the cancelled and skipped cases
fail.

Webhook suite 43 passed across 8 files; web typecheck clean.
Author
Owner

Preview environment is live: https://pr-433-forgegraph.forgegraf.com

Deployed 87f6fd09 with the beta stage's environment. It redeploys on every push and is destroyed when this PR closes.

Preview environment is live: https://pr-433-forgegraph.forgegraf.com Deployed `87f6fd09` with the beta stage's environment. It redeploys on every push and is destroyed when this PR closes.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
gmackie/ForgeGraph!433
No description provided.