Files
pezkuwi-apps/.github/workflows/push-main.yml
T
Satoshi Qazi MuhammedandClaude Opus 5.5 570586bae3 Deploy apps.pezkuwichain.io from main behind an approval
push-main.yml now builds build:www on every push to main and, once the
production environment is approved, copies it to the web host and switches
to it. The host keeps releases side by side and serves a 'current' symlink,
so going live is one rename and rollback is a dispatch with an earlier sha.
.github/deploy/release.sh checks the switch through nginx for the public
name and restores the previous release if the new one is not served.

Ships env-config.js, which index.html loads: on a static host the request
fell through to index.html and the browser ran HTML as a script.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 04:33:58 +04:00

82 lines
2.6 KiB
YAML

name: Main
on:
push:
branches:
- main
workflow_dispatch:
inputs:
rollback_to:
description: 'Make an earlier release live again (full commit sha); empty = deploy this commit'
required: false
default: ''
# Deploys wait for each other; a newer push queues behind a running one.
concurrency:
group: deploy-apps
cancel-in-progress: false
permissions:
contents: read
jobs:
build:
if: github.event.inputs.rollback_to == ''
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- name: build:www
env:
NODE_OPTIONS: --max-old-space-size=6144
run: |
yarn install --immutable
yarn build:www
echo "$GITHUB_SHA" > packages/apps/build/.deploy-sha
tar -C packages/apps/build -czf apps-www.tgz .
- uses: actions/upload-artifact@v4
with:
name: apps-www
path: apps-www.tgz
retention-days: 7
# The only job that names the environment, so a run asks for approval once,
# and the deploy secrets (environment-scoped) exist only after it is given.
deploy:
needs: build
if: always() && (needs.build.result == 'success' || (needs.build.result == 'skipped' && github.event.inputs.rollback_to != ''))
runs-on: ubuntu-latest
environment: production
env:
HOST: ${{ secrets.APPS_DEPLOY_HOST }}
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: .github/deploy
- name: ssh setup
env:
KEY: ${{ secrets.APPS_DEPLOY_SSH_KEY }}
KNOWN_HOSTS: ${{ secrets.APPS_DEPLOY_KNOWN_HOSTS }}
run: |
install -m 700 -d ~/.ssh
printf '%s\n' "$KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
printf '%s\n' "$KNOWN_HOSTS" > ~/.ssh/known_hosts
- uses: actions/download-artifact@v4
if: github.event.inputs.rollback_to == ''
with:
name: apps-www
- name: upload
if: github.event.inputs.rollback_to == ''
run: scp -o BatchMode=yes apps-www.tgz "apps-deploy@$HOST:/var/www/apps-deploy/incoming/$GITHUB_SHA.tgz"
- name: go live
env:
ROLLBACK_TO: ${{ github.event.inputs.rollback_to }}
run: |
if [ -n "$ROLLBACK_TO" ]; then set -- rollback "$ROLLBACK_TO"; else set -- deploy "$GITHUB_SHA"; fi
# ssh hands its arguments to the remote shell as one string: only a
# bare sha may get there.
[[ $2 =~ ^[0-9a-f]{40}$ ]] || { echo "not a full commit sha: $2"; exit 1; }
ssh -o BatchMode=yes "apps-deploy@$HOST" bash -s -- "$@" < .github/deploy/release.sh