Nimblesite / Nimblesite/Shipwright

[SWR-SEC-DEPENDABOT-STAGING] Shipped template's clobber-merge sweep cannot work — GITHUB_TOKEN can never push .github/workflows/*

Open
#60 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
0
Forks
0
Avg merge
1m
Merged PRs (30d)
10

Description

templates/gh-actions/dependabot-automerge.yml and the [SWR-SEC-DEPENDABOT-STAGING] spec section both still describe the clobber-merge generation. That design cannot work, and the spec's own reference implementation has already moved off it.

The defect

The template sweeps with:

git merge -X theirs --no-edit "origin/${PR_HEAD}"
git push origin "HEAD:dependabot-upgrades"

and subscribes to both dependabot-upgrades and main.

Security updates are the only Dependabot PRs that reach main — GitHub ignores target-branch for them, which the spec correctly documents as fixed behaviour. But a security bump is branched off current main. Merging it into a staging branch that has drifted behind main drags main's intervening commits along, including .github/workflows/* edits.

GITHUB_TOKEN can never push workflow files. There is no permissions: key that grants the workflows scope — it is a GitHub App scope the Actions token does not have. So the push is rejected:

! [remote rejected] HEAD -> dependabot-upgrades (refusing to allow a GitHub App
  to create or update workflow `.github/workflows/ci.yml` without `workflows` permission)

The rejection is permanent, and the template retries it five times before failing. The staging branch drifts behind main by construction — that is what a staging branch does — so this transitions from working to permanently broken the first time a workflow file changes on main, and never recovers.

Observed impact in a repo running the shipped template

Nimblesite/NimblesiteAgenticPlatform, template generation agent-pmo:372ce7f. Identical failure on every main-based bump from 2026-07-22 to 2026-09-04 — six weeks, always the same rejection, never once surfaced, because a merge bot going red is silent.

The damage compounds well past PR noise:

Security PRs never retired 10
npm PR quota 5/5 — saturated at open-pull-requests-limit
uv PR quota 5/5 — saturated
Open Dependabot alerts 92 (56 HIGH)
Routine bumps stranded on staging 54 commits
Consolidation PRs ever opened 0

Because nothing is ever retired, both ecosystems pin at their PR cap and Dependabot stops opening new security PRs altogether. A direct dependency (GitPython) accumulated 17 HIGH advisories without ever getting a PR.

Two further defects in the same template

  1. No drain. The template flows bumps into staging and has nothing that flows them out. Nothing opens the dependabot-upgrades → main consolidation PR the spec relies on, so it depends entirely on a maintainer noticing. In the repo above, zero were opened in three months while 54 commits accumulated.

  2. The main base filter hangs a dead check on every human PR. The job can only be narrowed to Dependabot with a job-level if:, and an if:-skipped job still materialises as a check run with conclusion skipped. Subscribing to PRs against main therefore pins a permanently-skipped check onto every human PR forever — one that by construction can never run.

The fix already exists

Nimblesite/deslop runs agent-pmo:0b21609, which resolves all three:

  • Path-restricted sweep. Copy only the files the PR itself changed (diff against its merge-base with the PR base) onto the staging tip. Immune to staging drift, and clobber semantics survive with no merge machinery left to conflict. A bump that edits .github/workflows/* itself is squash-merged server-side, since the merge API is not a push.
  • Base filter dependabot-upgrades only, so the workflow is never instantiated for a human PR.
  • A drain step that opens the consolidation PR whenever staging is ahead and none is open, on a weekly schedule so it runs from the default branch's copy of the file.

Nimblesite/Basilisk — named in the spec as the reference implementation — is on 0b21609 too, but only partially: its dependabot.yml header still describes the clobber-merge behaviour, and its ci.yml still carries the Dependabot actor skip.

Suggested changes

  1. Replace templates/gh-actions/dependabot-automerge.yml with the 0b21609 generation.
  2. Rewrite the [SWR-SEC-DEPENDABOT-STAGING] bullet "The sweep clobber-merges, latest wins" — it currently prescribes the broken mechanism.
  3. Add the drain to the spec as a load-bearing part; it is currently absent, and "a consolidation PR that the maintainer opens periodically" is the part that does not happen on its own.
  4. Reconsider the "CI runs once, on the consolidation PR" bullet. With the base filter narrowed to staging, routine bumps never trigger a main workflow at all, so the github.actor == 'dependabot[bot]' skip saves nothing on them — it applies only to security bumps, making the vulnerability fix the single PR class that reaches main with no build, no test and no dependency review. deslop has removed those skips.
  5. Finish Basilisk's migration so the reference implementation matches the template.

Fix as applied to NAP: Nimblesite/NimblesiteAgenticPlatform#324

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with templates/gh-actions/dependabot-automerge.yml and the [SWR-SEC-DEPENDABOT-STAGING] spec section, then compare them with the 0b21609 generation in Nimblesite/deslop and Basilisk. Update the template, spec, and Basilisk reference so the path-restricted sweep, staging-only filter, drain, and CI behavior match the described fix.

Written by the indexing model from the issue text.

Assessment

Tech stack
git, github-actions
Domain
ci-cd, devops, documentation
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.