diff --git a/.github/workflows/benchmark-full.yml b/.github/workflows/benchmark-full.yml new file mode 100644 index 0000000000..6cebd22c31 --- /dev/null +++ b/.github/workflows/benchmark-full.yml @@ -0,0 +1,121 @@ +name: VPS Full Release Benchmark + +# Mede TODAS as fases pesadas do release na VPS self-hosted, para dimensionar o ganho +# real end-to-end (não só unit+build). Cobre: unit shards, vitest, build web, build:cli, +# e2e (Playwright) e integration — as mesmas fases do pipeline de release. +# +# push na branch chore/vps-runner-benchmark -> roda na VPS (self-hosted) +# workflow_dispatch (target=github) -> ubuntu-latest (baseline) +# +# Segurança: label omni-release só existe aqui; fork nunca usa a VPS. + +on: + workflow_dispatch: + inputs: + target: + description: "Onde rodar (vps = self-hosted, github = ubuntu-latest)" + type: choice + options: [vps, github] + default: vps + +permissions: + contents: read + +concurrency: + group: vps-benchmark-full-${{ github.event.inputs.target || 'vps' }} + cancel-in-progress: true + +env: + RUNS_ON_JSON: >- + ${{ (github.event.inputs.target == 'github') && '"ubuntu-latest"' + || '["self-hosted","omni-release"]' }} + +jobs: + unit: + name: full-unit ${{ matrix.shard }} + runs-on: ${{ fromJSON(github.event.inputs.target == 'github' && '"ubuntu-latest"' || '["self-hosted","omni-release"]') }} + strategy: { fail-fast: false, matrix: { shard: [1, 2, 3, 4, 5, 6, 7, 8] } } + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v6 + with: { node-version: "24" } + - run: npm ci + - name: unit shard (timed) + id: t + env: { TEST_SHARD: "${{ matrix.shard }}/8" } + run: | + s=$(date +%s); npm run test:unit:ci:shard || true; echo "sec=$(( $(date +%s)-s ))" >> "$GITHUB_OUTPUT" + - run: echo "| unit ${{ matrix.shard }}/8 | \`${RUNNER_NAME:-github}\` | ${{ steps.t.outputs.sec }}s |" >> "$GITHUB_STEP_SUMMARY" + + vitest: + name: full-vitest + runs-on: ${{ fromJSON(github.event.inputs.target == 'github' && '"ubuntu-latest"' || '["self-hosted","omni-release"]') }} + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v6 + with: { node-version: "24" } + - run: npm ci + - name: vitest (timed) + id: t + run: | + s=$(date +%s); npm run test:vitest || true; echo "sec=$(( $(date +%s)-s ))" >> "$GITHUB_OUTPUT" + - run: echo "| vitest | \`${RUNNER_NAME:-github}\` | ${{ steps.t.outputs.sec }}s |" >> "$GITHUB_STEP_SUMMARY" + + build-web: + name: full-build-web + runs-on: ${{ fromJSON(github.event.inputs.target == 'github' && '"ubuntu-latest"' || '["self-hosted","omni-release"]') }} + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v6 + with: { node-version: "24" } + - run: npm ci + - name: build web (timed) + id: t + run: | + s=$(date +%s); npm run build; echo "sec=$(( $(date +%s)-s ))" >> "$GITHUB_OUTPUT" + - run: echo "| build-web | \`${RUNNER_NAME:-github}\` | ${{ steps.t.outputs.sec }}s |" >> "$GITHUB_STEP_SUMMARY" + + build-cli: + name: full-build-cli + runs-on: ${{ fromJSON(github.event.inputs.target == 'github' && '"ubuntu-latest"' || '["self-hosted","omni-release"]') }} + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v6 + with: { node-version: "24" } + - run: npm ci + - name: build cli (timed) + id: t + run: | + s=$(date +%s); npm run build:cli || true; echo "sec=$(( $(date +%s)-s ))" >> "$GITHUB_OUTPUT" + - run: echo "| build-cli | \`${RUNNER_NAME:-github}\` | ${{ steps.t.outputs.sec }}s |" >> "$GITHUB_STEP_SUMMARY" + + e2e: + name: full-e2e ${{ matrix.shard }} + runs-on: ${{ fromJSON(github.event.inputs.target == 'github' && '"ubuntu-latest"' || '["self-hosted","omni-release"]') }} + strategy: { fail-fast: false, matrix: { shard: [1, 2, 3] } } + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v6 + with: { node-version: "24" } + - run: npm ci + - run: npx playwright install --with-deps chromium + - name: e2e shard (timed, builds on demand) + id: t + run: | + s=$(date +%s); npx playwright test tests/e2e/*.spec.ts --shard=${{ matrix.shard }}/3 || true; echo "sec=$(( $(date +%s)-s ))" >> "$GITHUB_OUTPUT" + - run: echo "| e2e ${{ matrix.shard }}/3 | \`${RUNNER_NAME:-github}\` | ${{ steps.t.outputs.sec }}s |" >> "$GITHUB_STEP_SUMMARY" + + integration: + name: full-integration ${{ matrix.shard }} + runs-on: ${{ fromJSON(github.event.inputs.target == 'github' && '"ubuntu-latest"' || '["self-hosted","omni-release"]') }} + strategy: { fail-fast: false, matrix: { shard: [1, 2] } } + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v6 + with: { node-version: "24" } + - run: npm ci + - name: integration shard (timed) + id: t + run: | + s=$(date +%s); npm run test:integration -- --test-shard=${{ matrix.shard }}/2 || true; echo "sec=$(( $(date +%s)-s ))" >> "$GITHUB_OUTPUT" + - run: echo "| integration ${{ matrix.shard }}/2 | \`${RUNNER_NAME:-github}\` | ${{ steps.t.outputs.sec }}s |" >> "$GITHUB_STEP_SUMMARY" diff --git a/scripts/vps/release-runner-down.sh b/scripts/vps/release-runner-down.sh new file mode 100755 index 0000000000..dd27087cad --- /dev/null +++ b/scripts/vps/release-runner-down.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Desliga a VM self-hosted (VPS 113) ao fim do release e volta o CI para o GitHub-hosted. +# Idempotente: seguro chamar mesmo que a VM já esteja desligada. +# +# Uso: scripts/vps/release-runner-down.sh +set -uo pipefail + +PVE_HOST="${PVE_HOST:-192.168.0.100}" +VM_ID="${VM_ID:-113}" +REPO="${REPO:-diegosouzapw/OmniRoute}" +SSH="ssh -o BatchMode=yes -o ConnectTimeout=8" + +# 1) Volta o CI para ubuntu-latest ANTES de derrubar a VM (evita jobs presos). +echo "[release-runner] USE_VPS_RUNNER=false (CI volta ao GitHub-hosted)." +gh variable set USE_VPS_RUNNER --repo "$REPO" --body "false" >/dev/null 2>&1 || true + +# 2) Shutdown graceful da VM (libera os 32 cores / 24GB de volta ao host). +echo "[release-runner] desligando VM $VM_ID (graceful)..." +$SSH "root@$PVE_HOST" "qm shutdown $VM_ID --timeout 120" 2>/dev/null \ + || $SSH "root@$PVE_HOST" "qm stop $VM_ID" 2>/dev/null \ + || echo "[release-runner] ⚠️ não consegui desligar a VM $VM_ID — verifique manualmente." +echo "[release-runner] pronto." diff --git a/scripts/vps/release-runner-up.sh b/scripts/vps/release-runner-up.sh new file mode 100755 index 0000000000..8f35066d33 --- /dev/null +++ b/scripts/vps/release-runner-up.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Liga a VM self-hosted (VPS 113) e aguarda seus runners ficarem online, para a fase +# de release usar runners dedicados (anti-fila). Falha => o caller cai no GitHub-hosted. +# +# Uso: scripts/vps/release-runner-up.sh [timeout_seg] +# Saída: exit 0 + seta a repo-var USE_VPS_RUNNER=true quando >=1 runner omni-release online +# exit 1 + seta USE_VPS_RUNNER=false em qualquer falha/timeout (fallback) +# +# Pré-requisitos no host que roda o /generate-release: +# - chave SSH autorizada em root@$PVE_HOST (Proxmox) e root@$VPS_HOST (a VM) +# - gh autenticado com admin no repo (para ler runners + setar a variable) +set -uo pipefail + +PVE_HOST="${PVE_HOST:-192.168.0.100}" # Proxmox host +VPS_HOST="${VPS_HOST:-192.168.0.113}" # a VM dos runners +VM_ID="${VM_ID:-113}" +REPO="${REPO:-diegosouzapw/OmniRoute}" +LABEL="${RUNNER_LABEL:-omni-release}" +TIMEOUT="${1:-120}" +SSH="ssh -o BatchMode=yes -o ConnectTimeout=8" + +fallback() { + echo "[release-runner] ⚠️ $1 — usando GitHub-hosted (fallback)." + gh variable set USE_VPS_RUNNER --repo "$REPO" --body "false" >/dev/null 2>&1 || true + exit 1 +} + +echo "[release-runner] ligando VM $VM_ID no Proxmox $PVE_HOST..." +$SSH "root@$PVE_HOST" "qm start $VM_ID" 2>/dev/null || true # ok se já estiver rodando + +echo "[release-runner] aguardando runners '$LABEL' ficarem online (timeout ${TIMEOUT}s)..." +deadline=$(( $(date +%s) + TIMEOUT )) +while [ "$(date +%s)" -lt "$deadline" ]; do + online=$(gh api "repos/$REPO/actions/runners" \ + --jq "[.runners[] | select(.status==\"online\") | select(.labels[].name==\"$LABEL\")] | length" \ + 2>/dev/null || echo 0) + if [ "${online:-0}" -ge 1 ]; then + echo "[release-runner] ✅ $online runner(s) '$LABEL' online — usando a VPS." + gh variable set USE_VPS_RUNNER --repo "$REPO" --body "true" >/dev/null 2>&1 \ + || fallback "não consegui setar USE_VPS_RUNNER" + exit 0 + fi + sleep 6 +done +fallback "runners não ficaram online a tempo"