mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-11-13 09:13:30 +01:00
GitHub blocks pull_request_target by default in public repositories from December 2, 2026. The ai-self-review workflow now runs on pull_request. It still checks out and runs the check script of the base branch and no other code of the pull request. The workflow file itself now comes from the pull request, so a pull request that changes it can weaken its own check. .github/CODEOWNERS therefore makes a maintainer the code owner of the workflows, CODEOWNERS and the check script; this is enforced once the branch protection of main requires a review from code owners. Additional changes - Record the switch in ADR 0002, which supersedes the pull_request_target consequence of ADR 0001. - Skip the comment step for pull requests from forks, whose token is read-only, and point their error message to the job summary only. - Describe the trigger, code owners and fork limits in docs/develop/ai.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assisted-by: Claude Code (claude-opus-5-5)
121 lines
5.1 KiB
YAML
121 lines
5.1 KiB
YAML
name: ai-self-review
|
|
|
|
# Checks the self-review declaration of agent-assisted pull requests, see
|
|
# docs/adr/0001-self-declared-sha-bound-review-gate.md and docs/develop/ai.md.
|
|
#
|
|
# It runs on pull_request, see docs/adr/0002-self-review-check-on-pull-request.md. The workflow
|
|
# file therefore comes from the pull request, but the job checks out and runs the check script of
|
|
# the base branch; it never checks out or runs other code of the pull request and reads the body
|
|
# and the commit messages through the API only. A pull request that changes this workflow can
|
|
# weaken its own check, so .github/CODEOWNERS requires a maintainer's review for it.
|
|
#
|
|
# It runs only for pull requests into main, never on pushes to main or to other branches, and not
|
|
# for pull requests into other branches.
|
|
#
|
|
# On failure it posts one comment that explains the fix, found again by its marker and updated in
|
|
# place; once the check passes, the comment is updated to say so. Pull requests from forks get a
|
|
# read-only token, so the comment step is skipped for them; the report is in the job summary.
|
|
|
|
on:
|
|
pull_request:
|
|
types: [opened, edited, synchronize, reopened]
|
|
branches: [main]
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: write
|
|
|
|
env:
|
|
# Must equal COMMENT_MARKER in scripts/check_pr_self_review.py (checked by tests/test_ai.py).
|
|
COMMENT_MARKER: "<!-- ai-self-review -->"
|
|
|
|
concurrency:
|
|
group: ai-self-review-${{ github.event.pull_request.number }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
self-review:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check out the base branch (not the pull request)
|
|
uses: actions/checkout@v7
|
|
with:
|
|
ref: ${{ github.event.pull_request.base.sha }}
|
|
persist-credentials: false
|
|
- uses: actions/setup-python@v7
|
|
with:
|
|
python-version-file: .python-version
|
|
- name: Fetch the pull request body and commit messages
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
PR_BODY: ${{ github.event.pull_request.body }}
|
|
PR_URL: repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}
|
|
run: |
|
|
printf '%s' "$PR_BODY" > "$RUNNER_TEMP/body.md"
|
|
gh api --paginate "$PR_URL/commits" --jq '.[].commit.message | @json' \
|
|
> "$RUNNER_TEMP/commits.jsonl"
|
|
- name: Check the self-review declaration
|
|
id: check
|
|
env:
|
|
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
PR_TITLE: ${{ github.event.pull_request.title }}
|
|
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
|
|
run: |
|
|
set +e
|
|
python scripts/check_pr_self_review.py \
|
|
--body-file "$RUNNER_TEMP/body.md" \
|
|
--commits-file "$RUNNER_TEMP/commits.jsonl" \
|
|
--head-sha "$PR_HEAD_SHA" \
|
|
--title "$PR_TITLE" \
|
|
--author "$PR_AUTHOR" \
|
|
--report-file "$RUNNER_TEMP/report.md"
|
|
status=$?
|
|
if [ ! -s "$RUNNER_TEMP/report.md" ]; then
|
|
# The script failed before it could write its report.
|
|
status=1
|
|
{
|
|
echo "$COMMENT_MARKER"
|
|
echo "### ❌ AI self-review check could not run"
|
|
echo
|
|
echo "The check script failed before it could check the declaration. This is a"
|
|
echo "problem of the check, not necessarily of the pull request; see the log of the"
|
|
echo "workflow run."
|
|
} > "$RUNNER_TEMP/report.md"
|
|
fi
|
|
echo "status=$status" >> "$GITHUB_OUTPUT"
|
|
cat "$RUNNER_TEMP/report.md" >> "$GITHUB_STEP_SUMMARY"
|
|
- name: Comment on the pull request
|
|
# The token of a pull request from a fork is read-only and cannot comment.
|
|
if: github.event.pull_request.head.repo.full_name == github.repository
|
|
# A failing comment must not change the result of the check.
|
|
continue-on-error: true
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
STATUS: ${{ steps.check.outputs.status }}
|
|
ISSUE_URL: repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}
|
|
COMMENTS_URL: repos/${{ github.repository }}/issues/comments
|
|
run: |
|
|
comment_id=$(gh api --paginate "$ISSUE_URL/comments" --jq \
|
|
'.[] | select(.user.login == "github-actions[bot]")
|
|
| select(.body | startswith(env.COMMENT_MARKER)) | .id' | head -n 1)
|
|
if [ -n "$comment_id" ]; then
|
|
gh api --method PATCH "$COMMENTS_URL/$comment_id" -F "body=@$RUNNER_TEMP/report.md" \
|
|
> /dev/null
|
|
elif [ "$STATUS" != "0" ]; then
|
|
gh api --method POST "$ISSUE_URL/comments" -F "body=@$RUNNER_TEMP/report.md" > /dev/null
|
|
fi
|
|
- name: Report the result
|
|
if: always()
|
|
env:
|
|
STATUS: ${{ steps.check.outputs.status }}
|
|
FROM_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
|
|
run: |
|
|
if [ "${STATUS:-1}" != "0" ]; then
|
|
if [ "$FROM_FORK" = "true" ]; then
|
|
echo "::error::The self-review check failed; see the job summary of this run."
|
|
else
|
|
echo "::error::The self-review check failed; see the job summary or the pull request comment."
|
|
fi
|
|
fi
|
|
exit "${STATUS:-1}"
|