Skip to content

Auto-fix Dependabot lockfiles so pnpm dedupe --check passes #2242

Description

@mjuarros

The install-and-test job in unit.yml runs pnpm dedupe --check after install. Dependabot regenerates pnpm-lock.yaml during updates but never runs pnpm dedupe — Dependabot has no post-update hook (known upstream limitation, e.g. dependabot/dependabot-core#9763). Group bump PRs therefore fail CI whenever the update leaves a dedupable transitive duplicate.

Example: #2236 failed with ERR_PNPM_DEDUPE_CHECK_ISSUES (lru-cache 11.5.2 -> 11.5.3 under path-scurry) and needed a manual dedupe commit (#2240). Every future Dependabot npm PR can hit this.

Recommended approach: dedupe main, don't push to PR branches

Feedback on the original proposal raised a fair concern: pushing from CI to the Dependabot branch requires a contents: write token in a job that executes untrusted dependency code (pnpm dedupe triggers pnpm install, which runs postinstall/prepare lifecycle scripts). A compromised package in the bump could abuse that token to push to any branch, including main.

So instead of auto-pushing to PR branches:

  1. Make --check non-blocking for Dependabot PRs in install-and-test — warn-only gated on github.actor == 'dependabot[bot]' (e.g. continue-on-error or || echo "::warning::"). Human PRs keep the strict check.
  2. Add a lockfile-maintenance job on main (post-merge or scheduled) that runs pnpm dedupe and opens — or updates — a "Dedupe lockfile" PR when drift exists. The write token then only ever operates on first-party code on main, never on PR code.

Trade-off: main tolerates temporary duplicate-dep drift between merges, but duplicated transitive versions are lockfile hygiene, not a correctness issue — and main converges back every time the maintenance PR lands.

Fallback if auto-push to the bot branch is preferred

If a job must push to the Dependabot branch, harden it:

  • pnpm dedupe --ignore-scripts — removes the lifecycle-script execution vector
  • Only commit if git status --porcelain shows pnpm-lock.yaml alone modified
  • git push origin HEAD:${{ github.event.pull_request.head.ref }} — push to exactly that ref
  • concurrency group per PR to avoid racing Dependabot force-pushes
  • Prefer a fine-grained token scoped to that branch over repo-wide contents: write

A middle option that avoids touching the bot's ref: CI opens a fix PR into the Dependabot branch (the manual flow used in #2240). CI only ever creates new branches; a human merges.

Alternatives considered

Related: #2236, #2240

Important

Internal only — this issue is maintained by the core team and is not accepting external contributions.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions