Enable AWS #57
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
--- | ||
name: CI Matrix | ||
# Build and run tests in containers | ||
# Store test and prod images to GitHub Container Registry (GHCR) | ||
# Build prod image and push to AWS ECR | ||
# Run tests and quality checks on test image | ||
# Run security scans on code and prod images | ||
# Run tasks in parallel | ||
# Use GHA caching | ||
# Use test matrix for multiple versions of Elixir, OTP, and OS | ||
on: push | ||
# on: | ||
# push: | ||
# branches: [main] | ||
# paths-ignore: | ||
# - 'README.md' | ||
# - '.github/**' | ||
# - '.vscode' | ||
# - '.gitignore' | ||
# pull_request: | ||
# # branches: [main] | ||
# types: [opened,synchronize,reopened,labeled,unlabeled] | ||
env: | ||
# Name of image | ||
IMAGE_NAME: foo-app | ||
# Name of org in GHCR Docker repository | ||
IMAGE_OWNER: ${{ github.repository_owner }} | ||
# Name of org in external Docker repository | ||
ECR_IMAGE_OWNER: cogini | ||
# Tag for release images | ||
# IMAGE_TAG: ${{ (github.ref == 'refs/heads/main' && 'staging') || (github.ref == 'refs/heads/qa' && 'qa') }} | ||
IMAGE_TAG: latest | ||
IMAGE_VER: ${{ github.sha }} | ||
# Docker build args | ||
ELIXIR_VER: 1.15.5 | ||
OTP_VER: 26.0.2 | ||
BUILD_OS_VER: bullseye-20230612-slim | ||
PROD_OS_VER: bullseye-slim | ||
BASE_OS: debian | ||
# Variant if test matrix is not used | ||
VAR: '1.15.5-erlang-26.0.2-debian-bullseye-20230612-slim' | ||
# Variant that is deployed | ||
PROD_VAR: '1.15.5-erlang-26.0.2-debian-bullseye-20230612-slim' | ||
# Registry for test images | ||
REGISTRY: ghcr.io/ | ||
# Registry for public images, default is docker.io | ||
PUBLIC_REGISTRY: '' | ||
# Give GitHub Actions access to AWS | ||
AWS_ENABLED: ${{ true }} | ||
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} | ||
# AWS_ROLE_TO_ASSUME: arn:aws:iam::XXX:role/cogini-foo-dev-app-github-action | ||
AWS_ROLE_TO_ASSUME: ${{ secrets.AWS_ROLE_TO_ASSUME }} | ||
AWS_REGION: ap-northeast-1 | ||
# Health check port for app | ||
APP_PORT: 4000 | ||
# Datadog | ||
# DD_API_KEY: ${{ secrets.ACTIONS_DD_API_KEY }} | ||
# DD_ENV: ci | ||
# DD_TAGS: "environment:ci" | ||
# Docker | ||
DOCKER_BUILDKIT: '1' | ||
COMPOSE_DOCKER_CLI_BUILD: '1' | ||
COMPOSE_FILE: docker-compose.gha.yml | ||
DOCKER_FILE: deploy/debian.Dockerfile | ||
ELIXIR_MODULE: PhoenixContainerExample | ||
ECS_CLUSTER: foo | ||
ECS_SERVICE: foo-app | ||
ECS_CONTAINER: foo-app | ||
CODEDEPLOY_APPLICATION: foo-app | ||
CODEDEPLOY_DEPLOYMENT_GROUP: foo-app-ecs | ||
TASKDEF: ecs/task-definition.json | ||
# AWS SSM Parameter Store name prefix | ||
AWS_PS_PREFIX: cogini/foo/dev | ||
# Name of environment for resources created by Terraform | ||
TERRAFORM_ENV: dev | ||
# GitHub Advanced Security | ||
# https://docs.github.com/en/get-started/learning-about-github/about-github-advanced-security | ||
# https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning | ||
# https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github | ||
GITHUB_ADVANCED_SECURITY: ${{ true }} | ||
DEPLOY_DOCKER_HUB: ${{ false }} | ||
jobs: | ||
build-test: | ||
name: Build test image | ||
permissions: | ||
contents: read | ||
# Push to ghcr.io repository | ||
packages: write | ||
# Cancel previous runs | ||
actions: write | ||
runs-on: ubuntu-latest | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
# Specify versions of Erlang, Elixir, and base OS | ||
# Choose a combination supported by https://hub.docker.com/r/hexpm/elixir/tags | ||
os: [alpine, debian, ubuntu] | ||
otp: [25.3.2.6] | ||
elixir: [1.14.5] | ||
include: | ||
- os: alpine | ||
otp: 25.3.2.6 | ||
build_os_ver: '3.17.0' | ||
prod_os_ver: '3.17.0' | ||
- os: debian | ||
build_os_ver: bullseye-20230612-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: 20230612 | ||
otp: 26.0.2 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 25.2.3 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 25.2.3 | ||
- os: ubuntu | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
env: | ||
DOCKER_FILE: deploy/${{ matrix.os }}.Dockerfile | ||
VAR: ${{ matrix.elixir }}-erlang-${{ matrix.otp }}-${{ matrix.os }}-${{ matrix.build_os_ver }} | ||
steps: | ||
# - name: Dump event | ||
# run: cat "$GITHUB_EVENT_PATH" | ||
- name: Cancel previous runs in progress | ||
uses: styfle/[email protected] | ||
with: | ||
access_token: ${{ github.token }} | ||
- name: Check out source | ||
uses: actions/checkout@v3 | ||
- name: Set variables | ||
run: | | ||
echo "GITHUB_SHA_SHORT=$(echo $GITHUB_SHA | cut -c 1-7)" >> $GITHUB_ENV | ||
echo "run_id=${GITHUB_RUN_ID}" >> $GITHUB_OUTPUT | ||
echo "run_num=${GITHUB_RUN_NUMBER}" >> $GITHUB_OUTPUT | ||
- name: Get branch name for main | ||
if: github.event_name != 'pull_request' | ||
run: echo "BRANCH=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_ENV | ||
- name: Get branch name for pull_request | ||
if: github.event_name == 'pull_request' | ||
run: echo "BRANCH=$(echo $GITHUB_HEAD_REF | tr '//\\' '.' | cut -c -55)" >> $GITHUB_ENV | ||
- name: Log in to GHCR | ||
uses: docker/login-action@v2 | ||
# https://github.com/marketplace/actions/docker-login | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
# Pull public images without rate limits | ||
- name: Log in to Docker Hub | ||
uses: docker/login-action@v2 | ||
with: | ||
username: ${{ secrets.DOCKERHUB_USERNAME }} | ||
password: ${{ secrets.DOCKERHUB_TOKEN }} | ||
# - name: Configure ssh keys | ||
# uses: webfactory/[email protected] | ||
# # Configure machine key or deploy keys to access private repos from build | ||
# # https://github.com/marketplace/actions/webfactory-ssh-agent | ||
# # https://docs.github.com/en/developers/overview/managing-deploy-keys#deploy-keys | ||
# # ssh-keygen -t ed25519 -m pem -C "[email protected]:reachfh/api-utils.git" -f api-utils | ||
# with: | ||
# ssh-private-key: | | ||
# ${{ secrets.SSH_PRIVATE_KEY }} | ||
- name: Set env vars for builds | ||
run: | | ||
echo 'DATABASE_HOST=postgres' >> ./.env.test | ||
# - name: Set up QEMU for multi-platform builds | ||
# id: qemu | ||
# uses: docker/setup-qemu-action@v2 | ||
# with: | ||
# platforms: linux/amd64,linux/arm64 | ||
# - name: Display available platforms | ||
# run: echo "${{ steps.qemu.outputs.platforms }}" | ||
- name: Set up Docker buildx | ||
id: buildx | ||
uses: docker/setup-buildx-action@v2 | ||
with: | ||
driver-opts: network=host | ||
- name: Build test image and push to GHCR | ||
uses: docker/build-push-action@v3 | ||
# https://github.com/docker/build-push-action | ||
with: | ||
file: ${{ env.DOCKER_FILE }} | ||
target: test-image | ||
build-args: | | ||
ELIXIR_VER=${{ matrix.elixir }} | ||
OTP_VER=${{ matrix.otp }} | ||
BUILD_OS_VER=${{ matrix.build_os_ver }} | ||
PROD_OS_VER=${{ matrix.prod_os_ver }} | ||
context: . | ||
builder: ${{ steps.buildx.outputs.name }} | ||
push: true | ||
# https://github.com/moby/buildkit#export-cache | ||
cache-from: type=gha,scope=${{ github.workflow }}-test-${{ env.VAR }} | ||
cache-to: type=gha,scope=${{ github.workflow }}-test-${{ env.VAR }},mode=max | ||
# ssh: default | ||
tags: | | ||
ghcr.io/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_NAME }}:test${{ env.VAR }}${{ env.IMAGE_VER }} | ||
# secrets: | | ||
# "access_token=${{ secrets.DEVOPS_ACCESS_TOKEN }}" | ||
# "oban_key_fingerprint=${{ secrets.OBAN_KEY_FINGERPRINT }}" | ||
# "oban_license_key=${{ secrets.OBAN_LICENSE_KEY }}" | ||
test: | ||
name: Run tests | ||
# permissions: write-all | ||
permissions: | ||
# Read from ghcr.io repository | ||
packages: read | ||
# Upload JUnit report files | ||
# https://github.com/EnricoMi/publish-unit-test-result-action#permissions | ||
contents: read | ||
checks: write | ||
pull-requests: write | ||
issues: read | ||
needs: [build-test] | ||
runs-on: ubuntu-latest | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
os: [alpine, debian, ubuntu] | ||
elixir: [1.15.5, 1.14.3] | ||
include: | ||
- os: alpine | ||
otp: 24.3.4.6 | ||
build_os_ver: '3.15.6' | ||
prod_os_ver: '3.15.6' | ||
- os: alpine | ||
otp: 25.2.3 | ||
build_os_ver: '3.17.0' | ||
prod_os_ver: '3.17.0' | ||
- os: debian | ||
build_os_ver: bullseye-20230612-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: 20230612 | ||
otp: 26.0.2 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 25.2.3 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 25.2.3 | ||
- os: ubuntu | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 24.3.4.9 | ||
- os: ubuntu | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 25.2.3 | ||
# ci_node_total: [2] | ||
# ci_node_index: [1, 2] | ||
env: | ||
DOCKER_FILE: deploy/${{ matrix.os }}.Dockerfile | ||
VAR: ${{ matrix.elixir }}-erlang-${{ matrix.otp }}-${{ matrix.os }}-${{ matrix.build_os_ver }} | ||
steps: | ||
- name: Log in to GHCR | ||
uses: docker/login-action@v2 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
- name: Check out source | ||
uses: actions/checkout@v3 | ||
- name: Pull repos | ||
run: | | ||
docker compose pull --quiet --include-deps test | ||
docker images --no-trunc | ||
- name: Start services | ||
run: docker compose up --detach test | ||
- name: Show docker logs | ||
if: failure() | ||
run: | | ||
docker compose logs --timestamps postgres | ||
docker compose logs --timestamps test | ||
docker compose ps --format json | jq . | ||
- name: Display health check results | ||
if: failure() | ||
run: | | ||
echo postgres | ||
docker inspect --format "{{json .State.Health }}" $(docker compose ps -q postgres) | jq | ||
echo redis | ||
docker inspect --format "{{json .State.Health }}" $(docker compose ps -q redis) | jq | ||
- name: Debug env | ||
if: failure() | ||
run: | | ||
docker compose run test env | ||
# docker compose run test env PGPASSWORD=postgres /usr/bin/psql -w -h postgres -U postgres -d postgres -c "SELECT 1" | ||
# docker compose run test env PGPASSWORD=postgres /usr/lib/postgresql/13/bin/pg_isready -h postgres -p 5432 -d postgres -U postgres | ||
- name: Initialize test database | ||
run: docker compose run test mix do ecto.create, ecto.migrate | ||
- name: Run tests | ||
# run: docker compose run test mix test --cover | ||
# run: docker compose run test env MIX_TEST_PARTITION=${{ matrix.ci_node_index }} mix test --partitions ${{ matrix.ci_node_total }} | ||
run: docker compose run test mix test | ||
- name: Run quality checks | ||
run: docker compose run test mix do format --check-formatted, deps.unlock --check-unused, credo --all, hex.audit, deps.audit, sobelow | ||
- name: Publish unit test results to GitHub | ||
uses: EnricoMi/publish-unit-test-result-action@v2 | ||
# Run even if tests fail | ||
if: always() | ||
with: | ||
# Volume mounted from local filesystem into build by docker compose | ||
junit_files: junit-reports/*.xml | ||
# - name: Upload test results to Datadog | ||
# if: always() | ||
# continue-on-error: true | ||
# run: | | ||
# npm install -g @datadog/datadog-ci | ||
# datadog-ci junit upload --service api-graphql junit-reports/ | ||
test-dialyzer: | ||
name: Run dialyzer | ||
needs: [build-test] | ||
permissions: | ||
contents: read | ||
# Read from ghcr.io repository | ||
packages: read | ||
# Upload JUnit report files | ||
# https://github.com/EnricoMi/publish-unit-test-result-action#permissions | ||
checks: write | ||
pull-requests: write | ||
issues: read | ||
runs-on: ubuntu-latest | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
os: [alpine, debian, ubuntu] | ||
elixir: [1.15.5, 1.14.3] | ||
include: | ||
- os: alpine | ||
otp: 24.3.4.6 | ||
build_os_ver: '3.15.6' | ||
prod_os_ver: '3.15.6' | ||
- os: alpine | ||
otp: 25.2.3 | ||
build_os_ver: '3.17.0' | ||
prod_os_ver: '3.17.0' | ||
- os: debian | ||
build_os_ver: bullseye-20230612-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: 20230612 | ||
otp: 26.0.2 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 25.2.3 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 25.2.3 | ||
- os: ubuntu | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 24.3.4.9 | ||
- os: ubuntu | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 25.2.3 | ||
env: | ||
DOCKER_FILE: deploy/${{ matrix.os }}.Dockerfile | ||
VAR: ${{ matrix.elixir }}-erlang-${{ matrix.otp }}-${{ matrix.os }}-${{ matrix.build_os_ver }} | ||
steps: | ||
- name: Log in to GHCR | ||
uses: docker/login-action@v2 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
- name: Check out source | ||
uses: actions/checkout@v3 | ||
- name: Pull repos | ||
run: | | ||
docker compose pull --quiet test | ||
# docker images --no-trunc | ||
- name: Run dialyzer | ||
run: docker compose run test mix dialyzer --no-check --format github | ||
test-scan: | ||
name: Security scan code | ||
needs: [build-test] | ||
permissions: | ||
contents: read | ||
# Read from ghcr.io repository | ||
packages: read | ||
# Upload JUnit report files | ||
# https://github.com/EnricoMi/publish-unit-test-result-action#permissions | ||
checks: write | ||
pull-requests: write | ||
issues: read | ||
# Upload SARIF report files | ||
security-events: write | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Log in to GHCR | ||
uses: docker/login-action@v2 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
- name: Checkout source | ||
uses: actions/checkout@v3 | ||
- name: Scan code with trivy | ||
uses: aquasecurity/trivy-action@master | ||
# https://github.com/marketplace/actions/aqua-security-trivy | ||
with: | ||
scan-type: 'fs' | ||
scan-ref: '.' | ||
# ignore-unfixed: true | ||
# severity: 'CRITICAL' | ||
# trivy-config: trivy.yaml | ||
# format: 'table' | ||
format: 'sarif' | ||
output: 'trivy-results.sarif' | ||
- name: Display scan results | ||
run: cat trivy-results.sarif | jq . | ||
- name: Upload trivy scan results to GitHub Security tab | ||
if: ${{ env.GITHUB_ADVANCED_SECURITY == 1 }} | ||
uses: github/codeql-action/upload-sarif@v2 | ||
if: always() | ||
Check failure on line 495 in .github/workflows/ci-matrix.yml GitHub Actions / CI MatrixInvalid workflow file
|
||
with: | ||
sarif_file: 'trivy-results.sarif' | ||
category: trivy | ||
- name: Scan code with grype | ||
uses: anchore/scan-action@v3 | ||
# https://github.com/marketplace/actions/anchore-container-scan | ||
id: scan-grype | ||
with: | ||
path: . | ||
# output-format: table | ||
output-format: 'sarif' | ||
fail-build: false | ||
# severity-cutoff: critical | ||
- name: Display scan results | ||
run: cat ${{ steps.scan-grype.outputs.sarif }} | jq . | ||
- name: Upload grype scan results to GitHub Security tab | ||
if: ${{ env.GITHUB_ADVANCED_SECURITY == 1 }} | ||
uses: github/codeql-action/upload-sarif@v2 | ||
if: always() | ||
with: | ||
sarif_file: ${{ steps.scan-grype.outputs.sarif }} | ||
category: grype | ||
build-prod: | ||
name: Build prod image | ||
permissions: | ||
# Interact with GitHub OIDC Token endpoint for AWS | ||
id-token: write | ||
contents: read | ||
# Push to ghcr.io repository | ||
packages: write | ||
# Cancel previous runs | ||
actions: write | ||
runs-on: ubuntu-latest | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
os: [alpine, chiseled, debian, distroless, ubuntu] | ||
elixir: [1.15.5, 1.14.3] | ||
include: | ||
- os: alpine | ||
otp: 24.3.4.6 | ||
build_os_ver: '3.15.6' | ||
prod_os_ver: '3.15.6' | ||
- os: alpine | ||
otp: 25.2.3 | ||
build_os_ver: '3.17.0' | ||
prod_os_ver: '3.17.0' | ||
- os: chiseled | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 25.2.3 | ||
- os: debian | ||
build_os_ver: bullseye-20230612-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: 20230612 | ||
otp: 26.0.2 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 25.2.3 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 25.2.3 | ||
- os: distroless | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '' | ||
otp: 25.2.3 | ||
- os: ubuntu | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 24.3.4.9 | ||
- os: ubuntu | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 25.2.3 | ||
env: | ||
DOCKER_FILE: deploy/${{ matrix.os }}.Dockerfile | ||
VAR: ${{ matrix.elixir }}-erlang-${{ matrix.otp }}-${{ matrix.os }}-${{ matrix.build_os_ver }} | ||
steps: | ||
- name: Cancel previous runs in progress | ||
uses: styfle/[email protected] | ||
with: | ||
access_token: ${{ github.token }} | ||
- name: Log in to GHCR | ||
uses: docker/login-action@v2 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
- name: Log in to Docker Hub | ||
uses: docker/login-action@v2 | ||
with: | ||
username: ${{ secrets.DOCKERHUB_USERNAME }} | ||
password: ${{ secrets.DOCKERHUB_TOKEN }} | ||
- name: Check out source | ||
uses: actions/checkout@v3 | ||
- name: Set variables | ||
id: vars | ||
run: | | ||
echo "GITHUB_SHA_SHORT=$(echo $GITHUB_SHA | cut -c 1-7)" >> $GITHUB_ENV | ||
echo "run_id=${GITHUB_RUN_ID}" >> $GITHUB_OUTPUT | ||
echo "run_num=${GITHUB_RUN_NUMBER}" >> $GITHUB_OUTPUT | ||
- name: Get branch name for push | ||
if: github.event_name != 'pull_request' | ||
run: echo "BRANCH=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_ENV | ||
- name: Get branch name for pull_request | ||
if: github.event_name == 'pull_request' | ||
run: echo "BRANCH=$(echo $GITHUB_HEAD_REF | tr '//\\' '.' | cut -c -55)" >> $GITHUB_ENV | ||
# - name: Configure ssh keys | ||
# uses: webfactory/[email protected] | ||
# # https://github.com/marketplace/actions/webfactory-ssh-agent | ||
# # https://docs.github.com/en/developers/overview/managing-deploy-keys#deploy-keys | ||
# # ssh-keygen -t ed25519 -m pem -C "[email protected]:reachfh/api-utils.git" -f api-utils | ||
# with: | ||
# ssh-private-key: | | ||
# ${{ secrets.SSH_PRIVATE_KEY }} | ||
- name: Set up Docker buildx | ||
id: buildx | ||
uses: docker/setup-buildx-action@v2 | ||
with: | ||
driver-opts: network=host | ||
- name: Build prod image and push to GHCR | ||
uses: docker/build-push-action@v3 | ||
with: | ||
file: ${{ env.DOCKER_FILE }} | ||
target: prod | ||
build-args: | | ||
ELIXIR_VER=${{ matrix.elixir }} | ||
OTP_VER=${{ matrix.otp }} | ||
BUILD_OS_VER=${{ matrix.build_os_ver }} | ||
PROD_OS_VER=${{ matrix.prod_os_ver }} | ||
context: . | ||
builder: ${{ steps.buildx.outputs.name }} | ||
push: true | ||
cache-from: type=gha,scope=${{ github.workflow }}-${{ env.VAR }} | ||
cache-to: type=gha,scope=${{ github.workflow }}-${{ env.VAR }},mode=max | ||
# ssh: default | ||
tags: | | ||
ghcr.io/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_NAME }}:${{ env.VAR }}${{ env.IMAGE_VER }} | ||
ghcr.io/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_NAME }}:${{ env.BRANCH }}-${{ env.GITHUB_SHA_SHORT }} | ||
# secrets: | | ||
# "access_token=${{ secrets.DEVOPS_ACCESS_TOKEN }}" | ||
# "oban_key_fingerprint=${{ secrets.OBAN_KEY_FINGERPRINT }}" | ||
# "oban_license_key=${{ secrets.OBAN_LICENSE_KEY }}" | ||
- name: Build prod image and push to Docker Hub | ||
if: ${{ env.DEPLOY_DOCKER_HUB == 1 }} | ||
uses: docker/build-push-action@v3 | ||
with: | ||
file: ${{ env.DOCKER_FILE }} | ||
target: prod | ||
context: . | ||
builder: ${{ steps.buildx.outputs.name }} | ||
push: true | ||
cache-from: type=gha,scope=${{ github.workflow }}-${{ env.VAR }} | ||
cache-to: type=gha,scope=${{ github.workflow }}-${{ env.VAR }},mode=max | ||
# ssh: default | ||
tags: | | ||
docker.io/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_NAME }}:${{ env.VAR }}${{ env.IMAGE_VER }} | ||
docker.io/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_NAME }}:${{ env.BRANCH }}-${{ env.GITHUB_SHA_SHORT }} | ||
# secrets: | | ||
# "access_token=${{ secrets.DEVOPS_ACCESS_TOKEN }}" | ||
# "oban_key_fingerprint=${{ secrets.OBAN_KEY_FINGERPRINT }}" | ||
# "oban_license_key=${{ secrets.OBAN_LICENSE_KEY }}" | ||
- name: Configure AWS credentials | ||
if: ${{ env.AWS_ENABLED == 1 }} | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
# https://github.com/aws-actions/configure-aws-credentials | ||
# https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services | ||
with: | ||
role-to-assume: ${{ env.AWS_ROLE_TO_ASSUME }} | ||
aws-region: ${{ env.AWS_REGION }} | ||
- name: Log in to Amazon ECR | ||
if: ${{ env.AWS_ENABLED == 1 }} | ||
id: ecr-login | ||
uses: aws-actions/amazon-ecr-login@v1 | ||
- name: Set vars | ||
if: ${{ env.AWS_ENABLED == 1 }} | ||
run: echo "ECR_REGISTRY=${{ steps.ecr-login.outputs.registry }}" >> $GITHUB_ENV | ||
# - name: Log in to ECR | ||
# uses: docker/login-action@v2 | ||
# with: | ||
# registry: ${{ env.ECR_REGISTRY }} | ||
# username: ${{ secrets.AWS_ACCESS_KEY_ID }} | ||
# password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | ||
- name: Build prod image and push to AWS ECR | ||
if: ${{ env.AWS_ENABLED == 1 }} | ||
uses: docker/build-push-action@v3 | ||
env: | ||
REGISTRY: "${{ env.ECR_REGISTRY }}/" | ||
IMAGE_OWNER: "${{ env.ECR_IMAGE_OWNER }}/" | ||
with: | ||
file: ${{ env.DOCKER_FILE }} | ||
target: prod | ||
context: . | ||
builder: ${{ steps.buildx.outputs.name }} | ||
push: true | ||
cache-from: type=gha,scope=${{ github.workflow }}-${{ env.VAR }} | ||
cache-to: type=gha,scope=${{ github.workflow }}-${{ env.VAR }},mode=max | ||
# ssh: default | ||
tags: | | ||
${{ env.ECR_REGISTRY }}/${{ env.ECR_IMAGE_OWNER }}/${{ env.IMAGE_NAME }}:${{ env.VAR }}${{ env.IMAGE_VER }} | ||
${{ env.ECR_REGISTRY }}/${{ env.ECR_IMAGE_OWNER }}/${{ env.IMAGE_NAME }}:${{ env.BRANCH }}-${{ env.GITHUB_SHA_SHORT }} | ||
# secrets: | | ||
# "access_token=${{ secrets.DEVOPS_ACCESS_TOKEN }}" | ||
# "oban_key_fingerprint=${{ secrets.OBAN_KEY_FINGERPRINT }}" | ||
# "oban_license_key=${{ secrets.OBAN_LICENSE_KEY }}" | ||
# build-newman: | ||
# name: Build newman image | ||
# permissions: | ||
# # Push to ghcr.io repository | ||
# packages: write | ||
# # Cancel previous runs | ||
# actions: write | ||
# runs-on: ubuntu-latest | ||
# steps: | ||
# - name: Cancel previous runs | ||
# uses: styfle/[email protected] | ||
# with: | ||
# access_token: ${{ github.token }} | ||
# | ||
# - name: Check out source | ||
# uses: actions/checkout@v3 | ||
# | ||
# - name: Log in to GHCR | ||
# uses: docker/login-action@v2 | ||
# with: | ||
# registry: ghcr.io | ||
# username: ${{ github.actor }} | ||
# password: ${{ secrets.GITHUB_TOKEN }} | ||
# | ||
# # Pull public images without rate limits | ||
# # - name: Log in to Docker Hub | ||
# # uses: docker/login-action@v2 | ||
# # with: | ||
# # username: ${{ secrets.DOCKERHUB_USERNAME }} | ||
# # password: ${{ secrets.DOCKERHUB_TOKEN }} | ||
# | ||
# - name: Set up Docker buildx | ||
# id: buildx | ||
# uses: docker/setup-buildx-action@v2 | ||
# with: | ||
# driver-opts: network=host | ||
# | ||
# - name: Build newman image | ||
# uses: docker/build-push-action@v3 | ||
# with: | ||
# file: deploy/newman.Dockerfile | ||
# context: . | ||
# builder: ${{ steps.buildx.outputs.name }} | ||
# push: true | ||
# cache-from: type=gha,scope=${{ github.workflow }}-newman | ||
# cache-to: type=gha,scope=${{ github.workflow }}-newman,mode=max | ||
# tags: | | ||
# ghcr.io/${{ env.IMAGE_OWNER }}/newman:latest | ||
test-prod: | ||
name: Run external API tests | ||
# needs: [build-prod, build-newman] | ||
needs: [build-prod] | ||
permissions: | ||
# Read from ghcr.io repository | ||
packages: read | ||
# Upload JUnit report files | ||
# https://github.com/EnricoMi/publish-unit-test-result-action#permissions | ||
contents: read | ||
issues: read | ||
checks: write | ||
pull-requests: write | ||
runs-on: ubuntu-latest | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
os: [alpine, chiseled, debian, distroless, ubuntu] | ||
elixir: [1.15.5, 1.14.3] | ||
include: | ||
- os: alpine | ||
otp: 24.3.4.6 | ||
build_os_ver: '3.15.6' | ||
prod_os_ver: '3.15.6' | ||
- os: alpine | ||
otp: 25.2.3 | ||
build_os_ver: '3.17.0' | ||
prod_os_ver: '3.17.0' | ||
- os: chiseled | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 25.2.3 | ||
- os: debian | ||
build_os_ver: bullseye-20230612-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: 20230612 | ||
otp: 26.0.2 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 25.2.3 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 25.2.3 | ||
- os: distroless | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '' | ||
otp: 25.2.3 | ||
- os: ubuntu | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 24.3.4.9 | ||
- os: ubuntu | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 25.2.3 | ||
env: | ||
DOCKER_FILE: deploy/${{ matrix.os }}.Dockerfile | ||
VAR: ${{ matrix.elixir }}-erlang-${{ matrix.otp }}-${{ matrix.os }}-${{ matrix.build_os_ver }} | ||
steps: | ||
- name: Log in to GHCR | ||
uses: docker/login-action@v2 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
- name: Check out source | ||
uses: actions/checkout@v3 | ||
- name: Pull repos | ||
# run: echo "newman postgres router prod" | xargs -n 1 -P 8 docker compose pull --quiet | ||
# docker compose pull --quiet newman | ||
# docker images --no-trunc | ||
run: | | ||
docker compose pull --quiet --include-deps prod | ||
- name: Start services | ||
run: docker compose up --wait --detach prod | ||
- name: Display logs | ||
if: failure() | ||
run: | | ||
docker compose logs --timestamps prod | ||
docker compose logs --timestamps postgres | ||
echo prod | ||
docker inspect --format "{{json .State.Health }}" $(docker compose ps -q prod) | jq | ||
echo postgres | ||
docker inspect --format "{{json .State.Health }}" $(docker compose ps -q postgres) | jq | ||
docker compose ps --format json | jq . | ||
# - name: Debug env | ||
# if: failure() | ||
# run: | | ||
# docker compose run --entrypoint /bin/bash prod env | ||
# docker compose run --entrypoint /bin/bash prod env PGPASSWORD=postgres /usr/bin/psql -w -h postgres -U postgres -d postgres -c "SELECT 1" | ||
# # docker compose run --entrypoint /bin/bash prod pg_isready -h postgres -p 5432 -d postgres -U postgres | ||
- name: Initialize database | ||
run: | | ||
docker compose run prod eval '${{ env.ELIXIR_MODULE }}.Release.create_repos()' | ||
docker compose run prod eval '${{ env.ELIXIR_MODULE }}.Release.migrate()' | ||
docker compose run prod eval '${{ env.ELIXIR_MODULE }}.Release.run_seeds()' | ||
- name: Run health check | ||
run: curl -v http://localhost:${{ env.APP_PORT }}/healthz/liveness | ||
# - name: Run API tests | ||
# env: | ||
# NEWMAN_ARGS: "--verbose -r cli,junitfull --reporter-junitfull-export /junit-reports/newman.xml -e ci.json" | ||
# # NEWMAN_ARGS: "--verbose -r cli,junit --reporter-junit-export /junit-reports/newman.xml -e ci.json" | ||
# # https://hub.docker.com/r/postman/newman/ | ||
# run: docker compose run newman run ${{env.NEWMAN_ARGS}} Queries.postman_collection.json | ||
- name: Display logs | ||
if: failure() | ||
run: | | ||
docker compose logs --timestamps prod | ||
# docker compose logs --timestamps newman | ||
- name: Publish unit test results to GitHub | ||
uses: EnricoMi/publish-unit-test-result-action@v2 | ||
# Run even if tests fail | ||
if: always() | ||
with: | ||
# Volume mounted from local filesystem into build | ||
junit_files: ./junit-reports/*.xml | ||
check_name: "External API Tests" | ||
scan: | ||
name: Security scan prod image | ||
needs: [build-prod] | ||
permissions: | ||
# Interact with GitHub OIDC Token endpoint for AWS | ||
id-token: write | ||
contents: read | ||
# Read from ghcr.io repository | ||
packages: read | ||
# Upload JUnit report files | ||
# https://github.com/EnricoMi/publish-unit-test-result-action#permissions | ||
checks: write | ||
pull-requests: write | ||
issues: read | ||
# Upload SARIF report files | ||
security-events: write | ||
runs-on: ubuntu-latest | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
os: [alpine, chiseled, debian, distroless, ubuntu] | ||
elixir: [1.15.5, 1.14.3] | ||
include: | ||
- os: alpine | ||
otp: 24.3.4.6 | ||
build_os_ver: '3.15.6' | ||
prod_os_ver: '3.15.6' | ||
- os: alpine | ||
otp: 25.2.3 | ||
build_os_ver: '3.17.0' | ||
prod_os_ver: '3.17.0' | ||
- os: chiseled | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 25.2.3 | ||
- os: debian | ||
build_os_ver: bullseye-20230612-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: 20230612 | ||
otp: 26.0.2 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230109-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230109' | ||
otp: 25.2.3 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 24.3.4.9 | ||
- os: debian | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '20230202' | ||
otp: 25.2.3 | ||
- os: distroless | ||
build_os_ver: bullseye-20230202-slim | ||
prod_os_ver: bullseye-slim | ||
snapshot_ver: '' | ||
otp: 25.2.3 | ||
- os: ubuntu | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 24.3.4.9 | ||
- os: ubuntu | ||
build_os_ver: jammy-20221130 | ||
prod_os_ver: jammy-20221130 | ||
otp: 25.2.3 | ||
env: | ||
DOCKER_FILE: deploy/${{ matrix.os }}.Dockerfile | ||
VAR: ${{ matrix.elixir }}-erlang-${{ matrix.otp }}-${{ matrix.os }}-${{ matrix.build_os_ver }} | ||
steps: | ||
- name: Log in to GHCR | ||
uses: docker/login-action@v2 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
- name: Pull image | ||
run: docker pull ghcr.io/${{env.IMAGE_OWNER}}/${{env.IMAGE_NAME}}:${{ env.VAR }}${{ env.IMAGE_VER }} | ||
- name: Scan image with Trivy | ||
uses: aquasecurity/trivy-action@master | ||
# https://github.com/aquasecurity/trivy-action | ||
# https://github.com/marketplace/actions/aqua-security-trivy#inputs | ||
with: | ||
image-ref: ghcr.io/${{env.IMAGE_OWNER}}/${{env.IMAGE_NAME}}:${{ env.VAR }}${{ env.IMAGE_VER }} | ||
# exit-code: '1' # fail build | ||
# ignore-unfixed: true | ||
# vuln-type: 'os,library' | ||
# severity: 'CRITICAL,HIGH' | ||
# cache-dir: /var/cache | ||
format: 'sarif' | ||
output: 'trivy.sarif' | ||
- name: Display scan results | ||
run: cat trivy.sarif | jq . | ||
- name: Upload Trivy scan results to GitHub Security tab | ||
if: ${{ env.GITHUB_ADVANCED_SECURITY == 1 }} | ||
uses: github/codeql-action/upload-sarif@v2 | ||
# Requires GitHub Advanced Security | ||
# https://docs.github.com/en/get-started/learning-about-github/about-github-advanced-security | ||
# https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning | ||
# https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github | ||
if: always() | ||
with: | ||
sarif_file: 'trivy.sarif' | ||
category: trivy | ||
- name: Scan image with Grype | ||
uses: anchore/scan-action@v3 | ||
# https://github.com/marketplace/actions/anchore-container-scan | ||
id: scan-grype | ||
with: | ||
image: ghcr.io/${{env.IMAGE_OWNER}}/${{env.IMAGE_NAME}}:${{ env.VAR }}${{ env.IMAGE_VER }} | ||
# severity-cutoff: critical | ||
fail-build: false | ||
output-format: 'sarif' | ||
# output-format: table | ||
- name: Display scan results | ||
run: cat ${{ steps.scan-grype.outputs.sarif }} | jq . | ||
- name: Upload Grype scan results to GitHub Security tab | ||
if: ${{ env.GITHUB_ADVANCED_SECURITY == 1 }} | ||
uses: github/codeql-action/upload-sarif@v2 | ||
if: always() | ||
with: | ||
sarif_file: ${{ steps.scan-grype.outputs.sarif }} | ||
category: grype | ||
# - name: Scan image with snyk | ||
# # if: github.event_name != 'pull_request' | ||
# uses: snyk/actions/docker@master | ||
# continue-on-error: true | ||
# env: | ||
# SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} | ||
# with: | ||
# command: test | ||
# image: ghcr.io/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_NAME }}:${{ env.VAR }}${{ env.IMAGE_VER }} | ||
# args: --file=${{ env.DOCKER_FILE }} --project-name=api | ||
prod: | ||
name: Push prod images | ||
if: github.event_name != 'pull_request' | ||
# if: contains(github.ref, 'refs/heads/main') | ||
needs: [build-prod, test-prod, test] | ||
permissions: | ||
# Interact with GitHub OIDC Token endpoint for AWS | ||
id-token: write | ||
contents: read | ||
# Push to ghcr.io repository | ||
packages: write | ||
# Upload JUnit report files | ||
# https://github.com/EnricoMi/publish-unit-test-result-action#permissions | ||
checks: write | ||
pull-requests: write | ||
issues: read | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Log in to GHCR | ||
uses: docker/login-action@v2 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
# - name: Tag GHCR release as latest | ||
# run: | | ||
# docker buildx imagetools create \ | ||
# --append ghcr.io/${{env.IMAGE_OWNER}}/${{env.IMAGE_NAME}}:${{env.PROD_VAR}}${{env.IMAGE_VER}} \ | ||
# --tag ghcr.io/${{env.IMAGE_OWNER}}/${{env.IMAGE_NAME}}:${{env.IMAGE_TAG}} | ||
- name: Log in to Docker Hub | ||
uses: docker/login-action@v2 | ||
with: | ||
username: ${{ secrets.DOCKERHUB_USERNAME }} | ||
password: ${{ secrets.DOCKERHUB_TOKEN }} | ||
- name: Check out source | ||
uses: actions/checkout@v3 | ||
- name: Set up Docker buildx | ||
id: buildx | ||
uses: docker/setup-buildx-action@v2 | ||
with: | ||
driver-opts: network=host | ||
# - name: Build final prod image and push to GHCR as latest | ||
# uses: docker/build-push-action@v3 | ||
# with: | ||
# file: ${{ env.DOCKER_FILE }} | ||
# target: prod | ||
# context: . | ||
# builder: ${{ steps.buildx.outputs.name }} | ||
# push: true | ||
# cache-from: type=gha,scope=${{ github.workflow }}-${{ env.PROD_VAR }} | ||
# cache-to: type=gha,scope=${{ github.workflow }}-${{ env.PROD_VAR }},mode=max | ||
# tags: | | ||
# ghcr.io/${{env.IMAGE_OWNER}}/${{env.IMAGE_NAME}}:${{ env.IMAGE_VER }} | ||
# ghcr.io/${{env.IMAGE_OWNER}}/${{env.IMAGE_NAME}}:${{ env.IMAGE_TAG }} | ||
- name: Build final prod image and push to Docker Hub | ||
if: ${{ env.DEPLOY_DOCKER_HUB == 1 }} | ||
uses: docker/build-push-action@v3 | ||
with: | ||
file: ${{ env.DOCKER_FILE }} | ||
target: prod | ||
context: . | ||
builder: ${{ steps.buildx.outputs.name }} | ||
push: true | ||
cache-from: type=gha,scope=${{ github.workflow }}-${{ env.PROD_VAR }} | ||
cache-to: type=gha,scope=${{ github.workflow }}-${{ env.PROD_VAR }},mode=max | ||
# ssh: default | ||
tags: | | ||
docker.io/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} | ||
docker.io/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_VER }} | ||
# secrets: | | ||
# "access_token=${{ secrets.DEVOPS_ACCESS_TOKEN }}" | ||
# "oban_key_fingerprint=${{ secrets.OBAN_KEY_FINGERPRINT }}" | ||
# "oban_license_key=${{ secrets.OBAN_LICENSE_KEY }}" | ||
- name: Configure AWS credentials | ||
if: env.AWS_ENABLED | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
with: | ||
role-to-assume: ${{ env.AWS_ROLE_TO_ASSUME }} | ||
aws-region: ${{ env.AWS_REGION }} | ||
- name: Log in to Amazon ECR | ||
if: ${{ env.AWS_ENABLED == 1 }} | ||
id: ecr-login | ||
uses: aws-actions/amazon-ecr-login@v1 | ||
- name: Set vars | ||
if: ${{ env.AWS_ENABLED == 1 }} | ||
run: echo "ECR_REGISTRY=${{ steps.ecr-login.outputs.registry }}" >> $GITHUB_ENV | ||
# - name: Log in to ECR | ||
# uses: docker/login-action@v2 | ||
# with: | ||
# registry: ${{ env.ECR_REGISTRY }} | ||
# username: ${{ secrets.AWS_ACCESS_KEY_ID }} | ||
# password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | ||
# - name: Tag ECR release as latest | ||
# if: ${{ env.AWS_ENABLED == 1 }} | ||
# run: | | ||
# export MANIFEST=$(aws ecr batch-get-image --repository-name "${{env.ECR_IMAGE_OWNER}}/${{env.IMAGE_NAME}}" \ | ||
# --image-ids imageTag=${{ env.IMAGE_VER }} --output json | jq --raw-output --join-output '.images[0].imageManifest') | ||
# aws ecr put-image --repository-name "${{env.ECR_IMAGE_OWNER}}/${{env.IMAGE_NAME}}" \ | ||
# --image-tag ${{ env.IMAGE_TAG }} --image-manifest "$MANIFEST" | ||
# aws ecr describe-images --repository-name "${{env.ECR_IMAGE_OWNER}}/${{env.IMAGE_NAME}}" | ||
- name: Build final prod image and push to AWS ECR | ||
if: ${{ env.AWS_ENABLED == 1 }} | ||
uses: docker/build-push-action@v3 | ||
env: | ||
REGISTRY: "${{ env.ECR_REGISTRY }}/" | ||
IMAGE_OWNER: "${{ env.ECR_IMAGE_OWNER }}/" | ||
VAR: ${{ env.PROD_VAR }} | ||
with: | ||
file: ${{ env.DOCKER_FILE }} | ||
target: prod | ||
context: . | ||
builder: ${{ steps.buildx.outputs.name }} | ||
push: true | ||
cache-from: type=gha,scope=${{ github.workflow }}-${{ env.PROD_VAR }} | ||
cache-to: type=gha,scope=${{ github.workflow }}-${{ env.PROD_VAR }},mode=max | ||
# ssh: default | ||
tags: | | ||
${{env.ECR_REGISTRY}}/${{env.ECR_IMAGE_OWNER}}/${{env.IMAGE_NAME}}:${{env.IMAGE_TAG}} | ||
${{env.ECR_REGISTRY}}/${{env.ECR_IMAGE_OWNER}}/${{env.IMAGE_NAME}}:${{env.IMAGE_VER}} | ||
# secrets: | | ||
# "access_token=${{ secrets.DEVOPS_ACCESS_TOKEN }}" | ||
# "oban_key_fingerprint=${{ secrets.OBAN_KEY_FINGERPRINT }}" | ||
# "oban_license_key=${{ secrets.OBAN_LICENSE_KEY }}" | ||
deploy: | ||
name: Deploy to ECS | ||
if: ${{ env.AWS_ENABLED == 1 }} | ||
needs: [prod] | ||
permissions: | ||
# Interact with GitHub OIDC Token endpoint for AWS | ||
id-token: write | ||
contents: read | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Configure AWS credentials | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
with: | ||
role-to-assume: ${{ env.AWS_ROLE_TO_ASSUME }} | ||
aws-region: ${{ env.AWS_REGION }} | ||
- name: Log in to Amazon ECR | ||
id: ecr-login | ||
uses: aws-actions/amazon-ecr-login@v1 | ||
- name: Set vars | ||
run: echo "ECR_REGISTRY=${{ steps.ecr-login.outputs.registry }}" >> $GITHUB_ENV | ||
- name: Check out source | ||
uses: actions/checkout@v3 | ||
# https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure-resources.html | ||
# - name: Generate CodeDeploy appspec.yml | ||
# env: | ||
# CONTAINER_NAME: "iot-app" | ||
# PORT: "4000" | ||
# run: sed -i -e "s!<NAME>!${CONTAINER_NAME}!g" -e "s!<PORT>!${PORT}!g" ecs/appspec.yml | ||
- name: Generate ECS task-defintion.json | ||
env: | ||
AWSLOGS_REGION: ${{ env.AWS_REGION }} | ||
TASK_ROLE_ARN: "arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/iot-app-20230922164312318900000004" | ||
EXECUTION_ROLE_ARN: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/iot-ecs-task-execution-role | ||
HOST: rubegoldberg.io | ||
run: jq --null-input -f ecs/task-definition.json.jq | tee ecs/task-definition.json | ||
- name: Put new image ID in ECS task definition | ||
id: task-def | ||
uses: aws-actions/amazon-ecs-render-task-definition@v1 | ||
with: | ||
task-definition: ${{ env.TASKDEF }} | ||
container-name: ${{ env.ECS_CONTAINER }} | ||
image: ${{env.ECR_REGISTRY}}/${{ env.ECR_IMAGE_OWNER }}/${{env.IMAGE_NAME}}:${{env.PROD_VAR}}${{env.IMAGE_VER}} | ||
- name: Deploy to Amazon ECS | ||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1 | ||
with: | ||
task-definition: ${{ steps.task-def.outputs.task-definition }} | ||
cluster: ${{ env.ECS_CLUSTER }} | ||
service: ${{ env.ECS_SERVICE }} | ||
wait-for-service-stability: true | ||
codedeploy-appspec: ecs/appspec.yml | ||
codedeploy-application: ${{ env.CODEDEPLOY_APPLICATION }} | ||
codedeploy-deployment-group: ${{ env.CODEDEPLOY_DEPLOYMENT_GROUP }} | ||
# https://github.com/marketplace/actions/slack-notify-build | ||
# https://github.com/marketplace/actions/post-slack-message |