Skip to content
Merged
Show file tree
Hide file tree
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
105 changes: 105 additions & 0 deletions .github/workflows/cerberus-notify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
name: Cerberus notify

# Ported from the `notify-on-master-fail` job in the retired .gitlab-ci.yml as
# part of the GitLab -> GitHub migration (STAC-25142 / STAC-25519). The GitHub
# migration in STAC-25420 dropped it, which left a failing master completely
# silent -- image publishing broke on 2026-07-23 and went unnoticed for 12 days
# (STAC-25510).
#
# Called by ci.yml as a terminal job so a failed master build reaches the team's
# Slack CI channel. Cerberus is the internal notify/block Lambda (source:
# https://gitlab.com/stackvista/devops/cerberus); the calling convention here
# follows `cerberus-block-on-master-fail` in StackVista/stackstate's
# .github/workflows/ci.yml, with `platform: github` in the context so Cerberus
# builds 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`) on every master failure,
# additionally requires the Cerberus GitHub App to be installed on the repo, and
# mutates Pulumi-managed branch protection out from under it.
#
# The repo's own .cerberus/cerberus_notify_failure.sh is not reused -- it was
# deleted with the GitLab files, was built around GitLab's CI_* variables, and
# predates the `platform` field.
#
# Prerequisite: CERBERUS_LAMBDA_URL must reach this repo as a REPO-level secret.
# The org-level copy is visibility=private, which excludes this PUBLIC repo, and
# widening it is not an option: the Cerberus endpoint is unauthenticated, so the
# URL is the whole capability. Until the pulumi-infra change applies, this
# workflow warns and exits 0 rather than adding a second red job to an already
# failed run -- the annotation is the signal.
#
# 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:
suite:
description: Suite label shown in the Slack message, e.g. build.
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

# Nothing here reads the repository; the payload is built entirely from the
# github context.
permissions: {}

jobs:
notify:
name: Notify Slack via Cerberus
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- name: Post the failure to Cerberus
env:
CERBERUS_LAMBDA_URL: ${{ secrets.CERBERUS_LAMBDA_URL }}
REPOSITORY: ${{ github.repository }}
BRANCH: ${{ github.ref_name }}
PIPELINE: ${{ github.run_id }}
COMMIT_SHA: ${{ github.sha }}
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
SUITE: ${{ inputs.suite }}
run: |
set -euo pipefail

if [ -z "${CERBERUS_LAMBDA_URL}" ]; then
echo "::warning title=Cerberus not configured::CERBERUS_LAMBDA_URL is not visible to this repo, so the ${SUITE} failure was not reported to Slack. Needs the repo-level secret from pulumi-infra (STAC-25519)."
exit 0
fi

COMMIT_TITLE=$(printf '%s' "${COMMIT_MESSAGE}" | head -n1)

curl --verbose --fail \
-X POST "${CERBERUS_LAMBDA_URL}" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg repo "${REPOSITORY}" \
--arg branch "${BRANCH}" \
--arg pipeline "${PIPELINE}" \
--arg sha "${COMMIT_SHA}" \
--arg title "${COMMIT_TITLE}" \
--arg suite "${SUITE}" \
'{
action: "notify",
context: {
platform: "github",
"project.id": $repo,
"project.slug": $repo,
"project.name": "StackState Process Agent",
branch: $branch,
pipeline: $pipeline,
"commit.sha": $sha,
"commit.title": $title,
suite: $suite
}
}'
)"
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,20 @@ jobs:
exit 1
fi
echo "All required process-agent jobs passed."

# Terminal job, master only. ci-success aggregates every other job, so hanging
# the notification off it means one funnel for all failures rather than a
# notify job per pipeline job. Replaces `notify-on-master-fail` from the
# retired .gitlab-ci.yml (STAC-25519).
cerberus-notify:
name: Report failure to Slack (Cerberus)
needs: ci-success
if: >-
failure() &&
github.ref == 'refs/heads/master' &&
github.event_name == 'push'
uses: ./.github/workflows/cerberus-notify.yml
with:
suite: build
secrets:
CERBERUS_LAMBDA_URL: ${{ secrets.CERBERUS_LAMBDA_URL }}
Loading