From 474a7a527c2f7690130de7acffbf6c83f1b816c8 Mon Sep 17 00:00:00 2001 From: Patrick Dodgen Date: Thu, 9 Jul 2026 13:45:53 -0600 Subject: [PATCH] =?UTF-8?q?feat(slack):=20badge=20prod=20deploys=20as=20?= =?UTF-8?q?=F0=9F=9A=82=20RT=20or=20=E2=9A=A1=20Hotfix=20for=20P0=20triage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Peace Room ask (2026-07-09): during P0 triage the team needs to spot which prod deploys skipped the RT sign-off flow, since hotfixes see less scrutiny and are more likely culprits. Adds a classify-deploy-type step ahead of send-notification. The signal is already in the image_tag shape โ€” RT deploys tag vX.Y.Z-rc.YYYY-MM-DD.N, everything else (plain semver main deploys, feature-branch tags, ad-hoc) is treated as hotfix. No new inputs, no per-caller changes. Message prefix change: before: *webstore deployed by pdodgen* RT: ๐Ÿš‚ *RT* ยท *webstore deployed by pdodgen* Hotfix: โšก *Hotfix* ยท *webstore deployed by pdodgen* Fallback `text` field (used for notifications + screen readers) gets the plain-text badge form ("๐Ÿš‚ RT ยท webstore deployed"). Prod-only by structural design: callers only invoke this workflow from prod deploy paths (deploy-eks.yaml โ†’ slack-notification), so every message emitted here is a prod message. No env gate needed. Jellyfish parser (per previous dual-tag-format work) anchors on the version line and repo name, not the header prefix โ€” the added badge does not affect its regex. --- .../workflows/slack-deploy-notification.yaml | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/.github/workflows/slack-deploy-notification.yaml b/.github/workflows/slack-deploy-notification.yaml index 691e5e4..b997079 100644 --- a/.github/workflows/slack-deploy-notification.yaml +++ b/.github/workflows/slack-deploy-notification.yaml @@ -28,6 +28,41 @@ jobs: notify: runs-on: ubuntu-latest steps: + # Classify the deploy as Release Train (rt) or Hotfix based on the + # image tag shape. RT deploys tag `vX.Y.Z-rc.YYYY-MM-DD.N` โ€” the rc + # suffix with a train-date is the tell. Everything else (plain + # `vX.Y.Z` main deploys, feature-branch tags, ad-hoc) is treated + # as a hotfix / out-of-band deploy. + # + # Rationale (Peace Room 2026-07-09): during P0 triage the team needs + # to quickly spot which prod deploys skipped the RT sign-off flow, + # since hotfixes see less scrutiny and are more likely culprits. + # This runs unconditionally because the workflow is prod-only by + # structural design โ€” callers only invoke it from prod deploy + # paths (deploy-eks.yaml โ†’ slack-notification), so every message + # emitted here is a prod message. + - name: Classify deploy type + id: type + env: + IMAGE_TAG: ${{ inputs.image_tag }} + run: | + set -euo pipefail + if [[ "$IMAGE_TAG" =~ -rc\.[0-9]{4}-[0-9]{2}-[0-9]{2}\.[0-9]+$ ]]; then + BADGE_MRKDWN="๐Ÿš‚ *RT*" + BADGE_TEXT="๐Ÿš‚ RT" + CLASSIFICATION="release-train" + else + BADGE_MRKDWN="โšก *Hotfix*" + BADGE_TEXT="โšก Hotfix" + CLASSIFICATION="hotfix" + fi + echo "Classified $IMAGE_TAG as $CLASSIFICATION" + { + echo "badge_mrkdwn=$BADGE_MRKDWN" + echo "badge_text=$BADGE_TEXT" + echo "classification=$CLASSIFICATION" + } >> "$GITHUB_OUTPUT" + # Compute the previous production release tag by walking the GH # Releases API and picking the most recent non-current, non-draft, # non-prerelease entry. Callers gate this workflow on @@ -77,13 +112,13 @@ jobs: with: payload: | { - "text": "${{ github.event.repository.name }} deployed", + "text": "${{ steps.type.outputs.badge_text }} ยท ${{ github.event.repository.name }} deployed", "blocks": [ { "type": "section", "text": { "type": "mrkdwn", - "text": "*${{ github.event.repository.name }} deployed by ${{ github.triggering_actor }}*\n\tVersion: `${{ inputs.image_tag }}`\n\tView the <${{ inputs.dashboard_url }}|Deployment>\n\tView the <${{ inputs.apm_url }}|Service APM>${{ steps.diff.outputs.diff_line }}" + "text": "${{ steps.type.outputs.badge_mrkdwn }} ยท *${{ github.event.repository.name }} deployed by ${{ github.triggering_actor }}*\n\tVersion: `${{ inputs.image_tag }}`\n\tView the <${{ inputs.dashboard_url }}|Deployment>\n\tView the <${{ inputs.apm_url }}|Service APM>${{ steps.diff.outputs.diff_line }}" }, "accessory": { "type": "button",