From e22f02870884789a424c8b040aeb791e61b251f5 Mon Sep 17 00:00:00 2001 From: kirich1409 Date: Sat, 14 Feb 2026 23:48:45 +0300 Subject: [PATCH 1/4] ci: add Claude Code GitHub Action integration Configure Claude Code integration with GitHub Actions: - Trigger on @claude mentions in issues/PRs/reviews - Set up JDK 17 and Gradle for Android builds - Allow Gradle commands for check, build, format, coverage - Include project conventions in system prompt Based on official example from anthropics/claude-code-action Co-Authored-By: Claude Opus 4.6 --- .github/workflows/claude.yml | 53 ++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/claude.yml diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml new file mode 100644 index 0000000..ac4d6fa --- /dev/null +++ b/.github/workflows/claude.yml @@ -0,0 +1,53 @@ +name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + issues: + types: [opened, assigned] + pull_request_review: + types: [submitted] + +jobs: + claude: + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + issues: write + id-token: write + actions: read # Required for Claude to read CI results on PRs + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 1 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + + # Configure Claude's behavior for Android/Gradle project + claude_args: | + --model claude-opus-4-6 + --max-turns 15 + --allowedTools "Bash(./gradlew check),Bash(./gradlew assembleRelease),Bash(./gradlew ktlintFormat),Bash(./gradlew koverHtmlReport),Bash(./gradlew :vbpd-core:*),Bash(./gradlew :vbpd:*),Bash(./gradlew :vbpd-reflection:*),Bash(git *)" + --system-prompt "Follow coding standards from CLAUDE.md. Use explicit API mode (all public declarations need visibility modifiers). Ensure Kotlin formatting with ktlintFormat before committing. Run ./gradlew check to verify changes. Target JVM 11. PRs target develop branch, except hotfixes which target master." From 711e51b0a433f49a1ac18175439af3198d476ada Mon Sep 17 00:00:00 2001 From: kirich1409 Date: Sun, 15 Feb 2026 00:00:21 +0300 Subject: [PATCH 2/4] refactor: update Claude Code config for project specifics - Use JDK 21 (matches android.yml, build.yml) - Add Gradle cache for faster CI - Expand allowed commands: detekt, ktlintCheck, tests, coverage - Add git commands: status, diff, log, show - Include sample module commands - Update system prompt with architecture details - Increase max-turns to 20 for complex tasks Co-Authored-By: Claude Opus 4.6 --- .github/workflows/claude.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index ac4d6fa..ba08c32 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -30,11 +30,12 @@ jobs: with: fetch-depth: 1 - - name: Set up JDK 17 - uses: actions/setup-java@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v5 with: - java-version: '17' + java-version: '21' distribution: 'temurin' + cache: gradle - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 @@ -48,6 +49,6 @@ jobs: # Configure Claude's behavior for Android/Gradle project claude_args: | --model claude-opus-4-6 - --max-turns 15 - --allowedTools "Bash(./gradlew check),Bash(./gradlew assembleRelease),Bash(./gradlew ktlintFormat),Bash(./gradlew koverHtmlReport),Bash(./gradlew :vbpd-core:*),Bash(./gradlew :vbpd:*),Bash(./gradlew :vbpd-reflection:*),Bash(git *)" - --system-prompt "Follow coding standards from CLAUDE.md. Use explicit API mode (all public declarations need visibility modifiers). Ensure Kotlin formatting with ktlintFormat before committing. Run ./gradlew check to verify changes. Target JVM 11. PRs target develop branch, except hotfixes which target master." + --max-turns 20 + --allowedTools "Bash(./gradlew check),Bash(./gradlew assembleRelease),Bash(./gradlew ktlintFormat),Bash(./gradlew ktlintCheck),Bash(./gradlew detekt),Bash(./gradlew testDebugUnitTest),Bash(./gradlew koverHtmlReport),Bash(./gradlew koverXmlReport),Bash(./gradlew :vbpd-core:*),Bash(./gradlew :vbpd:*),Bash(./gradlew :vbpd-reflection:*),Bash(./gradlew :sample:*),Bash(git status),Bash(git diff),Bash(git log*),Bash(git show*)" + --system-prompt "Android library project (ViewBindingPropertyDelegate). Three modules: vbpd-core (foundation), vbpd (lifecycle delegates), vbpd-reflection (reflection + cache). Follow CLAUDE.md: explicit API mode required, Kotlin code style 'official', JVM target 11. Always run ktlintFormat before commit. Use './gradlew check' to verify. PRs → develop (feature/fix/chore/docs branches), hotfixes → master. Version in gradle/libs.versions.toml. Package: dev.androidbroadcast.vbpd." From 85b8b44aba88d0da4b839135e1cec511feed1761 Mon Sep 17 00:00:00 2001 From: kirich1409 Date: Sun, 15 Feb 2026 00:13:26 +0300 Subject: [PATCH 3/4] fix: address PR review comments for Claude workflow - Add author_association check (OWNER/MEMBER/COLLABORATOR only) - Remove id-token: write permission (not needed) - Remove fetch-depth: 1, add dynamic ref detection for PR contexts - Add chmod +x gradlew step before Gradle commands Co-Authored-By: Claude Opus 4.6 --- .github/workflows/claude.yml | 52 +++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index ba08c32..491a9d3 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -12,23 +12,58 @@ on: jobs: claude: + # Only allow trusted collaborators to trigger Claude via @claude mention if: | - (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || - (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + ( + github.event.comment.author_association == 'OWNER' || + github.event.comment.author_association == 'MEMBER' || + github.event.comment.author_association == 'COLLABORATOR' || + github.event.review.author_association == 'OWNER' || + github.event.review.author_association == 'MEMBER' || + github.event.review.author_association == 'COLLABORATOR' || + github.event.issue.author_association == 'OWNER' || + github.event.issue.author_association == 'MEMBER' || + github.event.issue.author_association == 'COLLABORATOR' + ) && ( + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + ) runs-on: ubuntu-latest permissions: contents: write pull-requests: write issues: write - id-token: write - actions: read # Required for Claude to read CI results on PRs + actions: read steps: + - name: Determine checkout ref + id: determine-ref + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const eventName = context.eventName; + let ref = context.sha; + + if (eventName === 'pull_request_review' || eventName === 'pull_request_review_comment') { + ref = context.payload.pull_request.head.sha; + } else if (eventName === 'issue_comment' && context.payload.issue && context.payload.issue.pull_request) { + const prNumber = context.payload.issue.number; + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + }); + ref = pr.head.sha; + } + + core.setOutput('ref', ref); + - name: Checkout repository uses: actions/checkout@v6 with: - fetch-depth: 1 + ref: ${{ steps.determine-ref.outputs.ref }} - name: Set up JDK 21 uses: actions/setup-java@v5 @@ -37,6 +72,9 @@ jobs: distribution: 'temurin' cache: gradle + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 From 54052ee4d3231085852913da686cef9df99ccba9 Mon Sep 17 00:00:00 2001 From: kirich1409 Date: Sun, 15 Feb 2026 00:18:04 +0300 Subject: [PATCH 4/4] refactor: simplify Claude workflow, remove redundant logic - Remove custom determine-ref step (action handles checkout internally) - Remove @claude mention checks from if (action filters mentions itself) - Keep author_association gate as the only custom security check Co-Authored-By: Claude Opus 4.6 --- .github/workflows/claude.yml | 54 +++++++----------------------------- 1 file changed, 10 insertions(+), 44 deletions(-) diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 491a9d3..c2d72e3 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -12,24 +12,17 @@ on: jobs: claude: - # Only allow trusted collaborators to trigger Claude via @claude mention + # Only allow trusted collaborators to trigger Claude if: | - ( - github.event.comment.author_association == 'OWNER' || - github.event.comment.author_association == 'MEMBER' || - github.event.comment.author_association == 'COLLABORATOR' || - github.event.review.author_association == 'OWNER' || - github.event.review.author_association == 'MEMBER' || - github.event.review.author_association == 'COLLABORATOR' || - github.event.issue.author_association == 'OWNER' || - github.event.issue.author_association == 'MEMBER' || - github.event.issue.author_association == 'COLLABORATOR' - ) && ( - (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || - (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || - (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) - ) + github.event.comment.author_association == 'OWNER' || + github.event.comment.author_association == 'MEMBER' || + github.event.comment.author_association == 'COLLABORATOR' || + github.event.review.author_association == 'OWNER' || + github.event.review.author_association == 'MEMBER' || + github.event.review.author_association == 'COLLABORATOR' || + github.event.issue.author_association == 'OWNER' || + github.event.issue.author_association == 'MEMBER' || + github.event.issue.author_association == 'COLLABORATOR' runs-on: ubuntu-latest permissions: contents: write @@ -37,33 +30,8 @@ jobs: issues: write actions: read steps: - - name: Determine checkout ref - id: determine-ref - uses: actions/github-script@v7 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const eventName = context.eventName; - let ref = context.sha; - - if (eventName === 'pull_request_review' || eventName === 'pull_request_review_comment') { - ref = context.payload.pull_request.head.sha; - } else if (eventName === 'issue_comment' && context.payload.issue && context.payload.issue.pull_request) { - const prNumber = context.payload.issue.number; - const { data: pr } = await github.rest.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: prNumber, - }); - ref = pr.head.sha; - } - - core.setOutput('ref', ref); - - name: Checkout repository uses: actions/checkout@v6 - with: - ref: ${{ steps.determine-ref.outputs.ref }} - name: Set up JDK 21 uses: actions/setup-java@v5 @@ -83,8 +51,6 @@ jobs: uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - - # Configure Claude's behavior for Android/Gradle project claude_args: | --model claude-opus-4-6 --max-turns 20