Skip to content

Instantly share code, notes, and snippets.

@liamfoneill
Created June 20, 2023 09:01
Show Gist options
  • Save liamfoneill/c673e7a1efcdf2a0c3dabb44fbd0ff25 to your computer and use it in GitHub Desktop.
Save liamfoneill/c673e7a1efcdf2a0c3dabb44fbd0ff25 to your computer and use it in GitHub Desktop.
This is an example of a 'proper' Azure DevOps Pipeline for deploying Infrastructure with Terraform. It leverage Environments and publishes and consume the Terraform plan in separate stages. It also use the Service Connection credentials from Azure DevOps so we aren't duplicating Service Principals for no good reason.
trigger:
- main
pool:
vmImage: ubuntu-latest
stages:
- stage: build
jobs:
- job: plan
displayName: Infrastructure Plan
steps:
- checkout: self
fetchDepth: 1
- task: AzureCLI@2
displayName: 'Prepare Credentials'
inputs:
addSpnToEnvironment: true
azureSubscription: 'Online(afe07a9d-e6de-4b4c-91eb-3ae7265a9245)'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
set -euo pipefail
echo "##vso[task.setvariable variable=AZURE_CLIENT_ID;issecret=true]${servicePrincipalId}"
echo "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;issecret=true]${servicePrincipalKey}"
echo "##vso[task.setvariable variable=AZURE_SUBSCRIPTION_ID;issecret=true]$(az account show --query 'id' -o tsv)"
echo "##vso[task.setvariable variable=AZURE_TENANT_ID;issecret=true]${tenantId}"
- task: Bash@3
displayName: 'Pin Terraform'
inputs:
targetType: 'inline'
script: |
set -euo pipefail
curl -SL "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" --output terraform.zip
# echo "${TERRAFORM_DOWNLOAD_SHA} terraform.zip" | sha256sum -c -
unzip "terraform.zip"
sudo mv terraform /usr/local/bin
terraform --version
rm terraform.zip
- task: Bash@3
displayName: Terraform Init
env:
ARM_CLIENT_ID: $(AZURE_CLIENT_ID)
ARM_CLIENT_SECRET: $(AZURE_CLIENT_SECRET)
ARM_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
ARM_TENANT_ID: $(AZURE_TENANT_ID)
inputs:
targetType: 'inline'
script: |
set -euo pipefail
echo "Initialise"
terraform init \
-input=false
echo "Sanity Check"
terraform validate
echo "Show Terraform Version and Providers"
terraform -v
terraform providers
workingDirectory: './Terraform/03-modules/'
- task: Bash@3
name: 'terraform_plan'
displayName: 'Terraform Plan'
env:
ARM_CLIENT_ID: $(AZURE_CLIENT_ID)
ARM_CLIENT_SECRET: $(AZURE_CLIENT_SECRET)
ARM_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
ARM_TENANT_ID: $(AZURE_TENANT_ID)
inputs:
targetType: 'inline'
workingDirectory: './Terraform/03-modules/'
script: |
set -euo pipefail
if [ ${BUILD_REASON} == 'PullRequest' ]; then
export TF_CLI_ARGS="-lock=false"
fi
terraform plan \
-input=false \
-out ${BUILD_BUILDNUMBER}.tfplan
- task: ArchiveFiles@2
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
displayName: 'Create Plan Artifact'
inputs:
rootFolderOrFile: './Terraform/03-modules/'
includeRootFolder: false
archiveType: 'tar'
tarCompression: 'gz'
archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildNumber).tgz'
replaceExistingArchive: true
- task: PublishPipelineArtifact@1
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
displayName: 'Publish Plan Artifact'
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)'
artifactName: 'plan'
- stage: deploy
jobs:
- deployment: terraform
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
displayName: 'Change Infrastructure'
environment: 'dev'
strategy:
runOnce:
deploy:
steps:
- task: ExtractFiles@1
displayName: 'Extract Plan Artifact'
inputs:
archiveFilePatterns: '$(Pipeline.Workspace)/plan/$(Build.BuildNumber).tgz'
destinationFolder: '$(project_folder)/'
cleanDestinationFolder: true
- task: AzureCLI@2
displayName: 'Prepare Credentials'
inputs:
addSpnToEnvironment: true
azureSubscription: 'Online(afe07a9d-e6de-4b4c-91eb-3ae7265a9245)'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
set -euo pipefail
echo "##vso[task.setvariable variable=AZURE_CLIENT_ID;issecret=true]${servicePrincipalId}"
echo "##vso[task.setvariable variable=AZURE_CLIENT_SECRET;issecret=true]${servicePrincipalKey}"
echo "##vso[task.setvariable variable=AZURE_SUBSCRIPTION_ID;issecret=true]$(az account show --query 'id' -o tsv)"
echo "##vso[task.setvariable variable=AZURE_TENANT_ID;issecret=true]${tenantId}"
- task: Bash@3
displayName: 'Pin Terraform'
inputs:
targetType: 'inline'
script: |
set -euo pipefail
curl -SL "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" --output terraform.zip
# echo "${TERRAFORM_DOWNLOAD_SHA} terraform.zip" | sha256sum -c -
unzip "terraform.zip"
sudo mv terraform /usr/local/bin
terraform --version
rm terraform.zip
- task: Bash@3
displayName: 'Terraform Apply'
env:
ARM_CLIENT_ID: $(AZURE_CLIENT_ID)
ARM_CLIENT_SECRET: $(AZURE_CLIENT_SECRET)
ARM_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
ARM_TENANT_ID: $(AZURE_TENANT_ID)
inputs:
targetType: 'inline'
workingDirectory: $(project_folder)
script: |
set -euo pipefail
terraform apply \
-input=false \
${BUILD_BUILDNUMBER}.tfplan
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment