fix(release): the workflow has been invalid since #512 — secrets is not allowed in an if: - #558
Merged
Merged
Conversation
…s not allowed in an `if:` `Release` has not been dispatchable since 2026-08-23. Every push since has recorded a failed run, and the last twenty are all the same failure. ── WHAT WAS WRONG ───────────────────────────────────────────────────────────── The four signing steps #512 added were gated as: if: runner.os == 'macOS' && secrets.MACOS_CERT_P12_BASE64 != '' && ... `secrets` is not a context GitHub allows in a step-level `if:`. It rejects the file at PARSE time -- "Unrecognized named-value: 'secrets'", lines 500, 598, 608 and 644 -- so the whole workflow was invalid, not just those steps. ── WHY NOBODY NOTICED FOR THREE DAYS ────────────────────────────────────────── An unparseable workflow cannot report its own name. GitHub recorded each failure under the FILE PATH (`.github/workflows/release.yml`) rather than under `name: Release`, with zero jobs, on a `push` event -- for a workflow that is `workflow_dispatch`-only and should never run on push at all. Three signals that each look like noise: a run nobody triggered, for a workflow nobody recognises, that failed before doing anything. It was then masked entirely: an unrelated org billing lock started failing every workflow on 2026-08-26 with a three-second "account is locked" error, and this became one red X among many. ── THE FIX, AND THE ONE IT IS NOT ───────────────────────────────────────────── The usual remedy is a job-level `env:` block, because `env` IS allowed in `if:`. Rejected here: it would put every signing certificate and notarisation key into the environment of EVERY step in the job -- `uv sync`, the PyInstaller build, the lot -- which is the exposure #512's own "protected signing environment" exists to prevent. So the secrets stay scoped to the single step that reads them, and what leaves that step is a boolean. `steps.signing.outputs.{macos,windows}` is `yes`/`no`, nothing derived from a certificate reaches an output, and the four conditions read the boolean instead. `shell: bash` on that step because it runs on both macOS and Windows runners and the Windows default is pwsh. ── WHAT THIS MEANS FOR D5 ───────────────────────────────────────────────────── The signing and notarisation work in #512 has never executed. The workflow could not be dispatched, so no release has been cut through it since it landed. This restores the ability to dispatch; whether signing then WORKS is unverified and needs a real run with the secrets present. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T6yA5khYnJ2qzheArRToQ2
eaitbrahim
added a commit
that referenced
this pull request
Aug 26, 2026
…, and one they missed (#559) `main` is red because I merged #558 without running the suite. Three tests in `test_desktop_packaging.py` assert the signing gates by looking for `secrets.X != ''` inside each step's `if:` -- the exact expression #558 had to remove, because GitHub rejects `secrets` in an `if:` at parse time. The GUARANTEE is unchanged and is still pinned: all five Apple credentials or none, both Windows credentials or none, and each skip notice firing on the exact complement of its sign step. What moved is where that is decided -- from four `if:` conditions into one `signing` step whose outputs the conditions read -- so the assertions move with it. ── AND A PIN FOR THE FAILURE THESE TESTS COULD NOT SEE ──────────────────────── The old tests asserted that a string appeared in a condition. That says nothing about whether GitHub can PARSE the file, which is why they were green for the three days the workflow was undispatchable. Two new pins close that: * no `secrets` in any `if:`, in any job or step -- the thing that made the whole workflow invalid; * no signing credential in a job-level `env:` -- the obvious fix for the first one, and the wrong one, because it exposes every certificate to `uv sync`, the PyInstaller build and every other step in the job. All three are mutation-checked: restoring a secret to an `if:` fails two tests, dropping one credential from the gate fails a third, and hoisting a secret to job-level env fails the fourth. ── THE PROCESS FAILURE, RECORDED ────────────────────────────────────────────── I validated #558's YAML, checked its structure, and let GitHub's own parser confirm the fix -- and did not run `pytest`, because it was "only a workflow file". This repository pins its workflows WITH tests; that is the whole reason those three existed. The suite is not optional on a workflow change here. Claude-Session: https://claude.ai/code/session_01T6yA5khYnJ2qzheArRToQ2 Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Releasehas not been dispatchable since 2026-08-23, when #512 landed. Every push since hasrecorded a failed run; the last twenty are all the same failure.
What was wrong
The four signing steps #512 added were gated on the
secretscontext in a step-levelif::secretsis not a context GitHub allows inif:. It rejects the file at parse time —Unrecognized named-value: 'secrets'at lines 500, 598, 608 and 644 — so the entire workflow wasinvalid, not just those steps.
Why it went unnoticed for three days
An unparseable workflow can't report its own name. GitHub recorded each failure under the file
path (
.github/workflows/release.yml) rather thanname: Release, with zero jobs, on apushevent — for a workflow that isworkflow_dispatch-only and should never run on push atall. Three signals that each individually look like noise: a run nobody triggered, for a workflow
nobody recognises, failing before it did anything.
Then it was masked completely. An unrelated org billing lock began failing every workflow on
2026-08-26 with a three-second "account is locked" error, and this became one red X among many.
The fix, and the one it deliberately isn't
The usual remedy is a job-level
env:block, sinceenvis allowed inif:. Rejected here:that would put every signing certificate and notarisation key into the environment of every step
in the job —
uv sync, the PyInstaller build, all of it — which is precisely the exposure #512's own"protected signing environment" exists to prevent.
So the secrets stay scoped to the single step that reads them, and what leaves that step is a
boolean.
steps.signing.outputs.{macos,windows}isyes/no; nothing derived from a certificatereaches an output (outputs are visible in the run's API payload); the four conditions read the
boolean.
shell: bashon that step because it runs on both macOS and Windows runners and theWindows default is pwsh.
Verification
GitHub's parser is the only authority here, so I let it judge:
release.ymlrun at all.main).chore-pwa-archdid produceone (09:22), so a feature-branch push does generate the synthetic failure while the file is
invalid. It no longer does.
Locally: parses as YAML, no duplicate keys,
desktopjob structurally intact with the newsigningstep id and all four conditions rewritten.What this means for D5
The signing and notarisation work in #512 has never executed. The workflow could not be
dispatched, so no release has been cut through it since it landed. This restores the ability to
dispatch it; whether signing then works is unverified and needs a real run with the secrets
present on the
signingenvironment.🤖 Generated with Claude Code
https://claude.ai/code/session_01T6yA5khYnJ2qzheArRToQ2