From a612f21eff82195ccb6c7de4b3c049e0ad524ae1 Mon Sep 17 00:00:00 2001 From: idy Date: Thu, 3 Sep 2026 13:06:55 +0800 Subject: [PATCH] workflows: report a withheld review payload instead of crashing GitHub withholds a job output whose value matches a registered secret. When that happened to the review output, the publish step ran JSON.parse(process.env.REVIEW) on an empty string and died with "SyntaxError: Unexpected end of JSON input", and the job surfaced the generic "GitHub could not publish the generated pull-request review". The completed review was lost and the real cause was invisible. Guard both payloads and fail with a reason that names the withheld output, so the log points at the secret match rather than at a JSON parse error. Co-Authored-By: Claude Opus 5 --- .github/workflows/codex-openai-review.yml | 26 +++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codex-openai-review.yml b/.github/workflows/codex-openai-review.yml index 6bbe89d..263bafa 100644 --- a/.github/workflows/codex-openai-review.yml +++ b/.github/workflows/codex-openai-review.yml @@ -1151,8 +1151,30 @@ jobs: script: | const maxCommentLength = 60_000; const maxFindingLength = 12_000; - const review = JSON.parse(process.env.REVIEW); - const readiness = JSON.parse(process.env.READINESS_EVIDENCE); + // A job output is withheld when its value matches a repository or + // organization secret, which leaves the variable empty here. Report + // that instead of dying inside JSON.parse with a bare SyntaxError. + const requirePayload = (name) => { + const raw = process.env[name] ?? ''; + if (raw.trim() === '') { + const reason = `The review job produced no ${name} payload. GitHub withholds a job output whose value matches a registered secret; check the review job log for "Skip output".`; + core.setOutput('failure_reason', reason); + core.setFailed(reason); + return undefined; + } + try { + return JSON.parse(raw); + } catch (error) { + const reason = `The ${name} payload was not valid JSON: ${error.message}`; + core.setOutput('failure_reason', reason); + core.setFailed(reason); + return undefined; + } + }; + const review = requirePayload('REVIEW'); + if (review === undefined) return; + const readiness = requirePayload('READINESS_EVIDENCE'); + if (readiness === undefined) return; const count = (value) => Number(value || 0).toLocaleString('en-US'); const duration = (value) => { const seconds = Math.max(0, Number(value || 0));