Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 17 additions & 50 deletions .github/workflows/cerberus-notify.yml
Original file line number Diff line number Diff line change
@@ -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 <token>` 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:
Expand All @@ -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:
Expand All @@ -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)
Expand Down