Files
IntelliJ-IdeaVim/.github/workflows/updateWhatsNewClaude.yml
1grzyb1andClaude Opus 5.5 3580099c61 Fix(VIM-4350): Restrict What's New Claude workflow to maintainers and allowed files
Anyone could open a fork PR with the What's New title and inject a prompt
via a comment into a Claude run with repository write access.

- Run only for OWNER/MEMBER/COLLABORATOR comments, and verify the PR head is
  JetBrains/ideavim:whatsnew-tbr and the commenter has write access.
- Claude can only edit whatsnew-tbr.html and CHANGES.md and has no
  commit/push access; the push token is not persisted in .git/config.
- A separate step pushes the edits only if no other files changed.

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

134 lines
6.4 KiB
YAML

name: Update What's New with Claude
# Reacts to comments on the "What's New" PR opened by prepareWhatsNewClaude.yml.
# That PR always lives on the `whatsnew-tbr` branch and is titled
# "Prepare What's New for the upcoming release". When a maintainer leaves a
# comment there, Claude reads it and updates the page / changelog accordingly.
# Claude itself can't commit or push: a separate step pushes its edits back to
# the same branch, and only if they touch the What's New page or the changelog.
on:
issue_comment:
types: [created]
jobs:
update-whats-new:
runs-on: ubuntu-latest
# Only on the What's New PR, only for comments from maintainers, and never on
# comments left by bots (the preview bot and Claude itself comment here —
# reacting to those would loop). The title alone is not trusted: anyone can
# open a fork PR with the same title, so the PR branch and the commenter's
# write access are verified in the first step.
if: |
github.repository == 'JetBrains/ideavim' &&
github.event.issue.pull_request &&
contains(github.event.issue.title, 'Prepare What''s New for the upcoming release') &&
github.event.comment.user.type != 'Bot' &&
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
permissions:
contents: write
pull-requests: write
id-token: write
issues: read
actions: read
steps:
- name: Verify the PR and the commenter
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
COMMENTER: ${{ github.event.comment.user.login }}
run: |
head=$(gh api "repos/$REPO/pulls/$PR_NUMBER" --jq '.head.repo.full_name + ":" + .head.ref')
if [ "$head" != "$REPO:whatsnew-tbr" ]; then
echo "::error::PR #$PR_NUMBER head is '$head', expected '$REPO:whatsnew-tbr'"
exit 1
fi
permission=$(gh api "repos/$REPO/collaborators/$COMMENTER/permission" --jq '.permission')
if [ "$permission" != "admin" ] && [ "$permission" != "write" ]; then
echo "::error::$COMMENTER has '$permission' permission, write access is required"
exit 1
fi
- name: Checkout the What's New PR branch
uses: actions/checkout@v4
with:
ref: whatsnew-tbr
fetch-depth: 0 # Full history for the changelog skill
# Keep the push token out of .git/config so Claude can't use it
persist-credentials: false
- name: Run Claude Code to apply the requested changes
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 }}
additional_permissions: |
actions: read
prompt: |
A maintainer left a comment on the "What's New" pull request (branch
`whatsnew-tbr`). Read the comment below and apply exactly what it asks
by editing the files in the working tree. Do NOT commit or push — the
workflow does that after you finish.
## The maintainer's comment
${{ github.event.comment.body }}
## What you can change
- The What's New page: `src/main/resources/whatsnew-tbr.html`.
- The changelog `## [To Be Released]` section of `CHANGES.md`, if the
comment asks for changelog changes (use the `changelog` skill for its rules).
Changes to any other file are rejected and nothing gets pushed.
Make the smallest change that satisfies the comment — do NOT rewrite or
restyle anything that wasn't asked about.
## Hard rules for the page (keep the existing look intact)
- Keep the entire `<head>`/`<style>` block, every CSS class, the
`data-theme="__THEME__"` attribute and the `__VERSION__` token unchanged.
- Never hard-code a version; leave `__VERSION__` exactly as-is.
- Keep the `<!-- whatsnew-release-commit: ... -->` line at the top unchanged.
- Escape HTML correctly inside `code`/`kbd`/`pre` (`&lt;` `&gt;` `&amp;`).
- Keep the friendly, user-facing tone; no `VIM-####` ids or raw issue URLs.
## Finish
- Leave your edits uncommitted in the working tree.
- If the comment doesn't request any actionable change to the page or
changelog, make no changes and briefly explain why.
# Edits limited to the two files + changelog skill + read-only git/gh.
claude_args: '--allowed-tools "Skill,Read,Glob,Grep,Edit(src/main/resources/whatsnew-tbr.html),Write(src/main/resources/whatsnew-tbr.html),Edit(CHANGES.md),Write(CHANGES.md),Bash(git log:*),Bash(git show:*),Bash(git diff:*),Bash(git tag --list:*),Bash(gh pr view:*),Bash(gh pr list:*),WebSearch,WebFetch(domain:plugins.jetbrains.com),WebFetch(domain:youtrack.jetbrains.com),WebFetch(domain:github.com)"'
- name: Push the allowed changes to whatsnew-tbr
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
run: |
changed=$(git status --porcelain --untracked-files=all | cut -c4-)
if [ -z "$changed" ]; then
echo "No changes to push"
exit 0
fi
disallowed=$(echo "$changed" | grep -vxE 'src/main/resources/whatsnew-tbr\.html|CHANGES\.md' || true)
if [ -n "$disallowed" ]; then
echo "::error::Claude changed files outside the allowed set:"
echo "$disallowed"
exit 1
fi
if [ "$(git rev-parse HEAD)" != "$(git rev-parse origin/whatsnew-tbr)" ]; then
echo "::error::HEAD moved away from origin/whatsnew-tbr, refusing to push"
exit 1
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add src/main/resources/whatsnew-tbr.html CHANGES.md
git commit -m "Update What's New based on review comment"
git push "https://x-access-token:${GH_TOKEN}@github.com/${REPO}.git" HEAD:whatsnew-tbr