@@ -48,7 +48,7 @@ inputs:
4848 cagent-version :
4949 description : " Version of cagent to use"
5050 required : false
51- default : " v1.23.4 "
51+ default : " v1.23.6 "
5252 model :
5353 description : " Model to use for reviews (e.g., anthropic/claude-sonnet-4-5, openai/gpt-4o)"
5454 required : false
@@ -64,7 +64,7 @@ outputs:
6464 value : ${{ steps.run-review.outputs.exit-code }}
6565 review-posted :
6666 description : " Whether a review was posted"
67- value : ${{ steps.run -review.outputs.review-posted }}
67+ value : ${{ steps.verify -review.outputs.review-verified }}
6868 review-url :
6969 description : " URL to the posted review"
7070 value : ${{ steps.post-summary.outputs.review-url }}
@@ -325,12 +325,18 @@ runs:
325325 # ========================================
326326 # RUN REVIEW using root cagent-action
327327 # ========================================
328+ - name : Record pre-review timestamp
329+ id : pre-review
330+ shell : bash
331+ run : echo "timestamp=$(date -u -d '5 seconds ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-5S +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_OUTPUT
332+
328333 - name : Run PR Review
329334 id : run-review
330335 uses : docker/cagent-action@latest
331336 with :
332337 agent : ${{ github.action_path }}/agents/pr-review.yaml
333338 prompt : ${{ steps.context.outputs.review_prompt }}
339+ timeout : " 1200" # 20 min — prevents GitHub App token expiry (1h limit)
334340 anthropic-api-key : ${{ inputs.anthropic-api-key }}
335341 openai-api-key : ${{ inputs.openai-api-key }}
336342 google-api-key : ${{ inputs.google-api-key }}
@@ -343,45 +349,46 @@ runs:
343349 extra-args : ${{ inputs.model && format('--model={0}', inputs.model) || '' }}
344350 add-prompt-files : ${{ inputs.add-prompt-files }}
345351
346- - name : Save reviewer memory
347- if : always()
348- continue-on-error : true # Don't fail if memory file doesn't exist (first run)
349- uses : actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
350- with :
351- path : ${{ github.workspace }}/.cache/pr-review-memory.db
352- key : pr-review-memory-${{ github.repository }}-${{ github.run_id }}
353-
354- - name : Clean up old memory caches
355- if : always()
352+ - name : Verify review was posted
353+ id : verify-review
356354 shell : bash
357355 env :
358- GH_TOKEN : ${{ steps.resolve-token.outputs.token }}
356+ GH_TOKEN : ${{ github.token }}
357+ PR_NUMBER : ${{ steps.resolve-context.outputs.pr-number }}
358+ PRE_REVIEW_TS : ${{ steps.pre-review.outputs.timestamp }}
359+ EXIT_CODE : ${{ steps.run-review.outputs.exit-code }}
359360 run : |
360- # Keep the 5 most recent caches, delete older ones
361- # This prevents proliferation while handling concurrent runs safely
362- CACHE_PREFIX="pr-review-memory-${{ github.repository }}-"
363-
364- echo "🧹 Cleaning up old memory caches (keeping 5 most recent)"
365-
366- # Get caches older than the 5 most recent (sorted by created_at descending, skip first 5)
367- OLD_CACHES=$(gh api "repos/${{ github.repository }}/actions/caches" \
368- --jq "[.actions_caches | map(select(.key | startswith(\"$CACHE_PREFIX\"))) | sort_by(.created_at) | reverse | .[5:] | .[].id] | .[]" \
369- 2>/dev/null || echo "")
370-
371- if [ -z "$OLD_CACHES" ]; then
372- echo "✅ No old caches to clean up"
361+ # If the agent failed, no review was posted
362+ if [ "$EXIT_CODE" != "0" ]; then
363+ echo "review-verified=false" >> $GITHUB_OUTPUT
373364 exit 0
374365 fi
375366
376- # Delete each old cache
377- DELETED=0
378- for CACHE_ID in $OLD_CACHES; do
379- if gh api "repos/${{ github.repository }}/actions/caches/$CACHE_ID" -X DELETE 2>/dev/null; then
380- ((DELETED++)) || true
381- fi
382- done
367+ # Check for a bot review submitted AFTER this run started
368+ API_ERR=$(mktemp)
369+ REVIEW_COUNT=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUMBER/reviews" \
370+ --jq --arg ts "$PRE_REVIEW_TS" \
371+ '[.[] | select(.user.type == "Bot" and .submitted_at >= $ts)] | length' \
372+ 2>"$API_ERR" || echo "0")
373+ if [ -s "$API_ERR" ]; then
374+ echo "::warning::Review verification API error: $(cat "$API_ERR")"
375+ fi
376+ rm -f "$API_ERR"
383377
384- echo "✅ Deleted $DELETED old cache(s)"
378+ if [ "$REVIEW_COUNT" -eq 0 ]; then
379+ echo "::warning::Review agent exited successfully but no review was found on the PR. The GitHub token may have expired during execution."
380+ echo "review-verified=false" >> $GITHUB_OUTPUT
381+ else
382+ echo "review-verified=true" >> $GITHUB_OUTPUT
383+ fi
384+
385+ - name : Save reviewer memory
386+ if : always()
387+ continue-on-error : true # Don't fail if memory file doesn't exist (first run)
388+ uses : actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
389+ with :
390+ path : ${{ github.workspace }}/.cache/pr-review-memory.db
391+ key : pr-review-memory-${{ github.repository }}-${{ github.run_id }}
385392
386393 # ========================================
387394 # POST-REVIEW: Clean summary & reactions
@@ -391,25 +398,43 @@ runs:
391398 if : always()
392399 shell : bash
393400 env :
401+ GH_TOKEN : ${{ github.token }}
394402 PR_NUMBER : ${{ steps.resolve-context.outputs.pr-number }}
395403 REPOSITORY : ${{ github.repository }}
396404 EXIT_CODE : ${{ steps.run-review.outputs.exit-code }}
405+ REVIEW_VERIFIED : ${{ steps.verify-review.outputs.review-verified }}
406+ RUN_URL : ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
397407 run : |
398408 REVIEW_URL="https://github.com/$REPOSITORY/pull/$PR_NUMBER"
399409 echo "review-url=$REVIEW_URL" >> $GITHUB_OUTPUT
400410
411+ # Determine status and post fallback comment if review wasn't posted
412+ if [ "$EXIT_CODE" != "0" ]; then
413+ STATUS="❌ **Review failed** (exit code: $EXIT_CODE)"
414+ if ! gh api "repos/$REPOSITORY/issues/$PR_NUMBER/comments" \
415+ -f body="❌ **PR Review Failed** — The review agent encountered an error and could not complete the review. [View logs]($RUN_URL)." \
416+ 2>&1; then
417+ echo "::warning::Failed to post fallback comment to PR"
418+ fi
419+ elif [ "$REVIEW_VERIFIED" == "false" ]; then
420+ STATUS="⚠️ **Review not posted** — agent completed but review was not found on the PR (possible token expiry)"
421+ if ! gh api "repos/$REPOSITORY/issues/$PR_NUMBER/comments" \
422+ -f body="⚠️ **PR Review Incomplete** — The review agent completed analysis but was unable to post the review due to an authentication timeout. [View logs]($RUN_URL)." \
423+ 2>&1; then
424+ echo "::warning::Failed to post fallback comment to PR"
425+ fi
426+ else
427+ STATUS="✅ **Review posted successfully**"
428+ fi
429+
401430 # Override the default summary with a cleaner one for PR reviews
402431 {
403432 echo ""
404433 echo "---"
405434 echo ""
406435 echo "## PR Review Summary"
407436 echo ""
408- if [ "$EXIT_CODE" == "0" ]; then
409- echo "✅ **Review posted successfully**"
410- else
411- echo "❌ **Review failed** (exit code: $EXIT_CODE)"
412- fi
437+ echo "$STATUS"
413438 echo ""
414439 echo "📝 [View Pull Request #$PR_NUMBER]($REVIEW_URL)"
415440 } >> $GITHUB_STEP_SUMMARY
@@ -418,9 +443,11 @@ runs:
418443 if : steps.resolve-context.outputs.comment-id != '' && always()
419444 shell : bash
420445 env :
421- GH_TOKEN : ${{ steps.resolve- token.outputs.token }}
446+ GH_TOKEN : ${{ github. token }} # Use github.token (6h lifetime) — App token may have expired
422447 EXIT_CODE : ${{ steps.run-review.outputs.exit-code }}
448+ REVIEW_VERIFIED : ${{ steps.verify-review.outputs.review-verified }}
423449 PR_NUMBER : ${{ steps.resolve-context.outputs.pr-number }}
450+ PRE_REVIEW_TS : ${{ steps.pre-review.outputs.timestamp }}
424451 run : |
425452 if [ "$EXIT_CODE" != "0" ]; then
426453 # Error: add confused reaction
@@ -429,9 +456,23 @@ runs:
429456 exit 0
430457 fi
431458
432- # Get the latest review state from the PR (use last? to handle empty arrays safely)
459+ if [ "$REVIEW_VERIFIED" == "false" ]; then
460+ # Agent succeeded but review wasn't posted (likely token expiry)
461+ gh api "repos/${{ github.repository }}/issues/comments/${{ steps.resolve-context.outputs.comment-id }}/reactions" \
462+ -X POST -f content='confused' || true
463+ exit 0
464+ fi
465+
466+ # Get the state of the review posted during THIS run
467+ API_ERR=$(mktemp)
433468 REVIEW_STATE=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUMBER/reviews" \
434- --jq '[.[] | select(.user.type == "Bot")] | last? | .state? // empty' 2>/dev/null || echo "")
469+ --jq --arg ts "$PRE_REVIEW_TS" \
470+ '[.[] | select(.user.type == "Bot" and .submitted_at >= $ts)] | last | .state // empty' \
471+ 2>"$API_ERR" || echo "")
472+ if [ -s "$API_ERR" ]; then
473+ echo "::warning::Review state API error: $(cat "$API_ERR")"
474+ fi
475+ rm -f "$API_ERR"
435476
436477 if [ "$REVIEW_STATE" == "APPROVED" ]; then
437478 # Approved: thumbs up
0 commit comments