Handle external contributor CI permissions gracefully

- Add continue-on-error to all comment-posting steps in lint-reporter
- Check for fork PRs and skip Claude reviews for external contributors
- Add permission checks to prevent CI failures on forks
- Create documentation explaining external contributor CI behavior
- Ensure all workflows handle permission errors without failing the build

This allows external contributors to submit PRs without CI failures due to
missing write permissions, while still running all tests and validations.
This commit is contained in:
Peter Steinberger 2025-06-28 14:27:00 +02:00
parent 520c3ea443
commit f90478b74a
3 changed files with 105 additions and 3 deletions

66
.github/EXTERNAL_CONTRIBUTORS.md vendored Normal file
View file

@ -0,0 +1,66 @@
# External Contributor CI Permissions
This document explains how our CI handles pull requests from external contributors (forks).
## Background
When external contributors submit PRs from forked repositories, GitHub restricts certain permissions for security reasons. This means actions that require write permissions (like posting comments) will fail.
## Our Approach
We've implemented graceful handling of these permission restrictions:
1. **Detection**: CI workflows detect when a PR is from a fork
2. **Graceful Failure**: Actions that require write permissions use `continue-on-error: true`
3. **Skip When Appropriate**: Some workflows skip entirely for external contributors
4. **Clear Logging**: We log when actions are skipped due to permissions
## Affected Workflows
### Lint Reporter (`/.github/actions/lint-reporter/`)
- Posts code quality reports as PR comments
- Uses `continue-on-error: true` on all comment-related steps
- Logs when running from a fork
### Claude Code Review (`/.github/workflows/claude-code-review.yml`)
- Runs AI-powered code reviews
- Skips entirely for PRs from forks (requires API keys)
- Checks permissions before attempting to run
## For External Contributors
If you're submitting a PR from a fork:
- Your code will still be tested and validated
- Some automated comments (linting reports, AI reviews) won't appear
- This is normal and expected - your PR will still be reviewed by maintainers
- All test results are still visible in the GitHub Actions tab
## For Maintainers
When reviewing PRs from external contributors:
- Check the Actions tab for test results (since automated comments may not appear)
- Run local linting/tests if needed
- Consider manually running Claude review after merge if desired
## Implementation Details
Key patterns used in our workflows:
```yaml
# Check if PR is from a fork
- name: Check permissions
id: check-permissions
run: |
if [[ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]]; then
echo "is_fork=true" >> $GITHUB_OUTPUT
else
echo "is_fork=false" >> $GITHUB_OUTPUT
fi
# Use continue-on-error for steps that might fail due to permissions
- name: Post comment
continue-on-error: true
uses: some-action-that-posts-comments@v1
```
This approach ensures CI never fails solely due to permission issues while still providing full functionality for contributors with write access.

View file

@ -17,10 +17,24 @@ inputs:
runs:
using: 'composite'
steps:
- name: Check permissions
if: github.event_name == 'pull_request'
id: check-permissions
shell: bash
run: |
# Check if this is from a fork (external contributor)
if [[ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]]; then
echo "is_fork=true" >> $GITHUB_OUTPUT
echo " PR from fork detected - comment posting may fail due to permissions"
else
echo "is_fork=false" >> $GITHUB_OUTPUT
fi
- name: Find Comment
if: github.event_name == 'pull_request'
uses: peter-evans/find-comment@v3
id: fc
continue-on-error: true
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]'
@ -29,6 +43,7 @@ runs:
- name: Prepare Comment Body
if: github.event_name == 'pull_request'
id: prepare
continue-on-error: true
uses: actions/github-script@v7
with:
github-token: ${{ inputs.github-token }}
@ -111,8 +126,15 @@ runs:
- name: Create or Update Comment
if: github.event_name == 'pull_request'
uses: peter-evans/create-or-update-comment@v4
continue-on-error: true
with:
comment-id: ${{ steps.fc.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body: ${{ steps.prepare.outputs.comment_body }}
edit-mode: replace
edit-mode: replace
- name: Log comment status
if: github.event_name == 'pull_request' && steps.check-permissions.outputs.is_fork == 'true'
shell: bash
run: |
echo " Comment posting may have failed due to fork permissions - this is expected and OK"

View file

@ -36,8 +36,20 @@ jobs:
with:
fetch-depth: 0 # Full history for better context
- name: Check permissions
id: check-permissions
run: |
# Check if this is from a fork (external contributor)
if [[ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]]; then
echo "is_fork=true" >> $GITHUB_OUTPUT
echo " PR from fork detected - Claude review will be skipped due to permissions"
else
echo "is_fork=false" >> $GITHUB_OUTPUT
fi
- name: Check if already reviewed
id: check-review
if: steps.check-permissions.outputs.is_fork != 'true'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
@ -68,8 +80,9 @@ jobs:
}
- name: Run Claude Code Review
if: steps.check-review.outputs.skip != 'true'
if: steps.check-permissions.outputs.is_fork != 'true' && steps.check-review.outputs.skip != 'true'
id: claude-review
continue-on-error: true
uses: anthropics/claude-code-action@beta
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
@ -151,7 +164,8 @@ jobs:
DELETIONS: ${{ github.event.pull_request.deletions }}
- name: Clean up old Claude comments
if: steps.check-review.outputs.skip != 'true'
if: steps.check-permissions.outputs.is_fork != 'true' && steps.check-review.outputs.skip != 'true'
continue-on-error: true
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}