Skip to content

feat(schema): clean useSchema API, local-first frozen resolve, faster… #2702

feat(schema): clean useSchema API, local-first frozen resolve, faster…

feat(schema): clean useSchema API, local-first frozen resolve, faster… #2702

Workflow file for this run

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