Automate Deployments
Schedule Terraform deployments, create approval workflows, and set up automated pipelines for infrastructure changes.
Scenario
Your team wants to:
- Automatically deploy changes to staging every night
- Require manager approval before production deployments
- Trigger deployments when PRs are merged
- Get notifications when deployments complete or fail
Prerequisites
✓IaC project with Terraform code
✓Slack integration (for notifications and approvals)
Option 1: Scheduled Deployments
Deploy automatically on a schedule (e.g., nightly staging updates).
Create a Scheduled Workflow
1Click Workflows in the sidebar
2Click + New Workflow
3Name it:
nightly-staging-deployConfigure the Trigger
Select Schedule trigger and set the cron expression:
| Schedule | Cron Expression |
|---|---|
| Every night at 2 AM | 0 2 * * * |
| Every Monday at 9 AM | 0 9 * * 1 |
| Every hour | 0 * * * * |
| First of month | 0 0 1 * * |
Add Workflow Steps
┌───────────────────────────────────────────────────────────────┐
│ Trigger: Schedule (Daily at 2 AM UTC) │
└───────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ Step 1: Terraform Plan │
│ Project: staging-infrastructure │
│ Action: Plan │
└───────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ Step 2: Terraform Apply │
│ Project: staging-infrastructure │
│ Action: Apply │
│ Condition: Only if plan has changes │
└───────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ Step 3: Notify Slack │
│ Channel: #infrastructure │
│ Message: "Staging deployment complete: {{ result }}" │
└───────────────────────────────────────────────────────────────┘
Click Save & Enable to activate the workflow.
Option 2: Approval Workflows
Require human approval before deploying to production.
Create an Approval Workflow
1Create a new workflow:
production-deploy2Set trigger to Manual or GitHub PR Merged
Workflow with Approval Step
┌───────────────────────────────────────────────────────────────┐
│ Trigger: Manual or GitHub (PR merged to main) │
└───────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ Step 1: Terraform Plan │
│ Project: production-infrastructure │
└───────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ Step 2: Request Approval │
│ Approvers: @platform-team │
│ Notify via: Slack #prod-approvals │
│ Timeout: 4 hours │
│ Include: Plan output, cost estimate │
└───────────────────────────────────────────────────────────────┘
│
┌─────────┴─────────┐
│ │
▼ ▼
Approved Rejected/Timeout
│ │
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ Step 3: Apply │ │ Notify: Deployment │
│ │ │ cancelled │
└──────────────────────┘ └──────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ Step 4: Notify Success │
│ Channel: #infrastructure │
└───────────────────────────────────────────────────────────────┘
Approval Request in Slack
When the workflow reaches the approval step:
ops0 Bot in #prod-approvals
Production Deployment Approval Required
Project: production-infrastructure
Requested by: jane@company.com
Changes: 2 to add, 1 to change, 0 to destroy
Cost Impact: +$45.00/month
ApproveRejectView Plan
Option 3: Event-Driven Deployments
Deploy automatically when specific events occur.
Available Triggers
| Trigger | Use Case |
|---|---|
| GitHub PR Merged | Deploy when code reaches main branch |
| Webhook | Trigger from external systems (CI/CD, Slack) |
| Manual | On-demand deployment button |
| Another Workflow | Chain workflows together |
| Drift Detected | Auto-remediate when drift is found |
Example: Deploy on PR Merge
┌───────────────────────────────────────────────────────────────┐
│ Trigger: GitHub │
│ Event: Pull Request Merged │
│ Branch: main │
│ Path Filter: terraform/** │
└───────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ Condition: Check Environment │
│ If: PR labels contain "production" │
│ → Go to Production Deploy Path │
│ Else: │
│ → Go to Staging Deploy Path │
└───────────────────────────────────────────────────────────────┘
Configuring Notifications
Add notifications to any workflow step:
Slack Notifications
1Add a Slack Notification step
2Select channel:
#infrastructure3Customize message with variables:
Available Variables
| Variable | Value |
|---|---|
{{ workflow.name }} | Name of the workflow |
{{ trigger.user }} | Who triggered (or "scheduled") |
{{ steps.plan.changes }} | Number of changes in plan |
{{ steps.apply.status }} | Success/Failed |
{{ steps.apply.duration }} | How long apply took |
{{ project.name }} | Project name |
Example Message Template
{{ workflow.name }} completed!
Triggered by: {{ trigger.user }}
Project: {{ project.name }}
Status: {{ steps.apply.status }}
Changes: {{ steps.plan.changes }}
Duration: {{ steps.apply.duration }}
View details: {{ workflow.url }}
Monitoring Workflow Runs
View Execution History
1Click Workflows > select your workflow
2Click Runs tab
3Click on any run to see step-by-step logs
Run Status
| Status | Meaning |
|---|---|
| Running | Currently executing |
| Waiting | Waiting for approval |
| Succeeded | All steps completed successfully |
| Failed | A step failed (click for details) |
| Cancelled | Manually stopped or timeout |
Best Practices
Always Plan Before Apply
Even in automated workflows, run plan first. Use conditions to skip apply if no changes.
Use Approvals for Production
Automated staging deploys are fine. Production should have a human checkpoint.
Set Timeouts
Don't let workflows hang forever. Set approval timeouts and step timeouts.
Notify on Failure
Add a notification step that runs on failure so someone knows to investigate.