From 085059de4763d258c79fb65634e35238cef796f8 Mon Sep 17 00:00:00 2001 From: Evangelos Giataganas Date: Tue, 7 Mar 2023 19:49:07 +0200 Subject: [PATCH] Add GA to deploy ECS --- .aws/appspec.yml | 9 ++ .github/workflows/deploy-environment.yml | 120 ++++++++++++++++++++--- 2 files changed, 118 insertions(+), 11 deletions(-) create mode 100644 .aws/appspec.yml diff --git a/.aws/appspec.yml b/.aws/appspec.yml new file mode 100644 index 0000000000..2fe720847a --- /dev/null +++ b/.aws/appspec.yml @@ -0,0 +1,9 @@ +version: 0.0 +Resources: + - TargetService: + Type: AWS::ECS::Service + Properties: + taskDefinition: "arn:aws:ecs:*:*:task-definition/*" + LoadBalancerInfo: + ContainerName: bops + ContainerPort: 3000 diff --git a/.github/workflows/deploy-environment.yml b/.github/workflows/deploy-environment.yml index 82f22e1246..fb76823e44 100644 --- a/.github/workflows/deploy-environment.yml +++ b/.github/workflows/deploy-environment.yml @@ -19,15 +19,10 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - - name: Setup ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: 2.7.5 - - - name: Install gems + - name: Create an image tag based on the commit sha + id: image_tag run: | - gem install bundler - bundle install --jobs 4 --retry 3 --path vendor/bundle + echo "sha=$(echo ${GITHUB_SHA} | cut -c1-7)" >>$GITHUB_OUTPUT - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1-node16 @@ -36,8 +31,111 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: eu-west-2 - - run: echo "Deploying to ${{ inputs.environment-name }} on branch $GITHUB_REF" + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Setup docker cache + id: cache + uses: actions/cache@v2 + with: + path: docker-cache + key: ${{ runner.os }}-docker-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-docker- + + - name: Load docker cache + run: | + if [ -d "docker-cache" ]; then + cat docker-cache/x* > bops.tar + docker load < bops.tar + rm -rf docker-cache + fi + + - name: Build, tag, and push ${{ inputs.environment-name }} image to Amazon ECR + id: build-image + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + ECR_REPOSITORY: bops/${{ inputs.environment-name }} + IMAGE_TAG: ${{ steps.image_tag.outputs.sha }} + run: | + # Build a docker container and + # push it to ECR so that it can + # be deployed to ECS. + docker build -t bops:$IMAGE_TAG -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f Dockerfile.production . + docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + docker save bops:$IMAGE_TAG $(docker history -q bops:$IMAGE_TAG | awk '!//{print}') >bops.tar + mkdir docker-cache + split -b 5G bops.tar docker-cache/x + echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >>$GITHUB_OUTPUT + + - name: Download task definition for db_migrate and strip unused properties + env: + IMAGE_ARN: ${{ steps.build-image.outputs.image }} + run: | + aws ecs describe-task-definition --task-definition bops-db-migrate-${{ inputs.environment-name }} --query taskDefinition | \ + jq -r 'del(.compatibilities, .taskDefinitionArn, .requiresAttributes, .revision, .status, .registeredAt, .registeredBy)' | \ + jq -r '.containerDefinitions[].image = "'$IMAGE_ARN'"' > db_migrate.json + + - name: Register db_migrate on a new revision + run: | + aws ecs register-task-definition \ + --cli-input-json file://db_migrate.json + + - name: Run db_migrate + env: + CLUSTER: bops-${{ inputs.environment-name }} + TASK_DEFINITION: bops-db-migrate-${{ inputs.environment-name }} + BOPS_SUBNETS: subnet-${{ secrets.BOPS_SUBNETS }} + BOPS_SG: sg-${{ secrets.BOPS_SG }} + run: | + aws ecs run-task --cluster $CLUSTER \ + --task-definition $TASK_DEFINITION --launch-type FARGATE \ + --network-configuration '{"awsvpcConfiguration": {"subnets": ["'$BOPS_SUBNETS'"],"securityGroups": ["'$BOPS_SG'"],"assignPublicIp": "ENABLED"}}' + + - name: Download task definition for worker and strip unused properties + env: + IMAGE_ARN: ${{ steps.build-image.outputs.image }} + run: | + aws ecs describe-task-definition --task-definition bops-worker-${{ inputs.environment-name }} --query taskDefinition | \ + jq -r 'del(.compatibilities, .taskDefinitionArn, .requiresAttributes, .revision, .status, .registeredAt, .registeredBy)' > worker.json + + - name: Generate task definition for worker + id: task-def-worker + uses: aws-actions/amazon-ecs-render-task-definition@v1 + with: + task-definition: worker.json + container-name: bops + image: ${{ steps.build-image.outputs.image }} + + - name: Deploy worker + uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + with: + task-definition: ${{ steps.task-def-worker.outputs.task-definition }} + service: bops-worker-${{ inputs.environment-name }} + cluster: bops-${{ inputs.environment-name }} + wait-for-service-stability: true - - name: Deploy ${{ inputs.environment-name }} application + - name: Download task definition for web and strip unused properties run: | - bundle exec rake deploy:${{ inputs.environment-name }} + aws ecs describe-task-definition --task-definition bops-web-${{ inputs.environment-name }} --query taskDefinition | \ + jq -r 'del(.compatibilities, .taskDefinitionArn, .requiresAttributes, .revision, .status, .registeredAt, .registeredBy)' > web.json + + - name: Generate task definition for web + id: task-def-web + uses: aws-actions/amazon-ecs-render-task-definition@v1 + with: + task-definition: web.json + container-name: bops + image: ${{ steps.build-image.outputs.image }} + + - name: Deploy web + uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + with: + task-definition: ${{ steps.task-def-web.outputs.task-definition }} + service: bops-web-${{ inputs.environment-name }} + cluster: bops-${{ inputs.environment-name }} + wait-for-service-stability: true + codedeploy-appspec: .aws/appspec.yml + codedeploy-application: bops-${{ inputs.environment-name }} + codedeploy-deployment-group: default