Skip to content

STAC-25555: fail closed when Cerberus secrets are missing - #369

Draft
LouisParkin wants to merge 2 commits into
STAC-25533-cerberus-notifyfrom
STAC-25555-cerberus-fail-closed
Draft

STAC-25555: fail closed when Cerberus secrets are missing#369
LouisParkin wants to merge 2 commits into
STAC-25533-cerberus-notifyfrom
STAC-25555-cerberus-fail-closed

Conversation

@LouisParkin

Copy link
Copy Markdown
Contributor

Answers @LouisLotter's [P2] on #366: the unconfigured guard warned and exited 0, so it reported success in exactly the case where no Slack alert was sent, and the warning only ever rendered inside an unattended failed run. Missing or drifted secrets disabled the safeguard silently.

Now exits non-zero and names which secret is missing — the two are provisioned together, so exactly one missing means drift or a partial apply.

required: false stays. Louis offered "make these secrets required or return non-zero"; the second is strictly better. A caller passing ${{ secrets.X }} for a secret the repo lacks yields an empty string, which GitHub rejects against a required secret as "not provided" — failing the call before any step runs, with an opaque error and no annotation naming what to fix.

Held — do not merge yet

Blocked on StackVista/pulumi-infra#277 being merged and applied, per Louis's sequencing request. That PR grants the two secrets. Merging this first would add a second red job to every failed release-branch run that nobody could fix from this repo. Draft until then.

Also stacked under #366; base retargets to stackstate-7.78.2 when that merges.

Validation

actionlint, shellcheck (extracted run block), Zizmor — all clean. Guard exercised across all four secret states: passes only when both are set, exits 1 with the right name otherwise.

LouisParkin and others added 2 commits August 7, 2026 10:50
The unconfigured guard warned and exited 0. That reported success in exactly
the case where no Slack message was sent, and the warning rendered only inside
an unattended failed run, where nobody reads it. Missing or drifted secrets
therefore disabled the safeguard silently -- the failure mode the safeguard
exists to prevent.

Exit non-zero instead, and name the individual missing secret: the two are
provisioned together, so exactly one missing distinguishes a partial apply or
drift from a repo that was never wired up.

The `workflow_call` secrets stay `required: false`, which is not in tension
with this. A caller passing `${{ secrets.X }}` for a secret the repo does not
hold yields an empty string, and GitHub rejects that against a required secret
as "not provided" -- failing the call before any step runs, with an opaque
error and no annotation naming what to fix. Accepting the empty value and
checking it here fails just as closed and says who provisions what.

The job is `if: failure() && github.event_name == 'push'`, so the only run it
can ever redden is one that is already red. There the red is the point: it
distinguishes "the build broke" from "the alarm is broken too".

Raised by LouisLotter in review of #366.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
House convention is uncommented YAML. Removes every YAML-level comment from
this workflow, including the ones the previous commit added.

Shell comments inside the `run:` block are kept: they are string content
rather than YAML syntax, and they explain non-obvious runtime choices at the
point of use -- why the guard names each secret separately, and why curl is
not run with --verbose.

Verified as a pure comment removal: the parsed document is identical before
and after, and the `run:` block is byte-identical. actionlint and Zizmor clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant