Skip to content

ci: stop security patches from stranding on main - #117

Merged
MansiVisuals merged 2 commits into
devfrom
ci/security-patch-routing
Sep 8, 2026
Merged

MansiVisuals merged 2 commits into
devfrom
ci/security-patch-routing

Conversation

@MansiVisuals

Copy link
Copy Markdown
Owner

Follow-up to the v1.3.5 release failure (#115). That run failed because browserslist ≤4.28.6 tripped the Dockerfile's npm audit --audit-level=high gate on both build architectures. The fix (#116) already existed — it had been open against main for a day.

Why it went unnoticed

dependabot.yml sets target-branch: dev, which applies to version updates only. Security updates ignore it and are raised against the default branch, main. Three things followed from that:

  1. They were never tested. docker-integration-tests.yml ran on pull_request: branches: [dev], so Bump browserslist from 4.28.4 to 4.28.9 in the npm_and_yarn group across 1 directory #116 got CodeQL and nothing else — not the 41-test suite that would have flagged the lockfile.
  2. They were never merged. dependabot-auto-merge.yml also only triggers on dev, so a main-targeted security PR waits on a human indefinitely.
  3. They never reached dev. The release train cuts from dev, so it kept building the vulnerable lockfile even after main was patched.

The npm-security group in dependabot.yml implied advisories arrive on dev, grouped and prefixed. They never did — #116 came through as npm_and_yarn, ungrouped, with no deps: prefix.

Changes

  • docker-integration-tests.yml — run on PRs to main as well as dev, so security patches face the same gate everything else does.
  • weekly-security-release.yml — the check audit fails instead of warning. It already warned on 2026-09-07; the Dockerfile then hard-failed on the same advisory three jobs later, but by then publish had merged dev and pushed the version bump. Failing in check leaves main untouched, so the re-run after the patch lands is clean.
  • sync-main-to-dev.yml (new) — opens an issue when main is ahead of dev.
  • dependabot.yml — drop the dead npm-security group, document where security PRs actually go.

Two things deliberately not done

Auto-merge for main-targeted security PRs. main currently has no branch protection, so gh pr merge --auto would merge on creation without waiting for the suite — the opposite of the intent. Worth enabling once main requires Test Summary; happy to do that separately.

A sync PR instead of an issue. A PR opened with GITHUB_TOKEN does not trigger pull_request workflows, so Test Summary would never run and the PR would block on dev's required check forever. There is no PAT in the repo. An issue can't get stuck.

Timing

Targeting dev per convention, so these reach main at the v1.3.6 release. The audit gate and sync workflow run from main's copy, so they take effect from the release after that.

Dependabot security updates ignore target-branch and land on main, where
nothing tested them and nothing carried them back to dev. A browserslist
advisory sat there while the release train kept building the vulnerable
lockfile, and the audit gate only fired inside the Docker build, after
publish had already pushed v1.3.5's commits to main.

- test PRs to main, not just dev, so security patches are gated
- fail the release audit in check, before publish mutates main
- open an issue when dev falls behind main
- drop the security-updates group that never applied
Counting commits fired after every release: the version bump lands on main
only, by design, so dev is behind every single week and the issue would have
been weekly noise for a healthy state.

Filter the release train's own commits out by author instead, so it reports
only patches that reached main and never made it back to dev. Checked against
both v1.3.4 and v1.3.5: silent after each release, and it fires on exactly
the browserslist merge that stranded. Closes the issue once dev catches up,
so a stale one cannot mask the next.
@MansiVisuals

Copy link
Copy Markdown
Owner Author

Reviewed this against the actual history and found the sync workflow was wrong, now fixed in 4a37924.

As first written it reported how far dev was behind main. That fires after every release: the version bump and changelog land on main only — dev deliberately never carries VERSION — so main was 4 commits ahead after v1.3.4 and 9 after v1.3.5. It would have filed a "dev is behind" issue every week for a state that is supposed to be true.

It now reports what is stranded instead, filtering out the release train's own commits by author (github-actions[bot]), so only patches that reached main and never came back are flagged. Verified by replaying the real history, taking dev's SHA from each release merge's second parent:

scenario expected result
after v1.3.4 release (dev 4963896 → main a95dc95) silent silent
after v1.3.5 release (dev 1418ad2 → main 6e7b961) silent silent
#116 stranded on main (dev 1418ad2 → main 333d730) fires fires, on exactly that commit
today, dev synced (dev eee7c71 → main 333d730) silent silent

It also closes its own issue once dev catches up, so a stale one cannot mask the next strand.

One thing worth being straight about on the rest of the PR: running the integration suite on PRs to main would not have prevented this failure. #116 was never merged, not never tested. That change is defence-in-depth and a prerequisite for auto-merging on main later. The audit-gate change is the one that pays for itself today.

@MansiVisuals
MansiVisuals merged commit 7ee5057 into dev Sep 8, 2026
8 checks passed
@MansiVisuals
MansiVisuals deleted the ci/security-patch-routing branch September 8, 2026 11:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant