From 4e129204640daf98334f863f93626a1a96028e5b Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 27 May 2026 16:48:49 -0700 Subject: [PATCH 1/4] Add eyes reactions to Codex review workflow Show review-in-progress on the PR description or triggering comment, then remove the reaction when the review finishes. Co-authored-by: Cursor --- .github/workflows/codex-review.yml | 79 ++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/.github/workflows/codex-review.yml b/.github/workflows/codex-review.yml index 7d532af06045..dd0964b697e7 100644 --- a/.github/workflows/codex-review.yml +++ b/.github/workflows/codex-review.yml @@ -60,6 +60,32 @@ jobs: GITHUB_TOKEN: ${{ github.token }} OS_BOTIFY_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} + - name: Add review in progress reaction + if: steps.gate.outputs.IS_AUTHORIZED == 'true' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v7 + env: + PR_NUMBER: ${{ env.PR_NUMBER }} + with: + script: | + const {owner, repo} = context.repo; + + if (context.eventName === 'pull_request_target') { + await github.rest.reactions.createForIssue({ + owner, + repo, + issue_number: Number(process.env.PR_NUMBER), + content: 'eyes', + }); + return; + } + + await github.rest.reactions.createForIssueComment({ + owner, + repo, + comment_id: context.payload.comment.id, + content: 'eyes', + }); + - name: Build Codex prompt from PR diff if: steps.gate.outputs.IS_AUTHORIZED == 'true' env: @@ -102,6 +128,59 @@ jobs: sandbox: read-only prompt-file: prompt.txt + - name: Remove review in progress reaction + if: always() && steps.gate.outputs.IS_AUTHORIZED == 'true' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v7 + env: + PR_NUMBER: ${{ env.PR_NUMBER }} + with: + script: | + const {owner, repo} = context.repo; + const botLogin = 'github-actions[bot]'; + + const deleteEyesReaction = async (reactions, deleteReaction) => { + const eyesReaction = reactions.find( + (reaction) => reaction.content === 'eyes' && reaction.user.login === botLogin, + ); + + if (eyesReaction) { + await deleteReaction(eyesReaction.id); + } + }; + + if (context.eventName === 'pull_request_target') { + const {data: reactions} = await github.rest.reactions.listForIssue({ + owner, + repo, + issue_number: Number(process.env.PR_NUMBER), + }); + + await deleteEyesReaction(reactions, (reactionId) => + github.rest.reactions.deleteForIssue({ + owner, + repo, + issue_number: Number(process.env.PR_NUMBER), + reaction_id: reactionId, + }), + ); + return; + } + + const {data: reactions} = await github.rest.reactions.listForIssueComment({ + owner, + repo, + comment_id: context.payload.comment.id, + }); + + await deleteEyesReaction(reactions, (reactionId) => + github.rest.reactions.deleteForIssueComment({ + owner, + repo, + comment_id: context.payload.comment.id, + reaction_id: reactionId, + }), + ); + - name: Post Codex feedback if: steps.gate.outputs.IS_AUTHORIZED == 'true' && steps.codex.outputs.final-message != '' uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v7 From 024aa5b33750eb4383a2de81e079da243124af65 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 27 May 2026 16:48:56 -0700 Subject: [PATCH 2/4] Post LGTM when Codex review has no feedback Comment with LGTM :+1: when Codex succeeds but returns an empty message. Co-authored-by: Cursor --- .github/workflows/codex-review.yml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/codex-review.yml b/.github/workflows/codex-review.yml index dd0964b697e7..ffa17087fbfa 100644 --- a/.github/workflows/codex-review.yml +++ b/.github/workflows/codex-review.yml @@ -182,7 +182,7 @@ jobs: ); - name: Post Codex feedback - if: steps.gate.outputs.IS_AUTHORIZED == 'true' && steps.codex.outputs.final-message != '' + if: steps.gate.outputs.IS_AUTHORIZED == 'true' && steps.codex.outcome == 'success' uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v7 env: PR_NUMBER: ${{ env.PR_NUMBER }} @@ -190,13 +190,17 @@ jobs: WORKFLOW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} with: script: | - const body = [ - '## Codex review', - '', - process.env.CODEX_FINAL_MESSAGE, - '', - `_[Workflow run](${process.env.WORKFLOW_RUN_URL})_`, - ].join('\n'); + const codexMessage = process.env.CODEX_FINAL_MESSAGE?.trim() ?? ''; + const body = + codexMessage === '' + ? 'LGTM :+1:' + : [ + '## Codex review', + '', + codexMessage, + '', + `_[Workflow run](${process.env.WORKFLOW_RUN_URL})_`, + ].join('\n'); await github.rest.issues.createComment({ owner: context.repo.owner, From 74831fbfce1cb9c6bb5ee7f3b707a7ffb0f8675f Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 27 May 2026 17:05:04 -0700 Subject: [PATCH 3/4] Switch to GitHub runner --- .github/workflows/codex-review.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codex-review.yml b/.github/workflows/codex-review.yml index ffa17087fbfa..1fbbfcb6a443 100644 --- a/.github/workflows/codex-review.yml +++ b/.github/workflows/codex-review.yml @@ -34,7 +34,7 @@ jobs: concurrency: group: codex-review-${{ github.event.pull_request.number || github.event.issue.number }} cancel-in-progress: true - runs-on: blacksmith-2vcpu-ubuntu-2404 + runs-on: ubuntu-latest permissions: contents: read pull-requests: read @@ -45,7 +45,7 @@ jobs: ACTOR_ASSOCIATION: ${{ case(github.event_name == 'pull_request_target', github.event.pull_request.author_association, github.event.comment.author_association) }} steps: - name: Checkout - uses: useblacksmith/checkout@c9796daa2a4bdebdab5bd16be2c09a70cd4e1121 # v1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # Important: `pull_request_target` should never checkout the PR head. ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.base.sha || github.sha }} From af5c2c42328ea2020a65789c8a3cbe644f122df9 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 27 May 2026 17:06:15 -0700 Subject: [PATCH 4/4] Move cleanup step to the end --- .github/workflows/codex-review.yml | 56 +++++++++++++++--------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/codex-review.yml b/.github/workflows/codex-review.yml index 1fbbfcb6a443..8c34d67b1349 100644 --- a/.github/workflows/codex-review.yml +++ b/.github/workflows/codex-review.yml @@ -128,6 +128,34 @@ jobs: sandbox: read-only prompt-file: prompt.txt + - name: Post Codex feedback + if: steps.gate.outputs.IS_AUTHORIZED == 'true' && steps.codex.outcome == 'success' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v7 + env: + PR_NUMBER: ${{ env.PR_NUMBER }} + CODEX_FINAL_MESSAGE: ${{ steps.codex.outputs.final-message }} + WORKFLOW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + with: + script: | + const codexMessage = process.env.CODEX_FINAL_MESSAGE?.trim() ?? ''; + const body = + codexMessage === '' + ? 'LGTM :+1:' + : [ + '## Codex review', + '', + codexMessage, + '', + `_[Workflow run](${process.env.WORKFLOW_RUN_URL})_`, + ].join('\n'); + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: Number(process.env.PR_NUMBER), + body, + }); + - name: Remove review in progress reaction if: always() && steps.gate.outputs.IS_AUTHORIZED == 'true' uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v7 @@ -180,31 +208,3 @@ jobs: reaction_id: reactionId, }), ); - - - name: Post Codex feedback - if: steps.gate.outputs.IS_AUTHORIZED == 'true' && steps.codex.outcome == 'success' - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v7 - env: - PR_NUMBER: ${{ env.PR_NUMBER }} - CODEX_FINAL_MESSAGE: ${{ steps.codex.outputs.final-message }} - WORKFLOW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - with: - script: | - const codexMessage = process.env.CODEX_FINAL_MESSAGE?.trim() ?? ''; - const body = - codexMessage === '' - ? 'LGTM :+1:' - : [ - '## Codex review', - '', - codexMessage, - '', - `_[Workflow run](${process.env.WORKFLOW_RUN_URL})_`, - ].join('\n'); - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: Number(process.env.PR_NUMBER), - body, - });