Using Terraform and GitLab CI

This GitLab CI script allows Terraform to be executed (in a native fashion) inside of pipelines, coupled with logic for determining if it should be an apply or a destroy.

image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest
variables:
  TF_ROOT: ${CI_PROJECT_DIR}
  TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_PROJECT_NAME}

cache:
  key: httpcats-beta
  paths:
    - ${TF_ROOT}/.terraform

before_script:
  - cd ${TF_ROOT}

stages:
  - prepare
  - validate
  - plan
  - apply
  - destroy

init:
  stage: prepare
  rules:
    # If the file .destroy exists, exclude this stage
    - exists:
        - .destroy
      when: never
    # Include this stage if there re changes to .tf files in the commit
    - changes:
        - "*.tf"
  script:
    - gitlab-terraform init

validate:
  stage: validate
  rules:
    - exists:
        - .destroy
      when: never
    - changes:
        - "*.tf"
  script:
    - gitlab-terraform init
    - gitlab-terraform validate

plan:
  stage: plan
  artifacts:
    name: plan
    paths:
      - ${TF_ROOT}/plan.cache

    # This is a piece of magic that pushes the plan into the Terraform
    # backend of GitLab (CI)
    reports:
      terraform: ${TF_ROOT}/plan.json
  rules:
    - exists:
        - .destroy
      when: never
    - changes:
        - "*.tf"
  script:
    - gitlab-terraform plan
    - gitlab-terraform plan-json

apply:
  stage: apply
  environment:
    name: production
  dependencies:
    - plan
  rules:
    - exists:
        - .destroy
      when: never

    # This is a nested condition:
    # - Include the stage if the commit branch is the project's default branch (such as master)
    # - Include the stage if there are changes to .tf files in the commit
    # - (attribute) Include the stage but make sure it's a manual run
    # - (attribute) Allow the stage to fail
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      changes:
        - "*.tf"
      when: manual
      allow_failure: true
  script:
    - gitlab-terraform apply

destroy:
  stage: destroy
  environment:
    name: production
  rules:
    # Never include this stage if there are changes to .tf files in this commit
    # (because why would you destroy if you're making code changes?)
    - changes:
        - "*.tf"
      when: never

    # Nested condition, again...
    # - If we're on the default branch
    # - and the file .destroy exists
    # - (attribute) then add the stage but make it a manual step
    # - (attribute) and allow it to fail
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      exists:
        - .destroy
      when: manual
      allow_failure: true
  script:
    - gitlab-terraform destroy -auto-approve

Enjoy.

Michael Crilly

Michael Crilly

A simple nerd.
Brisbane, Australia