Skip to content

Add Formation safety handoff guidance #878

Add Formation safety handoff guidance

Add Formation safety handoff guidance #878

Workflow file for this run

name: Deploy
on:
push:
branches: [main]
workflow_dispatch:
concurrency:
group: deploy
cancel-in-progress: true
env:
NODE_VERSION: "22"
APP_DOMAIN: ethosian.info
APP_DIR: /opt/ethos
SITE_DIR: /opt/ethos/site
VPS_HOST: deploy@77.42.30.181
VPS_IP: 77.42.30.181
SSH_OPTS: -i ~/.ssh/deploy_key -o BatchMode=yes -o StrictHostKeyChecking=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=6
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: web/package-lock.json
- name: Install dependencies
run: npm ci
working-directory: web
- name: Type-check and build static site
run: npm run typecheck && npm run build
working-directory: web
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.VPS_SSH_KEY }}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh-keyscan -H "${{ env.VPS_IP }}" >> ~/.ssh/known_hosts
- name: Bootstrap Caddy site
run: |
ssh ${{ env.SSH_OPTS }} ${{ env.VPS_HOST }} <<'REMOTE'
set -euo pipefail
sudo mkdir -p /opt/ethos/site /etc/caddy/sites
sudo chown -R deploy:deploy /opt/ethos
sudo chmod 755 /opt /opt/ethos /opt/ethos/site
cat <<'CADDY' | sudo tee /etc/caddy/sites/ethosian.info.caddy >/dev/null
www.ethosian.info {
redir https://ethosian.info{uri} permanent
}
ethosian.info {
encode zstd gzip
root * /opt/ethos/site
try_files {path} {path}/index.html {path}/
file_server
handle_errors {
rewrite * /404.html
file_server
}
}
CADDY
sudo caddy validate --config /etc/caddy/Caddyfile
REMOTE
- name: Deploy static assets
run: |
rsync -az --delete -e "ssh ${{ env.SSH_OPTS }}" \
web/dist/ ${{ env.VPS_HOST }}:${{ env.SITE_DIR }}/
- name: Reload Caddy
run: |
ssh ${{ env.SSH_OPTS }} ${{ env.VPS_HOST }} \
"sudo systemctl reload caddy && sudo systemctl is-active caddy"
- name: Verify deployed files
run: |
ssh ${{ env.SSH_OPTS }} ${{ env.VPS_HOST }} <<'REMOTE'
set -euo pipefail
test -f /opt/ethos/site/index.html
test -f /opt/ethos/site/books/index.html
test -f /opt/ethos/site/books/ethos/index.html
test -f /opt/ethos/site/books/ethos/chapters/foundation/index.html
test -f /opt/ethos/site/books/commons-framework/chapters/shared-world/index.html
test -f /opt/ethos/site/chapters/index.html
test -f /opt/ethos/site/chapters/foundation/index.html
test -f /opt/ethos/site/llms.txt
test -f /opt/ethos/site/404.html
REMOTE
- name: Verify public site
run: |
curl -fsSI --max-time 30 \
--resolve '${{ env.APP_DOMAIN }}:443:${{ env.VPS_IP }}' \
https://${{ env.APP_DOMAIN }}/
curl -fsSI --max-time 30 \
--resolve '${{ env.APP_DOMAIN }}:443:${{ env.VPS_IP }}' \
https://${{ env.APP_DOMAIN }}/chapters/
curl -fsSI --max-time 30 \
--resolve '${{ env.APP_DOMAIN }}:443:${{ env.VPS_IP }}' \
https://${{ env.APP_DOMAIN }}/chapters/foundation
curl -fsSI --max-time 30 \
--resolve '${{ env.APP_DOMAIN }}:443:${{ env.VPS_IP }}' \
https://${{ env.APP_DOMAIN }}/books/
curl -fsSI --max-time 30 \
--resolve '${{ env.APP_DOMAIN }}:443:${{ env.VPS_IP }}' \
https://${{ env.APP_DOMAIN }}/books/ethos/chapters/foundation
curl -fsSI --max-time 30 \
--resolve '${{ env.APP_DOMAIN }}:443:${{ env.VPS_IP }}' \
https://${{ env.APP_DOMAIN }}/books/commons-framework/chapters/shared-world
curl -fsSI --max-time 30 \
--resolve '${{ env.APP_DOMAIN }}:443:${{ env.VPS_IP }}' \
https://${{ env.APP_DOMAIN }}/llms.txt