Skip to content

Deploy application to sandbox-beta #101

Deploy application to sandbox-beta

Deploy application to sandbox-beta #101

name: Deploy application
run-name: Deploy application to ${{ inputs.environment }}
on:
workflow_dispatch:
inputs:
environment:
description: Deployment environment
required: true
type: choice
options:
- qa
- test
- preview
- training
- production
- sandbox-alpha
- sandbox-beta
server_types:
description: Server types to deploy
required: true
type: choice
options:
- all
- web
- good-job
- sidekiq
default: all
git_sha_to_deploy:
description: The git commit SHA to deploy.
required: false
type: string
workflow_call:
inputs:
environment:
required: true
type: string
server_types:
required: true
type: string
git_sha_to_deploy:
description: The git commit SHA to deploy.
required: true
type: string
app_version:
description: The git ref to deploy (branch, tag, or commit SHA).
required: false
type: string
permissions: {}
concurrency:
group: deploy-application-${{ inputs.environment }}
env:
aws-role: ${{ inputs.environment == 'production'
&& 'arn:aws:iam::820242920762:role/GithubDeployECSService'
|| 'arn:aws:iam::393416225559:role/GithubDeployECSService' }}
aws_account_id: ${{ inputs.environment == 'production' && '820242920762' || '393416225559' }}
cluster_name: mavis-${{ inputs.environment }}
app_version: ${{ inputs.app_version == '' && 'unknown' || inputs.app_version }}
jobs:
prepare-deployment:
name: Prepare deployment
runs-on: ubuntu-latest
permissions:
id-token: write
strategy:
fail-fast: true
matrix:
service: ${{ inputs.server_types == 'all' && fromJSON('["web", "good-job", "sidekiq"]') || fromJSON(format('["{0}"]', inputs.server_types)) }}
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
ref: ${{ inputs.git_sha_to_deploy || github.sha }}
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.aws-role }}
aws-region: eu-west-2
- name: Setup python
uses: actions/setup-python@v4
with:
python-version: 3.12.3
cache: pip
- name: Install Python dependencies
run: python3 -m pip install -r script/requirements.txt
- name: Get image digest
id: get-image-digest
run: |
digest=$(aws ecr describe-images \
--repository-name mavis/webapp \
--image-ids imageTag=${{ inputs.git_sha_to_deploy || github.sha }} \
--query 'imageDetails[0].imageDigest' \
--output text)
echo "digest=$digest" >> $GITHUB_OUTPUT
- name: Parse environment variables
id: parse-environment-variables
run: |
parsed_env_vars=$(yq -r '.environments.${{ inputs.environment }} | to_entries | .[] | .key + "=" + .value' config/container_variables.yml)
{
echo 'parsed_env_vars<<EOF'
echo "$parsed_env_vars"
echo 'EOF'
} >> "$GITHUB_OUTPUT"
- name: Populate web task definition
id: create-task-definition
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition-family: "mavis-${{ matrix.service }}-task-definition-${{ inputs.environment }}-template"
container-name: "application"
image: "${{ env.aws_account_id }}.dkr.ecr.eu-west-2.amazonaws.com/mavis/webapp@${{ steps.get-image-digest.outputs.digest }}"
environment-variables: ${{ steps.parse-environment-variables.outputs.parsed_env_vars }}
- name: Rename task definition file
run: mv ${{ steps.create-task-definition.outputs.task-definition }} ${{ runner.temp }}/${{ matrix.service }}-task-definition.json
- name: Populate SSM parameters for ${{ matrix.service }} service
run: |
python3 script/populate_ssm_parameters.py ${{ inputs.environment }} ${{ matrix.service }} --app-version ${{ env.app_version }}
- name: Upload artifact for ${{ matrix.service }} task definition
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.environment }}-${{ matrix.service }}-task-definition
path: ${{ runner.temp }}/${{ matrix.service }}-task-definition.json
approve-deployments:
name: Wait for approval if required
runs-on: ubuntu-latest
needs: prepare-deployment
environment: ${{ inputs.environment }}
steps:
- run: echo "Proceeding with deployment to ${{ inputs.environment }} environment"
deploy-web:
name: Deploy web service
runs-on: ubuntu-latest
if: ${{ inputs.server_types == 'web' || inputs.server_types == 'all' }}
needs: [ prepare-deployment, approve-deployments ]
permissions:
id-token: write
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.aws-role }}
aws-region: eu-west-2
- name: Checkout code
uses: actions/checkout@v5
- name: Download web task definition artifact
uses: actions/download-artifact@v4
with:
path: ${{ runner.temp }}
name: ${{ inputs.environment }}-web-task-definition
- name: Change family of task definition
run: |
file_path="${{ runner.temp }}/web-task-definition.json"
family_name="mavis-web-task-definition-${{ inputs.environment }}"
echo "$(jq --arg f "$family_name" '.family = $f' "$file_path")" > "$file_path"
- name: Register web task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ${{ runner.temp }}/web-task-definition.json
- name: Deploy web service with CodeDeploy
id: deploy-web-service
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ${{ runner.temp }}/web-task-definition.json
codedeploy-appspec: config/templates/appspec.yaml
cluster: ${{ env.cluster_name }}
service: mavis-${{ inputs.environment }}-web
codedeploy-application: mavis-${{ inputs.environment }}
codedeploy-deployment-group: blue-green-group-${{ inputs.environment }}
- name: Wait for deployment to complete
run: |
echo "Waiting for CodeDeploy deployment ${{ steps.deploy-web-service.outputs.codedeploy-deployment-id }} to complete..."
aws deploy wait deployment-successful --deployment-id "${{ steps.deploy-web-service.outputs.codedeploy-deployment-id }}"
echo "Deployment successful"
deploy-good-job:
name: Deploy good-job service
runs-on: ubuntu-latest
if: ${{ inputs.server_types == 'good-job' || inputs.server_types == 'all' }}
needs: [ prepare-deployment, approve-deployments ]
permissions:
id-token: write
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.aws-role }}
aws-region: eu-west-2
- name: Download good-job task definition artifact
uses: actions/download-artifact@v5
with:
path: ${{ runner.temp }}
name: ${{ inputs.environment }}-good-job-task-definition
- name: Change family of task definition
run: |
file_path="${{ runner.temp }}/good-job-task-definition.json"
family_name="mavis-good-job-task-definition-${{ inputs.environment }}"
echo "$(jq --arg f "$family_name" '.family = $f' "$file_path")" > "$file_path"
- name: Deploy good-job service
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ${{ runner.temp }}/good-job-task-definition.json
cluster: ${{ env.cluster_name }}
service: mavis-${{ inputs.environment }}-good-job
force-new-deployment: true
wait-for-service-stability: true
create-sidekiq-deployment:
name: Create sidekiq deployment
runs-on: ubuntu-latest
if: ${{ inputs.server_types == 'sidekiq' || inputs.server_types == 'all' }}
needs: [ prepare-deployment, approve-deployments ]
permissions:
id-token: write
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ env.aws-role }}
aws-region: eu-west-2
- name: Download sidekiq task definition artifact
uses: actions/download-artifact@v4
with:
path: ${{ runner.temp }}
name: ${{ inputs.environment }}-sidekiq-task-definition
- name: Change family of task definition
run: |
file_path="${{ runner.temp }}/sidekiq-task-definition.json"
family_name="mavis-sidekiq-task-definition-${{ inputs.environment }}"
echo "$(jq --arg f "$family_name" '.family = $f' "$file_path")" > "$file_path"
- name: Deploy sidekiq service
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ${{ runner.temp }}/sidekiq-task-definition.json
cluster: ${{ env.cluster_name }}
service: mavis-${{ inputs.environment }}-sidekiq
force-new-deployment: true
wait-for-service-stability: true