25
25
- web
26
26
- good-job
27
27
default : all
28
+ git_sha_to_deploy :
29
+ description : The git commit SHA to deploy.
30
+ required : false
31
+ type : string
28
32
workflow_call :
29
33
inputs :
30
34
environment :
38
42
required : true
39
43
type : string
40
44
41
- permissions : {}
45
+ permissions : { }
42
46
43
47
concurrency :
44
- group : deploy-application -${{ inputs.environment }}
48
+ group : deploy-mavis -${{ inputs.environment }}
45
49
46
50
env :
47
51
aws-role : ${{ inputs.environment == 'production'
48
52
&& 'arn:aws:iam::820242920762:role/GithubDeployMavisAndInfrastructure'
49
53
|| 'arn:aws:iam::393416225559:role/GithubDeployMavisAndInfrastructure' }}
54
+ web_codedeploy_application : mavis-${{ inputs.environment }}
55
+ web_codedeploy_group : blue-green-group-${{ inputs.environment }}
56
+ web_task_definition : mavis-web-task-definition-${{ inputs.environment }}
57
+ cluster_name : mavis-${{ inputs.environment }}
58
+ good_job_service : mavis-${{ inputs.environment }}-good-job
59
+ good_job_task_definition : mavis-good-job-task-definition-${{ inputs.environment }}
50
60
51
61
jobs :
52
62
prepare-deployment :
@@ -58,109 +68,165 @@ jobs:
58
68
steps :
59
69
- name : Checkout code
60
70
uses : actions/checkout@v4
61
- with :
62
- ref : ${{ inputs.git_sha_to_deploy || github.sha }}
63
71
- name : Configure AWS Credentials
64
72
uses : aws-actions/configure-aws-credentials@v4
65
73
with :
66
74
role-to-assume : ${{ env.aws-role }}
67
75
aws-region : eu-west-2
68
- - name : Install terraform
69
- uses : hashicorp/setup-terraform@v3
70
- with :
71
- terraform_version : 1.11.4
72
- - name : Get terraform output
73
- id : terraform-output
74
- working-directory : terraform/app
76
+ - name : Get image digest from ECR
77
+ id : get-image-digest
78
+ run : |
79
+ # Get AWS account ID and construct repository URI
80
+ AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
81
+ REPOSITORY_URI="${AWS_ACCOUNT_ID}.dkr.ecr.eu-west-2.amazonaws.com/mavis"
82
+
83
+ # Get the image digest for the git SHA
84
+ IMAGE_DIGEST=$(aws ecr describe-images \
85
+ --repository-name mavis/webapp \
86
+ --image-ids imageTag=${{ inputs.git_sha_to_deploy || github.sha }} \
87
+ --query 'imageDetails[0].imageDigest' \
88
+ --output text)
89
+
90
+ NEW_IMAGE_URI="${REPOSITORY_URI}@${IMAGE_DIGEST}"
91
+ echo "new-image-uri=${NEW_IMAGE_URI}" >> $GITHUB_OUTPUT
92
+ echo "New image URI: ${NEW_IMAGE_URI}"
93
+ - name : Populate web task definition
94
+ if : inputs.server_types == 'web' || inputs.server_types == 'all'
95
+ id : render-web-task-definition
75
96
run : |
76
- set -e
77
- terraform init -backend-config=env/${{ inputs.environment }}-backend.hcl -reconfigure
78
- terraform output -json | jq -r '
79
- "s3_bucket=" + .s3_bucket.value,
80
- "s3_key=" + .s3_key.value,
81
- "application=" + .codedeploy_application_name.value,
82
- "application_group=" + .codedeploy_deployment_group_name.value,
83
- "cluster_name=" + .ecs_variables.value.cluster_name,
84
- "good_job_service=" + .ecs_variables.value.good_job.service_name,
85
- "good_job_task_definition=" + .ecs_variables.value.good_job.task_definition.arn
86
- ' > ${{ runner.temp }}/DEPLOYMENT_ENVS
87
- - name : Upload Artifact
88
- uses : actions/upload-artifact@v4
97
+ ./script/populate_task_definition.sh ${{ inputs.environment }} web \
98
+ -i "${{ steps.get-image-digest.outputs.new-image-uri }}" \
99
+ -o web-task-definition.json
100
+ - name : Populate good-job task definition
101
+ if : inputs.server_types == 'good-job' || inputs.server_types == 'all'
102
+ id : render-good-job-task-definition
103
+ run : |
104
+ ./script/populate_task_definition.sh ${{ inputs.environment }} good-job \
105
+ -i "${{ steps.get-image-digest.outputs.new-image-uri }}" \
106
+ -o good-job-task-definition.json
107
+ - name : Upload web task definition
108
+ uses : aws-actions/amazon-ecs-deploy-task-definition@v2
109
+ id : upload-web-task-definition
110
+ with :
111
+ task-definition : web-task-definition.json
112
+ - name : Upload good-job task definition
113
+ uses : aws-actions/amazon-ecs-deploy-task-definition@v2
114
+ id : upload-good-job-task-definition
89
115
with :
90
- name : DEPLOYMENT_ENVS-${{ inputs.environment }}
91
- path : ${{ runner.temp }}/DEPLOYMENT_ENVS
116
+ task-definition : good-job-task-definition.json
117
+ outputs :
118
+ new-image-uri : ${{ steps.get-image-digest.outputs.new-image-uri }}
119
+ web-task-definition-arn : ${{ steps.upload-web-task-definition.outputs.task-definition-arn }}
120
+ good-job-task-definition-arn : ${{ steps.upload-good-job-task-definition.outputs.task-definition-arn }}
92
121
93
- create -web-deployment :
94
- name : Create web deployment
122
+ deploy -web :
123
+ name : Deploy web service
95
124
runs-on : ubuntu-latest
96
- needs : prepare-deployment
97
125
if : inputs.server_types == 'web' || inputs.server_types == 'all'
126
+ needs : prepare-deployment
127
+ environment : ${{ inputs.environment }}
98
128
permissions :
99
129
id-token : write
100
130
steps :
101
- - name : Download artifact
102
- uses : actions/download-artifact@v4
103
- with :
104
- name : DEPLOYMENT_ENVS-${{ inputs.environment }}
105
- path : ${{ runner.temp }}
106
131
- name : Configure AWS Credentials
107
132
uses : aws-actions/configure-aws-credentials@v4
108
133
with :
109
134
role-to-assume : ${{ env.aws-role }}
110
135
aws-region : eu-west-2
111
- - name : Trigger CodeDeploy deployment
136
+ - name : Download web task definition artifact
137
+ uses : actions/download-artifact@v4
138
+ with :
139
+ name : web-task-definition
140
+ path : ./artifacts
141
+ - name : Create appspec.yml
142
+ run : |
143
+ echo "version: 0.0" > appspec.yml
144
+ echo "Resources:" >> appspec.yml
145
+ echo " - TargetService:" >> appspec.yml
146
+ echo " Type: AWS::ECS::Service" >> appspec.yml
147
+ echo " Properties:" >> appspec.yml
148
+ echo " TaskDefinition: ${{ steps.render-web-task-definition.outputs.task-definition }}" >> appspec.yml
149
+ echo " LoadBalancerInfo:" >> appspec.yml
150
+ echo " ContainerName: web" >> appspec.yml
151
+ echo " ContainerPort: 80" >> appspec.yml
152
+ - name : Deploy web service with CodeDeploy
153
+ uses : aws-actions/amazon-ecs-deploy-task-definition@v2
154
+ with :
155
+ task-definition : ${{ steps.render-web-task-definition.outputs.task-definition }}
156
+ codedeploy-appspec :
157
+ codedeploy-application :
158
+ codedeploy-deployment-group :
159
+ - name : Deploy with CodeDeploy
112
160
run : |
113
- set -e
114
- source ${{ runner.temp }}/DEPLOYMENT_ENVS
161
+ # Create CodeDeploy deployment for blue-green deployment
115
162
deployment_id=$(aws deploy create-deployment \
116
- --application-name "$application" --deployment-group-name "$application_group" \
117
- --s3-location bucket="$s3_bucket",key="$s3_key",bundleType=yaml | jq -r .deploymentId)
118
- echo "Deployment started: $deployment_id"
163
+ --application-name ${{ env.web_codedeploy_application }} \
164
+ --deployment-group-name ${{ env.web_codedeploy_group }} \
165
+ --deployment-config-name CodeDeployDefault.ECSBlueGreenCanary10Percent5Minutes \
166
+ --description "Deployment from GitHub Actions" \
167
+ | jq -r .deploymentId)
168
+
169
+ echo "CodeDeploy deployment started: $deployment_id"
119
170
echo "deployment_id=$deployment_id" >> $GITHUB_ENV
120
- - name : Wait up to 30 minutes for deployment to complete
171
+ - name : Wait for deployment to complete
121
172
run : |
122
- set -e
173
+ echo "Waiting for CodeDeploy deployment $deployment_id to complete..."
123
174
aws deploy wait deployment-successful --deployment-id "$deployment_id"
124
175
echo "Deployment successful"
125
176
126
- create -good-job-deployment :
127
- name : Create good-job deployment
177
+ deploy -good-job :
178
+ name : Deploy good-job service
128
179
runs-on : ubuntu-latest
129
- needs : prepare-deployment
130
180
if : inputs.server_types == 'good-job' || inputs.server_types == 'all'
181
+ needs : prepare-deployment
182
+ environment : ${{ inputs.environment }}
131
183
permissions :
132
184
id-token : write
133
185
steps :
134
- - name : Download Artifact
135
- uses : actions/download-artifact@v4
136
- with :
137
- name : DEPLOYMENT_ENVS-${{ inputs.environment }}
138
- path : ${{ runner.temp }}
139
186
- name : Configure AWS Credentials
140
187
uses : aws-actions/configure-aws-credentials@v4
141
188
with :
142
189
role-to-assume : ${{ env.aws-role }}
143
190
aws-region : eu-west-2
144
- - name : Trigger ECS Deployment
191
+ - name : Download good-job task definition artifact
192
+ uses : actions/download-artifact@v4
193
+ with :
194
+ name : good-job-task-definition
195
+ path : ./artifacts
196
+ - name : Register new task definition
145
197
run : |
146
- set -e
147
- source ${{ runner.temp }}/DEPLOYMENT_ENVS
148
- DEPLOYMENT_ID=$(aws ecs update-service --cluster $cluster_name --service $good_job_service \
149
- --task-definition $good_job_task_definition --force-new-deployment \
150
- --query 'service.deployments[?rolloutState==`IN_PROGRESS`].[id][0]' --output text)
151
- echo "Deployment started: $DEPLOYMENT_ID"
198
+ # Find the task definition file in the artifacts directory
199
+ TASK_DEF_FILE=$(find ./artifacts -name "*.json" -type f | head -1)
200
+ TASK_DEFINITION_ARN=$(aws ecs register-task-definition --cli-input-json file://$TASK_DEF_FILE --query 'taskDefinition.taskDefinitionArn' --output text)
201
+ echo "New task definition registered: $TASK_DEFINITION_ARN"
202
+ echo "task_definition_arn=$TASK_DEFINITION_ARN" >> $GITHUB_ENV
203
+ - name : Update ECS service
204
+ run : |
205
+ # Update the good-job service with the new task definition
206
+ DEPLOYMENT_ID=$(aws ecs update-service \
207
+ --cluster ${{ env.cluster_name }} \
208
+ --service ${{ env.good_job_service }} \
209
+ --task-definition "$task_definition_arn" \
210
+ --force-new-deployment \
211
+ --query 'service.deployments[?rolloutState==`IN_PROGRESS`].[id][0]' \
212
+ --output text)
213
+
214
+ echo "ECS deployment started: $DEPLOYMENT_ID"
152
215
echo "deployment_id=$DEPLOYMENT_ID" >> $GITHUB_ENV
153
216
- name : Wait for deployment to complete
154
217
run : |
155
- set -e
156
- source ${{ runner.temp }}/DEPLOYMENT_ENVS
218
+ echo "Waiting for ECS deployment $deployment_id to complete..."
157
219
DEPLOYMENT_STATE=IN_PROGRESS
158
220
while [ "$DEPLOYMENT_STATE" == "IN_PROGRESS" ]; do
159
- echo "Waiting for deployment to complete ..."
221
+ echo "Checking deployment status ..."
160
222
sleep 30
161
- DEPLOYMENT_STATE="$(aws ecs describe-services --cluster $cluster_name --services $good_job_service \
162
- --query "services[0].deployments[?id == \`$deployment_id\`].[rolloutState][0]" --output text)"
223
+ DEPLOYMENT_STATE=$(aws ecs describe-services \
224
+ --cluster ${{ env.cluster_name }} \
225
+ --services ${{ env.good_job_service }} \
226
+ --query "services[0].deployments[?id == \`$deployment_id\`].[rolloutState][0]" \
227
+ --output text)
163
228
done
229
+
164
230
if [ "$DEPLOYMENT_STATE" != "COMPLETED" ]; then
165
231
echo "Deployment failed with state: $DEPLOYMENT_STATE"
166
232
exit 1
0 commit comments