Skip to content

Give the lock-file chore a button, and a failure that names it - #61

Merged
ivanvyd merged 2 commits into
mainfrom
chore/lockfile-refresh-workflow
Aug 14, 2026
Merged

Give the lock-file chore a button, and a failure that names it#61
ivanvyd merged 2 commits into
mainfrom
chore/lockfile-refresh-workflow

Conversation

@ivanvyd

@ivanvyd ivanvyd commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Dependabot bumps failed repeatedly this week for the same reason, and each was fixed by hand.

The constraint

Dependabot edits Directory.Packages.props but cannot rewrite packages.lock.json — the CentralTransitive entries have to be resolved by NuGet, not pattern-matched. So every NuGet bump arrives with lock files naming the old versions and dies at dotnet restore --locked-mode before anything builds:

error NU1004: Mistmatch between the requestedVersion of a lock file dependency marked as
CentralTransitive and the version specified in the central package management file.

What this adds

  • Refresh lock files — a workflow_dispatch job. Give it a branch; it runs --force-evaluate, proves the result with --locked-mode and a Release build before committing, and commits only **/packages.lock.json by name. contents: write is scoped to that single job, not the workflow.
  • A restore failure that names its own fix. NU1004 does not mention lock files needing regeneration, let alone how. CI now says which workflow to run and on which branch.
  • The constraint documented beside the nuget ecosystem in dependabot.yml.

Why a button and not an automatic push

This was the first instinct and it does not work. A push made with GITHUB_TOKEN does not re-trigger workflows — by design, to prevent loops. An auto-commit bot would push the fix and leave the required checks pinned to the superseded commit: one stall traded for another.

Making it automatic requires a PAT or a GitHub App private key. These repositories store no such credential deliberately. Adding a long-lived write credential to automate a dependency chore is the wrong trade, so the human keeps the write and gets a button.

Verified

Shipped and exercised on LakeWright.NET first: the workflow ran green end to end against two live Dependabot branches, and correctly declined to commit when the lock files already matched.

ivanvyd and others added 2 commits August 14, 2026 04:26
`Testcontainers` 4.13.0 resolves `SSH.NET` 2025.1.0, which is GHSA-q939-rpr3-3284,
high severity: ScpClient's recursive download writes wherever a malicious server's
filenames point. Every restore has been reporting it as NU1903, on both target
frameworks. It is a test-only path and this repository does not treat warnings as
errors, so nothing was failing -- it was just being printed and ignored.

Patched in 2026.0.0, and 4.13.0 is Testcontainers' own latest release, so there is
nothing upstream to wait for.

Raised by referencing it directly from Healthie.Tests.Unit rather than by turning
on CentralPackageTransitivePinningEnabled. That switch pins one version of every
transitive package across the solution, which collides with the per-target-framework
Microsoft.Extensions.* versions this file deliberately keeps apart: enabling it
fails restore with 34 NU1109 downgrade errors. Verified both ways round.

`dotnet restore --locked-mode` and `dotnet build -c Release` now finish with no
warnings at all, where they previously printed two.
Dependabot edits Directory.Packages.props but cannot rewrite packages.lock.json:
the CentralTransitive entries have to be resolved by NuGet rather than
pattern-matched. So every NuGet bump lands with stale lock files and dies at
`dotnet restore --locked-mode` with NU1004, before anything is built.

Three changes, none of which give a bot write access:

- `Refresh lock files`, a workflow_dispatch job that regenerates the lock files
  on a named branch, proves the result with `--locked-mode` and a Release build,
  and commits only `**/packages.lock.json`. `contents: write` is scoped to that
  one job.
- CI restore is named and, on failure, says which workflow to run and on which
  branch. NU1004 does not mention the fix itself.
- The constraint is written beside the nuget ecosystem in dependabot.yml.

Deliberately a button rather than an automatic push on every Dependabot PR: a
push made with GITHUB_TOKEN does not re-trigger workflows, so an automatic
version would commit the fix and leave the required checks pinned to the
superseded commit. Making it automatic needs a PAT or GitHub App key, which
these repositories avoid by design.

Verified on LakeWright.NET: green end to end against two live Dependabot
branches, and it correctly declined to commit when the locks already matched.
@ivanvyd
ivanvyd merged commit 37e0ca3 into main Aug 14, 2026
7 of 8 checks passed
@ivanvyd
ivanvyd deleted the chore/lockfile-refresh-workflow branch August 14, 2026 04:27
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