Files
IntelliJ-IdeaVim/.github/workflows/updateChangelogClaude.yml
1grzyb1andClaude Opus 5.5 a594a245c8 Fix(VIM-4350): Take GitHub write access away from the changelog Claude run
Claude reads untrusted text (PR comments, YouTrack tickets) while updating
the changelog, and its PRs were auto-merged, so a prompt injection could
reach master or leak secrets through `gh`.

- Claude can only edit CHANGES.md and use read-only git/gh commands; the
  push token is not persisted in .git/config.
- A separate step opens the PR with GITHUB_TOKEN only if CHANGES.md is the
  only changed file, dispatches PR verification for it and enables
  auto-merge.
- Remove mergeClaudeChangelogPR.yml, Claude no longer opens these PRs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 11:49:17 +01:00

121 lines
5.3 KiB
YAML

name: Update Changelog with Claude
on:
schedule:
# Run every day at 5 AM UTC
- cron: '0 5 * * *'
workflow_dispatch: # Allow manual trigger
jobs:
update-changelog:
runs-on: ubuntu-latest
if: github.repository == 'JetBrains/ideavim'
permissions:
contents: write
pull-requests: write
id-token: write
issues: read
actions: write # Dispatch PR verification for the changelog branch
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Need full history to analyze commits and tags
# Keep the push token out of .git/config so Claude can't use it
persist-credentials: false
- name: Get last processed commit
id: last_commit
run: |
# Get the commit SHA from the last successful workflow run
LAST_COMMIT=$(gh run list \
--workflow=updateChangelogClaude.yml \
--status=success \
--limit=1 \
--json headSha \
--jq '.[0].headSha // ""')
echo "sha=$LAST_COMMIT" >> $GITHUB_OUTPUT
if [ -n "$LAST_COMMIT" ]; then
echo "Last processed commit: $LAST_COMMIT"
else
echo "No previous successful run found, will analyze recent commits"
fi
env:
GH_TOKEN: ${{ github.token }}
- name: Run Claude Code to Update Changelog
id: claude
uses: anthropics/claude-code-action@v1
env:
ANTHROPIC_BASE_URL: ${{ secrets.PROXY_URL }}
ANTHROPIC_CUSTOM_HEADERS: |
Grazie-Agent: {"name":"ideavim-claude-code-action","version":"github-actions"}
Grazie-Authenticate-JWT: ${{ secrets.ANTHROPIC_API_KEY }}
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: |
## Task: Update the CHANGES.md Changelog File
You need to review the latest commits and maintain the changelog file (CHANGES.md) with meaningful changes.
Use the changelog skill to load the detailed changelog maintenance instructions.
**Important**: The last processed commit is: ${{ steps.last_commit.outputs.sha || 'not set - analyze commits from the last documented version in CHANGES.md' }}
Use `git log ${{ steps.last_commit.outputs.sha }}..HEAD --oneline` to see commits since the last changelog update (if the commit SHA is available).
If you find changes that need documenting, edit CHANGES.md and leave the edit
uncommitted. Do NOT create a branch, commit, push or open a pull request
(this overrides the skill's PR step) — the workflow does that after you finish.
Changes to any other file are rejected and nothing gets published.
Return:
- `summary`: super short summary for the PR title "Update changelog: <summary>"
Example: "Add gn text object, fix visual mode issues"
- `body`: brief summary of what was added, for the PR description
# Changelog edits + changelog skill + read-only git/gh and web access for checking releases and tickets
claude_args: >-
--allowed-tools "Skill,Read,Glob,Grep,Edit(CHANGES.md),Bash(git log:*),Bash(git show:*),Bash(git diff:*),Bash(git tag --list:*),Bash(gh pr list:*),Bash(gh pr view:*),WebSearch,WebFetch(domain:plugins.jetbrains.com),WebFetch(domain:youtrack.jetbrains.com),WebFetch(domain:github.com)"
--json-schema '{"type":"object","properties":{"summary":{"type":"string"},"body":{"type":"string"}},"required":["summary","body"]}'
# Claude has no write access to GitHub, so the PR is opened here, and only if
# nothing but the changelog changed. PRs opened with GITHUB_TOKEN don't trigger
# pull_request workflows, so the required `test` check is dispatched manually.
- name: Open and auto-merge the changelog PR
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
RESULT: ${{ steps.claude.outputs.structured_output }}
BRANCH: changelog/update-${{ github.run_id }}
run: |
set -e
changed=$(git status --porcelain --untracked-files=all | cut -c4-)
if [ -z "$changed" ]; then
echo "No changelog changes"
exit 0
fi
if [ "$changed" != "CHANGES.md" ]; then
echo "::error::Claude changed files other than CHANGES.md:"
echo "$changed"
exit 1
fi
summary=$(jq -r '.summary // empty' <<< "$RESULT" | head -n 1 | cut -c 1-100)
if [ -z "$summary" ]; then
echo "::error::Claude returned no PR summary"
exit 1
fi
jq -r '.body // empty' <<< "$RESULT" > "$RUNNER_TEMP/pr-body.md"
git config user.name "IdeaVim Bot"
git config user.email "maintainers@ideavim.dev"
git switch -c "$BRANCH"
git commit -q -m "Update changelog: $summary" CHANGES.md
git push "https://x-access-token:${GH_TOKEN}@github.com/${REPO}.git" "$BRANCH"
pr_url=$(gh pr create --base master --head "$BRANCH" \
--title "Update changelog: $summary" --body-file "$RUNNER_TEMP/pr-body.md")
gh workflow run pr-verification.yml --ref "$BRANCH"
gh pr merge --auto --rebase "$pr_url"