Skip to content

Commit 4928ef0

Browse files
[sc-30416] Allow generating predefined Slack user mapping (#167)
Signed-off-by: Jake Schurch <[email protected]> Co-authored-by: Nick Amoscato <[email protected]>
1 parent f6941c3 commit 4928ef0

28 files changed

+53705
-382
lines changed

.gitattributes

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
dist/** -diff linguist-generated=true
1+
dist/**/* -diff linguist-generated=true
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Generate Slack Deploy User Mapping
2+
3+
This action generates a mapping of Slack user details by GitHub username for use in [Slack Deploy Pipeline Notifications](../../../README.md). It intends to decouple the user mapping process, dependent on a conservatively rate limited [Slack API method](https://docs.slack.dev/reference/methods/users.list/), from the higher throughput notification action.
4+
5+
## Setup
6+
7+
### GitHub Token
8+
9+
A fine-grained personal access token must be configured as the default `GITHUB_TOKEN` does not include adequate permissions:
10+
11+
1. [Create a fine-grained personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token)
12+
2. Under **Resource owner**, select your GitHub organization
13+
3. Under **Permissions**, select "Members" (read-only)
14+
4. [Create a GitHub secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets) with this token, named `GH_ORG_MEMBERS_TOKEN`
15+
16+
### Slack Token
17+
18+
If you have not already provisioned a Slack Bot Token:
19+
20+
5. [Create a Slack App](https://api.slack.com/apps) for your workspace
21+
6. Under **OAuth & Permissions**, add the [`users:read`](https://api.slack.com/scopes/users:read) Bot Token Scope
22+
7. Copy the app's **Bot User OAuth Token**
23+
8. [Create a GitHub secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets) with this token, named `SLACK_DEPLOY_BOT_TOKEN`
24+
25+
## Usage
26+
27+
In a conventional setup, the user mapping is periodically uploaded as a GitHub workflow artifact and downloaded within deploy workflows.
28+
29+
### Schedule Workflow
30+
31+
Create a [`schedule`](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#schedule) event-triggered workflow that [uploads](https://github.com/actions/upload-artifact) the generated user mapping as a `slack-deploy-user-mapping.json` [workflow artifact](https://docs.github.com/en/actions/tutorials/store-and-share-data):
32+
33+
```yaml
34+
name: Generate Slack Deploy User Mapping
35+
36+
on:
37+
schedule:
38+
- cron: '0 0 * * *' # midnight UTC
39+
40+
jobs:
41+
generate:
42+
runs-on: ubuntu-latest
43+
steps:
44+
- name: Generate user mapping
45+
uses: Fieldguide/action-slack-deploy-pipeline/.github/actions/generate-user-mapping@v2
46+
id: user-mapping
47+
env:
48+
SLACK_DEPLOY_BOT_TOKEN: ${{ secrets.SLACK_DEPLOY_BOT_TOKEN }}
49+
with:
50+
github_token: ${{ secrets.GH_ORG_MEMBERS_TOKEN }}
51+
github_org: your-org # replace with your GitHub organization name
52+
53+
- name: Write to file
54+
run: |
55+
cat << 'EOF' > slack-deploy-user-mapping.json
56+
${{ steps.user-mapping.outputs.json }}
57+
EOF
58+
59+
- name: Upload artifact
60+
uses: actions/upload-artifact@v4
61+
with:
62+
name: slack-deploy-user-mapping
63+
path: slack-deploy-user-mapping.json
64+
if-no-files-found: 'error'
65+
retention-days: 2
66+
overwrite: true
67+
```
68+
69+
### Deploy Workflow
70+
71+
In your deploy workflows, [download the artifact](https://github.com/dawidd6/action-download-artifact) and set the `SLACK_DEPLOY_GITHUB_USERS` environment variable before using the [Slack Deploy Pipeline Notifications](../../../README.md) action:
72+
73+
```yaml
74+
name: Deploy
75+
76+
on:
77+
push:
78+
branches:
79+
- main
80+
81+
env:
82+
SLACK_DEPLOY_BOT_TOKEN: ${{ secrets.SLACK_DEPLOY_BOT_TOKEN }}
83+
SLACK_DEPLOY_CHANNEL: 'C040YVCUDRR' # replace with your Slack Channel ID
84+
85+
jobs:
86+
deploy:
87+
runs-on: ubuntu-latest
88+
steps:
89+
- name: Download Slack deploy user mapping artifact
90+
uses: dawidd6/action-download-artifact@v6
91+
with:
92+
workflow: slack_deploy_user_mapping.yaml
93+
name: slack-deploy-user-mapping
94+
if_no_artifact_found: warn
95+
96+
- name: Set Slack deploy user mapping environment variable
97+
if: hashFiles('slack-deploy-user-mapping.json') != ''
98+
run: |
99+
echo "SLACK_DEPLOY_GITHUB_USERS<<EOF" >> $GITHUB_ENV
100+
cat slack-deploy-user-mapping.json >> $GITHUB_ENV
101+
echo "EOF" >> $GITHUB_ENV
102+
103+
- name: Post to Slack
104+
uses: Fieldguide/action-slack-deploy-pipeline@v2
105+
id: slack
106+
107+
- name: Deploy code
108+
run: sleep 10 # replace with your deploy steps
109+
110+
- name: Post to Slack
111+
uses: Fieldguide/action-slack-deploy-pipeline@v2
112+
if: always()
113+
with:
114+
thread_ts: ${{ steps.slack.outputs.ts }}
115+
conclusion: true
116+
```
117+
118+
## Configuration
119+
120+
### Environment Variables
121+
122+
| variable | description |
123+
| ------------------------ | --------------------------------------- |
124+
| `SLACK_DEPLOY_BOT_TOKEN` | **Required** Slack bot user OAuth token |
125+
126+
### Inputs
127+
128+
| input | description |
129+
| -------------- | ------------------------------------------------------- |
130+
| `github_token` | GitHub organization personal access token secret |
131+
| `github_org` | GitHub organization name from which members are fetched |
132+
133+
### Outputs
134+
135+
| output | description |
136+
| ------ | ---------------------------------------------------------------- |
137+
| `json` | JSON-serialized mapping of Slack user details by GitHub username |
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: 'Generate Slack Deploy User Mapping'
3+
description: 'Generate mapping of Slack user details by GitHub username for use in Slack Deploy Pipeline Notifications'
4+
author: 'Fieldguide'
5+
inputs:
6+
github_token:
7+
description: 'GitHub organization personal access token secret'
8+
required: true
9+
github_org:
10+
description: 'GitHub organization name from which members are fetched'
11+
required: true
12+
outputs:
13+
json:
14+
description: 'JSON-serialized mapping of Slack user details by GitHub username'
15+
runs:
16+
using: 'node20'
17+
main: '../../../dist/generateUserMapping/index.js'
18+
branding:
19+
icon: bell
20+
color: purple

README.md

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@ Post [GitHub Action](https://github.com/features/actions) deploy workflow progre
1111
## Features
1212

1313
- Posts summary message at beginning of the deploy workflow, surfacing commit message and author
14-
- Maps GitHub actor to Slack user by full name, mentioning them in the summary message
14+
- Maps GitHub actor to Slack user by full name or mapping, mentioning them in the summary message
1515
- Threads intermediate stage completions, sending unexpected failures back to the channel
1616
- Adds summary message reaction to unsuccessful jobs (useful with [Reacji Channeler](https://reacji-channeler.builtbyslack.com/))
17-
- Updates summary message duration at conclusion of the workflow
17+
- Updates summary message with workflow duration at its conclusion
1818
- Supports `pull_request`, `push`, `release`, `schedule`, and `workflow_dispatch` [event types](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows)
1919

2020
## Setup
2121

2222
1. [Create a Slack App](https://api.slack.com/apps) for your workspace
23-
1. Under **OAuth & Permissions**, add two Bot Token Scopes:
24-
1. [`chat:write`](https://api.slack.com/scopes/chat:write) to post messages
25-
1. [`chat:write.customize`](https://api.slack.com/scopes/chat:write.customize) to customize messages with GitHub actor
26-
1. [`reactions:write`](https://api.slack.com/scopes/reactions:write) to add summary message error reactions
27-
1. [`users:read`](https://api.slack.com/scopes/users:read) to map GitHub user to Slack user
23+
1. Under **OAuth & Permissions**, add Bot Token Scopes:
24+
- [`chat:write`](https://api.slack.com/scopes/chat:write) to post messages
25+
- [`chat:write.customize`](https://api.slack.com/scopes/chat:write.customize) to customize messages with GitHub actor
26+
- [`reactions:write`](https://api.slack.com/scopes/reactions:write) to add summary message error reactions
27+
- [`users:read`](https://api.slack.com/scopes/users:read) to map GitHub user to Slack user
2828
1. Install the app to your workspace
2929
1. Copy the app's **Bot User OAuth Token** from the **OAuth & Permissions** page
3030
1. [Create a GitHub secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets) with this token, named `SLACK_DEPLOY_BOT_TOKEN`
@@ -90,15 +90,22 @@ jobs:
9090
1. As your workflow progresses, use this action with the `thread_ts` input to post threaded replies.
9191
1. Denote the last step with the `conclusion` input to update the initial message's status.
9292

93-
## Environment Variables
93+
## Configuration
9494

95-
| variable | description |
96-
| ----------------------------- | --------------------------------------- |
97-
| `SLACK_DEPLOY_BOT_TOKEN` | **Required** Slack bot user OAuth token |
98-
| `SLACK_DEPLOY_CHANNEL` | **Required** Slack channel ID |
99-
| `SLACK_DEPLOY_ERROR_REACTION` | Optional Slack emoji name |
95+
### Environment Variables
10096

101-
## Inputs
97+
Global configuration to be used across all Slack Deploy actions within the workflow.
98+
99+
| variable | description |
100+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------ |
101+
| `SLACK_DEPLOY_BOT_TOKEN` | **Required** Slack bot user OAuth token |
102+
| `SLACK_DEPLOY_CHANNEL` | **Required** Slack channel ID |
103+
| `SLACK_DEPLOY_ERROR_REACTION` | Optional Slack emoji name |
104+
| `SLACK_DEPLOY_GITHUB_USERS` | [Optional mapping](#predefined-user-mapping) of Slack user details by GitHub username in JSON or YAML format |
105+
106+
### Inputs
107+
108+
Optional step-specific input enables threading and denotes the conclusion.
102109

103110
| input | description |
104111
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
@@ -107,8 +114,26 @@ jobs:
107114
| `github_token` | Repository `GITHUB_TOKEN` or personal access token secret; defaults to [`github.token`](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context) |
108115
| `status` | The current status of the job; defaults to [`job.status`](https://docs.github.com/en/actions/learn-github-actions/contexts#job-context) |
109116

110-
## Outputs
117+
### Outputs
111118

112119
| output | description |
113120
| ------ | -------------------------- |
114121
| `ts` | Slack message timestamp ID |
122+
123+
## Slack User Mapping
124+
125+
By default, this GitHub Action attempts to [mention](https://slack.com/help/articles/205240127-Use-mentions-in-Slack) the Slack user corresponding to the GitHub actor by full name. This process depends on a conservatively rate limited [Slack API method](https://docs.slack.dev/reference/methods/users.list/); depending on your deploy throughput, it might fail and gracefully fallback to the GitHub username.
126+
127+
To improve reliability, the action can be provided a predefined user mapping via a `SLACK_DEPLOY_GITHUB_USERS` environment variable. The data should be an object keyed by GitHub username mapped to Slack user detail values in JSON or YAML format.
128+
129+
The data is conventionally JSON generated by the [Generate Slack Deploy User Mapping](./.github/actions/generate-user-mapping/README.md) GitHub Action. However, it can also be provided as inline YAML as in the example below:
130+
131+
```yaml
132+
- uses: Fieldguide/action-slack-deploy-pipeline@v2
133+
env:
134+
SLACK_DEPLOY_GITHUB_USERS: |
135+
namoscato:
136+
slack_user_id: U0411GE5J9J
137+
username: Nick
138+
icon_url: "https://secure.gravatar.com/avatar/d79555502b4c47fc9d31144af55dc3e5.jpg"
139+
```

action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ outputs:
2121
description: 'Slack message timestamp ID'
2222
runs:
2323
using: 'node20'
24-
main: 'dist/index.js'
24+
main: 'dist/notifySlack/index.js'
2525
branding:
2626
icon: bell
2727
color: purple

0 commit comments

Comments
 (0)