Background
A completed review was lost on GizClaw/gizclaw#1068 and the reported reason pointed at the wrong thing.
The review job of codex-openai-review.yml finished and produced a full review payload. GitHub then refused to set the job output:
##[warning]Skip output 'review' since it may contain secret
A job output is withheld when its value matches a registered repository or organization secret. needs.review.outputs.review was therefore empty, and the first statements of the publish step ran JSON.parse(process.env.REVIEW) on an empty string. The step died with SyntaxError: Unexpected end of JSON input, and the job's failure_reason fell through to the generic GitHub could not publish the generated pull-request review. The findings and the credits spent producing them were both lost, and nothing in the reported reason named the real cause.
Neighbouring parses in the same script already guard their input, for example JSON.parse(process.env.USAGE_JSON || '{}'); the REVIEW and READINESS_EVIDENCE parses did not.
Goal
Make the publish step fail with the real reason when a payload it depends on is missing or malformed, so an operator can act on a withheld output instead of reading a JSON parse error.
This issue owns the input handling of the publish step in codex-openai-review.yml.
Non-goals
- No change to how the review payload travels between jobs. Moving it to an artifact would also sidestep the 1 MB job-output limit, but it is a larger change and belongs to its own issue.
- No encoding of the payload to slip past the secret masker. The masker exists to stop a real leak; defeating it would publish a genuine secret if one ever appeared.
- No change to the secret value itself. A secret stored with stray whitespace or newlines is a configuration fix outside this repository.
Code Changes Tree
.github/workflows/
└── codex-openai-review.yml # guard the REVIEW and READINESS_EVIDENCE parses and report the withheld or malformed payload
No documentation change is required: the repository has no guide describing the publish step's internal error handling, and the workflow's observable inputs, outputs and job graph are unchanged.
Design
Both payloads go through one helper in the publish step's inline script. For an empty or whitespace-only value it sets failure_reason to a message naming the payload and pointing at the Skip output warning in the review job log, then calls core.setFailed and returns. For a value that is present but not valid JSON it reports the parse error separately, so a truncated payload is distinguishable from a withheld one. Behaviour is unchanged when both payloads are present.
The helper runs before any GitHub API call, so a failed run makes no partial publication.
Test And Acceptance Criteria
Acceptance Criteria
- When GitHub withholds the
review output, the publish step fails with a reason that names the payload and directs the reader to the Skip output warning, instead of SyntaxError: Unexpected end of JSON input.
- When a payload is present but malformed, the reported reason distinguishes the parse failure from a missing payload.
- When both payloads are present, the review publishes exactly as before.
Validation
actionlint .github/workflows/codex-openai-review.yml
node --check <extracted publish script>
actionlint reports only the pre-existing job.workflow_repository and job.workflow_sha warnings, which predate this change and do not sit on the changed lines. End-to-end confirmation is the next review run on a pull request: a run with both payloads present publishes normally, and a run with a withheld output reports the named reason.
Background
A completed review was lost on GizClaw/gizclaw#1068 and the reported reason pointed at the wrong thing.
The
reviewjob ofcodex-openai-review.ymlfinished and produced a full review payload. GitHub then refused to set the job output:A job output is withheld when its value matches a registered repository or organization secret.
needs.review.outputs.reviewwas therefore empty, and the first statements of thepublishstep ranJSON.parse(process.env.REVIEW)on an empty string. The step died withSyntaxError: Unexpected end of JSON input, and the job'sfailure_reasonfell through to the genericGitHub could not publish the generated pull-request review.The findings and the credits spent producing them were both lost, and nothing in the reported reason named the real cause.Neighbouring parses in the same script already guard their input, for example
JSON.parse(process.env.USAGE_JSON || '{}'); theREVIEWandREADINESS_EVIDENCEparses did not.Goal
Make the publish step fail with the real reason when a payload it depends on is missing or malformed, so an operator can act on a withheld output instead of reading a JSON parse error.
This issue owns the input handling of the
publishstep incodex-openai-review.yml.Non-goals
Code Changes Tree
No documentation change is required: the repository has no guide describing the publish step's internal error handling, and the workflow's observable inputs, outputs and job graph are unchanged.
Design
Both payloads go through one helper in the
publishstep's inline script. For an empty or whitespace-only value it setsfailure_reasonto a message naming the payload and pointing at theSkip outputwarning in the review job log, then callscore.setFailedand returns. For a value that is present but not valid JSON it reports the parse error separately, so a truncated payload is distinguishable from a withheld one. Behaviour is unchanged when both payloads are present.The helper runs before any GitHub API call, so a failed run makes no partial publication.
Test And Acceptance Criteria
Acceptance Criteria
reviewoutput, thepublishstep fails with a reason that names the payload and directs the reader to theSkip outputwarning, instead ofSyntaxError: Unexpected end of JSON input.Validation
actionlintreports only the pre-existingjob.workflow_repositoryandjob.workflow_shawarnings, which predate this change and do not sit on the changed lines. End-to-end confirmation is the next review run on a pull request: a run with both payloads present publishes normally, and a run with a withheld output reports the named reason.