From 42dc14023f9980558c543654044c534cd58e282d Mon Sep 17 00:00:00 2001 From: Piotr Zaniewski Date: Thu, 2 Jul 2026 11:03:30 +0200 Subject: [PATCH] feat(ci-test-notify): add info status for informational notices Callers that want a standalone Slack ping (a deploy landed, an RC reached staging) had no fitting status: success and failure force a pass/fail header with a "Success"/"Failed" suffix that misreads an informational notice, and the fallback case renders "Unknown". Add an `info` status that always notifies (still suppressed on an empty webhook, same as before) and renders a rocket header with no status suffix. This lets hosted-platform's staging RC notification reuse this action instead of hand-rolling a jq+curl Slack POST that duplicates the gate, payload, and send logic already living here (DEVOPS-577). --- .github/actions/ci-test-notify/README.md | 33 +++++++++++++++---- .github/actions/ci-test-notify/action.yml | 2 +- .../actions/ci-test-notify/build-payload.sh | 6 +++- .../actions/ci-test-notify/should-notify.sh | 4 +++ .../ci-test-notify/test/build-payload.bats | 7 ++++ .../ci-test-notify/test/should-notify.bats | 6 ++++ 6 files changed, 50 insertions(+), 8 deletions(-) diff --git a/.github/actions/ci-test-notify/README.md b/.github/actions/ci-test-notify/README.md index da88580..e1264dc 100644 --- a/.github/actions/ci-test-notify/README.md +++ b/.github/actions/ci-test-notify/README.md @@ -8,12 +8,12 @@ Replaces the nightly-specific `ci-notify-nightly-tests` action with a generic in -| INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION | -|-------------|--------|----------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| details | string | false | | Markdown text appended after the build
URL (test results, versions, artifact links, etc.) | -| status | string | true | | Run status, typically `needs..result` or `job.status`.
`success` and `failure` notify; `cancelled` and
`skipped` are treated as no-ops and
send nothing. | -| test-name | string | true | | Test suite name for the header
(e.g. "E2E Ginkgo Nightly Tests"). Keep under ~130 chars โ€”
Slack header blocks have a 150-char
limit and the status suffix takes
~15 chars. | -| webhook-url | string | true | | Slack incoming webhook URL | +| INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION | +|-------------|--------|----------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| details | string | false | | Markdown text appended after the build
URL (test results, versions, artifact links, etc.) | +| status | string | true | | Run status, typically `needs..result` or `job.status`.
`success` and `failure` notify; `cancelled` and
`skipped` are treated as no-ops and
send nothing. Use `info` for a
standalone informational notice (e.g. a deploy) that always
notifies with no pass/fail suffix. | +| test-name | string | true | | Test suite name for the header
(e.g. "E2E Ginkgo Nightly Tests"). Keep under ~130 chars โ€”
Slack header blocks have a 150-char
limit and the status suffix takes
~15 chars. | +| webhook-url | string | true | | Slack incoming webhook URL | @@ -29,6 +29,9 @@ Build URL: ยท Run # ``` +`status: info` renders a ๐Ÿš€ header with no `[status]` suffix, for informational +notices (e.g. a deploy) rather than pass/fail results. + ## Usage ### Nightly E2E tests @@ -58,6 +61,24 @@ Build URL: webhook-url: ${{ secrets.SLACK_WEBHOOK_URL_CI_TESTS_ALERTS }} ``` +### Informational deploy notice + +`info` always notifies (no pass/fail suffix) and uses a ๐Ÿš€ header, for a +standalone notice such as a release candidate landing in staging: + +```yaml +- uses: loft-sh/github-actions/.github/actions/ci-test-notify@ci-test-notify/v1 + with: + test-name: Release candidate deployed to staging.vcluster.cloud + status: info + details: | + โ€ข vcluster-platform: `4.10.0-rc.1` + + QA: spin up an instance on staging, verify it's healthy, then tick the + pre-release checklist. + webhook-url: ${{ secrets.SLACK_WEBHOOK_URL_QA }} +``` + ### Failure-only with summary ```yaml diff --git a/.github/actions/ci-test-notify/action.yml b/.github/actions/ci-test-notify/action.yml index 4f40dd6..34ba79f 100644 --- a/.github/actions/ci-test-notify/action.yml +++ b/.github/actions/ci-test-notify/action.yml @@ -8,7 +8,7 @@ inputs: description: 'Test suite name for the header (e.g. "E2E Ginkgo Nightly Tests"). Keep under ~130 chars โ€” Slack header blocks have a 150-char limit and the status suffix takes ~15 chars.' required: true status: - description: 'Run status, typically `needs..result` or `job.status`. `success` and `failure` notify; `cancelled` and `skipped` are treated as no-ops and send nothing.' + description: 'Run status, typically `needs..result` or `job.status`. `success` and `failure` notify; `cancelled` and `skipped` are treated as no-ops and send nothing. Use `info` for a standalone informational notice (e.g. a deploy) that always notifies with no pass/fail suffix.' required: true details: description: 'Markdown text appended after the build URL (test results, versions, artifact links, etc.)' diff --git a/.github/actions/ci-test-notify/build-payload.sh b/.github/actions/ci-test-notify/build-payload.sh index 1e1ffb7..e2b79a7 100755 --- a/.github/actions/ci-test-notify/build-payload.sh +++ b/.github/actions/ci-test-notify/build-payload.sh @@ -10,10 +10,14 @@ case "$STATUS" in failure) EMOJI="โŒ"; STATUS_TEXT="Failed" ;; cancelled) EMOJI="โš ๏ธ"; STATUS_TEXT="Cancelled" ;; skipped) EMOJI="โญ๏ธ"; STATUS_TEXT="Skipped" ;; + info) EMOJI="๐Ÿš€"; STATUS_TEXT="" ;; *) EMOJI="โ“"; STATUS_TEXT="Unknown ($STATUS)" ;; esac -HEADER="${EMOJI} ${TEST_NAME} ${STATUS_TEXT}" +# `info` carries no pass/fail meaning, so it gets no status suffix; every other +# status appends one (" Success", " Failed", โ€ฆ). Keep the space inside the +# expansion so an empty suffix leaves no trailing whitespace in the header. +HEADER="${EMOJI} ${TEST_NAME}${STATUS_TEXT:+ ${STATUS_TEXT}}" # Slack header blocks reject >150 chars if [[ ${#HEADER} -gt 150 ]]; then diff --git a/.github/actions/ci-test-notify/should-notify.sh b/.github/actions/ci-test-notify/should-notify.sh index a229af8..68ffdfc 100755 --- a/.github/actions/ci-test-notify/should-notify.sh +++ b/.github/actions/ci-test-notify/should-notify.sh @@ -10,6 +10,10 @@ set -euo pipefail # (or superseded), and a skipped job never executed. Neither warrants a Slack # alert, so both are silenced here rather than in every caller. # +# `info` is a status callers set deliberately for a standalone informational +# notice (e.g. a release candidate landing in staging) rather than a run +# conclusion; it is not a no-op and always notifies when a webhook is present. +# # An empty webhook (fork PRs, where secrets are unavailable) also suppresses # the notification, same as before. # diff --git a/.github/actions/ci-test-notify/test/build-payload.bats b/.github/actions/ci-test-notify/test/build-payload.bats index 8c10ae0..81d9b6e 100644 --- a/.github/actions/ci-test-notify/test/build-payload.bats +++ b/.github/actions/ci-test-notify/test/build-payload.bats @@ -48,6 +48,13 @@ payload_field() { [[ "$(payload_field '.text')" == *"Cancelled"* ]] } +@test "info status uses rocket emoji and no status suffix" { + STATUS="info" TEST_NAME="Deployed to staging" run bash "$SCRIPT" + [ "$status" -eq 0 ] + # Exact match asserts there is no trailing status word or whitespace. + [ "$(payload_field '.blocks[0].text.text')" = "๐Ÿš€ Deployed to staging" ] +} + @test "skipped status produces correct emoji and text" { STATUS="skipped" run bash "$SCRIPT" [ "$status" -eq 0 ] diff --git a/.github/actions/ci-test-notify/test/should-notify.bats b/.github/actions/ci-test-notify/test/should-notify.bats index a306861..93decb6 100644 --- a/.github/actions/ci-test-notify/test/should-notify.bats +++ b/.github/actions/ci-test-notify/test/should-notify.bats @@ -37,6 +37,12 @@ notify_value() { [ "$(notify_value)" = "true" ] } +@test "info notifies" { + STATUS="info" run bash "$SCRIPT" + [ "$status" -eq 0 ] + [ "$(notify_value)" = "true" ] +} + # --- Statuses that must stay silent (the bug this fixes) --- @test "cancelled does not notify" {