trails/.github/workflows/dependabot-dedupe.yml
Ullrich Schäfer da56eb2c19
Stop over-claiming the persist-credentials mechanism
The previous comment claimed `git push` reads the token via a git
credential helper wired into $RUNNER_TEMP. I don't actually know that's
how it works end to end — only that checkout stashes the token there
and that subsequent git ops in the same workspace end up authenticating
as the PAT. Describe just the observable contract, not an unverified
internal path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:58:26 +02:00

72 lines
2.8 KiB
YAML

name: Dependabot dedupe
# Dependabot opens a PR after a bump, but `pnpm install` alone doesn't
# dedupe peer copies of packages (e.g. two versions of i18next, each
# holding their own singleton state). That split caused a hydration
# mismatch on #272 until a manual `pnpm dedupe` collapsed them.
#
# This workflow fires on every dependabot PR, runs `pnpm dedupe`, and
# pushes the resulting lockfile update back to the PR branch so the
# subsequent CI run tests the deduped tree.
#
# Requires `DEPENDABOT_DEDUPE_TOKEN` — a repo secret holding a
# fine-grained PAT (or GitHub App token) with `contents: write` on
# this repo. The default `GITHUB_TOKEN` would work for the push but
# would NOT trigger a subsequent CI run on that push (GitHub's
# anti-loop safeguard), leaving the PR with stale green CI from
# before the dedupe commit. A PAT re-triggers CI so the reviewer
# sees test results for the state they'd actually be merging.
on:
pull_request:
branches: [main]
permissions:
contents: write
jobs:
dedupe:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- name: Require DEPENDABOT_DEDUPE_TOKEN
env:
TOKEN: ${{ secrets.DEPENDABOT_DEDUPE_TOKEN }}
run: |
if [ -z "$TOKEN" ]; then
echo "::error::DEPENDABOT_DEDUPE_TOKEN is not set. This workflow"
echo "::error::requires a PAT so the dedupe commit re-triggers CI."
echo "::error::See .github/workflows/dependabot-dedupe.yml header."
exit 1
fi
- uses: actions/checkout@v6
with:
ref: ${{ github.head_ref }}
# With `persist-credentials: true`, this PAT is stashed by the
# action (under $RUNNER_TEMP in recent versions) and made
# available to subsequent git operations in this workspace —
# so the later `git push` authenticates as the PAT, which is
# what gets CI to re-trigger on the dedupe commit. `true` is
# the checkout default; pinned explicitly here because it's
# load-bearing for this workflow.
token: ${{ secrets.DEPENDABOT_DEDUPE_TOKEN }}
persist-credentials: true
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v6
with:
node-version: 24
cache: pnpm
- run: pnpm install --frozen-lockfile=false
- run: pnpm dedupe
- name: Commit dedupe changes
run: |
if [ -n "$(git status --porcelain pnpm-lock.yaml)" ]; then
git config user.name "dependabot[bot]"
git config user.email "49699333+dependabot[bot]@users.noreply.github.com"
git add pnpm-lock.yaml
git commit -m "pnpm dedupe"
git push
echo "Deduped lockfile pushed."
else
echo "Lockfile already deduped."
fi