diff --git a/.github/workflows/reusable-aws-deploy.yml b/.github/workflows/reusable-aws-deploy.yml new file mode 100644 index 0000000..ebc26e3 --- /dev/null +++ b/.github/workflows/reusable-aws-deploy.yml @@ -0,0 +1,115 @@ +name: Reusable AWS Deploy +on: + workflow_call: + inputs: + aws-role-arn-to-assume: + type: string + required: false + description: | + see reusable docker build workflow + image: + required: true + type: string + description: | + uri of the image to deploy + service: + required: false + type: string + description: | + name of service if deploying + cluster: + required: false + type: string + description: | + name of cluster if deploying + rule-name: + required: false + type: string + description: | + name of EventBridge rule to update, if deploying + container: + required: false + type: string + description: | + name of container + task-name: + required: false + type: string + description: | + name of task definition + deployment-type: + required: false + type: string + description: | + type of deployment, valid values are + ecs, eventbridge, or empty for no deployment + default: '' + deployment-tag-param-name: + required: false + type: string + description: | + name of AWS System Store Parameter to save tag + outputs: + task-definition: + value: ${{ jobs.new-task-revision.outputs.task-definition }} + +permissions: + id-token: write + +jobs: + deploy-task-revision: + runs-on: ubuntu-latest + outputs: + task-definition: ${{ steps.task-def.outputs.task-definition }} + steps: + - if: ${{ startsWith(github.repository, 'GeoNet/') == false }} + name: require GeoNet org + run: | + exit 1 + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + with: + aws-region: ap-southeast-2 + role-to-assume: ${{ inputs.aws-role-arn-to-assume }} + - name: Download task definition + run: | + aws ecs describe-task-definition \ + --task-definition ${{ inputs.task-name }} \ + --query taskDefinition > task-definition.json + - name: Update task definition + id: task-def + uses: aws-actions/amazon-ecs-render-task-definition@5f07eab76e1851cbd4e07dea0f3ed53b304475bd # v1.3.0 + with: + task-definition: task-definition.json + container-name: ${{ inputs.container }} + image: ${{ inputs.image }} + - name: Deploy task definition + id: task-deploy + uses: aws-actions/amazon-ecs-deploy-task-definition@69e7aed9b8acdd75a6c585ac669c33831ab1b9a3 # v1.5.0 + with: + task-definition: ${{ steps.task-def.outputs.task-definition }} + # if service is empty, task revision will be created, but not deployed + service: ${{ inputs.deployment-type == 'ecs' && inputs.service || '' }} + cluster: ${{ inputs.deployment-type == 'ecs' && inputs.cluster || '' }} + wait-for-service-stability: true + - name: Update EventBridge target + run: | + # get target + aws events list-targets-by-rule \ + --rule ${{ inputs.rule-name }} > rule.json + + # update target + cat rule.json | jq '.Targets[0].EcsParameters.TaskDefinitionArn = "${{ steps.task-deploy.outputs.task-definition-arn }}"' > rule-updated-target.json + + # write target to aws + aws events put-targets \ + --rule ${{ inputs.rule-name }} \ + --cli-input-json file://rule-updated-target.json + - name: Save deployment information + if: inputs.deployment-type != '' + run: | + IMAGE_TAG=$(echo ${{ inputs.image }} | cut -d':' -f 2) + aws ssm put-parameter \ + --name ${{ inputs.deployment-tag-param-name }} \ + --value $(jq -cn --arg image-tag $IMAGE_TAG --arg task-arn ${{ steps.task-deploy.outputs.task-definition-arn }} '$ARGS.named') \ + --overwrite diff --git a/README.md b/README.md index d3b5d25..1fcf9cc 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ - [Copy to S3](#copy-to-s3) - [Clean container versions](#clean-container-versions) - [ESLint](#eslint) + - [AWS deploy](#aws-deploy) - [Composite Actions](#composite-actions) - [Tagging](#tagging) - [Other documentation](#other-documentation) @@ -1117,6 +1118,92 @@ jobs: ``` +### AWS deploy + +STATUS: beta + +CICD-driven container image deployment, using AWS ECR and ECS. + +This workflow supports: + +- ECS service deployments +- EventBridge rule target updates + +No deployment can also be specified, allowing the newly created task revision to be deployed via other mechanisms. + +Example: + +```yaml +name: build-and-deploy + +permissions: + contents: write + id-token: write + +jobs: + # build image + build: + uses: GeoNet/Actions/.github/workflows/reusable-docker-build.yml@main + + # example 1: deploy - ECS service + deploy: + needs: build + uses: GeoNet/Actions/.github/workflows/reusable-aws-deploy.yml@main + with: + aws-role-arn-to-assume: arn:aws:iam::ACCOUNT_ID:role/github-actions-geonet-deploy-ROLE_NAME + + # update task definition with new container image uri + task-name: my_task_name + container: my_task_container_name + image: ${{ needs.build.output.image }} + + # deploy + deployment-type: ecs + service: my_service + cluster: my_cluster + + # save deployment information + deployment-tag-param-name: /deployment/my_project/my_service + + # example 2: deploy - EventBridge rule target + deploy: + needs: build + uses: GeoNet/Actions/.github/workflows/reusable-aws-deploy.yml@main + with: + aws-role-arn-to-assume: arn:aws:iam::ACCOUNT_ID:role/github-actions-geonet-deploy-ROLE_NAME + + # update task definition with new container image uri + task-name: my_task_name + container: my_task_container_name + image: ${{ needs.build.output.image }} + + # deploy + deployment-type: eventbridge + rule-name: my_rule + + # save deployment information + deployment-tag-param-name: /deployment/my_project/my_service + + # example 3: only create new task revision + deploy: + needs: build + uses: GeoNet/Actions/.github/workflows/reusable-aws-deploy.yml@main + with: + aws-role-arn-to-assume: arn:aws:iam::ACCOUNT_ID:role/github-actions-geonet-deploy-ROLE_NAME + + # update task definition with new container image uri + task-name: my_task_name + container: my_task_container_name + image: ${{ needs.build.output.image }} + deployment-type: '' +``` + +The terraform module `gha_iam_ecs_deploy` can be used to setup appropriate permissions for this workflow. +The terraform module `ecs_docker_task_ng` can be used to configure services for use with this workflow, via the `use_cicd_deployment` variable. + +Some example repos using this workflow: `DevTools` and `gloria`. + + ## Composite Actions ### Tagging