From 0334f70991a926dfff5b097284f12bf2aa04e3d1 Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Fri, 27 Mar 2026 11:55:03 -0400 Subject: [PATCH 1/3] ci(ai-review): remove custom Claude CLI path to prevent version drift claude-code-action@v1 auto-updates its bundled Claude Code and Agent SDK. The custom path_to_claude_code_executable forced the runner's stale CLI (v2.1.39) to be used instead, causing validateHeaders auth failures when the SDK updated to 0.2.85. Let the action manage its own installation. Closes #810 --- .github/workflows/ai-review.yml | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/.github/workflows/ai-review.yml b/.github/workflows/ai-review.yml index 9c8b47fd..b8bda4ce 100644 --- a/.github/workflows/ai-review.yml +++ b/.github/workflows/ai-review.yml @@ -63,7 +63,6 @@ jobs: author_association: ${{ steps.context.outputs.author_association }} contributor_source: ${{ steps.context.outputs.contributor_source }} runs_on: ${{ steps.context.outputs.runs_on }} - claude_path: ${{ steps.context.outputs.claude_path }} # Conditions: # - PR event: on opened, synchronize (new commits), or reopened @@ -108,11 +107,9 @@ jobs: if [ "$HEAD_REPO" = "$REPOSITORY" ]; then CONTRIBUTOR_SOURCE="internal" RUNS_ON='["self-hosted","cliproxy"]' - CLAUDE_PATH="/home/github-runner/.local/bin/claude" else CONTRIBUTOR_SOURCE="external" RUNS_ON='["ubuntu-latest"]' - CLAUDE_PATH="" fi { @@ -124,7 +121,6 @@ jobs: echo "author_association=$AUTHOR_ASSOCIATION" echo "contributor_source=$CONTRIBUTOR_SOURCE" echo "runs_on=$RUNS_ON" - echo "claude_path=$CLAUDE_PATH" } >> "$GITHUB_OUTPUT" review: @@ -173,23 +169,6 @@ jobs: echo "XDG_STATE_HOME=$REVIEW_STATE_HOME" } >> "$GITHUB_ENV" - - name: Resolve runner Bun executable - id: bun-path - if: needs.prepare.outputs.contributor_source == 'internal' - run: | - RUNNER_BUN="" - if command -v bun >/dev/null 2>&1; then - RUNNER_BUN="$(command -v bun)" - fi - - echo "path=$RUNNER_BUN" >> "$GITHUB_OUTPUT" - - if [ -n "$RUNNER_BUN" ]; then - echo "[i] Using runner Bun executable: $RUNNER_BUN" - else - echo "[i] No runner Bun executable found; Claude action will install Bun" - fi - - name: Generate App Token id: app-token uses: actions/create-github-app-token@v1 @@ -244,8 +223,6 @@ jobs: anthropic_api_key: ${{ secrets.GLM_API_KEY }} github_token: ${{ steps.app-token.outputs.token }} allowed_non_write_users: ${{ needs.prepare.outputs.contributor_source == 'external' && '*' || '' }} - path_to_claude_code_executable: ${{ needs.prepare.outputs.claude_path }} - path_to_bun_executable: ${{ steps.bun-path.outputs.path }} track_progress: false # Disabled - no progress comments, just final review prompt: | ultrathink From 6dca069c7d4642b24c2270cd51e0f0c0d2c900d8 Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Fri, 27 Mar 2026 12:02:11 -0400 Subject: [PATCH 2/3] ci(ai-review): enable show_full_output for review visibility Allows seeing Claude's full output in CI logs instead of the opaque "full output hidden for security" message. Helps debug slow reviews and identify bottlenecks. --- .github/workflows/ai-review.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ai-review.yml b/.github/workflows/ai-review.yml index b8bda4ce..02b3fac1 100644 --- a/.github/workflows/ai-review.yml +++ b/.github/workflows/ai-review.yml @@ -223,6 +223,7 @@ jobs: anthropic_api_key: ${{ secrets.GLM_API_KEY }} github_token: ${{ steps.app-token.outputs.token }} allowed_non_write_users: ${{ needs.prepare.outputs.contributor_source == 'external' && '*' || '' }} + show_full_output: true # Visible logs for debugging slow/failing reviews track_progress: false # Disabled - no progress comments, just final review prompt: | ultrathink From bb5862f0a01772f975cc95bc2b6581c8b1bb454a Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Fri, 27 Mar 2026 12:09:24 -0400 Subject: [PATCH 3/3] ci(ai-review): upgrade model, add fallback extraction, preserve logs - Upgrade review model from glm-5 to glm-5.1 - Add fallback step: if Claude doesn't write pr_review.md, extract last assistant message from execution output as review content - Upload claude-execution-output.json as artifact (7-day retention) so review sessions can be inspected after the job completes - Publish review comment runs on always() instead of only on success, so fallback-extracted reviews still get posted --- .github/workflows/ai-review.yml | 49 +++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ai-review.yml b/.github/workflows/ai-review.yml index 02b3fac1..c300cb9d 100644 --- a/.github/workflows/ai-review.yml +++ b/.github/workflows/ai-review.yml @@ -137,11 +137,11 @@ jobs: # GLM API environment for model routing env: ANTHROPIC_BASE_URL: https://api.z.ai/api/anthropic - REVIEW_MODEL: glm-5 + REVIEW_MODEL: glm-5.1 ANTHROPIC_AUTH_TOKEN: ${{ secrets.GLM_API_KEY }} - ANTHROPIC_MODEL: glm-5 - ANTHROPIC_DEFAULT_OPUS_MODEL: glm-5 - ANTHROPIC_DEFAULT_SONNET_MODEL: glm-5 + ANTHROPIC_MODEL: glm-5.1 + ANTHROPIC_DEFAULT_OPUS_MODEL: glm-5.1 + ANTHROPIC_DEFAULT_SONNET_MODEL: glm-5.1 ANTHROPIC_DEFAULT_HAIKU_MODEL: GLM-4.7-FlashX DISABLE_BUG_COMMAND: '1' DISABLE_ERROR_REPORTING: '1' @@ -259,8 +259,36 @@ jobs: --model ${{ env.REVIEW_MODEL }} --allowedTools "Edit,Glob,Grep,LS,Read,Write,Bash(gh pr diff *),Bash(gh pr view *),Bash(gh issue view *),Bash(git diff *),Bash(git log *),Bash(git status *),Bash(cat *),Bash(ls *)" + # Fallback: if Claude didn't write the review file, extract from execution output + - name: Extract review from execution output (fallback) + if: always() && steps.claude-review.outcome != 'cancelled' + run: | + EXEC_LOG="$RUNNER_TEMP/claude-execution-output.json" + if [ -s "$REVIEW_OUTPUT_FILE" ]; then + echo "[i] Review file exists, skipping fallback extraction" + exit 0 + fi + if [ ! -f "$EXEC_LOG" ]; then + echo "::warning::No execution output found at $EXEC_LOG" + exit 0 + fi + # Extract last assistant text message as fallback review + EXTRACTED=$(jq -r ' + [.[] | select(.type == "assistant") | .message.content[]? + | select(.type == "text") | .text] | last // empty + ' "$EXEC_LOG" 2>/dev/null || true) + if [ -z "$EXTRACTED" ]; then + echo "::warning::Could not extract review content from execution output" + printf '## AI Review (incomplete)\n\nClaude completed but did not produce a structured review.\nCheck the [execution log artifact](%s) for details.\n\n> Reviewed by `%s` (fallback extraction)\n' \ + "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ + "$REVIEW_MODEL" > "$REVIEW_OUTPUT_FILE" + else + printf '%s\n' "$EXTRACTED" > "$REVIEW_OUTPUT_FILE" + fi + echo "[i] Fallback review extracted from execution output" + - name: Publish review comment - if: steps.claude-review.outcome == 'success' + if: always() && steps.claude-review.outcome != 'cancelled' env: GH_TOKEN: ${{ steps.app-token.outputs.token }} REVIEW_MARKER: >- @@ -271,7 +299,7 @@ jobs: sha:${{ needs.prepare.outputs.head_sha }} --> run: | if [ ! -s "$REVIEW_OUTPUT_FILE" ]; then - echo "::error::Claude review finished without writing $REVIEW_OUTPUT_FILE" + echo "::error::No review content available (neither Claude nor fallback produced output)" exit 1 fi @@ -297,6 +325,15 @@ jobs: echo "[i] Posted review comment for PR #${{ needs.prepare.outputs.pr_number }}" fi + - name: Upload execution log + if: always() + uses: actions/upload-artifact@v4 + with: + name: claude-review-pr${{ needs.prepare.outputs.pr_number }}-run${{ github.run_id }} + path: ${{ runner.temp }}/claude-execution-output.json + retention-days: 7 + if-no-files-found: ignore + - name: Add success reaction if: success() && github.event_name == 'issue_comment' run: |