name: CI true: push: branches: - main pull_request: types: - opened - synchronize jobs: test: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.26' - run: go test ./... - run: go vet ./... - run: go build -o review-bot ./cmd/review-bot review: runs-on: ubuntu-24.04 if: github.event_name == 'pull_request' && needs.review-gate.outputs.allow_review == 'true' needs: - test - review-gate strategy: matrix: include: - name: sonnet token_secret: SONNET_REVIEW_TOKEN model: anthropic--claude-4.6-sonnet - name: gpt token_secret: GPT_REVIEW_TOKEN model: gpt-5 - name: security token_secret: SECURITY_REVIEW_TOKEN model: gpt-5 patterns_repo: rodin/security-patterns patterns_files: . system_prompt_file: SECURITY_REVIEW.md steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: '1.26' - run: go build -o review-bot ./cmd/review-bot - name: Run ${{ matrix.name }} review env: VCS_URL: ${{ github.server_url }} GITEA_REPO: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }} REVIEWER_TOKEN: ${{ secrets[matrix.token_secret] }} REVIEWER_NAME: ${{ matrix.name }} LLM_PROVIDER: aicore LLM_MODEL: ${{ matrix.model }} AICORE_CLIENT_ID: ${{ secrets.AICORE_CLIENT_ID }} AICORE_CLIENT_SECRET: ${{ secrets.AICORE_CLIENT_SECRET }} AICORE_AUTH_URL: ${{ secrets.AICORE_AUTH_URL }} AICORE_API_URL: ${{ secrets.AICORE_API_URL }} AICORE_RESOURCE_GROUP: ${{ secrets.AICORE_RESOURCE_GROUP }} CONVENTIONS_FILE: CONVENTIONS.md PATTERNS_REPO: ${{ matrix.patterns_repo || 'rodin/go-patterns' }} PATTERNS_FILES: ${{ matrix.patterns_files || 'README.md,patterns/' }} LLM_TIMEOUT: '600' SYSTEM_PROMPT_FILE: ${{ matrix.system_prompt_file }} run: ./review-bot review-gate: runs-on: ubuntu-24.04 if: github.event_name == 'pull_request' outputs: allow_review: ${{ steps.gate.outputs.allow_review }} reason: ${{ steps.gate.outputs.reason }} steps: - name: Check self-review gate id: gate env: GITEA_TOKEN: ${{ secrets.RODIN_TOKEN }} run: 'REPO=${{ github.repository }} PR=${{ github.event.pull_request.number }} SHA=${{ github.event.pull_request.head.sha }} TTL_MIN=${SELF_REVIEW_TTL_MIN} API="${{ github.server_url }}/api/v1" PR_JSON=$(curl -sS -H "Authorization: token $GITEA_TOKEN" "$API/repos/$REPO/pulls/$PR") UPDATED_AT=$(echo "$PR_JSON" | jq -r .updated_at) NOW=$(date -u +%s) PR_TS=$(date -u -d "$UPDATED_AT" +%s) AGE_MIN=$(( (NOW - PR_TS) / 60 )) COMMENTS=$(curl -sS -H "Authorization: token $GITEA_TOKEN" "$API/repos/$REPO/issues/$PR/comments?limit=200") HAS_SR=$(echo "$COMMENTS" | jq -r --arg sha "$SHA" "[.[] | select(.user.login=="rodin") | select(.body|contains("Self-review against "+\$sha)) | select(.body|test("(?im)^### \\s+Doc consistency\\b"))] | length") if [ "$HAS_SR" -gt 0 ]; then ALLOW=true; REASON=self-review; elif [ "$AGE_MIN" -ge "$TTL_MIN" ]; then ALLOW=true; REASON=ttl; else ALLOW=false; REASON=missing; fi echo "allow_review=$ALLOW" >> $GITHUB_OUTPUT echo "reason=$REASON" >> $GITHUB_OUTPUT' env: SELF_REVIEW_TTL_MIN: '45' 'on': pull_request: types: - opened - synchronize push: branches: - main