Skip to content

ci: automate the lock-file fix that keeps breaking Dependabot's nuget PRs - #130

Merged
bgard68 merged 1 commit into
mainfrom
ci/dependabot-lockfix
Aug 17, 2026
Merged

ci: automate the lock-file fix that keeps breaking Dependabot's nuget PRs#130
bgard68 merged 1 commit into
mainfrom
ci/dependabot-lockfix

Conversation

@bgard68

@bgard68 bgard68 commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Dependabot regenerates packages.lock.json only for the projects whose .csproj it edits. Every project consuming the bumped package transitively keeps its old lock file, and locked-mode restore fails the whole solution with NU1004 — the PR is born red, and rebasing cannot help. Grouping (#126) turned five such PRs into one; this closes the loop on that one. It broke three workflows across two branches on 2026-08-17 alone, and the fix each time was the same mechanical dotnet restore --force-evaluate by hand.

What's added

dependabot-lockfix.yml — fires on any failed API / CodeQL / container run of a dependabot/nuget/** branch, regenerates the lock files, pushes the fix to the branch, and re-dispatches every required check on the fixed commit. Zero secrets, zero PATs. The three GitHub platform constraints that dictate its shape are documented in the file:

  1. Runs whose actor is dependabot[bot] get read-only tokens → workflow_run is the one trigger that still gets write.
  2. GITHUB_TOKEN pushes trigger no workflows → the fixed commit would sit checkless forever.
  3. workflow_dispatch is the documented exception to (2) → the last step re-dispatches all required checks, all of which already declare it.

It lives on main only because workflow_run only fires from the default branch's copy; it serves dapper-based Dependabot branches from here. Also manually dispatchable against any branch.

api-ci-cd.yml — gains a deploy input (default true) and the deploy gate becomes

if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && inputs.deploy)

Until now any manual dispatch deployed, so an automated checks-only rerun of a Dependabot branch would have shipped that branch to the App Service. Default true keeps the operator flow identical: Run workflow on main with the box ticked deploys exactly as before.

Edge behavior

  • Dependabot branches forked before this commit lack the deploy input; a deploy=false dispatch against them fails 422 Unexpected inputs — a loud no-op rather than a deploy. Self-heals as branches re-fork off the updated base.
  • If a re-dispatched run fails for a real reason, the fixer fires again, finds nothing to regenerate, and stops. No loop.
  • npm (frontend) and github-actions bumps are excluded: single root lock file handled correctly, and no lock file at all, respectively.

Verification

Both files parse; the gate expression is push-safe (inputs is empty on push events, so main still auto-deploys via the first clause). The full loop gets its first live test on the next grouped nuget PR — until then the manual dispatch path covers any occurrence.

🤖 Generated with Claude Code

… PRs

Dependabot regenerates packages.lock.json only for the projects whose .csproj
it edits; every project consuming the bumped package transitively keeps its old
lock file, and locked-mode restore fails the solution with NU1004. Grouping
(#126) turned five such pull requests into one - this closes the loop on that
one. The failure is not hypothetical: it broke three workflows across two
branches on 2026-08-17 alone, and the fix each time was the same mechanical
`dotnet restore --force-evaluate` done by hand.

dependabot-lockfix.yml (default branch only, by workflow_run's rules) fires on
any failed API/CodeQL/container run of a dependabot/nuget/** branch, regenerates
the lock files, pushes the fix, and re-dispatches every required check on the
fixed commit. The three GitHub constraints that dictate the shape are documented
in the file: dependabot-actor runs get read-only tokens (hence workflow_run),
GITHUB_TOKEN pushes trigger no workflows (hence explicit re-dispatch), and
workflow_dispatch is the documented exception that makes the re-dispatch land.

api-ci-cd.yml gains a `deploy` input (default true) and the deploy gate becomes

  github.ref == 'refs/heads/main' ||
    (github.event_name == 'workflow_dispatch' && inputs.deploy)

Until now ANY manual dispatch deployed, so an automated checks-only rerun of a
Dependabot branch would have shipped that branch to the App Service. Default
true keeps the existing operator flow: Run workflow on main with the box ticked
deploys exactly as before. Dependabot branches forked before this commit reject
a deploy=false dispatch with 422 Unexpected inputs - a loud no-op rather than a
deploy, gone as soon as branches re-fork off the updated base.

Verified: both files parse; the gate expression is push-safe (inputs is empty
on push events, so main still auto-deploys via the first clause). The full loop
gets its first live test on the next grouped nuget PR; until then the workflow
is also manually dispatchable against any branch.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@bgard68
bgard68 merged commit 34d91b5 into main Aug 17, 2026
10 checks passed
@bgard68
bgard68 deleted the ci/dependabot-lockfix branch August 17, 2026 18:57
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