From 42348f53bfc49768fad1c128232ad6d5189a3da1 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Fri, 3 Jul 2026 13:36:31 -0700 Subject: [PATCH] ci(runners): use github-hosted validation --- .github/workflows/audit.yml | 2 +- .github/workflows/ci.yml | 28 +++++++++---------------- .github/workflows/self-host-nightly.yml | 19 ++++++----------- 3 files changed, 17 insertions(+), 32 deletions(-) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 7a3734fa38..b703ae3845 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -21,7 +21,7 @@ concurrency: jobs: audit: name: audit - runs-on: [self-hosted, gittensory] + runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Checkout diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6704e263f0..34b2a848a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -115,15 +115,14 @@ jobs: - 'review-enrichment/**' - '.github/workflows/ci.yml' - # Path-aware validation. Keep this as one self-hosted job so a PR uses one - # runner slot and one dependency install instead of fanning out into several - # competing installs on the same VPS. Fork PRs still run on GitHub-hosted - # runners because their code is untrusted. + # Path-aware validation. Keep this as one job so a PR uses one dependency + # install and one coverage upload. Run on GitHub-hosted runners while the + # self-hosted review stack is CPU constrained. validate-code: name: validate-code needs: changes if: ${{ github.event_name == 'push' || needs.changes.outputs.backend == 'true' || needs.changes.outputs.mcp == 'true' || needs.changes.outputs.rees == 'true' || needs.changes.outputs.ui == 'true' }} - runs-on: ${{ fromJSON((github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true) && '["ubuntu-latest"]' || '["self-hosted","gittensory"]') }} + runs-on: ubuntu-latest timeout-minutes: 45 env: VITE_GITTENSORY_API_ORIGIN: https://gittensory-api.aethereal.dev @@ -142,14 +141,10 @@ jobs: # actions/checkout wipes node_modules (git clean -ffdx) on every run regardless of the self-hosted # runner's own persistence, and npm ci always deletes+reinstalls node_modules by design -- so # neither the runner nor npm ci gives node_modules any real cross-run reuse on its own. This - # explicit restore/save pair (via GitHub's own cache service, not the wiped local disk) fills that - # gap: an exact manifest+lockfile match skips npm ci entirely. Keyed separately per fork/trusted - # (see the runs-on expression above) because self-hosted's Docker image and GitHub's ubuntu-latest - # image are not guaranteed binary-compatible for native modules (sharp, workerd, fsevents, ...) -- - # crossing them could load an incompatible native binary. Fork PRs get read-only cache tokens (a - # documented actions/cache behavior), so a "fork"-keyed entry can never actually be written; that's - # fine, it just means fork PRs keep doing a full npm ci exactly as before -- no regression, no risk - # on the highest-stakes (no-retry) population. + # explicit restore/save pair (via GitHub's own cache service, not local disk) fills that gap: an + # exact manifest+lockfile match skips npm ci entirely. Keep fork/trusted keys separate even though + # both run on ubuntu-latest: fork PRs get read-only cache tokens, so a fork-keyed entry can never + # actually be written; trusted PRs keep their reusable cache without crossing trust boundaries. - name: Restore node_modules cache id: node-modules-cache uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 @@ -220,11 +215,8 @@ jobs: # above) didn't change. mcp-output-schemas.test.ts is never in the exclude list -- see that filter's # comment for why it can't be safely narrowed. SKIP_MCP_CLI_HARNESS: ${{ github.event_name == 'pull_request' && needs.changes.outputs.mcpCliHarness != 'true' }} - # Pinned to the self-hosted runner's actual Docker CPU quota (4), not "100%": Node's os.cpus() - # reports the HOST's full core count inside the container, ignoring the cgroup CPU limit, so - # --maxWorkers=100% oversubscribed the worker pool far past what the runner can actually execute - # in parallel, causing thrashing. A GitHub-hosted fork-PR runner has no such limit, but the - # standard 4-core GitHub runner makes 4 the right number there too. + # Pinned to the standard GitHub-hosted runner's effective CPU budget; keeping this explicit avoids + # accidental worker-pool thrash if os.cpus() reports a larger host in a future runner image. run: | EXCLUDE_ARGS=() if [ "$SKIP_MCP_CLI_HARNESS" = "true" ]; then diff --git a/.github/workflows/self-host-nightly.yml b/.github/workflows/self-host-nightly.yml index a960871002..bdc9265ece 100644 --- a/.github/workflows/self-host-nightly.yml +++ b/.github/workflows/self-host-nightly.yml @@ -1,14 +1,8 @@ -# Nightly maintenance on the self-hosted runner (gittensory channel). Deliberately NOT wired into PR CI: this -# repo's gate auto-closes PRs with red required checks, so a self-hosted runner being offline must never be able -# to fail-close a PR. This runs on a schedule + on demand only, and keeps the local RAG index fresh. -# -# Setup: this repo needs a self-hosted runner labelled `gittensory` (the self-host stack provides one), and -# optionally an INTERNAL_JOB_TOKEN repo secret (Settings → Secrets → Actions) to trigger the RAG re-index. -name: self-host nightly +# Manual maintenance hook for an externally reachable self-host stack. This is deliberately not scheduled while +# the review stack is running without colocated GitHub Actions runners. +name: self-host maintenance on: - schedule: - - cron: "0 4 * * *" # 04:00 UTC daily workflow_dispatch: {} permissions: @@ -20,12 +14,11 @@ concurrency: jobs: maintenance: - runs-on: [self-hosted, gittensory] + if: ${{ vars.SELF_HOST_URL != '' }} + runs-on: ubuntu-latest timeout-minutes: 30 env: - # The runner shares the stack's Docker network, so it reaches the engine by service name. Override with a - # repo variable SELF_HOST_URL if your runner is elsewhere (e.g. a published port / Tailscale address). - SELF_HOST_URL: ${{ vars.SELF_HOST_URL || 'http://gittensory:8787' }} + SELF_HOST_URL: ${{ vars.SELF_HOST_URL }} INTERNAL_JOB_TOKEN: ${{ secrets.INTERNAL_JOB_TOKEN }} steps: - name: Self-host health