1- name : Data replication pipeline
2- run-name : ${{ inputs.deployment_type }} for data replication resources for ${{ inputs.environment }}
1+ name : Deploy data replication
2+ run-name : Deploy data replication to ${{ inputs.environment }}
33
44on :
55 workflow_dispatch :
@@ -15,198 +15,127 @@ on:
1515 - qa
1616 - sandbox-alpha
1717 - sandbox-beta
18- deployment_type :
19- description : Deployment type
20- required : true
21- type : choice
22- options :
23- - Deployment with DB recreation
24- - Application only deployment
25- image_tag :
26- description : Docker image tag to deploy
27- required : false
28- type : string
29- db_snapshot_arn :
30- description : ARN of the DB snapshot to use (optional)
31- required : false
18+ git_ref_to_deploy :
19+ description :
20+ | # Use blank unicode character (U+2800) to force line-break
21+ Use code from : ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
22+ (Git ref to deploy, for example, a tag, branch name or commit SHA. Will use workflow ref if not provided.)
3223 type : string
33- egress_cidr :
34- description : CIDR blocks to allow egress traffic.
35- type : string
36- required : true
37- default : " []"
38- take_db_snapshot :
39- description : Take a new DB snapshot before creating the environment
40- type : boolean
41- default : false
24+
25+ permissions : {}
4226
4327env :
4428 environment : ${{ inputs.environment }}
4529 deployment_type : ${{ inputs.deployment_type }}
4630 db_snapshot_arn : ${{ inputs.db_snapshot_arn }}
4731 egress_cidr : ${{ inputs.egress_cidr }}
4832 take_db_snapshot : ${{ inputs.take_db_snapshot }}
33+ git_ref : ${{ inputs.git_ref_to_deploy || github.sha }}
4934 aws_role : ${{ inputs.environment == 'production'
5035 && 'arn:aws:iam::820242920762:role/GithubDeployDataReplicationInfrastructure'
5136 || 'arn:aws:iam::393416225559:role/GithubDeployDataReplicationInfrastructure' }}
52- db_snapshot_role : ${{ inputs.environment == 'production'
53- && 'arn:aws:iam::820242920762:role/DatabaseSnapshotRole'
54- || 'arn:aws:iam::393416225559:role/DatabaseSnapshotRole' }}
55-
56- defaults :
57- run :
58- working-directory : terraform/data_replication
37+ aws_account_id : ${{ inputs.environment == 'production' && '820242920762' || '393416225559' }}
5938
6039concurrency :
6140 group : deploy-data-replica-${{ inputs.environment }}
6241
6342jobs :
64- prepare-db-replica :
65- if : ${{ inputs.deployment_type == 'Deployment with DB recreation' }}
66- name : Prepare data replica
43+ validate-inputs :
6744 runs-on : ubuntu-latest
68- permissions :
69- id-token : write
45+ permissions : {}
7046 steps :
71- - name : Checkout code
72- uses : actions/checkout@v5
73- - name : Assume DB Snapshot role
74- if : inputs.take_db_snapshot
75- uses : aws-actions/configure-aws-credentials@v5
76- with :
77- role-to-assume : ${{ env.db_snapshot_role }}
78- aws-region : eu-west-2
79- - name : Take DB snapshot
80- if : inputs.take_db_snapshot
81- run : |
82- set -e
83- snapshot_identifier=snapshot-for-data-replication-$(date +"%Y-%m-%d-%H-%M-%S")
84- aws rds create-db-cluster-snapshot --db-cluster-identifier mavis-$environment --db-cluster-snapshot-identifier $snapshot_identifier
85- echo "Waiting for snapshot to be available. This can take a while."
86- aws rds wait db-cluster-snapshot-available --db-cluster-snapshot-identifier $snapshot_identifier
87- echo "New snapshot is now available"
88- - name : Configure AWS Credentials
89- uses : aws-actions/configure-aws-credentials@v5
90- with :
91- role-to-assume : ${{ env.aws_role }}
92- aws-region : eu-west-2
93- - name : Get latest snapshot
94- id : get-latest-snapshot
47+ - name : Validate inputs
9548 run : |
96- set -e
97- if [ -z "$db_snapshot_arn" ]; then
98- echo "No snapshot ARN provided, fetching the latest snapshot"
99- SNAPSHOT_ARN=$(aws rds describe-db-cluster-snapshots \
100- --query "DBClusterSnapshots[?DBClusterIdentifier=='mavis-$environment'].[DBClusterSnapshotArn, SnapshotCreateTime]" \
101- --output text | sort -k2 -r | head -n 1 | cut -f1)
102-
103- if [ -z "$SNAPSHOT_ARN" ]; then
104- echo "No snapshots found for mavis-$environment"
105- exit 1
106- fi
107- else
108- echo "Using provided snapshot ARN: $db_snapshot_arn"
109- SNAPSHOT_ARN="$db_snapshot_arn"
49+ if [[ "$environment" == "preview" || "$environment" == "production" ]]; then
50+ if [[ -z "$git_ref_to_deploy" ]]; then
51+ echo "Error: git_ref_to_deploy is required for preview and production environments."
52+ exit 1
53+ fi
11054 fi
111- echo "Using snapshot ARN: $SNAPSHOT_ARN"
112- echo "SNAPSHOT_ARN=$SNAPSHOT_ARN" >> $GITHUB_OUTPUT
113- - name : Install terraform
114- uses : hashicorp/setup-terraform@v3
115- with :
116- terraform_version : 1.13.3
117- outputs :
118- SNAPSHOT_ARN : ${{ steps.get-latest-snapshot.outputs.SNAPSHOT_ARN }}
11955
120- prepare-webapp :
121- name : Prepare webapp
56+ determine-git-sha :
12257 runs-on : ubuntu-latest
123- permissions :
124- id-token : write
58+ permissions : {}
59+ needs : validate-inputs
60+ outputs :
61+ git-sha : ${{ steps.get-git-sha.outputs.git-sha }}
12562 steps :
12663 - name : Checkout code
12764 uses : actions/checkout@v5
128- - name : Configure AWS Credentials
129- uses : aws-actions/configure-aws-credentials@v5
13065 with :
131- role-to-assume : ${{ env.aws_role }}
132- aws-region : eu-west-2
133- - name : ECR login
134- id : login-ecr
135- uses : aws-actions/amazon-ecr-login@v2
136- - name : Get docker image digest
137- id : get-docker-image-digest
138- env :
139- IMAGE_TAG : ${{ inputs.image_tag || github.sha }}
140- run : |
141- set -e
142- DOCKER_IMAGE="${{ steps.login-ecr.outputs.registry }}/mavis/webapp:$IMAGE_TAG"
143- docker pull "$DOCKER_IMAGE"
144- DOCKER_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "$DOCKER_IMAGE")
145- DIGEST="${DOCKER_DIGEST#*@}"
146- echo "DIGEST=$DIGEST" >> $GITHUB_OUTPUT
147- outputs :
148- DOCKER_DIGEST : ${{ steps.get-docker-image-digest.outputs.DIGEST }}
66+ ref : ${{ env.git_ref }}
67+ - name : Get git sha
68+ id : get-git-sha
69+ run : echo "git-sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
14970
150- plan :
151- name : Terraform plan
71+ build-and-push-image :
72+ permissions :
73+ id-token : write
74+ needs : determine-git-sha
75+ uses : ./.github/workflows/build-and-push-image.yml
76+ with :
77+ git_sha : ${{ needs.determine-git-sha.outputs.git-sha }}
78+
79+ prepare-deployment :
80+ name : Prepare deployment
15281 runs-on : ubuntu-latest
153- needs :
154- - prepare-db-replica
155- - prepare-webapp
156- if : ${{ !cancelled() &&
157- (needs.prepare-db-replica.result == 'success' || needs.prepare-db-replica.result == 'skipped') &&
158- needs.prepare-webapp.result == 'success' }}
159- env :
160- SNAPSHOT_ARN : ${{ needs.prepare-db-replica.outputs.SNAPSHOT_ARN }}
161- DB_SECRET_ARN : ${{ needs.prepare-db-replica.outputs.DB_SECRET_ARN || 'arn:aws:secretsmanager:eu-west-2:000000000000:secret:placeholder' }}
162- DOCKER_DIGEST : ${{ needs.prepare-webapp.outputs.DOCKER_DIGEST }}
163- REPLACE_DB_CLUSTER : ${{ inputs.deployment_type == 'Deployment with DB recreation' }}
82+ needs : build-and-push-image
16483 permissions :
16584 id-token : write
16685 steps :
16786 - name : Checkout code
16887 uses : actions/checkout@v5
88+ with :
89+ ref : ${{ env.git_ref }}
16990 - name : Configure AWS Credentials
17091 uses : aws-actions/configure-aws-credentials@v5
17192 with :
17293 role-to-assume : ${{ env.aws_role }}
17394 aws-region : eu-west-2
174- - name : Install terraform
175- uses : hashicorp/setup-terraform@v3
176- with :
177- terraform_version : 1.13.3
178- - name : Get db secret arn
179- id : get-db-secret-arn
180- working-directory : terraform/app
95+ - name : Get image digest
96+ id : get-image-digest
18197 run : |
182- terraform init -backend-config="env/$environment-backend.hcl" -upgrade
183- DB_SECRET_ARN=$(terraform output --raw db_secret_arn)
184- echo "DB_SECRET_ARN=$DB_SECRET_ARN" >> $GITHUB_OUTPUT
185- - name : Terraform Plan
186- id : plan
98+ digest=$(aws ecr describe-images \
99+ --repository-name mavis/webapp \
100+ --image-ids imageTag=$git_ref \
101+ --query 'imageDetails[0].imageDigest' \
102+ --output text)
103+ echo "digest=$digest" >> $GITHUB_OUTPUT
104+ - name : Parse environment variables
105+ id : parse-environment-variables
106+ env :
107+ MAVIS__PDS__RATE_LIMIT_PER_SECOND : ${{ inputs.environment == 'production' && 50 || 5 }}
187108 run : |
188- set -eo pipefail
189- terraform init -backend-config="env/$environment-backend.hcl" -upgrade
190-
191- PLAN_ARGS=(
192- "plan"
193- "-var=image_digest=$DOCKER_DIGEST"
194- "-var=db_secret_arn=${{ steps.get-db-secret-arn.outputs.DB_SECRET_ARN }}"
195- "-var=imported_snapshot=$SNAPSHOT_ARN"
196- "-var-file=env/$environment.tfvars"
197- "-var=allowed_egress_cidr_blocks=$egress_cidr"
198- "-out=${{ runner.temp }}/tfplan"
199- )
200-
201- if [ "$REPLACE_DB_CLUSTER" = "true" ]; then
202- PLAN_ARGS+=("-replace" "aws_rds_cluster.cluster")
203- fi
204- terraform "${PLAN_ARGS[@]}" | tee ${{ runner.temp }}/tf_stdout
205- - name : Upload artifact
109+ {
110+ echo 'parsed_env_vars<<EOF'
111+ echo "MAVIS__SPLUNK__ENABLED=false"
112+ echo "MAVIS__CIS2__ENABLED=false"
113+ echo "MAVIS__PDS__ENQUEUE_BULK_UPDATES=false"
114+ echo "MAVIS__PDS__RATE_LIMIT_PER_SECOND=$MAVIS__PDS__RATE_LIMIT_PER_SECOND"
115+ echo 'EOF'
116+ } >> "$GITHUB_OUTPUT"
117+ - name : Populate web task definition
118+ id : create-task-definition
119+ uses : aws-actions/amazon-ecs-render-task-definition@v1
120+ with :
121+ task-definition-family : " mavis-data-replication-task-definition-${{ inputs.environment }}-template"
122+ container-name : " application"
123+ image : " ${{ env.aws_account_id }}.dkr.ecr.eu-west-2.amazonaws.com/mavis/webapp@${{ steps.get-image-digest.outputs.digest }}"
124+ environment-variables : ${{ steps.parse-environment-variables.outputs.parsed_env_vars }}
125+ - name : Rename task definition file
126+ run : mv ${{ steps.create-task-definition.outputs.task-definition }} ${{ runner.temp }}/data-replication-task-definition.json
127+ - name : Upload artifact for data-replication task definition
206128 uses : actions/upload-artifact@v4
207129 with :
208- name : tfplan_infrastructure-${{ inputs.environment }}
209- path : ${{ runner.temp }}/tfplan
130+ name : ${{ inputs.environment }}-data-replication-task-definition
131+ path : ${{ runner.temp }}/data-replication-task-definition.json
132+
133+ notify-approval-required :
134+ name : Notify on approval required
135+ runs-on : ubuntu-latest
136+ needs : prepare-deployment
137+ if : ${{ inputs.environment == 'production' }}
138+ steps :
210139 - name : Notify pending approval
211140 if : inputs.environment == 'production'
212141 uses : slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a
@@ -227,40 +156,41 @@ jobs:
227156 - type: "mrkdwn"
228157 text: "*Triggered by:*\n${{ github.actor }}"
229158
230- apply :
231- name : Terraform apply
159+ approve-deployments :
160+ name : Wait for approval if required
232161 runs-on : ubuntu-latest
233- needs : plan
234- if : ${{ !cancelled() && needs.plan.result == 'success' }}
162+ needs : prepare-deployment
235163 environment : ${{ inputs.environment }}
164+ steps :
165+ - run : echo "Proceeding with deployment to $environment environment"
166+
167+ deploy-data-replication :
168+ name : Deploy data-replication service
169+ runs-on : ubuntu-latest
170+ needs : [prepare-deployment, approve-deployments]
236171 permissions :
237172 id-token : write
238173 steps :
239- - name : Checkout code
240- uses : actions/checkout@v5
241174 - name : Configure AWS Credentials
242175 uses : aws-actions/configure-aws-credentials@v5
243176 with :
244177 role-to-assume : ${{ env.aws_role }}
245178 aws-region : eu-west-2
246- - name : Download artifact
179+ - name : Download data-replication task definition artifact
247180 uses : actions/download-artifact@v5
248181 with :
249- name : tfplan_infrastructure-${{ inputs.environment }}
250182 path : ${{ runner.temp }}
251- - name : Install terraform
252- uses : hashicorp/setup-terraform@v3
253- with :
254- terraform_version : 1.13.3
255- - name : Apply the changes
256- run : |
257- set -e
258- terraform init -backend-config="env/$environment-backend.hcl" -upgrade
259- terraform apply ${{ runner.temp }}/tfplan
260- - name : Deploy db-access-service
183+ name : ${{ inputs.environment }}-data-replication-task-definition
184+ - name : Change family of task definition
261185 run : |
262- task_definition_arn=$(terraform output -raw task_definition_arn)
263- aws ecs update-service \
264- --cluster "mavis-$environment-data-replication" \
265- --service "mavis-$environment-data-replication" \
266- --task-definition $task_definition_arn
186+ file_path="${{ runner.temp }}/data-replication-task-definition.json"
187+ family_name="mavis-data-replication-task-definition-$environment"
188+ echo "$(jq --arg f "$family_name" '.family = $f' "$file_path")" > "$file_path"
189+ - name : Deploy data-replication service
190+ uses : aws-actions/amazon-ecs-deploy-task-definition@v2
191+ with :
192+ task-definition : ${{ runner.temp }}/data-replication-task-definition.json
193+ cluster : mavis-${{ inputs.environment }}-data-replication
194+ service : mavis-${{ inputs.environment }}-data-replication
195+ force-new-deployment : true
196+ wait-for-service-stability : true
0 commit comments