feat(schema): clean useSchema API, local-first frozen resolve, faster… #2702
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| on: [push, workflow_dispatch] | |
| # Main prefers Mancave (self-hosted) so Dagger cache volumes stay warm. | |
| # GitHub-hosted runs ONLY when Mancave is unavailable — never as a retry | |
| # after a red test suite. | |
| # | |
| # Flow: | |
| # 1. Pick runner — online self-hosted? (optional CI_RUNNER_STATUS_TOKEN) | |
| # 2. Main (Mancave) XOR Main (GitHub) — one path, not failure-failover | |
| # 3. Main — aggregator for the required status check | |
| # | |
| # Availability check needs a PAT that can list repo runners (GITHUB_TOKEN | |
| # cannot). Store it as Actions secret CI_RUNNER_STATUS_TOKEN. Without that | |
| # secret we assume Mancave is up (same as before) and will not fall back | |
| # when tests fail. | |
| # | |
| # Escape hatch (force hosted, skip Mancave): | |
| # Settings -> Secrets and variables -> Actions -> Variables | |
| # CI_RUNNER = ["ubuntu-latest"] | |
| # | |
| # Only this workflow uses the self-hosted runner. Releasing/deploying stay | |
| # on ubuntu-latest — a release must not depend on one PC being awake. | |
| # | |
| # SECURITY: pull_request / pull_request_target are forced onto hosted | |
| # runners (never Mancave). | |
| name: "Main pipeline: build, lint, test" | |
| jobs: | |
| pick: | |
| name: Pick runner | |
| runs-on: ubuntu-latest | |
| outputs: | |
| host: ${{ steps.pick.outputs.host }} | |
| steps: | |
| - id: pick | |
| env: | |
| GH_TOKEN: ${{ secrets.CI_RUNNER_STATUS_TOKEN }} | |
| FORCE_RUNNER: ${{ vars.CI_RUNNER }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| REPO: ${{ github.repository }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$EVENT_NAME" = "pull_request" ] || [ "$EVENT_NAME" = "pull_request_target" ]; then | |
| echo "PR event — forcing GitHub-hosted (never run untrusted code on Mancave)" | |
| echo "host=hosted" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if [ "$FORCE_RUNNER" = '["ubuntu-latest"]' ]; then | |
| echo "CI_RUNNER escape hatch — forcing GitHub-hosted" | |
| echo "host=hosted" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if [ -z "${GH_TOKEN:-}" ]; then | |
| echo "No CI_RUNNER_STATUS_TOKEN — assuming Mancave online" | |
| echo "host=mancave" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Any online runner carrying the self-hosted label counts as | |
| # available (busy is fine — the job will wait its turn). | |
| # On API errors (bad/insufficient PAT), prefer Mancave — do NOT | |
| # treat a 403 as "offline" or we skip the warm box forever. | |
| set +e | |
| body=$(gh api "repos/$REPO/actions/runners" 2>/tmp/runner-api.err) | |
| api_status=$? | |
| set -e | |
| if [ "$api_status" -ne 0 ]; then | |
| echo "Runner API failed (is CI_RUNNER_STATUS_TOKEN a fine-grained PAT with Repository Administration: Read?):" | |
| cat /tmp/runner-api.err || true | |
| echo "Assuming Mancave online" | |
| echo "host=mancave" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if printf '%s' "$body" | jq -e \ | |
| 'any(.runners[]; .status == "online" and any(.labels[]; .name == "self-hosted"))' \ | |
| >/dev/null; then | |
| echo "Self-hosted runner online — using Mancave" | |
| echo "host=mancave" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "No online self-hosted runner — falling back to GitHub-hosted" | |
| echo "host=hosted" >> "$GITHUB_OUTPUT" | |
| fi | |
| mancave: | |
| name: Main (Mancave) | |
| needs: pick | |
| if: needs.pick.outputs.host == 'mancave' | |
| uses: ./.github/workflows/main-ci.yml | |
| # `packages: write` lets the GITHUB_TOKEN push images to GHCR. An explicit | |
| # permissions block replaces the defaults, so `contents: read` (checkout) | |
| # has to come along. | |
| permissions: | |
| contents: read | |
| packages: write | |
| with: | |
| runner: ${{ vars.CI_RUNNER || '["self-hosted", "Linux", "X64"]' }} | |
| artifact-name: build-artifacts-mancave | |
| host-profile: mancave | |
| secrets: | |
| NETLIFY_TOKEN: ${{ secrets.NETLIFY_TOKEN }} | |
| DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
| DAGGER_CLOUD_TOKEN: ${{ secrets.DAGGER_CLOUD_TOKEN }} | |
| # Hosted only when pick said Mancave is unavailable (or escape/PR). | |
| # Deliberately does NOT run when Mancave finished with test failures. | |
| github: | |
| name: Main (GitHub) | |
| needs: pick | |
| if: needs.pick.outputs.host == 'hosted' | |
| uses: ./.github/workflows/main-ci.yml | |
| permissions: | |
| contents: read | |
| packages: write | |
| with: | |
| runner: '["ubuntu-latest"]' | |
| artifact-name: build-artifacts-github | |
| host-profile: hosted | |
| secrets: | |
| NETLIFY_TOKEN: ${{ secrets.NETLIFY_TOKEN }} | |
| DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
| DAGGER_CLOUD_TOKEN: ${{ secrets.DAGGER_CLOUD_TOKEN }} | |
| Main: | |
| name: Main | |
| needs: [pick, mancave, github] | |
| if: always() && needs.pick.result == 'success' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Resolve runner outcome | |
| run: | | |
| host="${{ needs.pick.outputs.host }}" | |
| m="${{ needs.mancave.result }}" | |
| g="${{ needs.github.result }}" | |
| echo "host=$host mancave=$m github=$g" | |
| if [ "$host" = "mancave" ] && [ "$m" = "success" ]; then | |
| exit 0 | |
| fi | |
| if [ "$host" = "hosted" ] && [ "$g" = "success" ]; then | |
| exit 0 | |
| fi | |
| exit 1 |