Skip to content

Backend React-dev deploy #46

Backend React-dev deploy

Backend React-dev deploy #46

# Roadmap: DEV-075
name: Backend React-dev deploy
on:
workflow_run:
workflows:
- Backend PostgreSQL CI
types:
- completed
branches:
- master
permissions:
contents: read
packages: write
concurrency:
group: backend-react-dev-deploy
cancel-in-progress: false
jobs:
deploy:
name: Deploy backend to React-dev
if: >-
${{
github.event.workflow_run.conclusion == 'success' &&
(
github.event.workflow_run.event == 'push' ||
github.event.workflow_run.event == 'workflow_dispatch'
) &&
github.event.workflow_run.head_branch == 'master' &&
github.event.workflow_run.head_repository.full_name == github.repository &&
github.event.workflow_run.head_sha != ''
}}
runs-on: ubuntu-latest
timeout-minutes: 30
env:
DEPLOY_SHA: ${{ github.event.workflow_run.head_sha }}
DEPLOY_RUN_ID: ${{ github.run_id }}
DEPLOY_IMAGE_TAG: >-
ghcr.io/procollab-github/api:react-dev-${{ github.event.workflow_run.head_sha }}
steps:
- name: Validate deploy source
shell: bash
run: |
set -Eeuo pipefail
if [[ ! "$DEPLOY_SHA" =~ ^[0-9a-f]{40}$ ]]; then
echo "Successful CI run did not provide a valid commit SHA." >&2
exit 1
fi
if [[ ! "$DEPLOY_RUN_ID" =~ ^[0-9]+$ ]]; then
echo "GitHub Actions run ID is invalid." >&2
exit 1
fi
if [[ ! "$DEPLOY_IMAGE_TAG" =~ ^ghcr\.io/procollab-github/api:react-dev-[0-9a-f]{40}$ ]]; then
echo "React-dev image tag is invalid." >&2
exit 1
fi
- name: Checkout tested commit
uses: actions/checkout@v4
with:
ref: ${{ github.event.workflow_run.head_sha }}
fetch-depth: 1
- name: Verify checked out commit
shell: bash
run: |
set -Eeuo pipefail
actual_sha="$(git rev-parse HEAD)"
if [[ "$actual_sha" != "$DEPLOY_SHA" ]]; then
echo "Checked out commit does not match the successful CI run." >&2
exit 1
fi
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and publish tested image
id: build
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
push: true
cache-from: type=gha,scope=backend-react-dev
cache-to: type=gha,mode=max,scope=backend-react-dev
tags: ${{ env.DEPLOY_IMAGE_TAG }}
labels: |
org.opencontainers.image.revision=${{ env.DEPLOY_SHA }}
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
- name: Pin published image by digest
shell: bash
env:
IMAGE_DIGEST: ${{ steps.build.outputs.digest }}
run: |
set -Eeuo pipefail
if [[ ! "$IMAGE_DIGEST" =~ ^sha256:[0-9a-f]{64}$ ]]; then
echo "Published image digest is invalid." >&2
exit 1
fi
deploy_image="ghcr.io/procollab-github/api@${IMAGE_DIGEST}"
echo "DEPLOY_IMAGE=${deploy_image}" >> "$GITHUB_ENV"
- name: Prepare pinned SSH configuration
shell: bash
env:
REACT_DEV_SSH_HOST: ${{ secrets.REACT_DEV_SSH_HOST }}
REACT_DEV_SSH_PORT: ${{ secrets.REACT_DEV_SSH_PORT }}
REACT_DEV_SSH_USER: ${{ secrets.REACT_DEV_SSH_USER }}
REACT_DEV_SSH_PRIVATE_KEY: ${{ secrets.REACT_DEV_SSH_PRIVATE_KEY }}
REACT_DEV_SSH_KNOWN_HOSTS: ${{ secrets.REACT_DEV_SSH_KNOWN_HOSTS }}
run: |
set -Eeuo pipefail
required_secrets=(
REACT_DEV_SSH_HOST
REACT_DEV_SSH_PORT
REACT_DEV_SSH_USER
REACT_DEV_SSH_PRIVATE_KEY
REACT_DEV_SSH_KNOWN_HOSTS
)
for secret_name in "${required_secrets[@]}"; do
if [[ -z "${!secret_name:-}" ]]; then
echo "Required GitHub Secret is empty: ${secret_name}" >&2
exit 1
fi
done
if [[ ! "$REACT_DEV_SSH_PORT" =~ ^[0-9]+$ ]] ||
((REACT_DEV_SSH_PORT < 1 || REACT_DEV_SSH_PORT > 65535)); then
echo "React-dev SSH port is invalid." >&2
exit 1
fi
if [[ ! "$REACT_DEV_SSH_USER" =~ ^[a-z_][a-z0-9_.-]*$ ]]; then
echo "React-dev SSH user is invalid." >&2
exit 1
fi
if [[ "$REACT_DEV_SSH_HOST" =~ [[:space:]] ]]; then
echo "React-dev SSH host is invalid." >&2
exit 1
fi
install -d -m 700 "$HOME/.ssh"
printf '%s\n' "$REACT_DEV_SSH_PRIVATE_KEY" |
tr -d '\r' > "$HOME/.ssh/react_dev_deploy_key"
printf '%s\n' "$REACT_DEV_SSH_KNOWN_HOSTS" |
tr -d '\r' > "$HOME/.ssh/react_dev_known_hosts"
chmod 600 \
"$HOME/.ssh/react_dev_deploy_key" \
"$HOME/.ssh/react_dev_known_hosts"
test -s "$HOME/.ssh/react_dev_deploy_key"
test -s "$HOME/.ssh/react_dev_known_hosts"
ssh-keygen -y -f "$HOME/.ssh/react_dev_deploy_key" >/dev/null
- name: Deploy tested commit to React-dev
shell: bash
env:
REACT_DEV_SSH_HOST: ${{ secrets.REACT_DEV_SSH_HOST }}
REACT_DEV_SSH_PORT: ${{ secrets.REACT_DEV_SSH_PORT }}
REACT_DEV_SSH_USER: ${{ secrets.REACT_DEV_SSH_USER }}
run: |
set -Eeuo pipefail
ssh_options=(
-i "$HOME/.ssh/react_dev_deploy_key"
-p "$REACT_DEV_SSH_PORT"
-o BatchMode=yes
-o IdentitiesOnly=yes
-o PasswordAuthentication=no
-o KbdInteractiveAuthentication=no
-o StrictHostKeyChecking=yes
-o UserKnownHostsFile="$HOME/.ssh/react_dev_known_hosts"
-o ConnectTimeout=10
-o ServerAliveInterval=15
-o ServerAliveCountMax=3
)
ssh "${ssh_options[@]}" \
-- "$REACT_DEV_SSH_USER@$REACT_DEV_SSH_HOST" \
"bash -s -- '$DEPLOY_SHA' '$DEPLOY_RUN_ID' '$DEPLOY_IMAGE'" \
< scripts/deploy_react_dev.sh