From 8626467b83ea8667f29cf919ad78745625eba28e Mon Sep 17 00:00:00 2001 From: Priyanshu Dangare Date: Tue, 15 Sep 2026 00:16:29 +0530 Subject: [PATCH 1/2] ci: remove codex review gate --- .github/scripts/codex-review.cjs | 66 --------------- .github/scripts/codex-review.test.cjs | 111 -------------------------- .github/workflows/ci.yml | 25 ------ 3 files changed, 202 deletions(-) delete mode 100644 .github/scripts/codex-review.cjs delete mode 100644 .github/scripts/codex-review.test.cjs diff --git a/.github/scripts/codex-review.cjs b/.github/scripts/codex-review.cjs deleted file mode 100644 index c305a38..0000000 --- a/.github/scripts/codex-review.cjs +++ /dev/null @@ -1,66 +0,0 @@ -const {setTimeout: sleep} = require("node:timers/promises") - -/** Checks the latest authentic Codex summary for completed reviews of the current commit. */ -function isCompleted(comments, sha) { - const summary = comments - .filter( - (comment) => - comment.user?.id === 199175422 && - comment.user?.login === "chatgpt-codex-connector[bot]" && - comment.user?.type === "Bot" && - comment.body?.startsWith(""), - ) - .sort((a, b) => b.id - a.id)[0] - const rows = (summary?.body ?? "") - .split("
")[0] - .split("\n") - .filter((line) => line.startsWith("|")) - .slice(2) - .map((line) => line.split("|").map((cell) => cell.trim())) - return ( - rows.some((row) => row[1].includes("**Code Review**")) && - rows.every((row) => { - const commit = /^`([a-f0-9]{7,40})`$/.exec(row[3] ?? "")?.[1] - return ( - /^āœ…\s+\*\*Completed\*\*(?:\s|$)/u.test(row[2] ?? "") && - commit !== undefined && - sha.startsWith(commit) - ) - }) - ) -} - -/** Waits for the PR's current commit to receive a completed Codex review, failing closed. */ -async function waitForReview({github, context, core}) { - const pull = context.payload.pull_request - const sha = pull.head.sha - const deadline = Date.now() + 30 * 60 * 1000 - while (Date.now() < deadline) { - const {data: current} = await github.rest.pulls.get({ - ...context.repo, - pull_number: pull.number, - }) - if (current.state !== "open" || current.head.sha !== sha) { - core.setFailed( - "The pull request closed or its head changed; a new run must check the latest commit.", - ) - return - } - const comments = await github.paginate(github.rest.issues.listComments, { - ...context.repo, - issue_number: pull.number, - per_page: 100, - }) - if (isCompleted(comments, sha)) { - core.info(`Codex review completed for ${sha}.`) - return - } - core.info(`Waiting for Codex to complete its review of ${sha}.`) - await sleep(30_000) - } - core.setFailed( - "Codex review did not complete for this commit within 30 minutes. Request a Codex review, then rerun this job.", - ) -} - -module.exports = {isCompleted, waitForReview} diff --git a/.github/scripts/codex-review.test.cjs b/.github/scripts/codex-review.test.cjs deleted file mode 100644 index 0547ff4..0000000 --- a/.github/scripts/codex-review.test.cjs +++ /dev/null @@ -1,111 +0,0 @@ -const assert = require("node:assert/strict") -const {test} = require("node:test") -const {isCompleted, waitForReview} = require("./codex-review.cjs") - -const sha = "9fb059d" + "0".repeat(33) - -function summary(status = "āœ… **Completed**", commit = sha.slice(0, 7)) { - return { - id: 1, - user: {id: 199175422, login: "chatgpt-codex-connector[bot]", type: "Bot"}, - body: `\n\n| Review | Status | Commit | Review trigger |\n| --- | --- | --- | --- |\n| šŸ“ **Code Review** | ${status} now | \`${commit}\` | PR opened |`, - } -} - -test("accepts the authentic completed summary for the current head", () => { - assert.equal(isCompleted([summary()], sha), true) - assert.equal(isCompleted([summary(undefined, sha)], sha), true) -}) - -test("rejects missing, unfinished, failed, and stale reviews", () => { - assert.equal(isCompleted([], sha), false) - for (const status of [ - "šŸ”„ **Running**", - "āŒ **Failed**", - "āœ… **Not Completed**", - "Completed", - ]) { - assert.equal(isCompleted([summary(status)], sha), false) - } - assert.equal(isCompleted([summary(undefined, "aaaaaaa")], sha), false) - assert.equal(isCompleted([summary(undefined, "9")], sha), false) -}) - -test("rejects copied comments from another identity", () => { - const comment = summary() - assert.equal(isCompleted([{...comment, user: {...comment.user, id: 1}}], sha), false) - assert.equal(isCompleted([{...comment, user: {...comment.user, type: "User"}}], sha), false) -}) - -test("an older completed summary cannot override a newer running summary", () => { - assert.equal(isCompleted([summary(), {...summary("šŸ”„ **Running**"), id: 2}], sha), false) -}) - -test("requires all listed reviews to finish for the current commit", () => { - const comment = summary() - const security = `\n| šŸ” **Security Review** | šŸ”„ **Running** | \`${sha.slice(0, 7)}\` | Manual |` - assert.equal(isCompleted([{...comment, body: comment.body + security}], sha), false) - assert.equal( - isCompleted( - [ - { - ...comment, - body: comment.body + security.replace("šŸ”„ **Running**", "āœ… **Completed**"), - }, - ], - sha, - ), - true, - ) -}) - -test("ignores completion text outside the review table", () => { - const comment = summary("šŸ”„ **Running**") - assert.equal( - isCompleted([{...comment, body: comment.body + "\nāœ… **Completed**"}], sha), - false, - ) -}) - -test("the action succeeds for a completed review", async () => { - const messages = [] - await waitForReview({ - context: { - repo: {owner: "owner", repo: "repo"}, - payload: {pull_request: {number: 5, head: {sha}}}, - }, - github: { - rest: { - pulls: {get: async () => ({data: {state: "open", head: {sha}}})}, - issues: {listComments: {}}, - }, - paginate: async () => [summary()], - }, - core: { - info: (message) => { - messages.push(message) - }, - setFailed: assert.fail, - }, - }) - assert.match(messages[0], /completed/) -}) - -test("a superseded head fails before accepting an old review", async () => { - const failures = [] - await waitForReview({ - context: { - repo: {owner: "owner", repo: "repo"}, - payload: {pull_request: {number: 5, head: {sha}}}, - }, - github: { - rest: {pulls: {get: async () => ({data: {state: "open", head: {sha: "changed"}}})}}, - }, - core: { - setFailed: (message) => { - failures.push(message) - }, - }, - }) - assert.match(failures[0], /head changed/) -}) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47b2dc4..386779d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,31 +19,6 @@ env: LEFTHOOK: "0" jobs: - codex-review: - name: Codex Review - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - timeout-minutes: 35 - permissions: - contents: read - issues: read - pull-requests: read - steps: - - name: Checkout - uses: actions/checkout@v6 - with: - persist-credentials: false - - - name: Test review gate - run: node --test .github/scripts/codex-review.test.cjs - - - name: Wait for completed Codex review - uses: actions/github-script@v8 - with: - script: | - const {waitForReview} = require('./.github/scripts/codex-review.cjs') - await waitForReview({github, context, core}) - formatting: name: Formatting runs-on: ubuntu-latest From 40fa5fde16a615dbb25cc1718f5b977f476aa7a3 Mon Sep 17 00:00:00 2001 From: Priyanshu Dangare Date: Tue, 15 Sep 2026 00:16:30 +0530 Subject: [PATCH 2/2] ci: upgrade github actions to latest releases --- .github/actions/setup-project/action.yml | 2 +- .github/workflows/ci.yml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/actions/setup-project/action.yml b/.github/actions/setup-project/action.yml index 5e3bf0a..fae79d5 100644 --- a/.github/actions/setup-project/action.yml +++ b/.github/actions/setup-project/action.yml @@ -5,7 +5,7 @@ runs: using: composite steps: - name: Set up pnpm and Node - uses: pnpm/setup@v1 + uses: pnpm/setup@v2.1.0 with: runtime: node@24 cache: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 386779d..b958ef2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: timeout-minutes: 10 steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7.0.1 - name: Set up project uses: ./.github/actions/setup-project @@ -39,7 +39,7 @@ jobs: timeout-minutes: 10 steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7.0.1 - name: Set up project id: setup @@ -58,7 +58,7 @@ jobs: - name: Upload build if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@v7.0.1 with: name: build path: packages/client/dist @@ -71,7 +71,7 @@ jobs: timeout-minutes: 10 steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7.0.1 - name: Set up project id: setup @@ -97,11 +97,11 @@ jobs: working-directory: cli steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7.0.1 - name: Set up Ruff id: setup - uses: astral-sh/ruff-action@v4.0.0 + uses: astral-sh/ruff-action@v4.1.0 with: version: "0.16.6" args: "--version" @@ -121,13 +121,13 @@ jobs: timeout-minutes: 10 steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7.0.1 - name: Set up project uses: ./.github/actions/setup-project - name: Download build - uses: actions/download-artifact@v8 + uses: actions/download-artifact@v8.0.1 with: name: build path: packages/client/dist