Add release workflow to bump Claude plugin version#50
Conversation
Manually-dispatched workflow that increments the version in .claude-plugin/plugin.json (patch/minor/major), commits the bump directly to main, and pushes a v<version> tag. Pushes over SSH using a deploy key so it can bypass the main ruleset. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| run: | | ||
| set -euo pipefail | ||
| PLUGIN_FILE=".claude-plugin/plugin.json" | ||
|
|
||
| OLD_VERSION=$(jq -r '.version' "$PLUGIN_FILE") | ||
| if [ -z "$OLD_VERSION" ] || [ "$OLD_VERSION" = "null" ]; then | ||
| echo "Could not read version from $PLUGIN_FILE" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| IFS='.' read -r MAJOR MINOR PATCH <<< "$OLD_VERSION" | ||
|
|
||
| case "${{ inputs.bump }}" in | ||
| major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;; | ||
| minor) MINOR=$((MINOR + 1)); PATCH=0 ;; | ||
| patch) PATCH=$((PATCH + 1)) ;; | ||
| esac | ||
|
|
||
| NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}" | ||
|
|
||
| tmp=$(mktemp) | ||
| jq --arg v "$NEW_VERSION" '.version = $v' "$PLUGIN_FILE" > "$tmp" | ||
| mv "$tmp" "$PLUGIN_FILE" | ||
|
|
||
| echo "old_version=$OLD_VERSION" >> "$GITHUB_OUTPUT" | ||
| echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT" | ||
| echo "Bumped $OLD_VERSION -> $NEW_VERSION" | ||
|
|
There was a problem hiding this comment.
Opengrep — security.gha.run-shell-injection-inputs (WARNING)
A composite-action / reusable-workflow / workflow_dispatch inputs.* value is interpolated directly into this run/script block. Inputs are supplied by the caller, who may pass attacker-controlled data into them — e.g. a caller invoking this with version: ${{ github.event.pull_request.head.ref }} (a fork branch name). Because the input value is substituted before the shell runs, the callee cannot trust it. Defensive fix: copy the input into a step-level env: entry (e.g. VERSION: ${{ inputs.version }}) and reference the quoted environment variable in the script instead (echo "$VERSION"). This is advisory (WARNING): not every input carries untrusted data, but routing inputs through env: makes the component safe regardless of how callers use it. If an input appears only as a condition selecting between hard-coded string literals (e.g. ${{ inputs.flag && 'a' || 'b' }}), the emitted value is constant and that specific use is not exploitable — but hoist the condition into bash (set a boolean env: var and branch with if) so the run line carries no ${{ }} and the safety stays local and stable. Directly-untrusted github.* contexts are covered separately by security.gha.run-shell-injection.
Fixed in 502b127
Copy inputs.bump into a step-level env var and reference "$BUMP" in the
run block instead of interpolating ${{ inputs.bump }} directly, per
opengrep security.gha.run-shell-injection-inputs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Adds a manually-dispatched GitHub Actions workflow that releases the Claude plugin by bumping its version number.
What it does
bumpinput (patch/minor/major, defaults topatch)..claude-plugin/plugin.jsonusingjq. Skill versions are intentionally left untouched. (.claude-plugin/marketplace.jsonhas no version field, so nothing to change there.)mainasBump version from X to Yand pushes av<version>tag.Auth / setup required
Pushes over SSH using a deploy key so it can bypass the
mainruleset (the built-ingithub-actions[bot]can't be added to a ruleset bypass list). Before first use:RELEASE_SSH_KEYrepo secret.mainruleset's bypass list.🤖 Generated with Claude Code