diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 141a677c..9f07668f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,36 +1,41 @@ name: CI -# Botsmann is deployed self-hosted on the Hetzner box "bitbaum" behind Caddy. -# Deployment runs from the local `.husky/pre-push` hook (build -> rsync -> systemd -# restart) when main is pushed. This workflow only validates build/lint/tests. +# The verification that used to live inside the Vercel deploy workflow. It +# belongs in its own file: prod is self-hosted on bitbaum, so the deploy +# workflow is now a shim over the shared pipeline — and that pipeline refuses +# to ship a commit whose CI is not green. Without this file there would be no +# CI to be green, and every deploy would sail through unverified. on: push: branches: [main] pull_request: - branches: [main] + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true jobs: - build-and-test: + verify: + name: Format, lint, test, build runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: '22' - cache: 'npm' - - - name: Install dependencies - run: npm ci - - # Single SSOT gate: format:check + lint + test + build. - # Runs verbatim what developers run locally via `npm run verify`. - # No --if-present: a missing/renamed gate script fails loudly. - - name: Verify (format + lint + test + build) - run: npm run verify - env: - NEXT_PUBLIC_DEPLOY_TIME: ${{ github.event.head_commit.timestamp }} + cache: npm + + - run: npm ci + + - name: Format check + run: npm run format:check --if-present + + - name: Lint + run: npm run lint --if-present + + - name: Test + run: npm run test --if-present + + - name: Build + run: npm run build diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 00000000..d1e57883 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,22 @@ +name: Deploy + +# Push to main → deploy botsmann.orangecat.ch to bitbaum. All the logic lives in +# one place: maonakamoto/fleetcrown/.github/workflows/selfhost-deploy.yml (docs: +# docs/infrastructure/self-host-cd.md there). It waits for this commit's own CI +# to go green before anything reaches the box. +# +# Replaces a Vercel deploy workflow: this app has been served from bitbaum +# behind Caddy for months, so those deploys were shipping to somewhere nobody +# looks while the real production build only ever changed by hand. + +on: + push: + branches: [main] + +jobs: + deploy: + uses: maonakamoto/fleetcrown/.github/workflows/selfhost-deploy.yml@main + with: + app: botsmann + node-version: '22' + secrets: inherit diff --git a/.husky/pre-push b/.husky/pre-push index 27673f50..44970cc2 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,8 +1,22 @@ #!/usr/bin/env sh # >>> fleetcrown push-deploy >>> -# Pushing main deploys to the Hetzner box (background; see /tmp/push-deploy-botsmann.log) -if git symbolic-ref --short HEAD 2>/dev/null | grep -qx main; then - ( sleep 5 && env -u CI -u VERCEL bash /home/g/dev/fleetcrown/scripts/hetzner/deploy.sh botsmann ) >> /tmp/push-deploy-botsmann.log 2>&1 & disown 2>/dev/null || true - echo "[push-deploy] botsmann: deploy started in background → /tmp/push-deploy-botsmann.log" +# Pushing the repo's default branch deploys to the Hetzner box +# (background; see /tmp/push-deploy-botsmann.log). Repos differ: some use +# 'main', some still use 'master' — match either so push-to-deploy fires +# regardless of the repo's branch convention. +# CI GATE: the background deploy first waits for GitHub CI on the pushed +# commit and is BLOCKED on a red — prod only receives what CI verified +# (ci-gate.sh; repos without CI pass after a short grace window). +if git symbolic-ref --short HEAD 2>/dev/null | grep -qxE 'main|master'; then + ( sleep 5 + _sha=$(git rev-parse HEAD) + _nwo=$(git remote get-url origin 2>/dev/null | sed -E 's#(git@github.com:|https://github.com/)##; s#\.git$##') + if [ -n "$_nwo" ] && ! bash "/home/g/dev/fleetcrown/scripts/hetzner/ci-gate.sh" "$_nwo" "$_sha"; then + echo "[push-deploy] botsmann: BLOCKED by CI gate for ${_sha} — fix CI, then re-push or deploy manually" + else + env -u CI bash /home/g/dev/fleetcrown/scripts/hetzner/deploy.sh botsmann + fi + ) >> /tmp/push-deploy-botsmann.log 2>&1 & disown 2>/dev/null || true + echo "[push-deploy] botsmann: CI-gated deploy started in background → /tmp/push-deploy-botsmann.log" fi # <<< fleetcrown push-deploy <<<