Files
marketplaces/.github/workflows/deploy.yml
sdarbinyan 03c750cae7
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
ci: target emergency deploy runner
2026-08-20 14:45:40 +04:00

137 lines
4.8 KiB
YAML

name: Deploy Frontend
# Multi-tenant: one bundle serves every customer domain, so a single deploy
# updates all of them at once. There is no per-tenant build or per-tenant deploy.
on:
push:
branches:
- main
workflow_dispatch:
inputs:
ref:
description: Branch or SHA to deploy
required: false
default: main
concurrency:
group: deploy-frontend
cancel-in-progress: false # never abandon a half-finished release swap
jobs:
deploy:
runs-on: urgent-deploy
environment: production
defaults:
run:
shell: bash
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.ref || github.ref }}
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci
- name: Enforce boundaries
run: npm run arch:check
- name: Build
run: npm run build -- --configuration production
- name: Resolve build output
id: dist
run: |
set -euo pipefail
# @angular/build:application emits into dist/<name>/browser.
# Fall back to the flat layout so this survives a builder change.
if [ -d dist/dexarmarket/browser ]; then
DIR=dist/dexarmarket/browser
elif [ -f dist/dexarmarket/index.html ]; then
DIR=dist/dexarmarket
else
echo "no build output found under dist/dexarmarket" >&2
ls -R dist || true
exit 1
fi
test -f "$DIR/index.html" || { echo "$DIR has no index.html" >&2; exit 1; }
echo "dir=$DIR" >> "$GITHUB_OUTPUT"
echo "Deploying from $DIR ($(find "$DIR" -type f | wc -l) files)"
- name: Configure SSH
env:
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
DEPLOY_KNOWN_HOSTS: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
run: |
set -euo pipefail
test -n "$DEPLOY_SSH_KEY" || { echo "secret DEPLOY_SSH_KEY is empty" >&2; exit 1; }
test -n "$DEPLOY_KNOWN_HOSTS" || { echo "secret DEPLOY_KNOWN_HOSTS is empty" >&2; exit 1; }
mkdir -p ~/.ssh
printf '%s\n' "$DEPLOY_SSH_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
# Pinned host key, so a MITM or a rebuilt server fails the deploy
# instead of being trusted silently.
printf '%s\n' "$DEPLOY_KNOWN_HOSTS" > ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: Upload release
env:
HOST: ${{ secrets.DEPLOY_HOST }}
USER: ${{ secrets.DEPLOY_USER }}
SRC: ${{ steps.dist.outputs.dir }}
run: |
set -euo pipefail
RELEASE="${GITHUB_SHA::12}"
echo "RELEASE=$RELEASE" >> "$GITHUB_ENV"
SSH="ssh -i ~/.ssh/deploy_key -o BatchMode=yes"
$SSH "$USER@$HOST" "mkdir -p /srv/marketplaces/releases/$RELEASE/frontend"
tar -C "$SRC" -czf - . | $SSH "$USER@$HOST" \
"tar -xzf - -C /srv/marketplaces/releases/$RELEASE/frontend"
- name: Activate release
env:
HOST: ${{ secrets.DEPLOY_HOST }}
USER: ${{ secrets.DEPLOY_USER }}
run: |
set -euo pipefail
ssh -i ~/.ssh/deploy_key -o BatchMode=yes "$USER@$HOST" bash -euo pipefail <<EOSSH
BASE=/srv/marketplaces
REL="\$BASE/releases/$RELEASE"
test -f "\$REL/frontend/index.html" || { echo "upload incomplete, refusing to swap" >&2; exit 1; }
# ln -T onto a temp name then mv: the swap is atomic, so no request
# is ever served from a half-updated root.
ln -sfnT "\$REL" "\$BASE/current.new"
mv -Tf "\$BASE/current.new" "\$BASE/current"
sudo /bin/systemctl reload nginx
# Keep the last 5 releases so a rollback is a symlink change.
ls -1dt "\$BASE"/releases/*/ | tail -n +6 | xargs -r rm -rf
echo "active: \$(readlink -f \$BASE/current)"
EOSSH
- name: Verify
env:
HOST: ${{ secrets.DEPLOY_HOST }}
USER: ${{ secrets.DEPLOY_USER }}
run: |
set -euo pipefail
ssh -i ~/.ssh/deploy_key -o BatchMode=yes "$USER@$HOST" \
'curl -fsS -o /dev/null -w "health=%{http_code}\n" http://127.0.0.1/health &&
curl -fsS -o /dev/null -w "index=%{http_code}\n" http://127.0.0.1/'
- name: Report
if: always()
run: |
if [ "${{ job.status }}" = "success" ]; then
echo "Deployed ${GITHUB_SHA::12} to ${{ secrets.DEPLOY_HOST }}" >> "$GITHUB_STEP_SUMMARY"
else
echo "Deploy of ${GITHUB_SHA::12} FAILED. The previous release is still active — the symlink only moves after a successful upload." >> "$GITHUB_STEP_SUMMARY"
fi