mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-21 13:55:54 +00:00
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:
parent
520c3ea443
commit
f90478b74a
3 changed files with 105 additions and 3 deletions
66
.github/EXTERNAL_CONTRIBUTORS.md
vendored
Normal file
66
.github/EXTERNAL_CONTRIBUTORS.md
vendored
Normal 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.
|
||||
24
.github/actions/lint-reporter/action.yml
vendored
24
.github/actions/lint-reporter/action.yml
vendored
|
|
@ -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"
|
||||
18
.github/workflows/claude-code-review.yml
vendored
18
.github/workflows/claude-code-review.yml
vendored
|
|
@ -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 }}
|
||||
|
|
|
|||
Loading…
Reference in a new issue