mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 23:53:05 +00:00
Job deploy em ci.yml (runs-on host na workstation) streama scripts/deploy-homeserver.sh para o homeserver via SSH: build dos stages runner+migrator com secrets do teqo-1313.env, push no registry local, migrate pelo serviço de maintenance antes do rollout, up + smoke. Zero secrets novos no Forgejo; HEAD guard + flock; rollback automático com backup do compose; runbook docs/ops/teqo-1313-deploy.md; invariantes unit do script (bash -n + estrutura).
228 lines
8.7 KiB
YAML
228 lines
8.7 KiB
YAML
# Post-merge verifier on `main`: always the FULL suite (no affected skips).
|
||
# When the suite is green, the `deploy` job publishes teqo-1313 on the
|
||
# homeserver (OPS53): it streams scripts/deploy-homeserver.sh to the homeserver
|
||
# over SSH; the remote script builds the standalone image at the pushed SHA,
|
||
# pushes it to the local registry (localhost:5000), applies pending migrations
|
||
# through the compose maintenance service and rolls the container out.
|
||
#
|
||
# Forgejo port (OPS50): Postgres services publish to per-job HOST ports on the
|
||
# runner machine (act/forgejo runner semantics — the canonical 5432 is the
|
||
# workstation's own dev database), and jobs reach them through the bridge
|
||
# gateway: DB_HOST = gateway IP from /proc/net/route. No `permissions:`
|
||
# (Forgejo issues one native GITHUB_TOKEN) and no `concurrency:` (unsupported).
|
||
# `gh workflow run` requeues became `node scripts/forgejo-dispatch.mjs`.
|
||
# The GitHub fail-fast action was dropped (Forgejo has no cancel-run plumbing);
|
||
# job timeouts cover that role.
|
||
|
||
name: CI
|
||
|
||
on:
|
||
push:
|
||
branches: [main]
|
||
workflow_dispatch:
|
||
|
||
env:
|
||
PAYLOAD_SECRET: test-only-secret-not-used-in-production
|
||
NEXT_PUBLIC_SITE_URL: http://localhost:3000
|
||
|
||
jobs:
|
||
static:
|
||
runs-on: ubuntu-latest
|
||
timeout-minutes: 20
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
- uses: pnpm/action-setup@v6
|
||
- uses: actions/setup-node@v5
|
||
with:
|
||
node-version: 24
|
||
cache: pnpm
|
||
- run: pnpm install --frozen-lockfile
|
||
- run: node scripts/check-test-locations.mjs
|
||
- run: pnpm lint
|
||
- run: pnpm format:check
|
||
- run: pnpm typecheck
|
||
- run: pnpm knip
|
||
- run: pnpm check:cycles
|
||
- run: pnpm test:unit
|
||
|
||
int:
|
||
runs-on: ubuntu-latest
|
||
timeout-minutes: 25
|
||
env:
|
||
# Self-hosted runner has 8 CPUs; vitest forks ≈ CPUs and each fork holds
|
||
# a Payload pool (max 10) → overflows the service Postgres' 100 clients
|
||
# ("too many clients already"). 4 forks stay well under. GitHub's 2–4
|
||
# vCPU runners keep the CPU-relative default (no env).
|
||
VITEST_MAX_WORKERS: 4
|
||
services:
|
||
postgres:
|
||
image: postgres:17-alpine
|
||
env:
|
||
POSTGRES_USER: teqo
|
||
POSTGRES_PASSWORD: teqo
|
||
POSTGRES_DB: teqo_test
|
||
ports:
|
||
- 5433:5432
|
||
options: >-
|
||
--health-cmd "pg_isready -U teqo"
|
||
--health-interval 5s
|
||
--health-timeout 5s
|
||
--health-retries 12
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
- uses: pnpm/action-setup@v6
|
||
- uses: actions/setup-node@v5
|
||
with:
|
||
node-version: 24
|
||
cache: pnpm
|
||
- run: pnpm install --frozen-lockfile
|
||
- name: Prepare database URL (service via bridge gateway)
|
||
run: |
|
||
set -euo pipefail
|
||
DB_HOST=$(awk '$2 == "00000000" {a=$3; print strtonum("0x" substr(a,7,2)) "." strtonum("0x" substr(a,5,2)) "." strtonum("0x" substr(a,3,2)) "." strtonum("0x" substr(a,1,2)); exit}' /proc/net/route)
|
||
echo "DATABASE_URL=postgresql://teqo:teqo@${DB_HOST}:5433/teqo_test" >> "$GITHUB_ENV"
|
||
# vitest re-loads .env.test over the process env, so the service URL
|
||
# must win through the .env.test.local layer (same mechanism
|
||
# `pnpm worktree next` uses). OPS50.
|
||
echo "DATABASE_URL=postgresql://teqo:teqo@${DB_HOST}:5433/teqo_test" > .env.test.local
|
||
- run: pnpm migrate
|
||
- run: pnpm db:seed:minimal
|
||
- run: pnpm test:int
|
||
|
||
build:
|
||
runs-on: ubuntu-latest
|
||
timeout-minutes: 25
|
||
services:
|
||
postgres:
|
||
image: postgres:17-alpine
|
||
env:
|
||
POSTGRES_USER: teqo
|
||
POSTGRES_PASSWORD: teqo
|
||
POSTGRES_DB: teqo_test
|
||
ports:
|
||
- 5434:5432
|
||
options: >-
|
||
--health-cmd "pg_isready -U teqo"
|
||
--health-interval 5s
|
||
--health-timeout 5s
|
||
--health-retries 12
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
- uses: pnpm/action-setup@v6
|
||
- uses: actions/setup-node@v5
|
||
with:
|
||
node-version: 24
|
||
cache: pnpm
|
||
- run: pnpm install --frozen-lockfile
|
||
- name: Prepare database URL (service via bridge gateway)
|
||
run: |
|
||
set -euo pipefail
|
||
DB_HOST=$(awk '$2 == "00000000" {a=$3; print strtonum("0x" substr(a,7,2)) "." strtonum("0x" substr(a,5,2)) "." strtonum("0x" substr(a,3,2)) "." strtonum("0x" substr(a,1,2)); exit}' /proc/net/route)
|
||
echo "DATABASE_URL=postgresql://teqo:teqo@${DB_HOST}:5434/teqo_test" >> "$GITHUB_ENV"
|
||
- name: Build (against the service database)
|
||
run: pnpm build
|
||
|
||
e2e:
|
||
runs-on: ubuntu-latest
|
||
timeout-minutes: 40
|
||
# Main always runs the full suite: split it across 2 jobs (OPS34), each
|
||
# building its own `.next-e2e` (measured 2026-08-10: build 172s + tests
|
||
# 196s + ~54s fixed → ≈ 5.5 min per shard vs 435s serial). `fail-fast:
|
||
# false` so one shard's failure keeps the other's diagnostics. Keep the
|
||
# [1, 2] / 2 literal in sync with `e2eShardConfig` in
|
||
# scripts/lib/test-affected-core.mjs (ci-pr pins the same literal).
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
shard: [1, 2]
|
||
env:
|
||
# Explicit CI workers; the local default stays 2 (playwright.config.ts).
|
||
PLAYWRIGHT_WORKERS: 2
|
||
services:
|
||
postgres:
|
||
image: postgres:17-alpine
|
||
env:
|
||
POSTGRES_USER: teqo
|
||
POSTGRES_PASSWORD: teqo
|
||
POSTGRES_DB: teqo_test
|
||
ports:
|
||
- ${{ matrix.shard == 1 && '5435' || '5436' }}:5432
|
||
options: >-
|
||
--health-cmd "pg_isready -U teqo"
|
||
--health-interval 5s
|
||
--health-timeout 5s
|
||
--health-retries 12
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
- uses: pnpm/action-setup@v6
|
||
- uses: actions/setup-node@v5
|
||
with:
|
||
node-version: 24
|
||
cache: pnpm
|
||
- run: pnpm install --frozen-lockfile
|
||
- name: Cache Playwright browsers
|
||
uses: actions/cache@v4
|
||
with:
|
||
path: ~/.cache/ms-playwright
|
||
key: playwright-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
||
restore-keys: |
|
||
playwright-${{ runner.os }}-
|
||
- name: Install Playwright chromium
|
||
run: pnpm exec playwright install --with-deps chromium
|
||
- name: Prepare database URL (service via bridge gateway)
|
||
run: |
|
||
set -euo pipefail
|
||
DB_HOST=$(awk '$2 == "00000000" {a=$3; print strtonum("0x" substr(a,7,2)) "." strtonum("0x" substr(a,5,2)) "." strtonum("0x" substr(a,3,2)) "." strtonum("0x" substr(a,1,2)); exit}' /proc/net/route)
|
||
DB_PORT=${{ matrix.shard == 1 && '5435' || '5436' }}
|
||
echo "DATABASE_URL=postgresql://teqo:teqo@${DB_HOST}:${DB_PORT}/teqo_test" >> "$GITHUB_ENV"
|
||
# playwright re-loads .env.test over the process env, so the service
|
||
# URL must win through the .env.test.local layer (same mechanism
|
||
# `pnpm worktree next` uses). OPS50.
|
||
echo "DATABASE_URL=postgresql://teqo:teqo@${DB_HOST}:${DB_PORT}/teqo_test" > .env.test.local
|
||
- run: pnpm migrate
|
||
- run: pnpm db:seed:minimal
|
||
- name: Build for e2e
|
||
run: pnpm build
|
||
env:
|
||
# Same dir the Playwright webServer serves (playwright.config.ts
|
||
# falls back to '.next-e2e'; gate-ci.mjs builds there too).
|
||
NEXT_DIST_DIR: .next-e2e
|
||
- name: E2E tests (full suite, shard ${{ matrix.shard }})
|
||
# No `--` separator: pnpm would forward it verbatim to playwright and
|
||
# the flag would be parsed as a file pattern ("No tests found").
|
||
run: pnpm test:e2e --shard=${{ matrix.shard }}/2
|
||
|
||
checks:
|
||
name: checks
|
||
runs-on: ubuntu-latest
|
||
needs: [static, int, build, e2e]
|
||
if: always()
|
||
steps:
|
||
- name: All main verifier checks green
|
||
env:
|
||
NEEDS: ${{ toJSON(needs) }}
|
||
run: |
|
||
set -euo pipefail
|
||
echo "$NEEDS" | jq -e '
|
||
to_entries
|
||
| all(.value.result == "success" or .value.result == "skipped")
|
||
'
|
||
|
||
deploy:
|
||
name: deploy homeserver (teqo-1313)
|
||
# OPS53. Runs directly on the runner HOST (not a job container): the
|
||
# deploy needs the workstation's SSH key to reach the homeserver
|
||
# (`ssh homeserver`) and streams the whole remote build/migrate/rollout
|
||
# to this job's logs. Deliberately wired ONLY here — push to main +
|
||
# workflow_dispatch — never in ci-pr.yml: a host job is code execution as
|
||
# `fsolla` on the workstation, and main only ever moves through a merged
|
||
# PR whose full suite was already green.
|
||
needs: [checks]
|
||
runs-on: host
|
||
timeout-minutes: 60
|
||
steps:
|
||
- uses: actions/checkout@v5
|
||
- name: Deploy teqo-1313 on the homeserver
|
||
run: |
|
||
set -euo pipefail
|
||
ssh homeserver "bash -s -- $GITHUB_SHA" < scripts/deploy-homeserver.sh
|