feat: support slack cli commands with composite action inputs (#560)

Co-authored-by: Claude <[email protected]>
Co-authored-by: William Bergamin <[email protected]>
This commit is contained in:
Eden Zimbelman
2026-03-12 15:51:47 -07:00
committed by GitHub
co-authored by Claude William Bergamin
parent 0aed2c2a70
commit e45cb891a6
22 changed files with 572 additions and 39 deletions
+1
View File
@@ -4,4 +4,5 @@
export SLACK_BOT_TOKEN=xoxb-01010101-example
export SLACK_CHANNEL_ID=C0123456789
export SLACK_INCOMING_WEBHOOK=https://hooks.slack.com/services/T0123456789/B0123456789/abcdefghijklmnopqrstuvwxyz
export SLACK_SERVICE_TOKEN=xoxp-01010101-example
export SLACK_WEBHOOK_TRIGGER=https://hooks.slack.com/triggers/T0123456789/00000000000/abcdefghijklmnopqrstuvwxyz
+3 -1
View File
@@ -1,5 +1,7 @@
{
"experiments": ["bolt"],
"manifest": {
"source": "local"
},
"project_id": "c4805b41-d1ce-4ea0-b297-ed2f8c64c267"
}
@@ -1,7 +1,7 @@
{
"runtime": "actions",
"hooks": {
"deploy": "open https://api.slack.com/apps || true",
"deploy": "echo https://api.slack.com/apps",
"get-manifest": "cat ./.slack/manifest.json #"
},
"config": {
+9 -1
View File
@@ -6,7 +6,7 @@ experiments with the [Slack CLI][cli].
## Overview
This app showcases all three techniques of sending data into Slack and follows
This app showcases all four techniques of interacting with Slack and follows
patterns found in the integration tests.
- **Technique 1** Slack Workflow Builder: Use a Slack webhook trigger to start a
@@ -15,6 +15,8 @@ patterns found in the integration tests.
data provided through the GitHub workflow.
- **Technique 3** Incoming webhook: Post a message to a Slack channel using an
incoming webhook.
- **Technique 4** Slack CLI Command: Install and run Slack CLI commands such as
`deploy` or `manifest` using a service token.
Configurations for the Slack app and workflow, and the GitHub Actions workflow
are found in the following files:
@@ -22,6 +24,9 @@ are found in the following files:
- Slack app setup: [`.github/resources/.slack/manifest.json`][slacktion]
- GitHub Actions steps: [`.github/workflows/develop.yml`][develop]
> **Note:** During CLI integration tests, `.github/resources/.slack` is moved to
> `.slack` at the project root so the Slack CLI can discover the app manifest.
Either the techniques or app setup and workflow steps can be adjusted during
testing and development. For experimenting with new changes, we recommend using
the [steps for development](#experimenting-for-development) while the
@@ -76,6 +81,8 @@ tested. Required values include:
https://hooks.slack.com/services/T0123456789/B0123456789/abcdefghijklmnopqrstuvwxyz
- `SLACK_WEBHOOK_TRIGGER`:
https://hooks.slack.com/triggers/T0123456789/00000000000/abcdefghijklmnopqrstuvwxyz
- `SLACK_SERVICE_TOKEN`: xoxp-service-token-example (secret — for CLI commands)
- `SLACK_APP_ID`: A0123456789 (variable — used with `--app` flag in CLI deploy)
### Experimenting for development
@@ -98,6 +105,7 @@ export SLACK_BOT_TOKEN=xoxb-01010101-example
export SLACK_CHANNEL_ID=C0123456789
export SLACK_INCOMING_WEBHOOK=https://hooks.slack.com/services/T0123456789/B0123456789/abcdefghijklmnopqrstuvwxyz
export SLACK_WEBHOOK_TRIGGER=https://hooks.slack.com/triggers/T0123456789/00000000000/abcdefghijklmnopqrstuvwxyz
export SLACK_SERVICE_TOKEN=xoxp-service-token-example
```
Environment variables and credentials should be set in the created `.env` file
+92 -27
View File
@@ -12,7 +12,7 @@ on:
jobs:
integration:
name: Run integration tests
name: Run API tests
runs-on: ubuntu-latest
environment: staging
permissions:
@@ -68,7 +68,7 @@ jobs:
env:
INPUT_REF: ${{ inputs.ref }}
- name: "integration(wfb): send a payload to workflow builder via webhook trigger"
- name: "test(wfb): send a payload to workflow builder via webhook trigger"
id: wfb
uses: ./
with:
@@ -82,12 +82,12 @@ jobs:
repo_name: ${{ github.event.repository.full_name }}
status: ${{ job.status }}
- name: "integration(wfb): confirm a payload was sent"
- name: "test(wfb): confirm a payload was sent"
run: test -n "$WFB_OUTPUT_TIME"
env:
WFB_OUTPUT_TIME: ${{ steps.wfb.outputs.time }}
- name: "integration(botToken): post a message to channel"
- name: "test(api): post a message to channel"
id: message
uses: ./
with:
@@ -98,12 +98,12 @@ jobs:
channel: ${{ secrets.SLACK_CHANNEL_ID }}
text: ":checkered_flag: Action happens at <https://github.com/${{ github.repository }}>"
- name: "integration(method): confirm a message was posted"
- name: "test(api): confirm a message was posted"
run: test -n "$MESSAGE_OUTPUT_TS"
env:
MESSAGE_OUTPUT_TS: ${{ steps.message.outputs.ts }}
- name: "integration(method): post a message with blocks"
- name: "test(api): post a message with blocks"
id: blocks
uses: ./
with:
@@ -120,12 +120,12 @@ jobs:
short: true
value: "Processing"
- name: "integration(method): confirm the blocks were posted"
- name: "test(api): confirm the blocks were posted"
run: test -n "$BLOCKS_OUTPUT_TS"
env:
BLOCKS_OUTPUT_TS: ${{ steps.blocks.outputs.ts }}
- name: "integration(method): post a threaded message"
- name: "test(api): post a threaded message"
id: timer
uses: ./
with:
@@ -137,15 +137,15 @@ jobs:
text: "Started at `${{ steps.blocks.outputs.time }}`"
thread_ts: "${{ steps.blocks.outputs.ts }}"
- name: "integration(incoming): confirm the thread started"
- name: "test(api): confirm the thread started"
run: test -n "$TIMER_OUTPUT_TIME"
env:
TIMER_OUTPUT_TIME: ${{ steps.timer.outputs.time }}
- name: "integration(method): wait to mock event processing"
- name: "test(api): wait to mock event processing"
run: sleep 3
- name: "integration(method): update the original message"
- name: "test(api): update the original message"
id: finished
uses: ./
with:
@@ -163,7 +163,7 @@ jobs:
short: true
value: "Completed"
- name: "integration(method): post another threaded message"
- name: "test(api): post another threaded message"
id: done
uses: ./
with:
@@ -175,7 +175,7 @@ jobs:
text: "Finished at `${{ steps.finished.outputs.time }}`"
thread_ts: "${{ steps.timer.outputs.thread_ts }}"
- name: "integration(method): post a file into a channel"
- name: "test(api): post a file into a channel"
id: file
uses: ./
with:
@@ -188,7 +188,7 @@ jobs:
file: .github/workflows/integration.yml
filename: integration.yml
- name: "integration(method): react to the completed update message"
- name: "test(api): react to the completed update message"
uses: ./
with:
errors: true
@@ -199,12 +199,12 @@ jobs:
timestamp: ${{ steps.blocks.outputs.ts }}
name: "tada"
- name: "integration(method): confirm the thread ended"
- name: "test(api): confirm the thread ended"
run: test -n "$DONE_OUTPUT_TIME"
env:
DONE_OUTPUT_TIME: ${{ steps.done.outputs.time }}
- name: "integration(incoming): post a message via incoming webhook"
- name: "test(incoming): post a message via incoming webhook"
id: incoming
uses: ./
with:
@@ -212,7 +212,7 @@ jobs:
webhook: ${{ secrets.SLACK_INCOMING_WEBHOOK }}
webhook-type: incoming-webhook
payload: |
text: "Incoming webhook test for slack send"
text: "Incoming webhook test for the Slack GitHub Action"
blocks:
- type: section
text:
@@ -220,17 +220,17 @@ jobs:
text: ":link: A message was received via incoming webhook"
emoji: true
- name: "integration(incoming): confirm a webhook was posted"
- name: "test(incoming): confirm a webhook was posted"
run: test -n "$INCOMING_WEBHOOK_OUTPUT_TIME"
env:
INCOMING_WEBHOOK_OUTPUT_TIME: ${{ steps.incoming.outputs.time }}
- name: "integration(incoming): reveal contents of the github payload"
- name: "test(incoming): reveal contents of the github payload"
run: echo "$JSON"
env:
JSON: ${{ toJSON(github) }}
- name: "integration(incoming): post a message via payload file"
- name: "test(incoming): post a message via payload file"
id: payload_file
uses: ./
with:
@@ -243,15 +243,80 @@ jobs:
JOB_STATUS: ${{ job.status }}
ATTACHMENT_COLOR: ${{ (job.status == 'success' && 'good') || (job.status == 'failure' && 'danger') || 'warning' }}
- name: "integration(incoming): confirm a payload file was posted"
- name: "test(incoming): confirm a payload file was posted"
run: test -n "$PAYLOAD_FILE_OUTPUT_TIME"
env:
PAYLOAD_FILE_OUTPUT_TIME: ${{ steps.payload_file.outputs.time }}
- name: "chore(health): check up on recent changes to the health score"
uses: slackapi/slack-health-score@d58a419f15cdaff97e9aa7f09f95772830ab66f7 # v0.1.1
cli:
name: Run CLI tests
runs-on: ${{ matrix.os }}
environment: staging
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
permissions:
contents: read
steps:
- name: "build: checkout the latest changes"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
codecov_token: ${{ secrets.CODECOV_API_TOKEN }}
github_token: ${{ secrets.GITHUB_TOKEN }}
extension: js
include: src
persist-credentials: false
ref: ${{ inputs.ref || github.event.pull_request.head.sha || github.sha }}
- name: "test(cli): run a slack cli version check"
id: version
uses: ./cli
with:
command: "version"
- name: "test(cli): confirm the version check outputs"
shell: bash
run: |
set -ex
[ "$CLI_OK" = "true" ]
echo "$CLI_TIME" | grep -qE '^[0-9]+$'
[ -n "$CLI_RESPONSE" ]
env:
CLI_OK: ${{ steps.version.outputs.ok }}
CLI_RESPONSE: ${{ steps.version.outputs.response }}
CLI_TIME: ${{ steps.version.outputs.time }}
- name: "test(cli): run an unknown command"
id: unknown
continue-on-error: true
uses: ./cli
with:
command: "off"
- name: "test(cli): confirm the unknown command outputs"
shell: bash
run: |
set -ex
[ "$CLI_OK" = "false" ]
echo "$CLI_TIME" | grep -qE '^[0-9]+$'
[ -n "$CLI_RESPONSE" ]
env:
CLI_OK: ${{ steps.unknown.outputs.ok }}
CLI_RESPONSE: ${{ steps.unknown.outputs.response }}
CLI_TIME: ${{ steps.unknown.outputs.time }}
- name: "chore: configure the actioneering application"
shell: bash
run: mv .github/resources/.slack .slack
- name: "test(cli): validate the app manifest"
uses: ./cli
with:
command: "manifest"
token: ${{ secrets.SLACK_SERVICE_TOKEN }}
- name: "test(cli): deploy the app"
uses: ./cli
with:
command: "deploy --app ${{ vars.SLACK_APP_ID }} --hide-triggers --force"
token: ${{ secrets.SLACK_SERVICE_TOKEN }}
+3
View File
@@ -38,6 +38,9 @@ jobs:
uses: teunmooij/github-versioned-release@3edf649c6e5e5e976d43f2584b15bdc8b4c8f0df # v1.2.1
with:
template: javascript-action
include: |
dist/**/*
cli/**/*
env:
GITHUB_TOKEN: ${{ github.token }}
+1 -1
View File
@@ -8,7 +8,7 @@ on:
jobs:
tests:
name: Run tests
name: Run unit tests
runs-on: ubuntu-latest
permissions:
checks: write
+3 -2
View File
@@ -1,6 +1,6 @@
# Slack Send GitHub Action
# Slack GitHub Action
> the GitHub Action for sending data to Slack
> the GitHub Action for sending data to Slack and running commands
[![codecov](https://codecov.io/gh/slackapi/slack-github-action/graph/badge.svg?token=OZNX7FHN78)](https://codecov.io/gh/slackapi/slack-github-action)
@@ -11,6 +11,7 @@ Use this GitHub Action to:
- [Send data with a webhook to start a workflow in Workflow Builder](https://docs.slack.dev/tools/slack-github-action/sending-techniques/sending-data-webhook-slack-workflow).
- [Send data using a Slack API method and a secret token with required scopes](https://docs.slack.dev/tools/slack-github-action/sending-techniques/sending-data-slack-api-method/).
- [Send data as a message with a Slack incoming webhook URL](https://docs.slack.dev/tools/slack-github-action/sending-techniques/sending-data-slack-incoming-webhook/).
- [Run Slack CLI commands with a service token](https://docs.slack.dev/tools/slack-github-action/sending-techniques/running-slack-cli-commands/).
## Project details
+2 -2
View File
@@ -1,6 +1,6 @@
name: "Slack: Send to Slack"
name: "Slack GitHub Action"
author: "slackapi"
description: "Send data to Slack to start a Slack workflow in Workflow Builder, call a Slack API method, or post a message into a channel"
description: "Post a message, call a Web API method, start a Slack workflow, or run a Slack CLI command from GitHub Actions"
inputs:
api:
description: "A custom API URL to send Slack API method requests to."
+150
View File
@@ -0,0 +1,150 @@
name: "Slack GitHub Action: CLI"
author: "slackapi"
description: "Install the Slack CLI and run a command in a GitHub Actions workflow"
inputs:
command:
description: "A Slack CLI command to run without the 'slack' prefix."
required: true
token:
description: "A service token passed as the '--token' flag to the CLI command."
required: false
version:
description: "The version of the Slack CLI to install. Defaults to the latest."
required: false
outputs:
ok:
description: "If the command completed with a '0' exit code."
value: ${{ steps.slack-cli-unix.outputs.ok || steps.slack-cli-windows.outputs.ok }}
response:
description: "The standard output from the CLI command."
value: ${{ steps.slack-cli-unix.outputs.response || steps.slack-cli-windows.outputs.response }}
time:
description: "The Unix epoch time that the step completed."
value: ${{ steps.slack-cli-unix.outputs.time || steps.slack-cli-windows.outputs.time }}
runs:
using: composite
steps:
- name: Check if Slack CLI already exists
id: slack-cli-check
shell: bash
run: |
if command -v slack &> /dev/null; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi
- name: Cache Slack CLI
if: steps.slack-cli-check.outputs.exists != 'true' && inputs.version != ''
id: cache-cli
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: |
${{ runner.os == 'Windows' && '~/AppData/Local/slack-cli' || '~/.slack/bin' }}
key: slack-cli-${{ runner.os }}-${{ runner.arch }}-${{ inputs.version }}
- name: Bash Add Slack CLI to PATH
if: steps.slack-cli-check.outputs.exists != 'true' && runner.os != 'Windows'
shell: bash
run: echo "$HOME/.slack/bin" >> "$GITHUB_PATH" # zizmor: ignore[github-env]
- name: Pwsh Add Slack CLI to PATH
if: steps.slack-cli-check.outputs.exists != 'true' && runner.os == 'Windows'
shell: pwsh
run: Add-Content -Path $env:GITHUB_PATH -Value "$env:USERPROFILE\AppData\Local\slack-cli\bin" # zizmor: ignore[github-env]
- name: Bash Install Slack CLI
if: >-
steps.slack-cli-check.outputs.exists != 'true' &&
steps.cache-cli.outputs.cache-hit != 'true' &&
runner.os != 'Windows'
shell: bash
run: |
if [ -n "$SLACK_CLI_VERSION" ]; then
curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash -s -- -v "$SLACK_CLI_VERSION"
else
curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash -s
fi
env:
SLACK_CLI_VERSION: ${{ inputs.version }}
- name: Pwsh Install Slack CLI
if: >-
steps.slack-cli-check.outputs.exists != 'true' &&
steps.cache-cli.outputs.cache-hit != 'true' &&
runner.os == 'Windows'
shell: pwsh
run: |
if ($env:SLACK_CLI_VERSION) {
$installer = Join-Path $env:TEMP "install-slack-cli.ps1"
Invoke-WebRequest -Uri "https://downloads.slack-edge.com/slack-cli/install-windows.ps1" -OutFile $installer
& $installer -v $env:SLACK_CLI_VERSION
} else {
irm https://downloads.slack-edge.com/slack-cli/install-windows.ps1 | iex
}
env:
SLACK_CLI_VERSION: ${{ inputs.version }}
- name: Bash Run Slack CLI command
id: slack-cli-unix
if: runner.os != 'Windows'
shell: bash
env:
SLACK_COMMAND: ${{ inputs.command }}
SLACK_TOKEN: ${{ inputs.token }}
run: |
args="$SLACK_COMMAND --skip-update"
if [ "$RUNNER_DEBUG" = "1" ]; then
args="$args --verbose"
fi
if [ -n "$SLACK_TOKEN" ]; then
args="$args --token $SLACK_TOKEN"
fi
set +e
output=$(slack $args 2>&1 | tee /dev/stderr)
exit_code=$?
set -e
echo "ok=$([ $exit_code -eq 0 ] && echo 'true' || echo 'false')" >> "$GITHUB_OUTPUT"
echo "time=$(date +%s)" >> "$GITHUB_OUTPUT"
echo "response<<SLACKCLIEOF" >> "$GITHUB_OUTPUT"
echo "$output" >> "$GITHUB_OUTPUT"
echo "SLACKCLIEOF" >> "$GITHUB_OUTPUT"
if [ $exit_code -ne 0 ]; then
exit $exit_code
fi
- name: Pwsh Run Slack CLI command
id: slack-cli-windows
if: runner.os == 'Windows'
shell: pwsh
env:
SLACK_COMMAND: ${{ inputs.command }}
SLACK_TOKEN: ${{ inputs.token }}
run: |
$cliArgs = "$env:SLACK_COMMAND --skip-update"
if ($env:RUNNER_DEBUG -eq "1") {
$cliArgs = "$cliArgs --verbose"
}
if ($env:SLACK_TOKEN) {
$cliArgs = "$cliArgs --token $env:SLACK_TOKEN"
}
$outputFile = New-TemporaryFile
slack $cliArgs.Split(' ') 2>&1 | Tee-Object -FilePath $outputFile.FullName
$exit_code = $LASTEXITCODE
$output = Get-Content $outputFile.FullName -Raw
"ok=$( if ($exit_code -eq 0) { 'true' } else { 'false' } )" >> $env:GITHUB_OUTPUT
"time=$([DateTimeOffset]::UtcNow.ToUnixTimeSeconds())" >> $env:GITHUB_OUTPUT
"response<<SLACKCLIEOF" >> $env:GITHUB_OUTPUT
$output >> $env:GITHUB_OUTPUT
"SLACKCLIEOF" >> $env:GITHUB_OUTPUT
if ($exit_code -ne 0) {
exit $exit_code
}
+14
View File
@@ -57,6 +57,20 @@
"tools/slack-github-action/sending-techniques/sending-data-slack-incoming-webhook/post-inline-block-message",
"tools/slack-github-action/sending-techniques/sending-data-slack-incoming-webhook/post-blocks-found-in-file"
]
},
{
"type": "category",
"label": "Running Slack CLI commands",
"link": {
"type": "doc",
"id": "tools/slack-github-action/sending-techniques/running-slack-cli-commands/running-slack-cli-commands"
},
"items": [
"tools/slack-github-action/sending-techniques/running-slack-cli-commands/running-slack-cli-commands",
"tools/slack-github-action/sending-techniques/running-slack-cli-commands/deploy-an-app",
"tools/slack-github-action/sending-techniques/running-slack-cli-commands/validate-a-manifest",
"tools/slack-github-action/sending-techniques/running-slack-cli-commands/manage-collaborators"
]
}
]
},
@@ -0,0 +1,13 @@
# Example workflow: deploy an app
This workflow deploys a Slack app when changes are pushed to the main branch.
This example uses a service token to authenticate the deploy command.
## Files
### GitHub Actions workflow
```js reference
https://github.com/slackapi/slack-github-action/blob/main/example-workflows/Technique_4_Slack_CLI_Command/deploy.yml
```
@@ -0,0 +1,13 @@
# Example workflow: manage collaborators
This workflow adds or removes an app collaborator using a manually triggered workflow.
This example combines the Slack API technique ([`users.lookupByEmail`](https://docs.slack.dev/reference/methods/users.lookupByEmail), [`chat.postMessage`](https://docs.slack.dev/reference/methods/chat.postMessage)) with the CLI technique ([`collaborators add`](https://docs.slack.dev/tools/slack-cli/reference/commands/slack_collaborators_add)/[`remove`](https://docs.slack.dev/tools/slack-cli/reference/commands/slack_collaborators_remove)) to look up a user by email, update collaborators, and post a confirmation message.
## Files
### GitHub Actions workflow
```js reference
https://github.com/slackapi/slack-github-action/blob/main/example-workflows/Technique_4_Slack_CLI_Command/collaborators.yml
```
@@ -0,0 +1,100 @@
---
sidebar_label: Overview
---
# Running Slack CLI commands
The Slack CLI technique installs and runs [Slack CLI](/tools/slack-cli/) commands directly from a GitHub Actions workflow.
This is useful for automating tasks such as deploying apps, validating an app manifest, or interacting with Slack platform features that are available with the CLI.
## Setup
### Authentication
Pass a [service token](/authentication/tokens/) via the `token` input. This is appended as `--token <value>` to the CLI command. The [`slack auth token`](/tools/slack-cli/reference/commands/slack_auth_token) command can be used to gather this.
### CLI version
By default, the latest version of the Slack CLI is installed. To pin a specific version, use the `version` input:
```yaml
- uses: slackapi/slack-github-action/cli@v2
with:
command: "version"
version: "3.14.0"
```
If the `slack` command already exists on `PATH`, installation is skipped entirely.
## Usage
Provide a `command` input with the Slack CLI command to run, omitting the `slack` prefix.
```yaml
- uses: slackapi/slack-github-action/cli@v2
with:
command: "version"
```
## Debug logging
When a workflow is re-run with **Enable debug logging**, the action automatically appends `--verbose` to the CLI command. You can also include `--verbose` in your `command` input manually at any time.
```yaml
- uses: slackapi/slack-github-action/cli@v2
with:
command: "deploy --app ${{ vars.SLACK_APP_ID }} --verbose"
token: ${{ secrets.SLACK_SERVICE_TOKEN }}
```
## Outputs
The following outputs are available after a CLI command runs:
| Output | Type | Description |
| ---------- | --------- | --------------------------------------------------------------------------------------- |
| `ok` | `boolean` | If the command completed with a `0` exit code. |
| `response` | `string` | The standard output from the CLI command. |
| `time` | `number` | The Unix [epoch time](https://en.wikipedia.org/wiki/Unix_time) that the step completed. |
## Examples
### Check the installed CLI version
```yaml
steps:
- uses: slackapi/slack-github-action/cli@v2
id: slack
with:
command: "version"
- run: echo "${{ steps.slack.outputs.response }}"
```
### Validate the app manifest
```yaml
steps:
- uses: actions/checkout@v4
- uses: slackapi/slack-github-action/cli@v2
with:
command: "manifest validate --app ${{ vars.SLACK_APP_ID }}"
token: ${{ secrets.SLACK_SERVICE_TOKEN }}
```
### Deploy an app with a service token
```yaml
steps:
- uses: actions/checkout@v4
- uses: slackapi/slack-github-action/cli@v2
with:
command: "deploy --app ${{ vars.SLACK_APP_ID }} --force"
token: ${{ secrets.SLACK_SERVICE_TOKEN }}
```
## Example workflows
* [**Deploy an app**](/tools/slack-github-action/sending-techniques/running-slack-cli-commands/deploy-an-app): Deploy to Slack on push to the main branch.
* [**Validate a manifest**](/tools/slack-github-action/sending-techniques/running-slack-cli-commands/validate-a-manifest): Check the app manifest on pull requests.
* [**Manage collaborators**](/tools/slack-github-action/sending-techniques/running-slack-cli-commands/manage-collaborators): Add or remove an app collaborator using CLI and API techniques together.
@@ -0,0 +1,13 @@
# Example workflow: validate a manifest
This workflow validates the app manifest on pull requests to catch configuration issues early.
This example checks the app manifest file in the repository.
## Files
### GitHub Actions workflow
```js reference
https://github.com/slackapi/slack-github-action/blob/main/example-workflows/Technique_4_Slack_CLI_Command/manifest.yml
```
@@ -4,11 +4,12 @@ sidebar_label: Overview
# Sending techniques
This GitHub Action offers three different techniques to send data to Slack:
This GitHub Action offers four different techniques to interact with Slack:
* [Send data with a webhook to start a workflow in Workflow Builder](/tools/slack-github-action/sending-techniques/sending-data-webhook-slack-workflow).
* [Send data using a Slack API method and a secret token with required scopes](/tools/slack-github-action/sending-techniques/sending-data-slack-api-method/).
* [Send data as a message with a Slack incoming webhook URL](/tools/slack-github-action/sending-techniques/sending-data-slack-incoming-webhook/).
* [Send data as a message with a Slack incoming webhook URL](/tools/slack-github-action/sending-techniques/sending-data-slack-incoming-webhook/).
* [Run Slack CLI commands with a service token](/tools/slack-github-action/sending-techniques/running-slack-cli-commands/running-slack-cli-commands).
## Expected outputs
+2 -2
View File
@@ -1,6 +1,6 @@
# Slack Send GitHub Action
# Slack GitHub Action
The GitHub Action for sending data to Slack.
The GitHub Action for sending data to Slack and running commands.
## Versioning
@@ -24,6 +24,7 @@ jobs:
- name: Send the issue link into the Slack channel
uses: slackapi/[email protected]
with:
errors: true
method: chat.postMessage # https://docs.slack.dev/reference/methods/chat.postMessage/
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
@@ -0,0 +1,37 @@
# Technique 4: Slack CLI Command
A [service token](https://docs.slack.dev/authentication/tokens/#service) is used to install and run [Slack CLI](https://docs.slack.dev/tools/slack-cli/) commands directly from a GitHub Actions workflow with this technique.
## Setup
For details on how to setup this technique in GitHub Actions, read the [setup](https://docs.slack.dev/tools/slack-github-action/sending-techniques/running-slack-cli-commands/) section of the docs.
## Example workflows
1. [**Deploy an app**](#deploy-an-app): Deploy to Slack on push to the main branch.
2. [**Validate the app manifest**](#validate-the-app-manifest): Check the app manifest on pull requests.
3. [**Manage a collaborator**](#manage-a-collaborator): Add or remove an app collaborator using CLI and API techniques together.
### Deploy an app
Deploy a Slack app when changes are pushed to the main branch. This example uses a service token to authenticate the deploy command.
**Related files**:
- [`deploy.yml`](./deploy.yml): GitHub Actions workflow.
### Validate the app manifest
Run manifest validation on pull requests to catch configuration issues early. This example checks the app manifest file in the repository.
**Related files**:
- [`manifest.yml`](./manifest.yml): GitHub Actions workflow.
### Manage a collaborator
Add or remove an app collaborator using a manually triggered workflow with [`workflow_dispatch`](https://docs.github.com/en/actions/how-tos/manage-workflow-runs/manually-run-a-workflow). This example combines the Slack API technique ([`users.lookupByEmail`](https://docs.slack.dev/reference/methods/users.lookupByEmail), [`chat.postMessage`](https://docs.slack.dev/reference/methods/chat.postMessage)) with the CLI technique ([`collaborators add`](https://docs.slack.dev/tools/slack-cli/reference/commands/slack_collaborators_add)/[`remove`](https://docs.slack.dev/tools/slack-cli/reference/commands/slack_collaborators_remove)) to look up a user by email, update collaborators, and post a confirmation message.
**Related files**:
- [`collaborators.yml`](./collaborators.yml): GitHub Actions workflow.
@@ -0,0 +1,59 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
name: Manage a collaborator
on:
workflow_dispatch:
inputs:
email:
description: "The collaborator's email address"
required: true
type: string
add:
description: "Checked to add, unchecked to remove"
required: false
default: true
type: boolean
jobs:
collaborator:
name: Add or remove a collaborator
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Look up the Slack user by email
id: email
uses: slackapi/slack-github-action@v2
with:
method: users.lookupByEmail # https://docs.slack.dev/reference/methods/users.lookupByEmail/
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
email: ${{ inputs.email }}
- name: Gather the display name
if: ${{ steps.email.outputs.ok }}
run: |
SLACK_USER_ID=$(echo '${{ steps.email.outputs.response }}' | jq -r '.user.id')
SLACK_DISPLAY_NAME=$(echo '${{ steps.email.outputs.response }}' | jq -r '(.user.profile.display_name | select(. != "")) // .user.real_name')
echo "SLACK_USER_ID=$SLACK_USER_ID" >> "$GITHUB_ENV"
echo "SLACK_DISPLAY_NAME=$SLACK_DISPLAY_NAME" >> "$GITHUB_ENV"
- name: Add or remove the collaborator
if: ${{ steps.email.outputs.ok }}
uses: slackapi/slack-github-action/cli@v2
with:
command: "collaborators ${{ inputs.add && 'add' || 'remove' }} ${{ inputs.email }} --app ${{ vars.SLACK_APP_ID }}"
token: ${{ secrets.SLACK_SERVICE_TOKEN }}
- name: Post a confirmation message
if: ${{ steps.email.outputs.ok }}
uses: slackapi/slack-github-action@v2
with:
errors: true
method: chat.postMessage # https://docs.slack.dev/reference/methods/chat.postMessage/
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: ${{ secrets.SLACK_CHANNEL_ID }}
text: "<@${{ env.SLACK_USER_ID }}> (${{ env.SLACK_DISPLAY_NAME }}) was ${{ inputs.add && 'added to' || 'removed from' }} the app collaborators."
@@ -0,0 +1,32 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
name: Deploy an app
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy to Slack
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Deploy the app
uses: slackapi/slack-github-action/cli@v2
with:
command: "deploy --app ${{ vars.SLACK_APP_ID }} --force"
token: ${{ secrets.SLACK_SERVICE_TOKEN }}
- name: Post a deployment message
uses: slackapi/slack-github-action@v2
with:
errors: true
method: chat.postMessage
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: ${{ secrets.SLACK_CHANNEL_ID }}
text: "Deployed to Slack from ${{ github.sha }}"
@@ -0,0 +1,20 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
name: Validate the app manifest
on:
pull_request:
jobs:
validate:
name: Check the app manifest
runs-on: ubuntu-latest
steps:
- name: Checkout the repo
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Validate the manifest
uses: slackapi/slack-github-action/cli@v2
with:
command: "manifest validate --app ${{ vars.SLACK_APP_ID }}"
token: ${{ secrets.SLACK_SERVICE_TOKEN }}