Skip to content

Deployment with DB recreation for data replication resources for production #211

Deployment with DB recreation for data replication resources for production

Deployment with DB recreation for data replication resources for production #211

name: Data replication pipeline
run-name: ${{ inputs.deployment_type }} for data replication resources for ${{ inputs.environment }}
on:
workflow_dispatch:
inputs:
environment:
description: Deployment environment
required: true
type: choice
options:
- training
- production
- test
- qa
- sandbox-alpha
- sandbox-beta
deployment_type:
description: Deployment type
required: true
type: choice
options:
- Deployment with DB recreation
- Application only deployment
image_tag:
description: Docker image tag to deploy
required: false
type: string
db_snapshot_arn:
description: ARN of the DB snapshot to use (optional)
required: false
type: string
egress_cidr:
description: CIDR blocks to allow egress traffic.
type: string
required: true
default: "[]"
take_db_snapshot:
description: Take a new DB snapshot before creating the environment
type: boolean
default: false
env:
aws_role: ${{ inputs.environment == 'production'
&& 'arn:aws:iam::820242920762:role/GithubDeployDataReplicationInfrastructure'
|| 'arn:aws:iam::393416225559:role/GithubDeployDataReplicationInfrastructure' }}
db_snapshot_role: ${{ inputs.environment == 'production'
&& 'arn:aws:iam::820242920762:role/DatabaseSnapshotRole'
|| 'arn:aws:iam::393416225559:role/DatabaseSnapshotRole' }}
defaults:
run:
working-directory: terraform/data_replication
concurrency:
group: deploy-data-replica-${{ inputs.environment }}
jobs:
prepare-db-replica:
if: ${{ inputs.deployment_type == 'Deployment with DB recreation' }}
name: Prepare data replica
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Assume DB Snapshot role
if: inputs.take_db_snapshot
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: ${{ env.db_snapshot_role }}
aws-region: eu-west-2
- name: Take DB snapshot
if: inputs.take_db_snapshot
run: |
set -e
snapshot_identifier=snapshot-for-data-replication-$(date +"%Y-%m-%d-%H-%M-%S")
aws rds create-db-cluster-snapshot --db-cluster-identifier mavis-${{ inputs.environment }} --db-cluster-snapshot-identifier $snapshot_identifier
echo "Waiting for snapshot to be available. This can take a while."
aws rds wait db-cluster-snapshot-available --db-cluster-snapshot-identifier $snapshot_identifier
echo "New snapshot is now available"
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: ${{ env.aws_role }}
aws-region: eu-west-2
- name: Get latest snapshot
id: get-latest-snapshot
run: |
set -e
if [ -z "${{ inputs.db_snapshot_arn }}" ]; then
echo "No snapshot ARN provided, fetching the latest snapshot"
SNAPSHOT_ARN=$(aws rds describe-db-cluster-snapshots \
--query "DBClusterSnapshots[?DBClusterIdentifier=='mavis-${{ inputs.environment }}'].[DBClusterSnapshotArn, SnapshotCreateTime]" \
--output text | sort -k2 -r | head -n 1 | cut -f1)
if [ -z "$SNAPSHOT_ARN" ]; then
echo "No snapshots found for mavis-${{ inputs.environment }}"
exit 1
fi
else
echo "Using provided snapshot ARN: ${{ inputs.db_snapshot_arn }}"
SNAPSHOT_ARN="${{ inputs.db_snapshot_arn }}"
fi
echo "Using snapshot ARN: $SNAPSHOT_ARN"
echo "SNAPSHOT_ARN=$SNAPSHOT_ARN" >> $GITHUB_OUTPUT
- name: Install terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.11.4
outputs:
SNAPSHOT_ARN: ${{ steps.get-latest-snapshot.outputs.SNAPSHOT_ARN }}
prepare-webapp:
name: Prepare webapp
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: ${{ env.aws_role }}
aws-region: eu-west-2
- name: ECR login
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Get docker image digest
id: get-docker-image-digest
run: |
set -e
DOCKER_IMAGE="${{ steps.login-ecr.outputs.registry }}/mavis/webapp:${{ inputs.image_tag || github.sha }}"
docker pull "$DOCKER_IMAGE"
DOCKER_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "$DOCKER_IMAGE")
DIGEST="${DOCKER_DIGEST#*@}"
echo "DIGEST=$DIGEST" >> $GITHUB_OUTPUT
outputs:
DOCKER_DIGEST: ${{ steps.get-docker-image-digest.outputs.DIGEST }}
plan:
name: Terraform plan
runs-on: ubuntu-latest
needs:
- prepare-db-replica
- prepare-webapp
if: ${{ !cancelled() &&
(needs.prepare-db-replica.result == 'success' || needs.prepare-db-replica.result == 'skipped') &&
needs.prepare-webapp.result == 'success' }}
env:
SNAPSHOT_ARN: ${{ needs.prepare-db-replica.outputs.SNAPSHOT_ARN }}
DB_SECRET_ARN: ${{ needs.prepare-db-replica.outputs.DB_SECRET_ARN || 'arn:aws:secretsmanager:eu-west-2:000000000000:secret:placeholder' }}
DOCKER_DIGEST: ${{ needs.prepare-webapp.outputs.DOCKER_DIGEST }}
REPLACE_DB_CLUSTER: ${{ inputs.deployment_type == 'Deployment with DB recreation' }}
permissions:
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: ${{ env.aws_role }}
aws-region: eu-west-2
- name: Install terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.11.4
- name: Get db secret arn
id: get-db-secret-arn
working-directory: terraform/app
run: |
terraform init -backend-config="env/${{ inputs.environment }}-backend.hcl" -upgrade
DB_SECRET_ARN=$(terraform output --raw db_secret_arn)
echo "DB_SECRET_ARN=$DB_SECRET_ARN" >> $GITHUB_OUTPUT
- name: Terraform Plan
id: plan
run: |
set -eo pipefail
terraform init -backend-config="env/${{ inputs.environment }}-backend.hcl" -upgrade
CIDR_BLOCKS='${{ inputs.egress_cidr }}'
PLAN_ARGS=(
"plan"
"-var=image_digest=${{ env.DOCKER_DIGEST }}"
"-var=db_secret_arn=${{ steps.get-db-secret-arn.outputs.DB_SECRET_ARN }}"
"-var=imported_snapshot=${{ env.SNAPSHOT_ARN }}"
"-var-file=env/${{ inputs.environment }}.tfvars"
"-var=allowed_egress_cidr_blocks=$CIDR_BLOCKS"
"-out=${{ runner.temp }}/tfplan"
)
if [ "${{ env.REPLACE_DB_CLUSTER }}" = "true" ]; then
PLAN_ARGS+=("-replace" "aws_rds_cluster.cluster")
fi
terraform "${PLAN_ARGS[@]}" | tee ${{ runner.temp }}/tf_stdout
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: tfplan_infrastructure-${{ inputs.environment }}
path: ${{ runner.temp }}/tfplan
apply:
name: Terraform apply
runs-on: ubuntu-latest
needs: plan
if: ${{ !cancelled() && needs.plan.result == 'success' }}
environment: ${{ inputs.environment }}
permissions:
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: ${{ env.aws_role }}
aws-region: eu-west-2
- name: Download artifact
uses: actions/download-artifact@v5
with:
name: tfplan_infrastructure-${{ inputs.environment }}
path: ${{ runner.temp }}
- name: Install terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.11.4
- name: Apply the changes
run: |
set -e
terraform init -backend-config="env/${{ inputs.environment }}-backend.hcl" -upgrade
terraform apply ${{ runner.temp }}/tfplan
- name: Deploy db-access-service
run: |
task_definition_arn=$(terraform output -raw task_definition_arn)
aws ecs update-service \
--cluster mavis-${{ inputs.environment }}-data-replication \
--service mavis-${{ inputs.environment }}-data-replication \
--task-definition $task_definition_arn