A deploy orchestrator built with Chat SDK and Vercel Workflow. Trigger deploys from Slack, gate production with approval, dispatch GitHub Actions, and notify GitHub and Linear when the run finishes.
/deploy stagingstarts a staging deploy onmainimmediately./deploy production(or/deploy prod) posts an approval card first, then runs only after approval./deploywith no arguments opens a modal where you can pick an environment and optionally specify a branch (defaults tomain).- The workflow dispatches a GitHub Actions run, polls it (up to 60 minutes), posts status updates, and ends with a summary card.
- On successful deploys, if Linear is enabled, the bot finds issues from the deploy branch and commit messages, comments on them, and transitions production issues to your configured done state.
- On successful deploys, GitHub PRs touched by the commit are commented with the deploy summary.
- If a deploy fails to dispatch or the run can't be found, the triggerer receives a private notification.
The quickest way to get started is to create your app from the included manifest:
- Go to api.slack.com/apps and click Create New App → From a manifest
- Select your workspace, paste the contents of
slack-manifest.json, and create the app - Replace
https://example.comin Interactivity & Shortcuts with your actual domain (or ngrok URL during development) - Install the app to your workspace
- Copy the Bot User OAuth Token from OAuth & Permissions and the Signing Secret from Basic Information into your
.env.local
Manual setup (without manifest)
- Create a Slack app at api.slack.com/apps.
- Under OAuth & Permissions, add the bot token scopes:
chat:write,commands,im:write,channels:history,channels:read,groups:history,groups:read,im:history,im:read,mpim:history,mpim:read,users:read - Add a slash command:
- Command:
/deploy - Request URL:
https://your-domain.vercel.app/api/webhooks/slack
- Command:
- Enable Interactivity & Shortcuts and set the request URL to the same Slack webhook URL.
- Install the app to your workspace and copy the bot token and signing secret.
- Create a fine-grained PAT for the target repository.
- Grant the repository permissions:
- Actions: read and write
- Contents: read
- Issues: write
- Pull requests: read
- Set
GITHUB_TOKEN,GITHUB_WEBHOOK_SECRET,GITHUB_REPO_OWNER,GITHUB_REPO_NAME, andGITHUB_WORKFLOW_ID(the workflow filename, e.g.deploy.yml, or its numeric ID). - Point the target workflow at a
workflow_dispatch-enabled deploy workflow.
Your target workflow should ideally accept:
environment(recommended)deploy_id(optional)
The bot gracefully degrades if the workflow doesn't accept all inputs — it tries { environment, deploy_id }, then { environment } alone, then no inputs.
Example:
name: Deploy
on:
workflow_dispatch:
inputs:
environment:
description: Target environment
required: true
type: choice
options:
- staging
- production
deploy_id:
description: Optional deploy correlation ID
required: false
type: string
run-name: Deploy ${{ inputs.environment }} (${{ inputs.deploy_id || github.sha }})deploy_id is optional, but including it in run-name helps the bot reliably match the run it just dispatched.
- If you want GitHub comment-thread support through the adapter, add a repository webhook pointing at
https://your-domain.vercel.app/api/webhooks/githubwith content typeapplication/jsonand the same secret asGITHUB_WEBHOOK_SECRET. Subscribe toissue_commentandpull_request_review_comment.
If Linear is enabled, your deploy pipeline must keep these tags moving in the target repo:
deploy/staging/previousdeploy/staging/latestdeploy/production/previousdeploy/production/latest
The bot compares deploy/{environment}/previous and deploy/{environment}/latest to find the commit range for Linear issue detection. It does not create or move those tags itself.
Linear is optional. Set LINEAR_API_KEY to enable it. No separate Linear webhook setup is required.
Behavior:
- Issue keys are extracted from the deploy branch and commit messages using
LINEAR_TEAM_PREFIX. LINEAR_TEAM_PREFIXdefaults toENG.LINEAR_PRODUCTION_STATEdefaults toDone.- On successful deploys, staging deploys comment on linked issues.
- On successful deploys, production deploys comment on linked issues and transition them to the configured production state.
- If the tag comparison fails, the bot skips Linear updates rather than guessing from unrelated commits.
- If the configured production state does not exist on a team, the workflow fails that Linear step instead of silently pretending it succeeded.
Required:
SLACK_BOT_TOKENSLACK_SIGNING_SECRETGITHUB_TOKENGITHUB_WEBHOOK_SECRETGITHUB_REPO_OWNERGITHUB_REPO_NAMEGITHUB_WORKFLOW_IDREDIS_URL
Optional:
LINEAR_API_KEYLINEAR_TEAM_PREFIXLINEAR_PRODUCTION_STATEDEPLOY_PROD_ALLOWEDDEPLOY_PROD_APPROVERS
DEPLOY_PROD_ALLOWEDcontrols who can start production deploys (comma-separated Slack user IDs). If empty or unset, nobody can trigger production deploys.DEPLOY_PROD_APPROVERScontrols who can approve production deploys (comma-separated Slack user IDs). If empty or unset, nobody can approve.- Only the person who triggered a deploy can cancel it.
- Staging deploys are available to everyone.
- A Slack slash command or modal submission creates a deploy request.
- For production deploys, the bot edits the initial deploy card to add an approval prompt with Approve and Cancel buttons, then pauses the workflow until someone responds.
- The workflow dispatches a GitHub Actions run and polls until it completes (up to 60 minutes).
- On successful runs, the bot comments on GitHub PRs and (if Linear is enabled) on linked Linear issues.
- A final summary card is posted back to Slack with environment, branch, commit, duration, linked issues, and a link to the workflow run.
git clone <repo-url>
cd <repo-dir>
pnpm install
cp .env.example .env.local
pnpm devOr deploy manually:
vercel deploy| Command | Description |
|---|---|
pnpm dev |
Start dev server with hot reload |
pnpm build |
Production build via Next.js |
pnpm test |
Run tests with coverage |
pnpm type-check |
Type-check without emitting |
pnpm check |
Lint and format check |
pnpm fix |
Auto-fix lint and format issues |
pnpm validate |
Run check, type-check, and tests |
Chat SDK supports multiple platforms. You can extend this bot to post deploy cards to Microsoft Teams, Google Chat, Discord, or Telegram by registering additional adapters:
// lib/bot.ts
import { createTeamsAdapter } from "@chat-adapter/teams";
import { createGoogleChatAdapter } from "@chat-adapter/gchat";
export const bot = new Chat({
adapters: {
slack: createSlackAdapter(),
teams: createTeamsAdapter(),
gchat: createGoogleChatAdapter(),
},
state: createRedisState(),
userName: "deploy-bot",
});Then add a webhook route for each platform — the existing app/api/webhooks/[platform]/route.ts dynamic route already supports any adapter name registered above.
Cards, fields, and buttons render natively on each platform (Block Kit on Slack, Adaptive Cards on Teams, Google Chat Cards, etc.). Note that modals are currently Slack-only, so the /deploy modal (no arguments) will only work on Slack.
See the Chat SDK adapter docs for the full list of supported platforms and their feature matrices.
Apache-2.0