a slack app that turns your terraform plans into a proper approval workflow. π shaaame π
Review request lands in your channel
Review has been approved, and an apply action has been triggered |
Full plan review with one-click approval |
when terraform runs and detects a change in the plan, this app:
- just found out the plans changed again
- posts a message to the
#prod-infra-reviewschannel - lets you approve/reject, publicly, proudly
- stores the decision so you can pretend you actually reviewed it later
- π’ low risk: "oh look, you're adding a tag. how brave."
- π‘ medium risk: "you're changing some stuff. i'm watching you."
β οΈ high risk: "you're touching iam or security groups. i hope you know what you're doing."- π΄ critical risk: "love that for you"
sequenceDiagram
participant CI as CI/CD Pipeline
participant Webhook as Webhook
participant Slack as Slack App
participant User as Human Reviewer
participant Datastore as Slack Datastore
participant GitHub as GitHub API
CI->>CI: Run Terraform Plan
alt Plan has changes
CI->>Webhook: POST Terraform plan data
Webhook->>Slack: Trigger approval workflow
Slack->>Datastore: Store review data
Slack->>User: Post message with buttons
User->>Slack: Click "Review & decide"
Slack->>User: Open review modal
User->>Slack: Approve/Reject in modal
alt Approve
Slack->>GitHub: POST repository_dispatch
GitHub->>CI: Trigger workflow (approve)
CI->>CI: Apply changes
Slack->>User: Update: β
Approved
else Reject
Slack->>GitHub: POST repository_dispatch
GitHub->>CI: Trigger workflow (reject)
CI->>CI: Cancel pipeline
Slack->>User: Update: β Rejected
end
else No changes
CI->>CI: Continue pipeline
end
built with:
- deno slack cli
- slack ui components
- a slack workspace (duh)
- a github repository with terraform (also duh)
- a ci/cd pipeline that can make http requests (github actions, gitlab ci, etc.)
- the ability to read documentation (you're doing great so far!)
more below.
- clone this repo (you already did this, good job!) β’ install the slack cli if you haven't:
brew install --cask slack-cli- link your app:
slack login- run the app:
slack run- get your webhook url from the slack app settings
add this to your ci/cd pipeline (github actions example):
- name: Notify Slack about Terraform Plan
run: |
curl -X POST ${{ secrets.SLACK_WEBHOOK_URL }} \
-H "Content-Type: application/json" \
-d '{
"id": "${{ github.run_id }}",
"slackChannelId": "C1234567890",
"repositoryFullName": "${{ github.repository }}",
"runId": "${{ github.run_id }}",
"runNumber": "${{ github.run_number }}",
"commitHash": "${{ github.sha }}",
"terraformAdds": "5",
"terraformChanges": "2",
"terraformDestroys": "0",
"commitMessage": "${{ github.event.head_commit.message }}",
"commitTimeEpoch": "${{ github.event.head_commit.timestamp }}",
"author": "${{ github.event.head_commit.author.name }}",
"branch": "${{ github.ref_name }}",
"organizationName": "${{ github.repository_owner }}",
"repositoryName": "${{ github.event.repository.name }}",
"friendlyName": "company/infrastructure",
"terraformPlanJson": "{\"resource_changes\":[]}"
}'using Slack CLI
slack env set GH_TOKEN xxxwhich has permission to dispatch events to the repositoryslack env set REVIEW_TRIGGER_URL xxxwhich is the url to dispatch the apply pipeline
- webhook trigger: our infra cd pipeline hits the webhook with terraform plan data
- workflow execution: slack starts the approval workflow
- latest claim: if there's already a review for this repo, it gets marked as stale and the new one becomes "latest"
- message posting: a beautiful message appears in your channel with:
- summary of changes (adds/changes/destroys)
- risk assessment (because we care about your job security)
- links to the full plan
- approve/reject buttons
- decision time: someone (hopefully not an intern) clicks a button
- github integration: the app calls github's api to approve/reject the run
- audit trail: everything gets stored for when the lawyers come calling
the app has a SopHisTicAteED algorithm to determine risk levels:
- iam changes: high risk (because permissions are scary)
- security groups: high risk (because security is important)
- database instances: high risk (because data is money)
- eks clusters: medium risk (because kubernetes is complex)
- s3 buckets: low risk (because storage is cheap)
to prevent chaos and ensure only the latest changes get applied:
- latest claims: when a new terraform plan comes in, it becomes the "latest" and any existing reviews are marked as stale
- modal blocking: only the latest review can open the approval modal - stale reviews show an error message
- no confusion: no more wondering which review is the "real" one
this app is weird, it's part of slack's new function platform.
it owns logs, deploying, running, the lot. nice.
# To run a dev version locally
slack run
# To deploy to production
slack deploy
# To view logs
slack logs# install dependencies (there aren't any, it's deno!)
# but you can run tests (there aren't any, yoloΒ±)
deno task test
# format code (because we're civilized)
deno fmt
# lint code (because we care about quality)
deno lintβββ functions/ # the main logic (where the magic happens)
βββ workflows/ # essentially proxies traffic through to the "function" layer
βββ triggers/ # a webhook from our ci pipeline with infra review data
βββ datastores/ # stores the review data, avoid slacks interactivity shit
βββ types/ # π΅
βββ utils/tf/ # terraform parsing and whatnot
βββ assets/ # πΌοΈ


