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" {