Skip to content

Publish Infra

Publish Infra #368

Workflow file for this run

name: Publish Infra
on:
# PR targeting master is created or new commits are pushed
push:
branches:
- master
paths:
- "infrastructure/**"
# Manual trigger via GH Actions UI
workflow_dispatch:
inputs:
environment:
description: "Select target environment"
required: true
default: "lz-dev"
type: choice
options:
- lz-dev
- lz-test
- lz-prod
- dev
- test
- prod
env:
WORKING_DIRECTORY: "./infrastructure/cloud/environments/${{ inputs.environment || 'lz-dev' }}"
DUMMY_IMAGE_NAME: dummy-image
GITHUB_IMAGE_REPO: ghcr.io/bcgov/jasper
APP_ECR_REPO_URL: ${{ vars.AWS_ACCOUNT }}.dkr.ecr.${{ vars.AWS_REGION }}.amazonaws.com/${{ vars.APP_NAME }}-app-repo-${{ inputs.environment || 'lz-dev' }}
LAMBDA_ECR_REPO_URL: ${{ vars.AWS_ACCOUNT }}.dkr.ecr.${{ vars.AWS_REGION }}.amazonaws.com/${{ vars.APP_NAME }}-lambda-repo-${{ inputs.environment || 'lz-dev' }}
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: ${{ inputs.environment || 'lz-dev' }}
env:
TF_VAR_app_name: ${{ vars.APP_NAME }}
TF_VAR_environment: ${{ vars.ENVIRONMENT_NAME }}
TF_VAR_kms_key_name: ${{ vars.KMS_KEY_NAME }}
TF_VAR_vpc_id: ${{ vars.VPC_ID }}
TF_VAR_lambda_memory_size: ${{ vars.LAMBDA_MEMORY_SIZE }}
TF_VAR_alarm_recipients: ${{ vars.ALARM_RECIPIENTS }}
permissions:
id-token: write
actions: read
contents: read
security-events: write
packages: write
steps:
- name: Determine environment
id: determine-environment
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "environment=${{ github.event.inputs.environment }}" >> $GITHUB_ENV
else
echo "environment=lz-dev" >> $GITHUB_ENV
fi
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: tfsec
uses: aquasecurity/tfsec-sarif-action@21ded20e8ca120cd9d3d6ab04ef746477542a608 # v0.1.4
with:
sarif_file: tfsec.sarif
working_directory: ${{ env.WORKING_DIRECTORY }}
tfsec_args: "--tfvars-file=${{ env.WORKING_DIRECTORY }}/${{ env.environment }}.tfvars"
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
with:
sarif_file: tfsec.sarif
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0
with:
role-skip-session-tagging: true
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
role-duration-seconds: 1800
role-session-name: ci-deployment
- name: Setup Terraform
uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # v4.0.0
with:
terraform_version: 1.14.1
- name: Terraform Init
id: init
run: |
terraform init -input=false -backend-config=backend.tfvars -var-file=${{ env.environment }}.tfvars
working-directory: ${{ env.WORKING_DIRECTORY }}
- name: Terraform Plan (Initial Stack)
id: plan-initial
run: |
terraform plan -target=module.initial -no-color -input=false -var-file=${{ env.environment }}.tfvars
continue-on-error: true
working-directory: ${{ env.WORKING_DIRECTORY }}
- name: Terraform Plan (Initial) Status
if: steps.plan-initial.outcome == 'failure'
run: exit 1
- name: Terraform Apply (Initial Stack)
run: |
terraform apply -target=module.initial --auto-approve -input=false -var-file=${{ env.environment }}.tfvars
working-directory: ${{ env.WORKING_DIRECTORY }}
- name: Log in to the GHCR
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Image Metadata
id: meta
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
with:
images: |
${{ env.GITHUB_IMAGE_REPO }}/${{ env.DUMMY_IMAGE_NAME }}
tags: |
type=raw,value=latest
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
with:
driver: docker
- name: Build ${{ env.DUMMY_IMAGE_NAME }} image
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
with:
push: true
file: ./docker/dummy-image/Dockerfile.release
context: .
provenance: false
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1
- name: Check dummy-image in App ECR exists
id: app-ecr-check
shell: bash
run: |
IMAGE_TAG=${{ env.DUMMY_IMAGE_NAME }}
REPOSITORY_NAME=${{ vars.APP_NAME }}-app-repo-${{ env.environment }}
IMAGE_EXISTS=$(aws ecr describe-images --repository-name "$REPOSITORY_NAME" --query "imageDetails[?imageTags && contains(imageTags, \`${IMAGE_TAG}\`)]" --output text)
if [ -z "$IMAGE_EXISTS" ]; then
echo "Image with tag $IMAGE_TAG does not exist."
echo "exists=false" >> $GITHUB_OUTPUT
else
echo "Image with tag $IMAGE_TAG already exists."
echo "exists=true" >> $GITHUB_OUTPUT
fi
- name: Push dummy image to App ECR
if: steps.app-ecr-check.outputs.exists == 'false'
shell: bash
run: |
echo 'Deploying ${{ env.DUMMY_IMAGE_NAME }} to App ECR'
docker tag ${{ env.GITHUB_IMAGE_REPO }}/${{ env.DUMMY_IMAGE_NAME }}:latest ${{ env.APP_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }}
docker push ${{ env.APP_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }}
- name: Check dummy-image in Lambda ECR exists
id: lambda-ecr-check
shell: bash
run: |
IMAGE_TAG=${{ env.DUMMY_IMAGE_NAME }}
REPOSITORY_NAME=${{ vars.APP_NAME }}-lambda-repo-${{ env.environment }}
IMAGE_EXISTS=$(aws ecr describe-images --repository-name "$REPOSITORY_NAME" --query "imageDetails[?imageTags && contains(imageTags, \`${IMAGE_TAG}\`)]" --output text)
if [ -z "$IMAGE_EXISTS" ]; then
echo "Image with tag $IMAGE_TAG does not exist."
echo "exists=false" >> $GITHUB_OUTPUT
else
echo "Image with tag $IMAGE_TAG already exists."
echo "exists=true" >> $GITHUB_OUTPUT
fi
- name: Push dummy images to Lambda ECR
if: steps.lambda-ecr-check.outputs.exists == 'false'
shell: bash
run: |
echo 'Deploying ${{ env.DUMMY_IMAGE_NAME }} to Lambda ECR'
docker tag ${{ env.GITHUB_IMAGE_REPO }}/${{ env.DUMMY_IMAGE_NAME }}:latest ${{ env.LAMBDA_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }}
docker push ${{ env.LAMBDA_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }}
- name: Terraform Plan (Main Stack)
id: plan-main
run: |
terraform plan -no-color -input=false -var-file=${{ env.environment }}.tfvars
continue-on-error: true
working-directory: ${{ env.WORKING_DIRECTORY }}
- name: Terraform Plan (Main) Status
if: steps.plan-main.outcome == 'failure'
run: exit 1
- name: Terraform Apply (Main Stack)
run: |
terraform apply --auto-approve -input=false -var-file=${{ env.environment }}.tfvars
working-directory: ${{ env.WORKING_DIRECTORY }}