How the Per‑Entry PR Model Works in the Claude Plugins Community Bump Workflow
The per‑entry PR model creates a dedicated Git branch and pull request for every plugin SHA update, guaranteeing that a validation or build failure in one plugin does not block or revert the bumping of any other plugin.
The bump-plugin-shas.yml workflow in the anthropics/claude-plugins-community repository automates the process of updating pinned Git SHAs for external Claude plugins. Unlike the default batch behavior, the per‑entry PR model generates isolated, single‑purpose pull requests that isolate failures and allow atomic merges. This article explains the exact implementation, referencing the Bash scripts and GraphQL mutations that power the process.
Workflow Architecture Overview
The workflow consists of a GitHub Actions orchestration layer and a custom composite action that executes shell logic. In .github/workflows/bump-plugin-shas.yml, the workflow accepts a pr-mode input that defaults to batch but can be set to per-entry (lines 84‑88). When selected, this mode triggers a surgical update process defined in .github/actions/bump-plugin-shas/scripts/bump.sh.
The core design goal, explicitly stated in the workflow file header (lines 5‑8), is isolation: each plugin bump lives in its own Git branch, receives its own cryptographically signed commit, and opens its own pull request. If the validate-plugins.yml check fails on one branch, the remaining branches stay green and mergeable.
Step‑by‑Step Execution in Per‑Entry Mode
Configuration and Input Handling
The workflow forwards the pr-mode selection to the custom action at line 88 of bump-plugin-shas.yml. Inside bump.sh, the script reads this value (lines 81‑86) and stores it in the PR_MODE environment variable, defaulting to batch if unspecified. This variable dictates the branching strategy for the remainder of the execution.
Deduplication and Skip Logic
Before processing begins, the script calls branch_for() (lines 14‑20) to sanitize the plugin name into a Git‑safe branch suffix (e.g., bump/<sanitized>). This handles scoped npm‑style names such as @scope/plugin.
In per‑entry mode, the script queries GitHub for existing bump PRs using gh pr list (lines 27‑33). If a PR already exists for the plugin, the entry is added to a skipped list and the script proceeds to the next plugin, preventing redundant work.
Validation and Branch Preparation
For every stale entry, the script performs upstream validation (lines 35‑46):
- Clones the upstream plugin repository.
- Runs
claude plugin validateagainst the candidate SHA. - Records failures in the skipped list, bypassing that plugin.
Only validated plugins proceed. The script then invokes create_or_reset_branch (lines 55‑61), which creates or force‑resets a branch named bump/<sanitized> to the current main HEAD. This guarantees a clean, mergeable base for every individual bump.
Isolated Commit Construction
Rather than modifying the entire marketplace.json, the per‑entry model builds a temporary file containing only the target plugin’s update. The script uses jq to substitute the new SHA into the original marketplace content (lines 103‑108):
entry_file=$(mktemp)
jq --arg n "$name" --arg s "$new_sha" \
'(.plugins[] | select(.name==$n) | .source.sha) = $s' \
<<<"$base_marketplace_content" > "$entry_file"
This isolated change is then committed via the create_signed_commit function (lines 65‑78). This function executes the createCommitOnBranch GraphQL mutation, which signs the commit using GitHub’s internal GPG key. This signing is mandatory to satisfy the repository’s organization‑level required_signatures branch protection rule.
Pull Request Generation and Tracking
After committing, the script generates a descriptive title and body containing a table of old and new SHAs. It opens the pull request using gh pr create (or updates an existing one with gh pr edit), posting a concise description that notes the SHA was pre‑validated.
Each successfully created PR URL is appended to a JSON array (pr_urls) that is later emitted as the workflow’s pr-urls output (lines 45‑48).
Post‑Creation Validation
With all per‑entry PRs opened, the workflow dispatches validate-plugins.yml against each bump branch (lines 102‑108 of bump-plugin-shas.yml). Because the PRs were created using the default GITHUB_TOKEN, the validation check runs on the branch tip without triggering GitHub’s pull‑request recursion guard. If any individual check fails, that specific PR remains open for human triage while others stay green and mergeable.
Operational Isolation Guarantees
The per‑entry PR model provides three critical safety properties:
- Failure containment: A build or validation error in one plugin affects only its dedicated branch, leaving other bumps untouched.
- Atomic merges: Maintainers can merge successful bumps immediately without waiting for flaky or broken upstream repositories.
- Auditability: Each SHA update exists as a discrete, signed Git commit with a dedicated PR history, making rollbacks and forensic analysis straightforward.
Running the Workflow Manually
Trigger the per‑entry mode manually via the GitHub CLI:
gh workflow run bump-plugin-shas.yml \
-f max_bumps=30 \
-f pr-mode=per-entry
Summary
- The per‑entry PR model is activated by setting
pr-mode: per-entryin the workflow dispatch inputs defined in.github/workflows/bump-plugin-shas.yml. - Each plugin update is validated with
claude plugin validatebefore any branch is created. - The
bump.shscript sanitizes plugin names into Git‑safe branch names usingbranch_for()and creates isolated branches viacreate_or_reset_branch(). - Commits are signed via the
createCommitOnBranchGraphQL mutation to satisfy branch protection rules. - The workflow dispatches
validate-plugins.ymlto each bump branch, ensuring failures in one plugin do not block others.
Frequently Asked Questions
What is the difference between batch mode and per‑entry PR mode?
Batch mode aggregates all SHA updates into a single pull request, which risks blocking every update if one plugin fails validation. Per‑entry PR mode creates a separate branch and PR for each plugin, isolating failures so that healthy updates can merge immediately without waiting for problematic upstreams to fix their builds.
How does the workflow prevent duplicate pull requests?
Before processing a plugin, the script queries open PRs using gh pr list (lines 27‑33 of bump.sh). If a bump PR already exists for that plugin, the script adds the entry to a skipped list and proceeds to the next candidate, ensuring no redundant branches are created while the workflow runs.
Why does the workflow use GraphQL to create commits instead of standard Git commands?
The repository enforces an organization‑level required_signatures branch protection rule. The createCommitOnBranch GraphQL mutation (lines 65‑78 of bump.sh) leverages GitHub’s internal GPG key to sign commits automatically. Standard git commit commands would fail this requirement in the GitHub Actions environment because the runner does not possess a trusted signing key.
Can I limit the number of plugins processed in a single run?
Yes. The workflow accepts a max_bumps input that the script respects when iterating through the plugin list. When running manually, pass -f max_bumps=N to the GitHub CLI, or specify the value in the workflow dispatch UI, to cap the number of per‑entry PRs generated in a single execution and prevent notification spam.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →