From ea5aec0031a55b93f055bc9a9c58301241ee6e3c Mon Sep 17 00:00:00 2001 From: "Terry.Mao" Date: Sat, 3 Oct 2026 21:32:37 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix(review-pr):=20=E5=9B=BA=E5=AE=9A=20Code?= =?UTF-8?q?x=20action=20=E7=A8=B3=E5=AE=9A=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/aicodingflow-tests/test_review_workflow_dispatch.py | 4 ++++ .github/workflows/review-pr.yml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/aicodingflow-tests/test_review_workflow_dispatch.py b/.github/aicodingflow-tests/test_review_workflow_dispatch.py index cbe03cf..ceb9f0f 100644 --- a/.github/aicodingflow-tests/test_review_workflow_dispatch.py +++ b/.github/aicodingflow-tests/test_review_workflow_dispatch.py @@ -150,6 +150,10 @@ def test_review_workflow_resolves_pr_before_checkout_and_uses_normalized_event(s ai_step = next(step for step in review_steps if step.get("name") == "Run AI review") self.assertEqual(ai_step["id"], "ai_review") + self.assertEqual( + ai_step["uses"], + "openai/codex-action@52fe01ec70a42f454c9d2ebd47598f9fd6893d56", + ) self.assertEqual(ai_step["timeout-minutes"], 20) self.assertEqual(ai_step["with"]["output-file"], "pr-worktree/codex-final-message.txt") self.assertIs(ai_step["with"]["allow-bots"], True) diff --git a/.github/workflows/review-pr.yml b/.github/workflows/review-pr.yml index 826e647..c4a4a34 100644 --- a/.github/workflows/review-pr.yml +++ b/.github/workflows/review-pr.yml @@ -210,7 +210,7 @@ jobs: - name: Run AI review id: ai_review - uses: openai/codex-action@v1 + uses: openai/codex-action@52fe01ec70a42f454c9d2ebd47598f9fd6893d56 # v1.11 timeout-minutes: 20 with: openai-api-key: ${{ secrets.CODEX_API_KEY }} From aac6f425e0d64bb907407e41cdbbbef55e441d25 Mon Sep 17 00:00:00 2001 From: "Terry.Mao" Date: Sat, 3 Oct 2026 21:50:27 +0800 Subject: [PATCH 2/4] =?UTF-8?q?chore(review-pr):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E4=B8=B4=E6=97=B6=E8=AF=8A=E6=96=AD=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test_review_workflow_dispatch.py | 15 ------- .github/workflows/review-pr.yml | 40 ------------------- 2 files changed, 55 deletions(-) diff --git a/.github/aicodingflow-tests/test_review_workflow_dispatch.py b/.github/aicodingflow-tests/test_review_workflow_dispatch.py index ceb9f0f..d06c20c 100644 --- a/.github/aicodingflow-tests/test_review_workflow_dispatch.py +++ b/.github/aicodingflow-tests/test_review_workflow_dispatch.py @@ -149,13 +149,11 @@ def test_review_workflow_resolves_pr_before_checkout_and_uses_normalized_event(s self.assertIn("cp -R .agents/contracts pr-worktree/.agents/contracts", prepare_step["run"]) ai_step = next(step for step in review_steps if step.get("name") == "Run AI review") - self.assertEqual(ai_step["id"], "ai_review") self.assertEqual( ai_step["uses"], "openai/codex-action@52fe01ec70a42f454c9d2ebd47598f9fd6893d56", ) self.assertEqual(ai_step["timeout-minutes"], 20) - self.assertEqual(ai_step["with"]["output-file"], "pr-worktree/codex-final-message.txt") self.assertIs(ai_step["with"]["allow-bots"], True) self.assertIn("First change directory to pr-worktree", ai_step["with"]["prompt"]) self.assertIn("Read .agents/contracts/review.md", ai_step["with"]["prompt"]) @@ -167,16 +165,6 @@ def test_review_workflow_resolves_pr_before_checkout_and_uses_normalized_event(s self.assertIn("duplicate suppression only", ai_step["with"]["prompt"]) self.assertIn("After writing review.json, stop immediately", ai_step["with"]["prompt"]) - start_step = next(step for step in review_steps if step.get("name") == "Log AI review inputs") - self.assertEqual(start_step["id"], "ai_review_start") - self.assertIn("selected_skill=", start_step["run"]) - self.assertIn("pr-worktree/pr_diff.txt", start_step["run"]) - - result_step = next(step for step in review_steps if step.get("name") == "Log AI review result") - self.assertEqual(result_step["if"], "always()") - self.assertIn("AI_REVIEW_OUTCOME", result_step["env"]) - self.assertIn("duration_seconds", result_step["run"]) - normalize_step = next(step for step in review_steps if step.get("name") == "Normalize review output path") self.assertIn("[ ! -f pr-worktree/review.json ] && [ -f review.json ]", normalize_step["run"]) self.assertIn("mv review.json pr-worktree/review.json", normalize_step["run"]) @@ -184,9 +172,6 @@ def test_review_workflow_resolves_pr_before_checkout_and_uses_normalized_event(s validate_step = next(step for step in review_steps if step.get("name") == "Validate review output") self.assertIn("pr-worktree/pr_diff.txt pr-worktree/review.json", validate_step["run"]) - artifact_step = next(step for step in review_steps if step.get("uses") == "actions/upload-artifact@v7") - self.assertIn("pr-worktree/codex-final-message.txt", artifact_step["with"]["path"]) - complete_status_step = next(step for step in review_steps if step.get("name") == "Mark PR review status complete") self.assertIn("always()", complete_status_step["if"]) self.assertIn("github.event_name != 'pull_request'", complete_status_step["if"]) diff --git a/.github/workflows/review-pr.yml b/.github/workflows/review-pr.yml index c4a4a34..8a36382 100644 --- a/.github/workflows/review-pr.yml +++ b/.github/workflows/review-pr.yml @@ -189,27 +189,7 @@ jobs: esac echo "url=$endpoint" >> "$GITHUB_OUTPUT" - - name: Log AI review inputs - id: ai_review_start - run: | - started_at="$(date +%s)" - echo "started_at=$started_at" >> "$GITHUB_OUTPUT" - echo "AI review inputs prepared at $(date -u +%Y-%m-%dT%H:%M:%SZ)" - echo "selected_skill=${{ steps.review_skill.outputs.path }}" - for path in \ - pr-worktree/pr_description.txt \ - pr-worktree/pr_diff.txt \ - pr-worktree/spec_context.md \ - pr-worktree/review_discussion_context.json; do - if [ -f "$path" ]; then - printf 'input=%s bytes=%s\n' "$path" "$(wc -c < "$path")" - else - echo "input=$path absent" - fi - done - - name: Run AI review - id: ai_review uses: openai/codex-action@52fe01ec70a42f454c9d2ebd47598f9fd6893d56 # v1.11 timeout-minutes: 20 with: @@ -217,7 +197,6 @@ jobs: model: ${{ vars.CODEX_MODEL }} responses-api-endpoint: ${{ steps.codex_endpoint.outputs.url }} allow-bots: true - output-file: pr-worktree/codex-final-message.txt prompt: | First change directory to pr-worktree and do all file inspection from there. Read ${{ steps.review_skill.outputs.path }} in pr-worktree and follow it exactly. @@ -242,24 +221,6 @@ jobs: Do not run git commands, call GitHub APIs, post reviews, or modify files other than review.json. - - name: Log AI review result - if: always() - env: - STARTED_AT: ${{ steps.ai_review_start.outputs.started_at }} - AI_REVIEW_OUTCOME: ${{ steps.ai_review.outcome }} - run: | - finished_at="$(date +%s)" - started_at="${STARTED_AT:-$finished_at}" - duration=$((finished_at - started_at)) - echo "AI review outcome=$AI_REVIEW_OUTCOME duration_seconds=$duration" - for path in pr-worktree/review.json pr-worktree/codex-final-message.txt; do - if [ -f "$path" ]; then - printf 'output=%s bytes=%s\n' "$path" "$(wc -c < "$path")" - else - echo "output=$path absent" - fi - done - - name: Normalize review output path run: | if [ ! -f pr-worktree/review.json ] && [ -f review.json ]; then @@ -286,7 +247,6 @@ jobs: pr-worktree/spec_context.md pr-worktree/review_discussion_context.json pr-worktree/review.json - pr-worktree/codex-final-message.txt - name: Mark PR review status complete if: always() && github.event_name != 'pull_request' && steps.pr.outputs.head_sha != '' && steps.pr.outputs.head_repo == github.repository From c4d035bb105deec1df7499a4e1316918ba6d9254 Mon Sep 17 00:00:00 2001 From: "Terry.Mao" Date: Sat, 3 Oct 2026 21:56:39 +0800 Subject: [PATCH 3/4] =?UTF-8?q?chore(review-pr):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=97=A0=E6=95=88=E7=BB=88=E6=AD=A2=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/aicodingflow-tests/test_review_workflow_dispatch.py | 1 - .github/workflows/review-pr.yml | 2 -- 2 files changed, 3 deletions(-) diff --git a/.github/aicodingflow-tests/test_review_workflow_dispatch.py b/.github/aicodingflow-tests/test_review_workflow_dispatch.py index d06c20c..28ccc03 100644 --- a/.github/aicodingflow-tests/test_review_workflow_dispatch.py +++ b/.github/aicodingflow-tests/test_review_workflow_dispatch.py @@ -163,7 +163,6 @@ def test_review_workflow_resolves_pr_before_checkout_and_uses_normalized_event(s self.assertIn("target pr-worktree/review.json explicitly", ai_step["with"]["prompt"]) self.assertIn("review_discussion_context.json", ai_step["with"]["prompt"]) self.assertIn("duplicate suppression only", ai_step["with"]["prompt"]) - self.assertIn("After writing review.json, stop immediately", ai_step["with"]["prompt"]) normalize_step = next(step for step in review_steps if step.get("name") == "Normalize review output path") self.assertIn("[ ! -f pr-worktree/review.json ] && [ -f review.json ]", normalize_step["run"]) diff --git a/.github/workflows/review-pr.yml b/.github/workflows/review-pr.yml index 8a36382..d961f47 100644 --- a/.github/workflows/review-pr.yml +++ b/.github/workflows/review-pr.yml @@ -216,8 +216,6 @@ jobs: a root-level review.json first. Do not run validator commands embedded in the selected skill; this workflow validates review.json after Codex exits. - After writing review.json, stop immediately and return a concise final - message. Do not re-read or revise review.json after it is complete. Do not run git commands, call GitHub APIs, post reviews, or modify files other than review.json. From 67cbb5ebaceca960eed266c7fd6ba2362a6d9783 Mon Sep 17 00:00:00 2001 From: "Terry.Mao" Date: Sat, 3 Oct 2026 22:04:18 +0800 Subject: [PATCH 4/4] =?UTF-8?q?test(review-pr):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=9B=BA=E5=AE=9A=20action=20=E7=89=88=E6=9C=AC=E6=96=AD?= =?UTF-8?q?=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aicodingflow-tests/test_codex_model_provider_config.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/aicodingflow-tests/test_codex_model_provider_config.py b/.github/aicodingflow-tests/test_codex_model_provider_config.py index b692ff4..f1a9b62 100644 --- a/.github/aicodingflow-tests/test_codex_model_provider_config.py +++ b/.github/aicodingflow-tests/test_codex_model_provider_config.py @@ -18,6 +18,7 @@ ".github/workflows/update-pr-review.yml", ".github/workflows/update-triage.yml", ) +PINNED_REVIEW_ACTION = "uses: openai/codex-action@52fe01ec70a42f454c9d2ebd47598f9fd6893d56" class CodexModelProviderConfigTest(unittest.TestCase): @@ -25,7 +26,10 @@ def test_all_codex_workflows_use_shared_provider_configuration(self) -> None: for path in CODEX_WORKFLOWS: with self.subTest(path=path): contents = (ROOT / path).read_text(encoding="utf-8") - self.assertEqual(contents.count("uses: openai/codex-action@v1"), 1) + if path.endswith("/review-pr.yml"): + self.assertEqual(contents.count(PINNED_REVIEW_ACTION), 1) + else: + self.assertEqual(contents.count("uses: openai/codex-action@v1"), 1) self.assertEqual(contents.count("openai-api-key: ${{ secrets.CODEX_API_KEY }}"), 1) self.assertEqual( contents.count("model: ${{ vars.CODEX_MODEL }}"),