How the bump‑plugin‑shas Action Refreshes Plugin SHAs Without a GitHub App

The bump‑plugin‑shas workflow updates pinned plugin commit SHAs using only the built‑in GITHUB_TOKEN provided by GitHub Actions, eliminating the need for a custom GitHub App or additional secrets.

The bump-plugin-shas action in the anthropics/claude-plugins-community repository automates the maintenance of SHA pins for external Claude plugins. Instead of relying on a dedicated GitHub App installation, the workflow leverages the automatically injected GITHUB_TOKEN to validate upstream changes, create signed commits, and open pull requests. This approach simplifies authentication while maintaining security through GitHub’s native workflow permissions.

Native Token Authentication Model

The workflow operates entirely within GitHub’s standard permission model by declaring explicit write access in its permissions block.

In .github/workflows/bump-plugin-shas.yml, the job specifies:

permissions:
  contents: write
  pull-requests: write

These permissions allow the default token to read the repository, push new branches, create commits, and open pull requests. All API calls execute as github-actions[bot], ensuring commits are properly signed and satisfy organizational requirements such as required_signatures rules.

The custom action ./.github/actions/bump-plugin-shas (invoked at step 80) performs a create‑commit‑on‑branch operation authenticated via ${{ github.token }}. This produces verified commits without requiring external SSH keys or App-based authentication certificates.

The SHA Refresh Logic

The action follows a strict validation pipeline before updating any plugin pin.

Reading the manifest – The workflow parses .claude-plugin/marketplace.json to identify each plugin’s currently pinned SHA. It compares these values against the latest upstream HEAD commits.

Validation at HEAD – When an upstream repository has advanced past the pinned commit, the workflow executes claude plugin validate using the latest Claude CLI against the new SHA. This ensures plugin compatibility before the pin moves forward.

Isolated branch creation – For each plugin requiring an update, the action creates a dedicated branch named bump/<plugin-name>. This isolation prevents a single failing validation from blocking updates for other plugins.

Commit and PR generation – After writing the new SHA back to the marketplace manifest, the action commits the change to the bump branch and opens a corresponding pull request. The process repeats for up to 30 plugins per run (configurable via the max_bumps input).

The Freeze List Safety Mechanism

To prevent perpetual CI failures, the workflow maintains a static exclusion list at .github/freeze-shas.txt.

The bump process loads this file (steps 63‑74) and filters out any plugins listed within it. This allows maintainers to temporarily exclude broken plugins from the automatic bump cycle without modifying workflow code. The workflow skips these entries entirely, ensuring only healthy plugins receive update PRs.

Post‑Bump Validation Dispatch

After creating per-entry pull requests, the workflow triggers additional validation checks using the same native token.

In steps 90‑99, the workflow dispatches the validate-plugins.yml workflow against each new bump branch:

- name: Dispatch validate per per-entry PR
  if: steps.bump.outputs.pr-urls != '' && steps.bump.outputs.pr-urls != '[]'
  env:
    GH_TOKEN: ${{ github.token }}
    PR_URLS: ${{ steps.bump.outputs.pr-urls }}
  run: |
    set -euo pipefail
    jq -c '.[]' <<<"$PR_URLS" | while read -r entry; do
      branch=$(jq -r '.branch' <<<"$entry")
      name=$(jq -r '.name' <<<"$entry")
      gh workflow run validate-plugins.yml --ref "$branch"
    done

This dispatch uses GH_TOKEN: ${{ github.token }} to authenticate the gh workflow run command. The validation workflow must complete successfully before the bump PR can merge, ensuring that only verified plugin versions enter the marketplace.

Manual Triggering and Configuration

Maintainers can run the workflow on demand or schedule it via cron. The workflow supports two key inputs defined in .github/workflows/bump-plugin-shas.yml:

  • max_bumps – Limits the number of plugins updated in a single run (default: 30)
  • plugin – When specified, bumps only the named plugin, enabling targeted hotfixes
on:
  schedule:
    - cron: '23 7 * * *'      # daily run

  workflow_dispatch:
    inputs:
      max_bumps:
        description: "Cap on plugins bumped this run"
        default: '30'
      plugin:
        description: "Bump ONLY this plugin name"
        default: ''

The custom action accepts these inputs along with the freeze list:

- uses: ./.github/actions/bump-plugin-shas
  with:
    marketplace-path: .claude-plugin/marketplace.json
    max-bumps: ${{ inputs.max_bumps || '30' }}
    freeze-shas: ${{ steps.freeze.outputs.list }}
    only: ${{ inputs.plugin }}
    pr-mode: per-entry
    claude-cli-version: latest

Summary

  • No GitHub App required – The workflow uses GitHub’s auto‑provided GITHUB_TOKEN with contents: write and pull-requests: write permissions to perform all repository operations.
  • Signed commits by default – The create-commit-on-branch API calls generate commits signed by github-actions[bot], satisfying branch protection rules without additional configuration.
  • Per-plugin isolation – Each bumped plugin receives its own bump/<name> branch and PR, preventing cross-contamination of validation failures.
  • Safety exclusions – The .github/freeze-shas.txt file allows maintainers to exclude broken plugins from automatic updates.
  • Validation gating – Post-creation dispatch of validate-plugins.yml ensures all bumped SHAs pass CLI validation before merge.

Frequently Asked Questions

Why does the action not require a GitHub App?

The action relies on the GITHUB_TOKEN secret that GitHub automatically generates for every workflow run. According to the source code in anthropics/claude-plugins-community, granting this token write permissions for contents and pull-requests provides sufficient scope to create branches, commit changes, and open pull requests. Since the repository trusts the github-actions[bot] actor, no external App identity is necessary.

How does the freeze list prevent broken plugins from updating?

The workflow reads .github/freeze-shas.txt at runtime and excludes any plugin names found within that file from the bump process. This allows maintainers to manually curate a list of plugins known to be incompatible with the latest upstream HEAD, preventing the workflow from generating failing PRs for those specific entries while continuing to update healthy plugins.

Can I run the bump process for a single plugin instead of all outdated ones?

Yes. The workflow supports a plugin input parameter available through workflow_dispatch triggers. When you provide a specific plugin name to this input, the ./.github/actions/bump-plugin-shas action filters its processing to only that entry, creating a targeted bump branch and PR regardless of the max_bumps limit or other pending updates.

How are the commits signed without an App’s private key?

The workflow uses GitHub’s create‑commit‑on‑branch GraphQL mutation or equivalent REST API calls authenticated with the default GITHUB_TOKEN. Commits created through GitHub’s API using this token are automatically signed by GitHub and attributed to github-actions[bot], satisfying the repository’s required_signatures branch protection rules without requiring manual GPG keys or App certificates.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →