Skip to content

Commit e1178f9

Browse files
Only recreate task definition in infrastructure on critical chances
- Also update deployment pipeline to reset parameter store variable from config
1 parent 0e12455 commit e1178f9

File tree

8 files changed

+45
-57
lines changed

8 files changed

+45
-57
lines changed

.github/workflows/deploy-application.yml

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ on:
4141
description: The git commit SHA to deploy.
4242
required: true
4343
type: string
44+
git_ref_to_deploy:
45+
description: The git ref to deploy (branch, tag, or commit SHA).
46+
required: false
47+
type: string
4448

4549
permissions: {}
4650

@@ -52,11 +56,8 @@ env:
5256
&& 'arn:aws:iam::820242920762:role/GithubDeployMavisAndInfrastructure'
5357
|| 'arn:aws:iam::393416225559:role/GithubDeployMavisAndInfrastructure' }}
5458
aws_account_id: ${{ inputs.environment == 'production' && '820242920762' || '393416225559' }}
55-
web_codedeploy_application: mavis-${{ inputs.environment }}
56-
web_codedeploy_group: blue-green-group-${{ inputs.environment }}
5759
cluster_name: mavis-${{ inputs.environment }}
58-
good_job_service: mavis-${{ inputs.environment }}-good-job
59-
web_service: mavis-${{ inputs.environment }}-web
60+
app_version: ${{ inputs.git_ref_to_deploy == '' && 'unknown' || inputs.git_ref_to_deploy }}
6061

6162
jobs:
6263
prepare-deployment:
@@ -75,6 +76,13 @@ jobs:
7576
with:
7677
role-to-assume: ${{ env.aws-role }}
7778
aws-region: eu-west-2
79+
- name: Setup python
80+
uses: actions/setup-python@v4
81+
with:
82+
python-version: 3.12.3
83+
cache: pip
84+
- name: Install Python dependencies
85+
run: python3 -m pip install -r script/requirements.txt
7886
- name: Get image digest
7987
id: get-image-digest
8088
run: |
@@ -90,33 +98,39 @@ jobs:
9098
parsed_env_vars=$(yq -r '.environments.${{ inputs.environment }} | to_entries | .[] | .key + "=" + .value' config/container_variables.yml)
9199
echo "parsed_env_vars=$parsed_env_vars" >> $GITHUB_OUTPUT
92100
- name: Populate web task definition
93-
if: inputs.server_types == 'web' || inputs.server_types == 'all'
101+
if: ${{ inputs.server_types == 'web' || inputs.server_types == 'all' }}
94102
id: create-web-task-definition
95103
uses: aws-actions/amazon-ecs-render-task-definition@v1
96104
with:
97105
task-definition-family: "mavis-web-task-definition-${{ inputs.environment }}"
98106
container-name: "application"
99107
image: "${{ env.aws_account_id }}.dkr.ecr.eu-west-2.amazonaws.com/mavis/webapp@${{ steps.get-image-digest.outputs.digest }}"
100108
environment-variables: ${{ steps.parse-environment-variables.outputs.parsed_env_vars }}
101-
secrets: | # We can define secrets here too if we want
102-
RAILS_MASTER_KEY=/copilot/mavis/secrets/STAGING_RAILS_MASTER_KEY
103109
- name: Populate good-job task definition
104-
if: inputs.server_types == 'good-job' || inputs.server_types == 'all'
110+
if: ${{ inputs.server_types == 'good-job' || inputs.server_types == 'all' }}
105111
id: create-good-job-task-definition
106112
uses: aws-actions/amazon-ecs-render-task-definition@v1
107113
with:
108114
task-definition-family: "mavis-good-job-task-definition-${{ inputs.environment }}"
109115
container-name: "application"
110116
image: "${{ env.aws_account_id }}.dkr.ecr.eu-west-2.amazonaws.com/mavis/webapp@${{ steps.get-image-digest.outputs.digest }}"
111117
environment-variables: ${{ steps.parse-environment-variables.outputs.parsed_env_vars }}
118+
- name: Populate SSM parameters for web service
119+
if: ${{ inputs.server_types == 'web' || inputs.server_types == 'all' }}
120+
run: |
121+
python3 script/populate_ssm_parameters.py ${{ inputs.environment }} web --app_version=${{ env.app_version }}
122+
- name: Populate SSM parameters for good-job service
123+
if: ${{ inputs.server_types == 'good-job' || inputs.server_types == 'all' }}
124+
run: |
125+
python3 script/populate_ssm_parameters.py ${{ inputs.environment }} good-job --app_version=${{ env.app_version }}
112126
- name: Upload artifact for web task definition
113-
if: inputs.server_types == 'web' || inputs.server_types == 'all'
127+
if: ${{ inputs.server_types == 'web' || inputs.server_types == 'all' }}
114128
uses: actions/upload-artifact@v4
115129
with:
116130
name: ${{ inputs.environment }}-web-task-definition
117131
path: ${{ steps.create-web-task-definition.outputs.task-definition }}
118132
- name: Upload artifact for good-job task definition
119-
if: inputs.server_types == 'good-job' || inputs.server_types == 'all'
133+
if: ${{ inputs.server_types == 'good-job' || inputs.server_types == 'all' }}
120134
uses: actions/upload-artifact@v4
121135
with:
122136
name: ${{ inputs.environment }}-good-job-task-definition
@@ -132,7 +146,7 @@ jobs:
132146
deploy-web:
133147
name: Deploy web service
134148
runs-on: ubuntu-latest
135-
if: inputs.server_types == 'web' || inputs.server_types == 'all'
149+
if: ${{ inputs.server_types == 'web' || inputs.server_types == 'all' }}
136150
needs: [ prepare-deployment, approve-deployments ]
137151
permissions:
138152
id-token: write
@@ -164,9 +178,9 @@ jobs:
164178
task-definition: ${{ needs.prepare-deployment.outputs.web-task-definition-path }}
165179
codedeploy-appspec: appspec.yaml
166180
cluster: ${{ env.cluster_name }}
167-
service: ${{ env.web_service }}
168-
codedeploy-application: ${{ env.web_codedeploy_application }}
169-
codedeploy-deployment-group: ${{ env.web_codedeploy_group }}
181+
service: mavis-${{ inputs.environment }}-web
182+
codedeploy-application: mavis-${{ inputs.environment }}
183+
codedeploy-deployment-group: blue-green-group-${{ inputs.environment }}
170184
- name: Wait for deployment to complete
171185
run: |
172186
echo "Waiting for CodeDeploy deployment ${{ steps.deploy-web-service.outputs.codedeploy-deployment-id }} to complete..."
@@ -176,7 +190,7 @@ jobs:
176190
deploy-good-job:
177191
name: Deploy good-job service
178192
runs-on: ubuntu-latest
179-
if: inputs.server_types == 'good-job' || inputs.server_types == 'all'
193+
if: ${{ inputs.server_types == 'good-job' || inputs.server_types == 'all' }}
180194
needs: [ prepare-deployment, approve-deployments ]
181195
permissions:
182196
id-token: write
@@ -196,6 +210,6 @@ jobs:
196210
with:
197211
task-definition: ${{ needs.prepare-deployment.outputs.good-job-task-definition-path }}
198212
cluster: ${{ env.cluster_name }}
199-
service: ${{ env.good_job_service }}
213+
service: mavis-${{ inputs.environment }}-good-job
200214
force-new-deployment: true
201215
wait-for-service-stability: true

.github/workflows/deploy-infrastructure.yml

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,25 +48,6 @@ jobs:
4848
with:
4949
role-to-assume: ${{ env.aws_role }}
5050
aws-region: eu-west-2
51-
- name: Set image tag
52-
run: |
53-
IMAGE_TAG="${{ inputs.image_tag || github.sha }}"
54-
echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV
55-
- name: Login to ECR
56-
id: login-ecr
57-
uses: aws-actions/amazon-ecr-login@v2
58-
- name: Pull Docker image
59-
run: |
60-
set -e
61-
DOCKER_IMAGE="${{ steps.login-ecr.outputs.registry }}/mavis/webapp:${IMAGE_TAG}"
62-
docker pull "$DOCKER_IMAGE"
63-
echo "DOCKER_IMAGE=$DOCKER_IMAGE" >> $GITHUB_ENV
64-
- name: Extract image digest
65-
run: |
66-
set -e
67-
DOCKER_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "$DOCKER_IMAGE")
68-
DIGEST="${DOCKER_DIGEST#*@}"
69-
echo "DIGEST=$DIGEST" >> $GITHUB_ENV
7051
- name: Install terraform
7152
uses: hashicorp/setup-terraform@v3
7253
with:
@@ -78,7 +59,7 @@ jobs:
7859
run: |
7960
set -e
8061
terraform init -backend-config="env/${{ inputs.environment }}-backend.hcl" -upgrade
81-
terraform plan -var="image_digest=$DIGEST" -var="app_version=${{ env.git_ref_to_deploy }}" \
62+
terraform plan \
8263
-var-file="env/${{ inputs.environment }}.tfvars" \
8364
-out ${{ runner.temp }}/tfplan | tee ${{ runner.temp }}/tf_stdout
8465
TF_EXIT_CODE=${PIPESTATUS[0]}

.github/workflows/deploy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,4 @@ jobs:
155155
environment: ${{ inputs.environment }}
156156
server_types: ${{ inputs.server_types }}
157157
git_sha_to_deploy: ${{ needs.determine-git-sha.outputs.git-sha }}
158+
app_version: ${{ inputs.git_ref_to_deploy }}

script/populate_ssm_parameters.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ def extract_cloud_variables(config: Dict[str, Any], environment: str, server_typ
3333
return cloud_vars
3434

3535

36-
def update_ssm_parameter(parameter_name: str, values: List[str]) -> None:
36+
def update_ssm_parameter(parameter_name: str, values: List[str], app_version: str) -> None:
3737
"""Update SSM parameter with StringList values."""
3838
try:
3939
ssm = boto3.client('ssm')
40-
40+
values.append(f"app_version={app_version}")
4141
string_list = ','.join(values)
4242

4343
print(f"Updating SSM parameter: {parameter_name}")
@@ -69,6 +69,7 @@ def main():
6969
parser.add_argument('server_type', help='Server type')
7070
parser.add_argument('-c', '--config-file', default='config/container_variables.yml',
7171
help='Container variables file path (default: config/container_variables.yml)')
72+
parser.add_argument('--app-version', default='unknown', help='Application version (default: unknown)')
7273

7374
args = parser.parse_args()
7475

@@ -81,7 +82,7 @@ def main():
8182
cloud_vars = extract_cloud_variables(config, args.environment, args.server_type)
8283

8384
ssm_parameter_path = f"/{args.environment}/envs/{args.server_type}"
84-
update_ssm_parameter(ssm_parameter_path, cloud_vars)
85+
update_ssm_parameter(ssm_parameter_path, cloud_vars, args.app_version)
8586

8687
print(f"Cloud variables updated successfully")
8788

terraform/app/ecs.tf

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ module "web_service" {
3131
}])
3232
cpu = 1024
3333
memory = 2048
34-
docker_image = "${var.account_id}.dkr.ecr.eu-west-2.amazonaws.com/${var.docker_image}@${var.image_digest}"
3534
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
3635
task_role_arn = aws_iam_role.ecs_task_role.arn
3736
log_group_name = aws_cloudwatch_log_group.ecs_log_group.name
@@ -75,7 +74,6 @@ module "good_job_service" {
7574
}])
7675
cpu = 1024
7776
memory = 2048
78-
docker_image = "${var.account_id}.dkr.ecr.eu-west-2.amazonaws.com/${var.docker_image}@${var.image_digest}"
7977
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
8078
task_role_arn = aws_iam_role.ecs_task_role.arn
8179
log_group_name = aws_cloudwatch_log_group.ecs_log_group.name

terraform/app/modules/ecs_service/main.tf

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ resource "aws_ecs_service" "this" {
6969
}
7070
}
7171

72+
resource "terraform_data" "this" {
73+
input = [
74+
var.server_type, var.task_config, var.container_name
75+
]
76+
}
77+
7278
resource "aws_ecs_task_definition" "this" {
7379
family = "mavis-${local.server_type_name}-task-definition-${var.environment}"
7480
requires_compatibilities = ["FARGATE"]
@@ -80,7 +86,7 @@ resource "aws_ecs_task_definition" "this" {
8086
container_definitions = jsonencode([
8187
{
8288
name = var.container_name
83-
image = var.task_config.docker_image
89+
image = "CHANGE_ME"
8490
essential = true
8591
portMappings = [
8692
{
@@ -108,7 +114,8 @@ resource "aws_ecs_task_definition" "this" {
108114
}
109115
])
110116
lifecycle {
111-
ignore_changes = all
117+
ignore_changes = all
118+
replace_triggered_by = [terraform_data.this]
112119
}
113120
}
114121

terraform/app/modules/ecs_service/variables.tf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ variable "task_config" {
5858
}))
5959
cpu = number
6060
memory = number
61-
docker_image = string
6261
execution_role_arn = string
6362
task_role_arn = string
6463
log_group_name = string

terraform/app/variables.tf

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -104,19 +104,6 @@ variable "rails_master_key_path" {
104104
nullable = false
105105
}
106106

107-
variable "docker_image" {
108-
type = string
109-
default = "mavis/webapp"
110-
description = "The docker image name for the essential container in the task definition"
111-
nullable = false
112-
}
113-
114-
variable "image_digest" {
115-
type = string
116-
description = "The docker image digest for the essential container in the task definition."
117-
nullable = false
118-
}
119-
120107
locals {
121108
is_production = var.environment == "production"
122109
parameter_store_variables = tomap({ #TODO: Remove this once all variables are sourced from application config

0 commit comments

Comments
 (0)