-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #853 from willscripted/add-build-and-deploy-actions
Add github actions for deploying AWS ECS envs
- Loading branch information
Showing
9 changed files
with
426 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
name: "Task: Build" | ||
on: | ||
workflow_call: | ||
inputs: | ||
override_sha: | ||
description: 'Optionally force checkout of a specific sha' | ||
default: '' | ||
type: string | ||
push: | ||
description: 'To push or not to push' | ||
required: true | ||
type: boolean | ||
outputs: | ||
container_image_digest: | ||
description: "The sha256 digest of the built container image" | ||
value: ${{ jobs.docker.outputs.digest }} | ||
|
||
permissions: | ||
packages: write | ||
contents: read | ||
attestations: write | ||
id-token: write | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
docker: | ||
runs-on: ubuntu-24.04 | ||
outputs: | ||
digest: ${{ steps.push.outputs.digest }} | ||
steps: | ||
- uses: actions/checkout@v4 | ||
if: ${{ inputs.override_sha != '' }} | ||
with: | ||
fetch-depth: 1 | ||
ref: ${{ inputs.override_sha }} | ||
|
||
- uses: actions/checkout@v4 | ||
if: ${{ inputs.override_sha == '' }} | ||
with: | ||
fetch-depth: 1 | ||
|
||
- name: Configuration | ||
id: config | ||
run: | | ||
REPOSITORY_OWNER=$(tr "[:upper:]" "[:lower:]" <<< "${{ github.repository_owner }}") | ||
echo "REPOSITORY_OWNER=${REPOSITORY_OWNER}" >> "$GITHUB_OUTPUT" | ||
REPOSITORY_NAME=$(tr "[:upper:]" "[:lower:]" <<< "${{ github.event.repository.name }}") | ||
echo "REPOSITORY_NAME=${REPOSITORY_NAME}" >> "$GITHUB_OUTPUT" | ||
TARGET_IMAGE="ghcr.io/${REPOSITORY_OWNER}/${REPOSITORY_NAME}" | ||
echo "TARGET_IMAGE=${TARGET_IMAGE}" >> "$GITHUB_OUTPUT" | ||
- name: Login to GitHub Container Registry | ||
uses: docker/login-action@v3 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ steps.config.outputs.REPOSITORY_OWNER }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v3 | ||
|
||
- name: Extract metadata (tags, labels) for Docker | ||
id: meta | ||
uses: docker/metadata-action@v5 | ||
with: | ||
context: workflow | ||
images: ${{ steps.config.outputs.TARGET_IMAGE }} | ||
tags: |- | ||
${{ inputs.override_sha == '' && 'type=ref,event=branch' || '' }} | ||
${{ inputs.override_sha == '' && 'type=ref,event=tag' || '' }} | ||
${{ inputs.override_sha == '' && 'type=ref,event=pr' || '' }} | ||
${{ inputs.override_sha == '' && '# skip raw sha' || format('type=raw,value=sha-{0}', inputs.override_sha) }} | ||
labels: |- | ||
${{ inputs.override_sha != '' && 'org.opencontainers.image.version=unknown' }} | ||
${{ inputs.override_sha != '' && format('org.opencontainers.image.revision={0}', inputs.override_sha) }} | ||
flavor: | | ||
latest=false | ||
- name: Build and push Docker image | ||
id: push | ||
uses: docker/build-push-action@v6 | ||
with: | ||
context: . | ||
file: ./Dockerfile | ||
push: ${{ inputs.push }} | ||
platforms: "linux/amd64" | ||
tags: ${{ steps.meta.outputs.tags }} | ||
labels: ${{ steps.meta.outputs.labels }} | ||
|
||
- name: Generate artifact attestation | ||
uses: actions/attest-build-provenance@v2 | ||
if: ${{ inputs.push }} | ||
with: | ||
subject-name: ${{ steps.config.outputs.TARGET_IMAGE }} | ||
subject-digest: ${{ steps.push.outputs.digest }} | ||
push-to-registry: ${{ inputs.push }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
name: "Task: Deploy" | ||
on: | ||
workflow_call: | ||
inputs: | ||
env: | ||
description: Target environment of deployment. (stg, prod) | ||
required: true | ||
type: string | ||
container_digest: | ||
description: 'The container sha256 digest to deploy' | ||
required: true | ||
type: string | ||
|
||
permissions: | ||
contents: 'read' | ||
id-token: 'write' | ||
|
||
concurrency: | ||
group: ${{ inputs.env }} | ||
cancel-in-progress: false | ||
|
||
jobs: | ||
deploy: | ||
name: dashboard | ||
runs-on: ubuntu-24.04 | ||
environment: ${{ inputs.env }} | ||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Configuration | ||
id: config | ||
run: | | ||
REPOSITORY_OWNER=$(tr "[:upper:]" "[:lower:]" <<< "${{ github.repository_owner }}") | ||
echo "REPOSITORY_OWNER=${REPOSITORY_OWNER}" >> "$GITHUB_OUTPUT" | ||
REPOSITORY_NAME=$(tr "[:upper:]" "[:lower:]" <<< "${{ github.event.repository.name }}") | ||
echo "REPOSITORY_NAME=${REPOSITORY_NAME}" >> "$GITHUB_OUTPUT" | ||
TARGET_IMAGE="ghcr.io/${REPOSITORY_OWNER}/${REPOSITORY_NAME}" | ||
echo "TARGET_IMAGE=${TARGET_IMAGE}" >> "$GITHUB_OUTPUT" | ||
TARGET_IMAGE_W_DIGEST="${TARGET_IMAGE}@${{ inputs.container_digest }}" | ||
echo "TARGET_IMAGE_W_DIGEST=${TARGET_IMAGE_W_DIGEST}" >> "$GITHUB_OUTPUT" | ||
- name: Configure AWS Credentials | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
with: | ||
role-to-assume: ${{ vars.IAM_ROLE_ARN }} | ||
aws-region: us-east-2 | ||
|
||
- name: Download task definition | ||
run: | | ||
aws ecs describe-task-definition \ | ||
--task-definition ${{ vars.ECS_TASK_DEF_FAMILY }} \ | ||
--query taskDefinition \ | ||
> task.json | ||
# Remove Ignored Properties | ||
echo "$( jq 'del(.compatibilities)' task.json )" > task.json | ||
echo "$( jq 'del(.taskDefinitionArn)' task.json )" > task.json | ||
echo "$( jq 'del(.requiresAttributes)' task.json )" > task.json | ||
echo "$( jq 'del(.revision)' task.json )" > task.json | ||
echo "$( jq 'del(.status)' task.json )" > task.json | ||
echo "$( jq 'del(.registeredAt)' task.json )" > task.json | ||
echo "$( jq 'del(.registeredBy)' task.json )" > task.json | ||
# Update Image | ||
echo "$( jq --arg image "${{ steps.config.outputs.TARGET_IMAGE_W_DIGEST }}" '.containerDefinitions |= map((select(.name == "dashboard") | .image) |= $image)' task.json )" > task.json | ||
cat task.json | ||
- name: Deploy Amazon ECS task definition | ||
uses: aws-actions/amazon-ecs-deploy-task-definition@v2 | ||
with: | ||
task-definition: task.json | ||
service: ${{ vars.ECS_SERVICE }} | ||
cluster: ${{ vars.ECS_CLUSTER }} | ||
wait-for-service-stability: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
name: 'Manual Deploy: Git Sha' | ||
on: | ||
workflow_dispatch: | ||
inputs: | ||
sha: | ||
type: string | ||
required: true | ||
description: Git sha (long format) to build and deploy | ||
env: | ||
type: environment | ||
default: stg | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ inputs.sha }} | ||
cancel-in-progress: false | ||
|
||
jobs: | ||
# This job builds a new container and deploys it to the target environment. It | ||
# is unsafe to deploy such arbitrary builds directly to production without | ||
# first trialing them in lower environments. | ||
|
||
validate: | ||
name: "Validate Inputs" | ||
runs-on: ubuntu-24.04 | ||
steps: | ||
- name: Verify not production | ||
if: ${{ inputs.env == 'prod' }} | ||
run: | | ||
cat << EOF | ||
#--------------------------------------------------------------------------------- | ||
# ERROR: Cannot deploy arbitrary sha to production | ||
#--------------------------------------------------------------------------------- | ||
# | ||
# DETAILS: | ||
# | ||
# This job builds a new container and deploys it to the target environment. It | ||
# is unsafe to deploy such arbitrary builds directly to production without | ||
# first trialing them in lower environments. | ||
# | ||
# WORKAROUND: | ||
# | ||
# If you truely must release a specific sha, | ||
# | ||
# 1) Use this workflow to build and deploy the sha to staging | ||
# 2) Deploy the assigned tag from that deployment using the | ||
# "Manual Deploy: Docker Tag" workflow | ||
# Note: You must cite a DOCKER tag | ||
# Which should look like "sha-9e14d6f3da3c3c3f7ea73b74dec8c931365745e4" | ||
# | ||
#--------------------------------------------------------------------------------- | ||
EOF | ||
exit 1 | ||
- name: Verify sha is hex | ||
run: | | ||
if [[ ! "${{ inputs.sha }}" =~ ^[0-9A-Fa-f]+$ ]]; then | ||
echo "sha must be hexidecimal"; exit 1 | ||
fi | ||
length=$(expr length "${{ inputs.sha }}") | ||
if [ "$length" != "40" ]; then | ||
echo "sha must be all 40 characters"; exit 1 | ||
fi | ||
- uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ inputs.sha }} | ||
|
||
- name: Verify commit exists | ||
run: | | ||
git cat-file commit ${{ inputs.sha }} | ||
build-docker: | ||
name: "Build" | ||
uses: ./.github/workflows/callable-build-docker.yml | ||
secrets: inherit | ||
with: | ||
override_sha: ${{ inputs.sha }} | ||
push: true | ||
needs: | ||
- validate | ||
|
||
deploy-ecs: | ||
name: "Deploy container to ECS" | ||
uses: ./.github/workflows/callable-deploy-ecs.yml | ||
secrets: inherit | ||
with: | ||
env: ${{ inputs.env }} | ||
container_digest: ${{ needs.build-docker.outputs.container_image_digest }} | ||
needs: | ||
- build-docker |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
name: 'Manual Deploy: Docker Tag' | ||
on: | ||
workflow_dispatch: | ||
inputs: | ||
tag: | ||
type: string | ||
required: true | ||
description: Tag of the DOCKER image to deploy | ||
env: | ||
type: environment | ||
default: stg | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ inputs.env }} | ||
cancel-in-progress: false | ||
|
||
jobs: | ||
|
||
locate: | ||
name: Find Target Image | ||
runs-on: ubuntu-24.04 | ||
outputs: | ||
digest: ${{ steps.inspect.outputs.digest }} | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 1 | ||
|
||
- name: Configuration | ||
id: config | ||
run: | | ||
REPOSITORY_OWNER=$(tr "[:upper:]" "[:lower:]" <<< "${{ github.repository_owner }}") | ||
echo "REPOSITORY_OWNER=${REPOSITORY_OWNER}" >> "$GITHUB_OUTPUT" | ||
REPOSITORY_NAME=$(tr "[:upper:]" "[:lower:]" <<< "${{ github.event.repository.name }}") | ||
echo "REPOSITORY_NAME=${REPOSITORY_NAME}" >> "$GITHUB_OUTPUT" | ||
TARGET_IMAGE="ghcr.io/${REPOSITORY_OWNER}/${REPOSITORY_NAME}" | ||
echo "TARGET_IMAGE=${TARGET_IMAGE}" >> "$GITHUB_OUTPUT" | ||
TARGET_IMAGE_W_TAG="${TARGET_IMAGE}:${{ inputs.tag }}" | ||
echo "TARGET_IMAGE_W_TAG=${TARGET_IMAGE_W_TAG}" >> "$GITHUB_OUTPUT" | ||
- name: Login to GitHub Container Registry | ||
uses: docker/login-action@v3 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.repository_owner }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v3 | ||
|
||
- name: Pull target tag & inspect | ||
id: inspect | ||
run: | | ||
set -e | ||
docker pull ${{ steps.config.outputs.TARGET_IMAGE_W_TAG }} | ||
checksum=$( | ||
docker inspect ${{ steps.config.outputs.TARGET_IMAGE_W_TAG }} \ | ||
| jq '.[].RepoDigests.[]' \ | ||
| tr -d '"' \ | ||
| sed 's/^.*@//' | ||
) | ||
echo "digest=${checksum}" >> "$GITHUB_OUTPUT" | ||
deploy: | ||
name: "Deploy" | ||
uses: ./.github/workflows/callable-deploy-ecs.yml | ||
secrets: inherit | ||
with: | ||
env: ${{ inputs.env }} | ||
container_digest: ${{ needs.locate.outputs.digest }} | ||
needs: | ||
- locate |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
name: On Branch Update (master) | ||
on: | ||
push: | ||
branches: | ||
- master | ||
workflow_dispatch: | ||
|
||
concurrency: | ||
group: ${{ github.workflow }} | ||
cancel-in-progress: false | ||
|
||
jobs: | ||
|
||
build-docker: | ||
name: "Build" | ||
uses: ./.github/workflows/callable-build-docker.yml | ||
secrets: inherit | ||
with: | ||
push: true | ||
|
||
deploy-env-stg: | ||
name: "Deploy Staging" | ||
uses: ./.github/workflows/callable-deploy-ecs.yml | ||
secrets: inherit | ||
with: | ||
env: stg | ||
container_digest: ${{ needs.build-docker.outputs.container_image_digest }} | ||
needs: | ||
- build-docker |
Oops, something went wrong.