Skip to content

Latest commit

 

History

History
546 lines (441 loc) · 20.2 KB

README.md

File metadata and controls

546 lines (441 loc) · 20.2 KB

Slack Send GitHub Action

the GitHub Action for sending data to Slack

codecov

Example workflows

For examples on how to leverage this Action in workflows, check out example workflows we have available.

Sending variables

There are different techniques to send data into Slack and whichever one is chosen will require a certain set of customized inputs, as described later.

You can provide data to send to Slack from this GitHub Action and either source:

  • The default event context with a payload matching the GitHub event.
  • A custom payload with optional variables provided in the GitHub Action step.

These input options are valid for all techniques, but some techniques require specific constraints with certain requirements for valid inputs.

Additional configurations and other details are also available for more customizations to the provided payload.

Sending techniques

This Action offers three different techniques to send data to Slack:

  1. Technique 1: Send data with a webhook to start a workflow in Workflow Builder.
  2. Technique 2: Send data using a Slack API method and a secret token with required scopes.
  3. Technique 3: Send data as a message with a Slack incoming webhook URL.

Technique 1: Slack Workflow Builder

📝 This technique requires a Slack paid plan to use Workflow Builder.

This technique sends data to Slack using a webhook to start a workflow created using Slack Workflow Builder.

Setup

Start in Slack to create a Slack workflow:

  1. Create a Slack workflow that starts from a webhook.
  2. Copy the webhook URL and add it as a repository secret called SLACK_WEBHOOK_URL.
  3. Add this Action as a step to your GitHub workflow and provide an input payload to send to the webhook.
  4. Configure your Slack workflow to use the payload variables sent from the GitHub Action. You can then update the steps of the Slack workflow to use these values in creative and clever ways.

The webhook URL will resemble something like so:

https://hooks.slack.com/triggers/T0123456789/3141592653589/c6e6c0d868b3054ca0f4611a5dbadaf

Usage

Update the input payloads sent from this GitHub Action to your Slack workflow using the following options:

Sending values from the default GitHub event context

In the example below, the default GitHub event context and event payload associated with the job that started the GitHub workflow are sent to the provided webhook URL:

- name: Send GitHub Action data to a Slack workflow
  uses: slackapi/[email protected]
  with:
    payload-delimiter: "_"
    webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
    webhook-type: webhook-trigger

Accessing variables sent to Workflow Builder with a webhook require that the payload variables are flattened with stringified values. Nested variables in the provided payload can be both flattened and also stringified with the payload-delimiter option or changed with other configurations to match this format expected from Workflow Builder.

Providing parsed payload information as strings

Provided input values for payload information are sent to the webhook URL after the job is started:

- name: Send custom event details to a Slack workflow
  uses: slackapi/[email protected]
  with:
    webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
    webhook-type: webhook-trigger
    payload: |
      status: "${{ job.status }}"
      option: "false"
Gathering details of the payload from a saved file

Input values for the payload to be sent can also be provided in a file, either in JSON or YAML format:

- name: Send a saved artifact to a Slack workflow
  uses: slackapi/[email protected]
  with:
    payload-file-path: "./artifacts.json"
    webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
    webhook-type: webhook-trigger

Technique 2: Slack API method

A bot token or user token or token of some other kind must be used to call one of the Slack API methods with this technique.

Setup

Different Slack API methods require different scopes, but setup should be similar for all methods:

  1. Create a Slack app for your workspace or use an existing app.
  2. Depending on the Slack API method you wish to call, add the required scopes to your app under the OAuth & Permissions page on app settings.
  3. Install the app to your workspace using the Install App page.
  4. Once your app is installed to a workspace, a new token with your app's specified scopes will be minted for that workspace. It is worth noting that tokens are only valid for a single workspace! Find the token on the OAuth & Permissions page.
  5. Add the token as a repository secret called SLACK_BOT_TOKEN or something similar and memorable.
  6. Add this Action as a step to your GitHub workflow and provide an input payload to send to the method.

Methods that require an app configuration token should gather this token from the app configuration token settings instead of from a specific app since this token is associated with the workspace.

Usage

Choosing inputs for these steps is left as an exercise for the actioneer since each of the Slack API methods requires certain values and specific parameters, but these snippets might be helpful when starting.

Posting a message with text

Posting a message with the chat.postMessage method can be achieved by adding this step to a job in your GitHub workflow and inviting the bot associated with your app to the channel for posting:

- name: Post to a Slack channel
  uses: slackapi/[email protected]
  with:
    method: chat.postMessage
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      channel: ${{ secrets.SLACK_CHANNEL_ID }}
      text: "howdy <@channel>!"
Posting a message with blocks

More complex message layouts, such as messages made with Block Kit blocks, can also be sent with one of the Slack API methods:

- name: Post to a Slack channel
  uses: slackapi/[email protected]
  with:
    method: chat.postMessage
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      channel: ${{ secrets.SLACK_CHANNEL_ID }}
      text: "GitHub Action build result: ${{ job.status }}\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}"
      blocks:
        - type: "section"
          text:
            type: "mrkdwn"
            text: "GitHub Action build result: ${{ job.status }}\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}"
Updating a message

Updating a message after it's posted can be done with the chat.update method and chaining multiple steps together using outputs from past steps as inputs to current ones:

- name: Initiate the deployment launch sequence
  id: slack
  uses: slackapi/[email protected]
  with:
    method: chat.postMessage
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      channel: ${{ secrets.SLACK_CHANNEL_ID }}
      text: "Deployment started :eyes:"
      attachments:
        - color: "dbab09"
          fields:
            - title: "Status"
              short: true
              value: "In Progress"
- name: Countdown until launch
  run: sleep 10
- name: Update the original message with success
  uses: slackapi/[email protected]
  with:
    method: chat.update
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      channel: ${{ secrets.SLACK_CHANNEL_ID }}
      ts: "${{ steps.slack.outputs.ts }}"
      text: "Deployment finished! :rocket:"
      attachments:
        - color: "28a745"
          fields:
            - title: "Status"
              short: true
              value: "Completed"
Replying to a message

Posting threaded replies to a message from a past job can be done by including the thread_ts attribute of the parent message in the payload:

- name: Initiate a deployment
  uses: slackapi/[email protected]
  id: deployment_message
  with:
    method: chat.postMessage
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      channel: ${{ secrets.SLACK_CHANNEL_ID }}
      text: "Deployment started :eyes:"
- name: Conclude the deployment
  uses: slackapi/[email protected]
  with:
    method: chat.postMessage
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      channel: ${{ secrets.SLACK_CHANNEL_ID }}
      thread_ts: "${{ steps.deployment_message.outputs.ts }}"
      text: "Deployment finished! :rocket:"
Uploading a file

Calling a Slack API method with @slack/web-api makes uploading a file just another API call with all of the convenience of the files.uploadV2 method:

- name: Share a file to that channel
  uses: slackapi/[email protected]
  with:
    method: files.uploadV2
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      channel_id: ${{ secrets.SLACK_CHANNEL_ID }}
      initial_comment: "the results are in!"
      file: "results.out"
      filename: "results-${{ github.sha }}.out"

Technique 3: Slack incoming webhook

This technique uses this Action to post a message to a channel or direct message with incoming webhooks and a Slack app.

Incoming webhooks follow the same formatting patterns as other Slack messaging APIs. Posted messages can be as short as a single line of text, include additional interactivity with interactive components, or be formatted with Block Kit to build visual components.

Setup

Gather a Slack incoming webhook URL:

  1. Create a Slack app for your workspace or use an existing app.
  2. Add the incoming-webhook bot scope under OAuth & Permissions page on app settings.
  3. Install the app to your workspace and select a channel to notify from the Install App page.
  4. Create additional webhooks from the Incoming Webhooks page.
  5. Add the generated incoming webhook URL as a repository secret called SLACK_WEBHOOK_URL.
  6. Add this Action as a step to your GitHub workflow and provide an input payload to send as a message.

Usage

Add the collected webhook from above to a GitHub workflow and configure the step using mrkdwn formatting values for a message or Block Kit blocks:

- name: Post a message in a channel
  uses: slackapi/[email protected]
  with:
    webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
    webhook-type: incoming-webhook
    payload: |
      text: "*GitHub Action build result*: ${{ job.status }}\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}"
      blocks:
        - type: "section"
          text:
            type: "mrkdwn"
            text: "GitHub Action build result: ${{ job.status }}\n${{ github.event.pull_request.html_url || github.event.head_commit.url }}"

Additional configurations

Not all of the above settings serve every customization of a workflow, so these options might be useful.

Exiting with errors

Invalid API requests or unexpected webhook payloads cause a failing response that can be used to fail the GitHub Actions step with the errors option.

The errors option defaults to false so failed requests do not cause the step to fail. This result can still be gathered from the ok output.

- name: Send GitHub Action data to a Slack workflow
  uses: slackapi/[email protected]
  with:
    errors: true
    method: chat.reverse
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      text: "palindrome"

Invalid inputs to the Action, such as not including a payload, will always cause the GitHub step to fail.

Flattening nested payloads

Variables and data provided in the payload might contain nested fields that need to be flattened before being sent with a webhook trigger to match the expected input format of Workflow Builder.

The payload-delimiter option will flatten the input payload using the provided delimiter and will also make values stringified:

- name: Send GitHub Action data to a Slack workflow
  uses: slackapi/[email protected]
  with:
    payload-delimiter: "_"
    webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
    webhook-type: webhook-trigger

Reference to the flattening implementation is available for exploration from within the flat package.

Parsing templated variables

Additional variables provided in the Github event context and event payload can be used to replace templated variables in the input payload with the payload-templated option:

- name: Send custom JSON data to Slack workflow
  id: slack
  uses: slackapi/[email protected]
  with:
    payload-file-path: "./payload-slack-content.json"
    payload-templated: true
    webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
    webhook-type: webhook-trigger

This replaces variables templated as ${{ github.payload.repository.html_url }} with the values found in the GitHub Action event payload.

Proxying HTTPS requests

If you need to use a proxy to connect to Slack, you can use the proxy option. In this example we use the technique that calls a Slack API method, but configuring a proxy is the same for all techniques:

- name: Post to a Slack channel via a proxy
  uses: slackapi/[email protected]
  with:
    method: chat.postMessage
    proxy: "http://proxy.example.org:8080" # Change this to a custom value
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      channel: ${{ secrets.SLACK_CHANNEL_ID }}
      text: "This message was sent through a proxy"

The proxy option can also be provided with the HTTPS_PROXY or https_proxy environment variable from within the GitHub Actions step.

Retrying failed requests

Sometimes outgoing requests fail due to rate limits or similar HTTP responses and can be retried later.

The retries option can be configured to the needs of your workflow with one of these values:

  • 0: No retries, just hope that things go alright.
  • 5: Five retries in five minutes. Default.
  • 10: Ten retries in about thirty minutes.
  • RAPID: A burst of retries to keep things running fast.
- name: Attempt a burst of requests
  uses: slackapi/[email protected]
  with:
    method: chat.postMessage
    retries: RAPID
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      channel: ${{ secrets.SLACK_CHANNEL_ID }}
      text: "status: all things are going good"

Behind the scenes, automatic retries are handled with the @slack/web-api package for Slack API methods, and axios-retry when sending with a webhook.

Expected outputs

Each technique above outputs values that can be used as inputs in following steps of a GitHub workflow.

The following outputs are returned with each of the techniques:

  • time: number. The Unix epoch time that the step completed.
  • ok: boolean. If the request completed with success.
  • response: string. The response from the request as stringified JSON.

While these outputs are returned with certain Slack API methods:

Example responses

The following snippet shows how multiple steps can be chained together to create a Slack channel before posting a message:

- name: Create a new Slack channel for recent changes
  id: conversation
  uses: slackapi/[email protected]
  with:
    method: conversations.create
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      name: pull-request-review-${{ github.sha }}
- name: Send the pull request link into the Slack channel
  if: ${{ steps.conversation.outputs.ok }}
  uses: slackapi/[email protected]
  with:
    method: chat.postMessage
    token: ${{ secrets.SLACK_BOT_TOKEN }}
    payload: |
      channel: ${{ steps.conversation.outputs.channel_id }}
      text: "A PR was created <!date^${{ steps.conversation.outputs.time }}^{date_num} at {time_secs}|just now>: ${{ github.event.pull_request.html_url }}"

License

This project is licensed under the MIT license.

Contributing

All contributions are encouraged! Check out the contributor's guide to learn more.