Skip to content

Add workflow to auto-regenerate lockfile for Dependabot PRs#312

Open
umair-ably wants to merge 2 commits intomainfrom
fix/dependabot-lockfile-regeneration
Open

Add workflow to auto-regenerate lockfile for Dependabot PRs#312
umair-ably wants to merge 2 commits intomainfrom
fix/dependabot-lockfile-regeneration

Conversation

@umair-ably
Copy link
Copy Markdown
Collaborator

Summary

How it works

  1. Triggers on any PR to main from dependabot[bot]
  2. Checks out the Dependabot branch
  3. Runs pnpm install --no-frozen-lockfile to regenerate the lockfile
  4. If pnpm-lock.yaml changed, commits and pushes it back
  5. If lockfile is already up to date, does nothing (idempotent)

Test plan

Dependabot sometimes fails to update the lockfile in pnpm workspace
setups, causing CI to fail with frozen-lockfile errors (see PR #308).

This workflow detects Dependabot PRs, runs pnpm install to regenerate
the lockfile, and commits it back. Uses a GitHub App token so that
subsequent CI runs are triggered automatically.
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cli-web-cli Ready Ready Preview, Comment Apr 10, 2026 10:48am

Request Review

@claude-code-ably-assistant
Copy link
Copy Markdown

Walkthrough

This PR adds a GitHub Actions workflow that automatically regenerates pnpm-lock.yaml when Dependabot opens a PR that fails to update the lockfile — a known issue in pnpm workspaces (as seen in #308). The workflow uses a GitHub App token so that the fix commit triggers downstream CI runs, making the process fully automated.

Changes

Area Files Summary
Config .github/workflows/dependabot-lockfile.yml New workflow: triggers on pull_request_target for Dependabot PRs to main, runs pnpm install --no-frozen-lockfile, commits and pushes lockfile if changed

Review Notes

  • pull_request_target security: This event runs with base-repo write permissions even for fork PRs. The if: github.actor == 'dependabot[bot]' guard is the key security control — reviewers should confirm this is sufficient given Dependabot is a GitHub-managed bot, not an arbitrary actor.
  • Secrets dependency: The workflow requires CLAUDE_APP_ID and CLAUDE_APP_PRIVATE_KEY to be present in repo secrets. If these are missing or renamed, the workflow fails silently at token generation rather than at checkout.
  • No lockfile coverage for non-lockfile changes: The workflow only commits pnpm-lock.yaml. If Dependabot's PR also has other unstaged changes (unlikely but possible with workspace hoisting), those would be ignored.
  • Idempotency: The git diff --exit-code pnpm-lock.yaml && exit 0 pattern is intentional — if the lockfile is already correct, the step exits cleanly. This is correct but non-obvious at first read.
  • No automated test coverage: By nature, this workflow can only be validated by triggering a real Dependabot PR. The test plan in the PR body covers this with a manual @dependabot recreate step.

@claude-code-ably-assistant
Copy link
Copy Markdown

Review Summary

This PR adds a GitHub Actions workflow to auto-regenerate pnpm-lock.yaml for Dependabot PRs. The logic is sound and the implementation is clean. One real security concern is worth discussing.


.github/workflows/dependabot-lockfile.yml

Security — pull_request_target + head ref checkout

This combines two things that GitHub explicitly warns about:

on:
  pull_request_target:     # runs with write permissions + secrets
    branches: [main]
...
      - name: Checkout Dependabot branch
        uses: actions/checkout@v6
        with:
          ref: ${{ github.event.pull_request.head.ref }}   # checks out PR code
...
      - name: Regenerate lockfile
        run: pnpm install --no-frozen-lockfile              # executes code from PR

pull_request_target runs in the context of the base repo with access to secrets. Checking out the PR head and then running pnpm install means lifecycle scripts (preinstall, postinstall, etc.) from packages in the Dependabot PR execute with access to those secrets and the CLAUDE_APP_PRIVATE_KEY.

The mitigations in place:

  • if: github.actor == 'dependabot[bot]' on the job — the whole job doesn't run unless GitHub's own bot opened the PR. This cannot be spoofed by regular users.
  • Only pnpm-lock.yaml is staged and committed back (git add pnpm-lock.yaml), so lifecycle scripts can't smuggle in other file changes.
  • Dependabot doesn't add arbitrary lifecycle scripts to package.json.

Residual risk: A compromised upstream package (supply chain attack) that adds a malicious postinstall script could exfiltrate CLAUDE_APP_PRIVATE_KEY during the pnpm install step. This is the inherent tension in auto-regenerating lockfiles — you're deliberately running code from packages you haven't reviewed yet.

This residual risk exists regardless of workflow design (you can't regenerate a lockfile without running install). But it's worth being aware of, especially since the secrets being exposed (CLAUDE_APP_PRIVATE_KEY) are high-value credentials. Consider whether the GitHub App's permissions are scoped as narrowly as possible to limit blast radius if a key were ever leaked this way.


No other issues. The actor guard is correctly placed at the job level (not just a step condition), the commit is scoped to only pnpm-lock.yaml, and the action versions are consistent with the rest of the repo. The workflow will be a no-op for non-Dependabot PRs.

Lockfile resolution doesn't require running package scripts. Skipping
them prevents a compromised upstream package from exfiltrating secrets
available in the workflow environment.
@umair-ably
Copy link
Copy Markdown
Collaborator Author

@claude addressed your residual risk concern by adding --ignore-scripts... we only want the lockfile to regen

Copy link
Copy Markdown

@claude-code-ably-assistant claude-code-ably-assistant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Add workflow to auto-regenerate lockfile for Dependabot PRs

One real concern, one item to verify.


1. pull_request_target + PR branch checkout — security risk worth noting

The combination of pull_request_target (runs with secrets access in the base-branch context) and checking out the PR branch (ref: ${{ github.event.pull_request.head.ref }}) is a well-documented attack vector. If an attacker could trigger this workflow with a malicious package.json, they could potentially exfiltrate secrets.

In practice, the risk here is low because:

  • The if: github.actor == 'dependabot[bot]' guard limits execution to GitHub's own bot
  • --ignore-scripts prevents lifecycle scripts from running, which is the main exploit vector

But it's worth knowing this is non-zero risk if the Dependabot account or GitHub infrastructure were ever compromised. An alternative pattern that eliminates the exposure is a two-workflow design: a pull_request workflow that generates the new lockfile as an artifact, then a workflow_run workflow that commits it — but that's significantly more complex. Given the actor guard + --ignore-scripts, this is an acceptable tradeoff.


2. GitHub App permissions — verify before merging

The workflow reuses CLAUDE_APP_ID / CLAUDE_APP_PRIVATE_KEY (the Claude review app). This app needs Contents: write on the repo to push commits back to Dependabot branches. The PR description says this is intentional, but worth confirming the app actually has that permission configured. If it doesn't, the git push step will fail and the workflow will error out without regenerating the lockfile.


Everything else looks correct

  • Action versions (checkout@v6, setup-node@v6, create-github-app-token@v3) are consistent with the rest of the repo's workflows
  • pnpm install --no-frozen-lockfile --ignore-scripts is the right incantation
  • git add pnpm-lock.yaml (not git add .) — only commits the lockfile
  • git diff --exit-code pnpm-lock.yaml && exit 0 idempotency check is correct
  • timeout-minutes: 10 guards against runaway jobs

@umair-ably
Copy link
Copy Markdown
Collaborator Author

@claude for point 2... i've raised a ticket so we create a minimally scoped github app to handle this instead of reusing the claude token... can you approve this as is for now? or should something else be addressed first?

@umair-ably
Copy link
Copy Markdown
Collaborator Author

Copy link
Copy Markdown

@claude-code-ably-assistant claude-code-ably-assistant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Add workflow to auto-regenerate lockfile for Dependabot PRs

No CLI source changes — command conventions don't apply here.

Summary

File Status Issues
.github/workflows/dependabot-lockfile.yml 1 concern GitHub App permissions may be insufficient

pull_request_target + branch checkout — acceptable with mitigations

The classic security footgun: pull_request_target runs with secrets access, and this workflow checks out untrusted PR code. The mitigations are in place and correct:

  • if: github.actor == 'dependabot[bot]' limits execution to GitHub's own bot (unimpersonatable by external actors)
  • --ignore-scripts prevents lifecycle hooks from running — the main exploit vector

This is the recommended approach for Dependabot lockfile workflows. The risk is acceptable.


GitHub App permissions — verify before merging

The CLAUDE_APP_ID / CLAUDE_APP_PRIVATE_KEY secrets are already used in pr-overview.yml and claude-review.yml, but those workflows only need PR comment permissions (pull-requests: write). Pushing commits to a branch requires Contents: write on the installation.

If the Claude GitHub App was only granted PR/review permissions when it was set up, the git push step will fail with a 403. Worth confirming the app installation includes repository contents write access before merging — otherwise the workflow will error on every Dependabot PR without regenerating anything.


Everything else looks correct

  • Action versions (checkout@v6, setup-node@v6, pnpm/action-setup@v5) are consistent with all other workflows in this repo
  • git add pnpm-lock.yaml (not git add .) — only the lockfile gets committed
  • git diff --exit-code pnpm-lock.yaml && exit 0 idempotency guard is correct
  • timeout-minutes: 10 is sensible for a lockfile regeneration job

@umair-ably umair-ably requested a review from AndyTWF April 10, 2026 11:20
id: generate-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.CLAUDE_APP_ID }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use these, it'll look like it's coming from Claude - which it isn't, I would probably look for the generic Ably CI account and use that

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants