Skip to content

Commit 9d383d1

Browse files
GHA-149 Add Notify Slack on Failure action to send notifications for failed jobs (#64)
Co-authored-by: Jonas Wielage <jonas.wielage@sonarsource.com>
1 parent df9d4e1 commit 9d383d1

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ A centralized collection of reusable GitHub Actions designed to streamline and a
1111
* [**Get Jira Release Notes**](get-jira-release-notes/README.md): Fetches Jira release notes and generates the release notes URL for a given project and version.
1212
* [**Get Jira Version**](get-jira-version/README.md): Extracts a Jira-compatible version number from a release version by formatting it appropriately for Jira.
1313
* [**Get Release Version**](get-release-version/README.md): Extracts the release version from the repox status on a specified branch.
14+
* [**Notify Slack on Failure**](notify-slack/README.md): Sends a Slack notification when a job fails.
1415
* [**Publish GitHub Release**](publish-github-release/README.md): Publishes a GitHub Release with notes fetched from Jira or provided directly.
1516
* [**Release Jira Version**](release-jira-version/README.md): Releases a Jira version and creates the next one.
1617
* [**Update Analyzer**](update-analyzer/README.md): Updates an analyzer version in SonarQube or SonarCloud and creates a pull request.

notify-slack/README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Notify Slack on Failure Action
2+
3+
This GitHub Action sends a Slack notification summarizing failed jobs in a workflow run when used with an `if: failure()` condition.
4+
5+
## Description
6+
7+
The action posts a concise message to a Slack channel containing:
8+
1. A link to the failed GitHub Actions run
9+
2. A list of failed jobs provided by the workflow
10+
3. A custom project-branded username and icon
11+
12+
It is intended to be used as the last step (or in a dedicated job) guarded by `if: failure()` so that it only triggers on failures.
13+
14+
## Dependencies
15+
16+
This action depends on:
17+
- [SonarSource/vault-action-wrapper](https://github.com/SonarSource/vault-action-wrapper) to retrieve the Slack token from Vault
18+
- [rtCamp/action-slack-notify](https://github.com/rtCamp/action-slack-notify) to send the Slack message
19+
20+
## Inputs
21+
22+
| Input | Description | Required | Default |
23+
|-----------------|------------------------------------------------------------------------|----------|-----------|
24+
| `project-name` | The display name of the project; used in the Slack username. | Yes | - |
25+
| `icon` | Emoji icon for the Slack message (Slack emoji code). | No | `:alert:` |
26+
| `slack-channel` | Slack channel (without `#`) to post the notification into. | Yes | - |
27+
| `jobs` | Comma-separated list of job names to report as failed (provided by you). | Yes | - |
28+
29+
Note: The list of failed jobs must be provided via the `jobs` input by your workflow logic.
30+
31+
## Outputs
32+
33+
No outputs are produced by this action.
34+
35+
## Usage
36+
37+
### Basic usage (in a dedicated failure notification job)
38+
39+
```yaml
40+
jobs:
41+
notify_on_failure:
42+
needs: [ build, test, deploy ] # Example job dependencies
43+
runs-on: ubuntu-latest
44+
if: failure()
45+
permissions:
46+
statuses: read
47+
id-token: write
48+
steps:
49+
- uses: SonarSource/release-github-actions/notify-slack@v1
50+
with:
51+
project-name: 'My Project'
52+
slack-channel: 'engineering-alerts'
53+
jobs: ${{ toJSON(needs) }}
54+
```
55+
56+
### Minimal usage (only required inputs)
57+
58+
```yaml
59+
- uses: SonarSource/release-github-actions/notify-slack@v1
60+
if: failure()
61+
with:
62+
project-name: 'My Project'
63+
slack-channel: 'engineering-alerts'
64+
jobs: 'build, test'
65+
```
66+
67+
### Custom icon
68+
69+
```yaml
70+
- uses: SonarSource/release-github-actions/notify-slack@v1
71+
if: failure()
72+
with:
73+
project-name: 'My Project'
74+
slack-channel: 'engineering-alerts'
75+
icon: ':rocket:'
76+
jobs: 'build, test'
77+
```
78+
79+
## Implementation Details
80+
81+
The action is a composite action that:
82+
- Fetches `SLACK_TOKEN` from Vault path `development/kv/data/slack` using `vault-action-wrapper`
83+
- Uses a workflow-provided `jobs` input (comma-separated string) to populate the "Failed Jobs" section
84+
- Constructs a Slack message with run URL and the provided failed jobs list
85+
- Uses `rtCamp/action-slack-notify` to send a minimal styled message (no title/footer) with danger color
86+
- Sets Slack username to: `<project-name> CI Notifier`
87+
- If the `jobs` list is empty or not provided, the "Failed Jobs" line will be blank
88+
89+
## Prerequisites
90+
91+
- Vault policy granting access to `development/kv/data/slack` must be configured for the repository.
92+
- The secret at that path must contain a key named `token`.
93+
- The Slack channel provided must exist and the token must have permission to post there.
94+
95+
## Notes
96+
97+
- Use `if: failure()` on the step or job; otherwise it will also fire on success.
98+
- `project-name`, `slack-channel`, and `jobs` are required inputs (no defaults).
99+
- Do not prefix the channel with `#`.
100+
- Message formatting is intentionally minimal for quick triage in alert-focused channels.
101+
- How you compute the failed jobs list is up to your workflow; you can use prior steps to gather job results and pass them to this action via `jobs`.

notify-slack/action.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: 'Notify Slack on Failure'
2+
description: 'Sends a Slack notification when a job fails.'
3+
4+
inputs:
5+
project-name:
6+
description: 'The name of the project.'
7+
required: true
8+
icon:
9+
description: 'The icon for the Slack notification.'
10+
required: false
11+
default: ':alert:'
12+
slack-channel:
13+
description: 'The Slack channel to send the notification to.'
14+
required: true
15+
jobs:
16+
description: 'A GitHub needs-like object string of jobs and their results (e.g., from toJSON(needs)).'
17+
required: true
18+
19+
runs:
20+
using: "composite"
21+
steps:
22+
- name: Collect Failed Jobs
23+
shell: bash
24+
id: collect_failed_jobs
25+
env:
26+
JOBS: ${{ inputs.jobs }}
27+
run: |
28+
echo "Checking Jobs: $JOBS"
29+
# Parse the provided jobs mapping string without relying on strict JSON. Extract keys where result == failure.
30+
# This handles inputs like: { build: { result: failure, outputs: {} }, qa_tests: { result: skipped, outputs: {} } }
31+
FAILED_JOBS=$(echo "$JOBS" | awk '
32+
/[[:alnum:]_.-]+:[[:space:]]*\{/{ key=$1; sub(/:$/, "", key) }
33+
/result[[:space:]]*:[[:space:]]*failure/{ fails=(fails?fails", ":"") key }
34+
END{ print fails }
35+
')
36+
echo "Failed Jobs: $FAILED_JOBS"
37+
echo "failed-jobs=$FAILED_JOBS" >> $GITHUB_OUTPUT
38+
- name: Vault Secrets
39+
id: secrets
40+
uses: SonarSource/vault-action-wrapper@v3
41+
with:
42+
secrets: |
43+
development/kv/data/slack token | SLACK_TOKEN;
44+
- name: Send Slack Notification
45+
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
46+
env:
47+
SLACK_CHANNEL: ${{ inputs.slack-channel }}
48+
SLACK_MSG_AUTHOR: " "
49+
SLACK_TITLE: " "
50+
SLACK_FOOTER: " "
51+
SLACK_COLOR: danger
52+
MSG_MINIMAL: true
53+
SLACK_MESSAGE: |
54+
*Run:* ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
55+
*Failed Jobs:* ${{ steps.collect_failed_jobs.outputs.failed-jobs }}
56+
SLACK_TOKEN: "${{ fromJSON(steps.secrets.outputs.vault).SLACK_TOKEN }}"
57+
SLACK_ICON_EMOJI: "${{ inputs.icon }}"
58+
SLACK_USERNAME: "${{ inputs.project-name }} CI Notifier"
59+

0 commit comments

Comments
 (0)