name: ๐Ÿท๏ธ Release on: release: types: - created - edited - published permissions: {} jobs: build: name: ๐Ÿ—๏ธ Build runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v5 - name: ๐Ÿ”— Log in to Docker Hub uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ vars.GHCR_USERNAME }} password: ${{ secrets.GHCR_TOKEN }} - id: build env: GHCR_REPO: openfront-prod GHCR_USERNAME: ${{ vars.GHCR_USERNAME }} RELEASE_BODY: ${{ github.event.release.body }} RELEASE_NAME: ${{ github.event.release.name }} RELEASE_TAG_NAME: ${{ github.event.release.tag_name }} ADDITIONAL_VERSION_TAG: ${{ github.event.action == 'published' && 'latest' || '' }} run: | set -euxo pipefail cat <> $GITHUB_STEP_SUMMARY Name: ${RELEASE_NAME} Tag: ${RELEASE_TAG_NAME} Changelog: ${RELEASE_BODY} EOF ./build.sh prod "${RELEASE_TAG_NAME}" "${RELEASE_NAME}" "${RELEASE_BODY}" /tmp/build-metadata.json IMAGE_ID=$(jq -r '."containerimage.digest"' /tmp/build-metadata.json) echo "IMAGE_ID=${IMAGE_ID}" >> $GITHUB_OUTPUT echo "Image ID: \`${IMAGE_ID}\`" >> $GITHUB_STEP_SUMMARY outputs: IMAGE_ID: ${{ steps.build.outputs.IMAGE_ID }} deploy-alpha: name: ๐Ÿงช Deploy to alpha runs-on: ubuntu-latest timeout-minutes: 30 needs: [build] steps: - uses: actions/checkout@v5 - name: ๐Ÿ”‘ Create SSH private key env: SERVER_HOST_STAGING: ${{ secrets.SERVER_HOST_STAGING }} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} run: | set -euxo pipefail mkdir -p ~/.ssh echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa test -n "$SERVER_HOST_STAGING" && ssh-keyscan -H "$SERVER_HOST_STAGING" >> ~/.ssh/known_hosts chmod 600 ~/.ssh/id_rsa - name: ๐Ÿš€ Deploy image env: GHCR_REPO: openfront-prod GHCR_USERNAME: ${{ vars.GHCR_USERNAME }} DOMAIN: ${{ vars.DOMAIN }} IMAGE_ID: ${{ needs.build.outputs.IMAGE_ID }} OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }} OTEL_AUTH_HEADER: ${{ secrets.OTEL_AUTH_HEADER }} TURNSTILE_SECRET_KEY: ${{ secrets.TURNSTILE_SECRET_KEY }} API_KEY: ${{ secrets.API_KEY }} SERVER_HOST_STAGING: ${{ secrets.SERVER_HOST_STAGING }} SSH_KEY: ~/.ssh/id_rsa run: | set -euxo pipefail bash -x ./deploy.sh staging staging "${IMAGE_ID}" alpha - name: โณ Wait for deployment to start env: FQDN: alpha.${{ vars.DOMAIN }} API_KEY: ${{ secrets.API_KEY }} run: | echo "::group::Wait for deployment to start" set -euxo pipefail while [ "$(curl -s -H "X-API-Key: ${API_KEY}" https://${FQDN}/commit.txt)" != "${GITHUB_SHA}" ]; do if [ "$SECONDS" -ge 300 ]; then echo "Timeout: deployment did not start within 5 minutes" exit 1 fi sleep 10 done echo "Deployment started in ${SECONDS} seconds" >> $GITHUB_STEP_SUMMARY echo "::endgroup::" deploy-beta: name: ๐Ÿž Deploy to beta runs-on: ubuntu-latest needs: [build, deploy-alpha] timeout-minutes: 30 environment: prod-beta steps: - uses: actions/checkout@v5 - name: ๐Ÿ”‘ Create SSH private key env: SERVER_HOST_FALK2: ${{ secrets.SERVER_HOST_FALK2 }} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} run: | set -euxo pipefail mkdir -p ~/.ssh echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa test -n "$SERVER_HOST_FALK2" && ssh-keyscan -H "$SERVER_HOST_FALK2" >> ~/.ssh/known_hosts chmod 600 ~/.ssh/id_rsa - name: ๐Ÿš€ Deploy image env: GHCR_REPO: ${{ vars.GHCR_REPO }} GHCR_USERNAME: ${{ vars.GHCR_USERNAME }} DOMAIN: ${{ vars.DOMAIN }} IMAGE_ID: ${{ needs.build.outputs.IMAGE_ID }} OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }} OTEL_AUTH_HEADER: ${{ secrets.OTEL_AUTH_HEADER }} TURNSTILE_SECRET_KEY: ${{ secrets.TURNSTILE_SECRET_KEY }} API_KEY: ${{ secrets.API_KEY }} SERVER_HOST_FALK2: ${{ secrets.SERVER_HOST_FALK2 }} SSH_KEY: ~/.ssh/id_rsa run: | set -euxo pipefail ./deploy.sh prod falk2 "${IMAGE_ID}" beta - name: โณ Wait for deployment to start env: FQDN: beta.${{ vars.DOMAIN }} API_KEY: ${{ secrets.API_KEY }} run: | echo "::group::Wait for deployment to start" set -euxo pipefail while [ "$(curl -s -H "X-API-Key: ${API_KEY}" https://${FQDN}/commit.txt)" != "${GITHUB_SHA}" ]; do if [ "$SECONDS" -ge 300 ]; then echo "Timeout: deployment did not start within 5 minutes" exit 1 fi sleep 10 done echo "Deployment started in ${SECONDS} seconds" >> $GITHUB_STEP_SUMMARY echo "::endgroup::" deploy-blue: name: ๐Ÿ”ต Deploy to blue runs-on: ubuntu-latest needs: [build, deploy-alpha] timeout-minutes: 30 environment: prod-blue steps: - uses: actions/checkout@v5 - name: ๐Ÿ”‘ Create SSH private key env: SERVER_HOST_FALK2: ${{ secrets.SERVER_HOST_FALK2 }} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} run: | set -euxo pipefail mkdir -p ~/.ssh echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa test -n "$SERVER_HOST_FALK2" && ssh-keyscan -H "$SERVER_HOST_FALK2" >> ~/.ssh/known_hosts chmod 600 ~/.ssh/id_rsa - name: ๐Ÿš€ Deploy image env: GHCR_REPO: ${{ vars.GHCR_REPO }} GHCR_USERNAME: ${{ vars.GHCR_USERNAME }} DOMAIN: ${{ vars.DOMAIN }} IMAGE_ID: ${{ needs.build.outputs.IMAGE_ID }} OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }} OTEL_AUTH_HEADER: ${{ secrets.OTEL_AUTH_HEADER }} TURNSTILE_SECRET_KEY: ${{ secrets.TURNSTILE_SECRET_KEY }} API_KEY: ${{ secrets.API_KEY }} SERVER_HOST_FALK2: ${{ secrets.SERVER_HOST_FALK2 }} SSH_KEY: ~/.ssh/id_rsa run: | set -euxo pipefail ./deploy.sh prod falk2 "${IMAGE_ID}" blue - name: โณ Wait for deployment to start env: FQDN: blue.${{ vars.DOMAIN }} API_KEY: ${{ secrets.API_KEY }} run: | echo "::group::Wait for deployment to start" set -euxo pipefail while [ "$(curl -s -H "X-API-Key: ${API_KEY}" https://${FQDN}/commit.txt)" != "${GITHUB_SHA}" ]; do if [ "$SECONDS" -ge 300 ]; then echo "Timeout: deployment did not start within 5 minutes" exit 1 fi sleep 10 done echo "Deployment started in ${SECONDS} seconds" >> $GITHUB_STEP_SUMMARY echo "::endgroup::" deploy-green: name: ๐ŸŸข Deploy to green runs-on: ubuntu-latest needs: [build, deploy-alpha] timeout-minutes: 30 environment: prod-green steps: - uses: actions/checkout@v5 - name: ๐Ÿ”‘ Create SSH private key env: SERVER_HOST_FALK2: ${{ secrets.SERVER_HOST_FALK2 }} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} run: | set -euxo pipefail mkdir -p ~/.ssh echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa test -n "$SERVER_HOST_FALK2" && ssh-keyscan -H "$SERVER_HOST_FALK2" >> ~/.ssh/known_hosts chmod 600 ~/.ssh/id_rsa - name: ๐Ÿš€ Deploy image env: GHCR_REPO: ${{ vars.GHCR_REPO }} GHCR_USERNAME: ${{ vars.GHCR_USERNAME }} DOMAIN: ${{ vars.DOMAIN }} IMAGE_ID: ${{ needs.build.outputs.IMAGE_ID }} OTEL_EXPORTER_OTLP_ENDPOINT: ${{ secrets.OTEL_EXPORTER_OTLP_ENDPOINT }} OTEL_AUTH_HEADER: ${{ secrets.OTEL_AUTH_HEADER }} TURNSTILE_SECRET_KEY: ${{ secrets.TURNSTILE_SECRET_KEY }} API_KEY: ${{ secrets.API_KEY }} SERVER_HOST_FALK2: ${{ secrets.SERVER_HOST_FALK2 }} SSH_KEY: ~/.ssh/id_rsa run: | set -euxo pipefail ./deploy.sh prod falk2 "${IMAGE_ID}" green - name: โณ Wait for deployment to start env: FQDN: green.${{ vars.DOMAIN }} API_KEY: ${{ secrets.API_KEY }} run: | echo "::group::Wait for deployment to start" set -euxo pipefail while [ "$(curl -s -H "X-API-Key: ${API_KEY}" https://${FQDN}/commit.txt)" != "${GITHUB_SHA}" ]; do if [ "$SECONDS" -ge 300 ]; then echo "Timeout: deployment did not start within 5 minutes" exit 1 fi sleep 10 done echo "Deployment started in ${SECONDS} seconds" >> $GITHUB_STEP_SUMMARY echo "::endgroup::"