feat: support GitHub App tokens for branded PR comments#83
Conversation
Add app-id and app-private-key inputs to the action so PR comments can be posted under a custom GitHub App identity instead of the generic github-actions bot. Uses actions/create-github-app-token to generate short-lived tokens. Falls back to the existing token input when app-id is not provided. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds support for posting PR comments using a GitHub App identity by generating a short-lived installation token, while preserving the existing token input fallback behavior.
Changes:
- Introduces
app-idandapp-private-keyinputs to enable GitHub App–based authentication. - Generates an installation token via
actions/create-github-app-token@v1and uses it forgh-based PR comment posting. - Updates CI workflow steps to pass the new app credentials into the action invocations.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
action.yml |
Adds new inputs and a token-generation step; switches PR comment posting to use the app token when configured. |
.github/workflows/tests.yml |
Passes GitHub App credentials to each report-rendering step in CI. |
| description: 'GitHub token for posting PR comments. Only needed when post-to includes pr-comment. Ignored when app-id is provided.' | ||
| required: false | ||
| default: ${{ github.token }} | ||
| app-id: | ||
| description: > | ||
| GitHub App ID for posting PR comments with a branded identity. | ||
| When provided (along with app-private-key), a short-lived token is | ||
| generated automatically and used instead of the token input. |
There was a problem hiding this comment.
The token input description says it is “Ignored when app-id is provided”, but inputs.token is still used for GitHub API calls in the “Collect GitHub PR data” step (e.g., when data-format: github-prs). Either narrow the description to clarify it’s only ignored for PR comment posting, or generate/reuse the app token earlier and use it for the collection step as well.
| description: 'GitHub token for posting PR comments. Only needed when post-to includes pr-comment. Ignored when app-id is provided.' | |
| required: false | |
| default: ${{ github.token }} | |
| app-id: | |
| description: > | |
| GitHub App ID for posting PR comments with a branded identity. | |
| When provided (along with app-private-key), a short-lived token is | |
| generated automatically and used instead of the token input. | |
| description: > | |
| GitHub token for GitHub API operations such as collecting PR data and | |
| posting PR comments. Required when those operations are used. When | |
| app-id is provided, a short-lived app token is generated and used for | |
| PR comment posting instead of this token input. | |
| required: false | |
| default: ${{ github.token }} | |
| app-id: | |
| description: > | |
| GitHub App ID for posting PR comments with a branded identity. | |
| When provided (along with app-private-key), a short-lived token is | |
| generated automatically and used for PR comment posting. |
| - name: Generate app token | ||
| id: app-token | ||
| if: inputs.app-id != '' | ||
| uses: actions/create-github-app-token@v1 | ||
| with: | ||
| app-id: ${{ inputs.app-id }} | ||
| private-key: ${{ inputs.app-private-key }} |
There was a problem hiding this comment.
Generate app token runs whenever app-id is set, even if post-to doesn’t include pr-comment. That can make step-summary-only runs fail (e.g., misconfigured app secrets / app not installed) despite not needing an app token. Consider gating this step on contains(inputs.post-to, 'pr-comment') (and similarly only using the app token when posting PR comments).
| - name: Generate app token | ||
| id: app-token | ||
| if: inputs.app-id != '' | ||
| uses: actions/create-github-app-token@v1 | ||
| with: | ||
| app-id: ${{ inputs.app-id }} | ||
| private-key: ${{ inputs.app-private-key }} | ||
|
|
||
| - name: Post report | ||
| id: post | ||
| shell: bash | ||
| env: | ||
| GH_TOKEN: ${{ inputs.token }} | ||
| GH_TOKEN: ${{ inputs.app-id != '' && steps.app-token.outputs.token || inputs.token }} | ||
| run: | |
There was a problem hiding this comment.
app-private-key is documented as required when app-id is set, but this isn’t enforced. With the current GH_TOKEN expression, a missing/empty app-private-key can silently fall back to inputs.token, masking configuration errors. Add an explicit validation that fails when inputs.app-id is non-empty and inputs.app-private-key is empty (and/or avoid fallback when app-id is provided).
| template: pytest | ||
| data: reports/pytest.xml | ||
| data-format: junit-xml | ||
| post-to: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && 'step-summary,pr-comment' || 'step-summary' }} | ||
| comment-header: CI Report | ||
| app-id: ${{ secrets.KIDA_APP_ID }} | ||
| app-private-key: ${{ secrets.KIDA_APP_PRIVATE_KEY }} | ||
| python-version: skip |
There was a problem hiding this comment.
These app credentials are passed unconditionally. On non-PR runs (push/schedule) this causes the action to attempt GitHub App token generation (given the current action.yml logic), which can fail even when post-to resolves to step-summary only, and also conflicts with the test plan’s stated “push falls back to default”. Consider only passing app-id / app-private-key when post-to includes pr-comment (e.g., via an expression conditioned on the PR event and same-repo check).
| data: reports/coverage.json | ||
| post-to: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && 'step-summary,pr-comment' || 'step-summary' }} | ||
| comment-header: CI Report | ||
| comment-mode: append | ||
| context: "${{ steps.changed.outputs.files && format('{0}{1}{2}', '{\"changed_files\": ', steps.changed.outputs.files, '}') || '' }}" | ||
| app-id: ${{ secrets.KIDA_APP_ID }} | ||
| app-private-key: ${{ secrets.KIDA_APP_PRIVATE_KEY }} | ||
| python-version: skip |
There was a problem hiding this comment.
These app credentials are passed unconditionally. On non-PR runs (push/schedule) this can trigger GitHub App token generation even when not posting PR comments, and may fail if app secrets/config are unavailable. Consider only passing app-id / app-private-key when post-to includes pr-comment.
| data: reports/ty.xml | ||
| data-format: junit-xml | ||
| post-to: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && 'step-summary,pr-comment' || 'step-summary' }} | ||
| comment-header: CI Report | ||
| comment-mode: append | ||
| app-id: ${{ secrets.KIDA_APP_ID }} | ||
| app-private-key: ${{ secrets.KIDA_APP_PRIVATE_KEY }} | ||
| python-version: skip |
There was a problem hiding this comment.
These app credentials are passed unconditionally. On non-PR runs (push/schedule) this can trigger GitHub App token generation even when not posting PR comments, and may fail if app secrets/config are unavailable. Consider only passing app-id / app-private-key when post-to includes pr-comment.
| template: ruff | ||
| data: reports/ruff.json | ||
| post-to: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && 'step-summary,pr-comment' || 'step-summary' }} | ||
| comment-header: CI Report | ||
| comment-mode: append | ||
| app-id: ${{ secrets.KIDA_APP_ID }} | ||
| app-private-key: ${{ secrets.KIDA_APP_PRIVATE_KEY }} | ||
| python-version: skip |
There was a problem hiding this comment.
These app credentials are passed unconditionally. On non-PR runs (push/schedule) this can trigger GitHub App token generation even when not posting PR comments, and may fail if app secrets/config are unavailable. Consider only passing app-id / app-private-key when post-to includes pr-comment.
Summary
app-idandapp-private-keyinputs to the Kida action so PR comments can be posted under a custom GitHub App identity instead of the generic "github-actions" botactions/create-github-app-token@v1to generate short-lived tokens; falls back to the existingtokeninput whenapp-idis not providedtests.ymlto pass the new app secrets to all four report stepsTest plan
🤖 Generated with Claude Code