Deploy from Slack, with approval for production
This guide builds a deploy command for Slack. Someone mentions the KloudMate bot with a request such as “deploy api to staging”, and the workflow starts your GitHub Actions deploy workflow, follows the run, and replies in the thread when it finishes. A deploy to production waits until an approver says yes.
The request is ordinary text, so an AI Extract step reads it and picks the service and the environment from fixed lists. The rest of the workflow works only with those values, never with the message itself.
The finished workflow has these steps:
Before you start
Section titled “Before you start”- You need the Developer role in a KloudMate workspace whose plan includes workflows.
- You need a Slack connection with the Workflows capability, and a channel for deploy requests. Invite the KloudMate bot to that channel.
- You need a GitHub repository where you can add a workflow, and permission to create a fine-grained personal access token for it.
- Each run uses workflow credits, and the AI Extract step uses more. See Check workflow usage.
Step 1: Add a deploy workflow in GitHub
Section titled “Step 1: Add a deploy workflow in GitHub”The workflow starts a GitHub Actions workflow named deploy.yml, and passes it the service and the environment. Add this file to your repository’s default branch as .github/workflows/deploy.yml, and replace the last step with your own deploy commands:
If you already have a deploy workflow, add the workflow_dispatch trigger with these two inputs to it instead.
Step 2: Save the repository and a token as variables
Section titled “Step 2: Save the repository and a token as variables”- In GitHub, create a fine-grained personal access token with access to the repository, and the Actions repository permission set to Read and write.
- In KloudMate, open Workflows → Variables, and create a Secret named
github_tokenwith the token as its value. - Create a Constant named
github_repowith the repository’s owner and name, such asacme/platform.
The token lets the workflow start runs and read their status, and nothing else in the repository.
Step 3: Import the workflow
Section titled “Step 3: Import the workflow”- Copy the YAML below.
- Open Workflows, click Import, paste the YAML, and click Import.
- Click Open workflow, and set these before you publish:
- On the trigger, pick your Slack connection under Account, and set Only in channel to your deploy channel.
- On every Slack step, pick your Slack connection.
- On Approve the production deploy, add the people who can approve a production deploy under Approvers.
How each step works
Section titled “How each step works”The trigger
Section titled “The trigger”The Bot is mentioned trigger runs when someone mentions the bot in a channel. Only in channel limits it to your deploy channel, so a mention anywhere else doesn’t start a deploy. The event carries the message as trigger.event.text, the person as trigger.event.user, and the message’s channel and timestamp.
Read the request
Section titled “Read the request”An AI Extract step reads {{ trigger.event.text }} and returns whether it’s a deploy request, the service, and the environment. Output fields limits each one to a fixed list, so the model can only answer with a service and an environment that you allow:
The message is text that anyone in the channel can write, which is why the workflow uses AI Extract rather than AI Prompt. A message that tries to steer the model still can’t produce a service or an environment outside these lists. See AI Extract.
A Branch then checks that intent equals deploy, and that service and environment are not empty. For anything else, the Else block replies with an example of how to ask.
Look up who asked
Section titled “Look up who asked”A Slack Look Up User step turns {{ trigger.event.user }} into a person, so the approval email can name the requester as {{ steps.who.output.user.real_name }} instead of a Slack user ID.
Approve a production deploy
Section titled “Approve a production deploy”A Branch checks whether environment equals production. If it does, the workflow replies in the thread that the deploy needs an approval, and an Approval step emails the approvers. Timeout is 30m, and On timeout is Continue.
The next Branch, OK to deploy?, uses Match any, so it continues when either condition holds:
steps.parse.output.environmentequalsstaging, orsteps.approve.output.approvedis not empty, which is true only after an approval.
A staging deploy never reaches the approval, so it goes straight through. A production deploy whose approval timed out takes the Else block, which replies that nobody approved it. If an approver rejects the deploy, the run ends there.
Start the deploy workflow
Section titled “Start the deploy workflow”An HTTP Request step sends a POST to GitHub’s workflow dispatch endpoint:
Authentication is Bearer token, with the token set to {{ secrets.github_token }}, so the token never appears in the workflow or in run history. The Headers set Accept to application/vnd.github+json and X-GitHub-Api-Version to 2022-11-28. The JSON body picks the branch and passes the two inputs:
return_run_details asks GitHub to return the new run’s ID and its web address, as workflow_run_id and html_url. The next steps use both.
Reply in the thread
Section titled “Reply in the thread”Every reply is a Slack Post Message step with Channel set to {{ trigger.event.channel }}, and Reply to thread set to this template:
If the mention was already a reply in a thread, Slack sends thread_ts, and the workflow replies in that thread. Otherwise, it starts a thread on the mention. The assign form picks one without leaving an unresolved reference behind when thread_ts isn’t there.
The first reply names the service, the environment, and the person who asked, with a link to the run in GitHub. Slack’s link syntax is <address|text>, as in <{{ steps.dispatch.output.body.html_url }}|Follow the run>.
Wait for the deploy to finish
Section titled “Wait for the deploy to finish”A Wait until step reads the run from GitHub, with an HTTP Request step in its check block:
It checks until steps.run.output.body.status equals completed, for up to 30m. The imported step has on_error: continue, so a deploy that takes longer than that still gets a reply. The builder keeps this setting but has no field for it, so if you build the workflow by hand, a deploy that runs past the timeout fails the run instead.
Report the result
Section titled “Report the result”The last reply reads the run’s status and conclusion, and says whether the deploy succeeded, failed, or is still running:
Step 4: Test and publish
Section titled “Step 4: Test and publish”- Open the trigger’s Test tab and click Test trigger. Then mention the bot in your deploy channel with a staging deploy, such as
@KloudMate deploy api to staging. The mention becomes the trigger’s sample. - Test Read the request from its Test tab to see what the model extracted.
- Click Test run. It runs every step for real, so it starts the staging deploy and replies in the thread.
- Click Publish. The first publish also switches the workflow on.
Try a production deploy the same way when you’re ready, and approve it from the email.
Adapt the workflow
Section titled “Adapt the workflow”- Deploy other services. Add each service to the
serviceoptions in Read the request, and to theoptionsof theserviceinput indeploy.yml. - Limit who can deploy. Add a condition to Is it a deploy request? that
trigger.event.useris in a list of Slack user IDs. - Deploy a branch other than main. Change
refin the body of Start the deploy workflow. - Use another CI system. Replace the two HTTP Request steps with the equivalent calls to your CI system’s API, such as starting a pipeline and reading its status.
Related
Section titled “Related”- AI Extract for output fields and why they’re safe with untrusted text.
- Approvals and collected input for approval timeouts.
- Wait until for how often it checks.
- Variables for secrets such as the GitHub token.