diff --git a/.github/workflows/cerberus-notify.yml b/.github/workflows/cerberus-notify.yml index 2b08e387..d049d157 100644 --- a/.github/workflows/cerberus-notify.yml +++ b/.github/workflows/cerberus-notify.yml @@ -1,44 +1,5 @@ name: Cerberus notify -# New capability, not a port (STAC-25142 / STAC-25533). Unlike stackstate-agent -# and stackstate-process-agent, this repo's retired .gitlab-ci.yml had no notify -# job and no .cerberus directory, so a failed release-branch pipeline has always -# been silent here. STAC-25510 is what that costs: process-agent's image -# publishing broke on 2026-07-23 and went unnoticed for 12 days. -# -# Structure and calling convention follow -# stackstate-process-agent/.github/workflows/cerberus-notify.yml, which in turn -# follows `cerberus-block-on-master-fail` in StackVista/stackstate. Cerberus is -# the internal notify/block Lambda (source: https://github.com/StackVista/cerberus). -# `platform: github` makes it build GitHub pipeline/commit URLs rather than -# GitLab ones. -# -# `action: notify`, never `action: block`. Policy for migrated repos is notify by -# default. Blocking locks the branch (`lock_branch`), additionally requires the -# Cerberus GitHub App to be installed here, and mutates branch protection that -# pulumi-infra owns (STAC-25522) out from under it -- a subsequent pulumi apply -# would silently unlock the branch again. -# -# Prerequisites: CERBERUS_LAMBDA_URL and CERBERUS_API_TOKEN must both reach this -# repo as REPO-level secrets. The org-level copies are visibility=private, which -# excludes this PUBLIC repo. pulumi-infra provisions the pair together -# (github/repoVariables/resources.yaml, StackVista/pulumi-infra#277). If either -# is missing, this workflow warns and exits 0 rather than adding a second red job -# to an already-failed run -- the annotation is the signal. -# -# The bearer token is not optional going forward. StackVista/cerberus#4 -# (STAC-24889) adds `Authorization: Bearer ` verification to every -# non-Slack request; before it, the endpoint was entirely unauthenticated. -# Sending the header is forward-compatible -- the currently deployed Lambda -# ignores unknown headers -- so this works either side of that deploy. Without -# it, the first failure after cerberus#4 ships would get a 401 and no Slack -# message. -# -# The Slack channel is deliberately not sent. Cerberus resolves it as -# `util.GetOrDefault(req.Context, "channel", s.Channel)`, and GetOrDefault treats -# an empty or whitespace value as absent, so omitting `channel` falls back to the -# Lambda's own SLACK_CHANNEL. - on: workflow_call: inputs: @@ -47,17 +8,11 @@ on: required: true type: string secrets: - # `required: false`. A caller passing `${{ secrets.X }}` for a secret the - # repo does not hold yields an empty string, which GitHub rejects as "not - # provided" against a required secret and fails the call before the run - # step's guard can warn -- the failure mode this workflow exists to avoid. CERBERUS_LAMBDA_URL: required: false CERBERUS_API_TOKEN: required: false -# Nothing here reads the repository; the payload is built entirely from the -# github context. permissions: {} jobs: @@ -74,16 +29,28 @@ jobs: BRANCH: ${{ github.ref_name }} PIPELINE: ${{ github.run_id }} COMMIT_SHA: ${{ github.sha }} - # Empty on tag pushes, which carry no head_commit. COMMIT_TITLE below - # falls back to the sha so the Slack message is never blank. COMMIT_MESSAGE: ${{ github.event.head_commit.message }} SUITE: ${{ inputs.suite }} run: | set -euo pipefail - if [ -z "${CERBERUS_LAMBDA_URL}" ] || [ -z "${CERBERUS_API_TOKEN}" ]; then - echo "::warning title=Cerberus not configured::CERBERUS_LAMBDA_URL and/or CERBERUS_API_TOKEN is not visible to this repo, so the ${SUITE} failure was not reported to Slack. Both are provisioned as repo-level secrets by pulumi-infra (STAC-25533)." - exit 0 + # Fail closed (STAC-25555). Naming the individual secret matters: the + # two are provisioned together, so exactly one missing means drift or a + # partial apply rather than a repo that was never wired up. + missing="" + if [ -z "${CERBERUS_LAMBDA_URL}" ]; then + missing="CERBERUS_LAMBDA_URL" + fi + if [ -z "${CERBERUS_API_TOKEN}" ]; then + if [ -n "${missing}" ]; then + missing="${missing} and CERBERUS_API_TOKEN" + else + missing="CERBERUS_API_TOKEN" + fi + fi + if [ -n "${missing}" ]; then + echo "::error title=Cerberus not configured::Missing secret(s): ${missing}. Not visible to this repository, so the ${SUITE} failure was NOT reported to Slack. Both are provisioned as repo-level secrets by pulumi-infra (github/repoVariables/resources.yaml, STAC-25533). This job fails rather than passing silently, because a notification path that quietly stops working is worse than a visibly broken one." + exit 1 fi COMMIT_TITLE=$(printf '%s' "${COMMIT_MESSAGE}" | head -n1)