.github/workflows/deploy-custom-env.yml
name: Build and deploy custom environment
on:
workflow_dispatch:
pull_request:
branches:
- main
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
branch_name: ${{ steps.check.outputs.branch_name }}
env_name: ${{ steps.prepare.outputs.env_name }}
api_image_tag: ${{ steps.prepare.outputs.api_image_tag }}
admin_image_tag: ${{ steps.prepare.outputs.admin_image_tag }}
app_image_tag: ${{ steps.prepare.outputs.app_image_tag }}
steps:
- name: Check branch name
id: check
run: |
if [[ ${{ github.event_name }} == 'pull_request' ]] ; then
branch_name=${{ github.head_ref }}
else
branch_name=${{ github.ref_name }}
fi
if [[ $branch_name == 'main' ]] || [[ $branch_name == 'production' ]] ; then
echo "This action is not available on the branch $branch_name"
exit 1
fi
echo "branch_name=$branch_name" >> $GITHUB_OUTPUT
- uses: actions/checkout@v4
with:
ref: ${{ steps.check.outputs.branch_name }}
fetch-depth: 0
- name: Prepare
id: prepare
run: |
env_name=$(.github/scripts/get_custom_env_name.sh ${{ steps.check.outputs.branch_name }})
echo "env_name: $env_name"
echo "env_name=$env_name" >> $GITHUB_OUTPUT
api_image_tag=$(git log --max-count=1 --oneline -- api packages package-lock.json | cut -d " " -f 1)
echo "api_image_tag: $api_image_tag"
echo "api_image_tag=$api_image_tag" >> $GITHUB_OUTPUT
admin_image_tag=$(git log --max-count=1 --oneline -- admin packages package-lock.json | cut -d " " -f 1)
echo "admin_image_tag: $admin_image_tag"
echo "admin_image_tag=$admin_image_tag" >> $GITHUB_OUTPUT
app_image_tag=$(git log --max-count=1 --oneline -- app packages package-lock.json | cut -d " " -f 1)
echo "app_image_tag: $app_image_tag"
echo "app_image_tag=$app_image_tag" >> $GITHUB_OUTPUT
run_tests_api:
needs: prepare
uses: ./.github/workflows/run-tests-api-pr.yml
with:
branch_name: ${{ needs.prepare.outputs.branch_name }}
secrets: inherit
run_tests_front:
needs: prepare
uses: ./.github/workflows/run-tests-front.yml
with:
branch_name: ${{ needs.prepare.outputs.branch_name }}
secrets: inherit
run_tests_lib:
needs: prepare
uses: ./.github/workflows/run-tests-lib.yml
with:
branch_name: ${{ needs.prepare.outputs.branch_name }}
secrets: inherit
build:
if: |
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' &&
!(contains(github.head_ref, '-no-ci-') ||
startsWith(github.head_ref, 'no-ci-') ||
endsWith(github.head_ref, 'no-ci') ||
contains(github.head_ref, '_no_ci_') ||
startsWith(github.head_ref, 'no_ci_') ||
endsWith(github.head_ref, '_no_ci'))
)
needs: prepare
runs-on: ubuntu-latest
strategy:
matrix:
app:
[
{
name: api,
path: api,
tag: "${{needs.prepare.outputs.api_image_tag}}",
},
{
name: app,
path: app,
tag: "${{needs.prepare.outputs.app_image_tag}}",
},
{
name: admin,
path: admin,
tag: "${{needs.prepare.outputs.admin_image_tag}}",
},
]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.prepare.outputs.branch_name }}
- name: Check if image exists
id: check
uses: ./.github/actions/check_docker_image_tag
with:
registry: ${{ secrets.SCW_CI_IMAGE_REGISTRY }}
image_name: ${{matrix.app.name}}
image_tag: ${{matrix.app.tag}}
secret_key: ${{ secrets.SCW_CI_DEPLOY_SECRET_KEY }}
- name: Docker Build & Publish
uses: ./.github/actions/build_docker_image
if: steps.check.outputs.tag_exists == 0
with:
username: nologin
password: ${{ secrets.SCW_CI_DEPLOY_SECRET_KEY }}
registry: ${{ secrets.SCW_CI_IMAGE_REGISTRY }}
image_name: ${{matrix.app.name}}
dockerfile_path: ${{matrix.app.path}}/Dockerfile
image_tag: ${{matrix.app.tag}}
sentry_auth_token: ${{ secrets.SENTRY_AUTH_TOKEN }}
deploy:
runs-on: ubuntu-latest
needs: [prepare, build]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }}
cancel-in-progress: false
env:
SCW_ACCESS_KEY: ${{ secrets.SCW_CI_DEPLOY_ACCESS_KEY }}
SCW_SECRET_KEY: ${{ secrets.SCW_CI_DEPLOY_SECRET_KEY }}
PG_CONN_STR: ${{ secrets.SCW_CI_BACKEND_CONN_STR }}
PGUSER: ${{ secrets.SCW_CI_BACKEND_USER }}
PGPASSWORD: ${{ secrets.SCW_CI_BACKEND_PASSWORD }}
custom_directory: ./devops/terraform/environments/ci/custom
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.prepare.outputs.branch_name }}
- uses: hashicorp/setup-terraform@v3
- name: Create custom env stack
working-directory: ${{ env.custom_directory }}
run: sed -i.bak "s|###___ENV_NAME___###|${{ needs.prepare.outputs.env_name }}|g" main.tf
# the -i option replaces main.tf in-place creating a .bak backup file
- name: Init terraform
working-directory: ${{ env.custom_directory }}
run: terraform init
- name: Validate terraform
working-directory: ${{ env.custom_directory }}
run: terraform validate -no-color
- name: Terraform plan
working-directory: ${{ env.custom_directory }}
# add -lock-timeout option until https://github.com/hashicorp/terraform/issues/33217 is fixed
run: |
terraform plan -no-color -input=false -lock-timeout=15m \
-var="api_image_tag=${{ needs.prepare.outputs.api_image_tag }}" \
-var="admin_image_tag=${{ needs.prepare.outputs.admin_image_tag }}" \
-var="app_image_tag=${{ needs.prepare.outputs.app_image_tag }}"
- name: Terraform auto-apply
working-directory: ${{ env.custom_directory }}
run: |
terraform apply -no-color -input=false -auto-approve -lock-timeout=15m \
-var="api_image_tag=${{ needs.prepare.outputs.api_image_tag }}" \
-var="admin_image_tag=${{ needs.prepare.outputs.admin_image_tag }}" \
-var="app_image_tag=${{ needs.prepare.outputs.app_image_tag }}"
- name: Add comment to PR
if: github.event_name == 'pull_request' && contains(fromJSON('["opened", "reopened"]'), github.event.action)
working-directory: ${{ env.custom_directory }}
env:
URL: ${{ github.event.pull_request.comments_url }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
api_endpoint=$(terraform output -raw api_endpoint)
app_endpoint=$(terraform output -raw app_endpoint)
admin_endpoint=$(terraform output -raw admin_endpoint)
curl \
-X POST \
$URL \
-H "Content-Type: application/json" \
-H "Authorization: token $GITHUB_TOKEN" \
--data "{ \"body\": \"Application endpoints :\n\n- $api_endpoint\n- $app_endpoint\n- $admin_endpoint\" }"
- name: Healthchecks
shell: bash
working-directory: ${{ env.custom_directory }}
run: |
# Sleep because status can still be an error if the previous deployement failed
sleep 10s
failure=false
while read name
do
status=$(terraform output -raw ${name}_container_status)
echo $name $status
if [[ $status != "ready" ]]
then
echo "Container ${name} is on '$status' state" 1>&2
failure=true
fi
done <<< 'app
admin
api'
if $failure
then
exit 1
fi