From e8c11c2617081feefd399c9065845fc64111294b Mon Sep 17 00:00:00 2001 From: Patrick Dodgen Date: Mon, 22 Jun 2026 13:58:26 -0600 Subject: [PATCH] feat: parse rt tag format in deploy notifications (Phase 4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 4 of Release Train v2 (DEVEX-1654). Adds a parse step to both slack-deploy-notification.yaml and jellyfish-deploy-notification.yaml that classifies the image_tag input into one of: * v2 (RT v2): vX.Y.Z-rc.. → captures train_date + iter * v1 (legacy): vX.Y.Z-rc. → captures iter * plain: vX.Y.Z → 'clean release' * unknown: anything else → passthrough Slack message now reads, e.g., 'listings-url-service deployed — train 2026-06-18 · rc.3' instead of just the bare tag string. Captains can read the train and rc iter at a glance from #releases. Jellyfish event 'name' field gets a parenthetical suffix containing train + iter. Useful for the Phase 6 captain-handbook dashboard plotting iter@promotion per train per app over time. The reference_id is unchanged so existing dashboards don't break. Dual-format support is the migration-window concern from DEVEX-1654: during Phase 3 rollout, both v1 and v2 tags coexist; parsers handle both without an if/else at the caller layer. Verified the regex against likely tag formats: v4.7.0-rc.2026-06-18.3 → v2, train=2026-06-18, iter=3 v4.7.0-rc.7 → v1, iter=7 v4.7.0 → plain v4.7.0-rt.147.rc.3 → unknown (the abandoned spec format) --- .../jellyfish-deploy-notification.yaml | 29 ++++++++++++++- .../workflows/slack-deploy-notification.yaml | 36 +++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/.github/workflows/jellyfish-deploy-notification.yaml b/.github/workflows/jellyfish-deploy-notification.yaml index 8d0e99c..4e852e6 100644 --- a/.github/workflows/jellyfish-deploy-notification.yaml +++ b/.github/workflows/jellyfish-deploy-notification.yaml @@ -16,8 +16,35 @@ jobs: notify-jellyfish: runs-on: ubuntu-latest steps: + - name: Parse rt tag (if applicable) + id: parse + env: + IMAGE_TAG: ${{ inputs.image_tag }} + run: | + # Extract train_date + iter for RT v2 tags so the Jellyfish event + # carries enough information for the captain-handbook dashboard to + # plot iter@promotion per train. v1 legacy and plain semver also + # supported. + if [[ "$IMAGE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-rc\.([0-9]{4}-[0-9]{2}-[0-9]{2})\.([0-9]+)$ ]]; then + TRAIN="${BASH_REMATCH[1]}" + ITER="${BASH_REMATCH[2]}" + echo "format=v2" >> "$GITHUB_OUTPUT" + echo "train_date=$TRAIN" >> "$GITHUB_OUTPUT" + echo "iter=$ITER" >> "$GITHUB_OUTPUT" + echo "name_suffix= (train $TRAIN · rc.$ITER)" >> "$GITHUB_OUTPUT" + elif [[ "$IMAGE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-rc\.([0-9]+)$ ]]; then + ITER="${BASH_REMATCH[1]}" + echo "format=v1" >> "$GITHUB_OUTPUT" + echo "iter=$ITER" >> "$GITHUB_OUTPUT" + echo "name_suffix= (rc.$ITER legacy)" >> "$GITHUB_OUTPUT" + else + echo "format=plain" >> "$GITHUB_OUTPUT" + echo "name_suffix=" >> "$GITHUB_OUTPUT" + fi + - name: Dynamically set timestamp var run: echo TIMESTAMP_NOW=$(date --iso-8601=seconds) >> $GITHUB_ENV + - name: Notify Jellyfish of deployment run: | curl -i -X POST \ @@ -25,7 +52,7 @@ jobs: -H 'X-jf-api-token: ${{ secrets.jellyfish_api_token }}' \ -d '{ "reference_id": "${{ github.event.repository.name }}-${{ inputs.image_tag }}-${{ github.run_id }}", - "name": "${{ github.event.repository.name }} deployment of ${{ inputs.image_tag }} to ${{ inputs.environment }} complete", + "name": "${{ github.event.repository.name }} deployment of ${{ inputs.image_tag }}${{ steps.parse.outputs.name_suffix }} to ${{ inputs.environment }} complete", "deployed_at": "${{ env.TIMESTAMP_NOW }}", "repo_name": "${{ github.repository }}", "commit_shas": ["${{ github.sha }}"], diff --git a/.github/workflows/slack-deploy-notification.yaml b/.github/workflows/slack-deploy-notification.yaml index c8d4db1..2eca408 100644 --- a/.github/workflows/slack-deploy-notification.yaml +++ b/.github/workflows/slack-deploy-notification.yaml @@ -28,6 +28,38 @@ jobs: notify: runs-on: ubuntu-latest steps: + - name: Parse rt tag (if applicable) + id: parse + env: + IMAGE_TAG: ${{ inputs.image_tag }} + run: | + # Surface train identifier + iter for RT-style tags so captains + # see "rc.3 of train 2026-06-18" in #releases, not just the full + # tag string. Two formats supported: + # v2 (RT v2): vX.Y.Z-rc.. + # v1 legacy: vX.Y.Z-rc. + # Anything else (clean semver, custom suffix) gets a neutral + # summary so the notification still goes out. + if [[ "$IMAGE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-rc\.([0-9]{4}-[0-9]{2}-[0-9]{2})\.([0-9]+)$ ]]; then + TRAIN="${BASH_REMATCH[1]}" + ITER="${BASH_REMATCH[2]}" + echo "format=v2" >> "$GITHUB_OUTPUT" + echo "train_date=$TRAIN" >> "$GITHUB_OUTPUT" + echo "iter=$ITER" >> "$GITHUB_OUTPUT" + echo "summary=train $TRAIN · rc.$ITER" >> "$GITHUB_OUTPUT" + elif [[ "$IMAGE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-rc\.([0-9]+)$ ]]; then + ITER="${BASH_REMATCH[1]}" + echo "format=v1" >> "$GITHUB_OUTPUT" + echo "iter=$ITER" >> "$GITHUB_OUTPUT" + echo "summary=rc.$ITER (legacy v1)" >> "$GITHUB_OUTPUT" + elif [[ "$IMAGE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "format=plain" >> "$GITHUB_OUTPUT" + echo "summary=clean release" >> "$GITHUB_OUTPUT" + else + echo "format=unknown" >> "$GITHUB_OUTPUT" + echo "summary=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" + fi + - name: Send deployment notification uses: slackapi/slack-github-action@v1.24.0 env: @@ -36,13 +68,13 @@ jobs: with: payload: | { - "text": "${{ github.event.repository.name }} deployed", + "text": "${{ github.event.repository.name }} deployed — ${{ steps.parse.outputs.summary }}", "blocks": [ { "type": "section", "text": { "type": "mrkdwn", - "text": "*${{ github.event.repository.name }} deployed by ${{ github.triggering_actor }}*\n\tView the <${{ inputs.dashboard_url }}|Deployment>\n\tView the <${{ inputs.apm_url }}|Service APM>" + "text": "*${{ github.event.repository.name }} deployed* — _${{ steps.parse.outputs.summary }}_\nby ${{ github.triggering_actor }}\n\tView the <${{ inputs.dashboard_url }}|Deployment>\n\tView the <${{ inputs.apm_url }}|Service APM>" }, "accessory": { "type": "button",