Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/pr-describe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,33 @@ jobs:
contents: read
pull-requests: write
issues: write
checks: write
steps:
- name: Check out Git repository
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0

- name: Create check run
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Orphaned in_progress check run if workflow is cancelled or times out

While the if: always() condition on the update step ensures it runs on normal job completion, it won't execute if the workflow is cancelled at the job level or hits a hard timeout before reaching the update step. This could leave an orphaned check permanently spinning in in_progress status on the PR.

Recommendation: Consider adding a separate cleanup workflow that runs periodically to find and close stale in_progress check runs, or use GitHub's auto-timeout feature for checks (though this requires additional configuration).

id: create-check
continue-on-error: true # Don't fail if checks: write permission is missing
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const prNumber = context.issue.number;
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
const { data: check } = await github.rest.checks.create({
owner: context.repo.owner,
repo: context.repo.repo,
name: 'Generate PR Description',
head_sha: pr.head.sha,
status: 'in_progress',
started_at: new Date().toISOString()
});
core.setOutput('check-id', check.id);

# Generate GitHub App token so actions appear as the custom app (optional - falls back to github.token)
- name: Get GitHub App token
id: app-token
Expand Down Expand Up @@ -284,3 +307,25 @@ jobs:
set -euo pipefail
rm -f commits.txt files.txt pr.diff || true
echo "🧹 Cleaned up temporary files"

- name: Update check run
if: always() && steps.create-check.outputs.check-id != ''
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
env:
CHECK_ID: ${{ steps.create-check.outputs.check-id }}
JOB_STATUS: ${{ job.status }}
with:
script: |
const conclusion = process.env.JOB_STATUS === 'cancelled' ? 'cancelled' : process.env.JOB_STATUS === 'success' ? 'success' : 'failure';
try {
await github.rest.checks.update({
owner: context.repo.owner,
repo: context.repo.repo,
check_run_id: parseInt(process.env.CHECK_ID, 10),
status: 'completed',
conclusion: conclusion,
completed_at: new Date().toISOString()
});
} catch (error) {
core.warning(`Failed to update check run: ${error.message}`);
}
48 changes: 48 additions & 0 deletions .github/workflows/review-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# contents: read # Read repository files and PR diffs
# pull-requests: write # Post review comments and approve/request changes
# issues: write # Create security incident issues if secrets are detected in output
# checks: write # (Optional) Show review progress as a check run on the PR
# secrets:
# ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
# CAGENT_ORG_MEMBERSHIP_TOKEN: ${{ secrets.CAGENT_ORG_MEMBERSHIP_TOKEN }} # PAT with read:org scope; gates auto-reviews to org members only
Expand Down Expand Up @@ -99,6 +100,7 @@ permissions:
contents: read
pull-requests: write
issues: write
checks: write

jobs:
# ==========================================================================
Expand Down Expand Up @@ -203,6 +205,30 @@ jobs:
exit-code: ${{ steps.run-review.outputs.exit-code }}

steps:
- name: Create check run
id: create-check
continue-on-error: true # Don't fail if caller didn't grant checks: write
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
PR_NUMBER: ${{ inputs.pr-number || github.event.issue.number }}
with:
script: |
const prNumber = parseInt(process.env.PR_NUMBER, 10);
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
const { data: check } = await github.rest.checks.create({
owner: context.repo.owner,
repo: context.repo.repo,
name: 'PR Review',
head_sha: pr.head.sha,
status: 'in_progress',
started_at: new Date().toISOString()
});
core.setOutput('check-id', check.id);

# Checkout PR head (not default branch)
# Note: Authorization is handled by the composite action's built-in check
- name: Checkout PR head
Expand Down Expand Up @@ -240,6 +266,28 @@ jobs:
nebius-api-key: ${{ secrets.NEBIUS_API_KEY }}
mistral-api-key: ${{ secrets.MISTRAL_API_KEY }}

- name: Update check run
if: always() && steps.create-check.outputs.check-id != ''
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
CHECK_ID: ${{ steps.create-check.outputs.check-id }}
JOB_STATUS: ${{ job.status }}
with:
script: |
const conclusion = process.env.JOB_STATUS === 'cancelled' ? 'cancelled' : process.env.JOB_STATUS === 'success' ? 'success' : 'failure';
try {
await github.rest.checks.update({
owner: context.repo.owner,
repo: context.repo.repo,
check_run_id: parseInt(process.env.CHECK_ID, 10),
status: 'completed',
conclusion: conclusion,
completed_at: new Date().toISOString()
});
} catch (error) {
core.warning(`Failed to update check run: ${error.message}`);
}

# ==========================================================================
# CAPTURE FEEDBACK
# Saves feedback data as an artifact for lazy processing. This job
Expand Down
45 changes: 45 additions & 0 deletions .github/workflows/self-review-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ permissions:
contents: read
pull-requests: write
issues: write
checks: write

jobs:
# ==========================================================================
Expand Down Expand Up @@ -111,6 +112,28 @@ jobs:
HAS_APP_SECRETS: ${{ secrets.CAGENT_REVIEWER_APP_ID != '' }}

steps:
- name: Create check run
id: create-check
continue-on-error: true # Don't fail if checks: write permission is missing
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const prNumber = context.issue.number;
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
const { data: check } = await github.rest.checks.create({
owner: context.repo.owner,
repo: context.repo.repo,
name: 'PR Review',
head_sha: pr.head.sha,
status: 'in_progress',
started_at: new Date().toISOString()
});
core.setOutput('check-id', check.id);

# Checkout PR head (not default branch)
# Note: Authorization is handled by the composite action's built-in check
- name: Checkout PR head
Expand Down Expand Up @@ -145,6 +168,28 @@ jobs:
nebius-api-key: ${{ secrets.NEBIUS_API_KEY }}
mistral-api-key: ${{ secrets.MISTRAL_API_KEY }}

- name: Update check run
if: always() && steps.create-check.outputs.check-id != ''
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
CHECK_ID: ${{ steps.create-check.outputs.check-id }}
JOB_STATUS: ${{ job.status }}
with:
script: |
const conclusion = process.env.JOB_STATUS === 'cancelled' ? 'cancelled' : process.env.JOB_STATUS === 'success' ? 'success' : 'failure';
try {
await github.rest.checks.update({
owner: context.repo.owner,
repo: context.repo.repo,
check_run_id: parseInt(process.env.CHECK_ID, 10),
status: 'completed',
conclusion: conclusion,
completed_at: new Date().toISOString()
});
} catch (error) {
core.warning(`Failed to update check run: ${error.message}`);
}

# ==========================================================================
# CAPTURE FEEDBACK
# Saves feedback data as an artifact for lazy processing. This job
Expand Down
Loading