Get started
More actions
This page takes one change to production: planned in a pull request, merged, approved and applied. The example repository has two workspaces, one per directory, network and dns, and keeps their state in a remote backend.
Create the environments
Each workspace applies in a GitHub environment of the same name, and its required reviewers are who can approve the apply. The module creates them:
module "tacos" {
source = "github.com/femiwiki/terraform-github-tacos?ref=v0.7.0"
repository = "infra"
environments = ["network", "dns"]
reviewer_teams = [github_team.deployer.id]
}
See Approvals for who can approve and the permissions each job needs.
Add the workflow
Put this workflow in .github/workflows/, change the workspace list and add your credentials. The full workflow also applies a branch by hand and hides outdated plan comments.
name: tofu
on:
pull_request:
push:
branches: [main]
permissions: {}
jobs:
plan:
name: ${{ matrix.workspace }} plan
strategy:
fail-fast: false
matrix:
workspace: [network, dns]
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: femiwiki/terraform-github-tacos@v0.7.0
with:
step: plan
workspace: ${{ matrix.workspace }}
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: dflook/tofu-plan@c7416238983bdd94c5486fb856bb7358f2bcc935 # v3.1.0
id: plan
env:
GITHUB_TOKEN: ${{ github.token }}
with:
path: ${{ matrix.workspace }}
- uses: femiwiki/terraform-github-tacos@v0.7.0
with:
step: changes
workspace: ${{ matrix.workspace }}
changes: ${{ steps.plan.outputs.changes }}
plan-json: ${{ steps.plan.outputs.json_plan_path }}
pending:
needs: plan
if: github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
actions: write
checks: read
outputs:
workspaces: ${{ steps.pending.outputs.workspaces }}
steps:
- uses: femiwiki/terraform-github-tacos@v0.7.0
id: pending
with:
step: pending
apply:
name: ${{ matrix.workspace }} apply
needs: pending
if: needs.pending.outputs.workspaces != '[]'
strategy:
fail-fast: false
matrix:
workspace: ${{ fromJSON(needs.pending.outputs.workspaces) }}
runs-on: ubuntu-latest
environment: ${{ matrix.workspace }}
permissions:
actions: read
contents: read
pull-requests: write
steps:
- uses: femiwiki/terraform-github-tacos@v0.7.0
id: approver
with:
step: apply
workspace: ${{ matrix.workspace }}
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: dflook/tofu-apply@e3e5dfc8f935d4b152c767801046f63abf8a77d3 # v3.1.0
id: apply
env:
GITHUB_TOKEN: ${{ github.token }}
with:
path: ${{ matrix.workspace }}
- uses: femiwiki/terraform-github-tacos@v0.7.0
if: always()
with:
step: result
workspace: ${{ matrix.workspace }}
outcome: ${{ steps.apply.outcome }}
plan-json: ${{ steps.apply.outputs.json_plan_path }}
approver: ${{ steps.approver.outputs.approver }}
# Make this the one required check
gate:
name: tofu gate
needs: plan
if: always() && github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions: {}
steps:
- uses: femiwiki/terraform-github-tacos@v0.7.0
with:
step: gate
needs: ${{ toJSON(needs) }}
The module makes the gate job's name, tofu gate, a required check of the default branch through a ruleset, so a pull request whose plan fails cannot merge. If you name the gate job differently, give that name as the module's gate_check.
Open a pull request
Change a file in network and open a pull request. Each workspace is planned, and its plan is commented on the pull request. Nothing is applied yet.
Merge and approve
Merge the pull request. The run for the push plans every workspace again, and the network apply job waits for its environment. A reviewer opens the run and approves the deployment under "Review deployments".
The apply makes a fresh plan and applies it only when it matches the one that was approved. The job summary shows who approved and what changed.
Next
- Runs says what each step of the workflow does.
- Auto apply skips the approval for chosen workspaces.
- Apply-before-merge applies a pull request before it merges.