Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions .github/workflows/local-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
# push to main -> affected ports only (scripts/ci-affected-ports.sh)
# nightly + dispatch -> full matrix
#
# Java is split into two parallel jobs — java-fast (java+kotlin conformance, the
# quick correctness signal ~2-3m) and java-slow (full reactor + docker
# integration). The split surfaces the conformance verdict fast and means a
# cancel/OOM mid-integration no longer kills the fast signal. `detect` emits the
# umbrella token `java`; both jobs gate on it.
# The ts and java ports are each split into two parallel jobs — a FAST lane (the
# quick pure-code correctness signal: ts-fast = build+typecheck/conformance/
# completeness, java-fast = java+kotlin conformance) and a SLOW lane (docker
# integration + heavy build: ts-slow, java-slow = reactor + integration). The
# split surfaces the verdict fast and means a cancel/OOM/flake mid-integration no
# longer kills the fast signal. `detect` emits the umbrella token (`ts` / `java`);
# both of that port's jobs gate on it.
#
# Integration-running jobs (ts, python, csharp, java-slow) share a Postgres
# Integration-running jobs (ts-slow, python, csharp, java-slow) share a Postgres
# SIDECAR instead of each test booting its own Testcontainers Postgres per
# scenario (the java+kotlin lanes alone booted ~30-40 serial containers). Each
# port's PG helper honors METAOBJECTS_TEST_PG_URL and CREATEs a uniquely-named
Expand Down Expand Up @@ -77,7 +79,22 @@ jobs:
persist-credentials: false
- run: scripts/ci-local.sh --only gates --strict-toolchains

ts:
# TS FAST lane — build+typecheck, conformance, completeness (the pure-code
# correctness signal). No docker/integration, so no sidecar.
ts-fast:
needs: detect
if: contains(needs.detect.outputs.ports, 'ts')
runs-on: [self-hosted, linux]
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- run: scripts/ci-local.sh --only ts-fast --strict-toolchains

# TS SLOW lane — build + docker/sidecar integration tests. Uses the shared
# Postgres sidecar (dynamic host port; see the note above the integration jobs).
ts-slow:
needs: detect
if: contains(needs.detect.outputs.ports, 'ts')
runs-on: [self-hosted, linux]
Expand All @@ -102,7 +119,7 @@ jobs:
persist-credentials: false
- env:
METAOBJECTS_TEST_PG_URL: postgres://metaobjects:metaobjects@localhost:${{ job.services.postgres.ports['5432'] }}/metaobjects_test
run: scripts/ci-local.sh --only ts --strict-toolchains
run: scripts/ci-local.sh --only ts-slow --strict-toolchains

# Java FAST lane — java + kotlin conformance only (the quick correctness signal).
# No docker/integration, so no sidecar.
Expand Down Expand Up @@ -201,7 +218,7 @@ jobs:
run: scripts/ci-local.sh --only csharp --strict-toolchains

notify:
needs: [detect, gates, ts, java-fast, java-slow, python, csharp]
needs: [detect, gates, ts-fast, ts-slow, java-fast, java-slow, python, csharp]
if: always() && contains(needs.*.result, 'failure')
runs-on: [self-hosted, linux]
steps:
Expand Down
30 changes: 24 additions & 6 deletions scripts/ci-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
# # doc-template drift, embedded-library drift
# # ts → ts build+typecheck, ts conformance,
# # completeness-gate, integration-tests ts
# # ts-fast → build+typecheck, conformance,
# # completeness (the pure-code signal)
# # ts-slow → build + integration-tests ts
# # (docker); CI runs the two lanes as
# # separate parallel jobs
# # java → java+kotlin conformance, reactor,
# # integration-tests java+kotlin
# # java-fast → java+kotlin conformance only
Expand Down Expand Up @@ -64,8 +69,8 @@ while [ $# -gt 0 ]; do
--quick) QUICK=1 ;;
--strict-toolchains) STRICT=1 ;;
--only) shift; case "${1:-}" in
gates|ts|java|java-fast|java-slow|python|csharp) ONLY="$ONLY ${1}" ;;
*) echo "--only expects gates|ts|java|java-fast|java-slow|python|csharp, got '${1:-}'" >&2; exit 2 ;;
gates|ts|ts-fast|ts-slow|java|java-fast|java-slow|python|csharp) ONLY="$ONLY ${1}" ;;
*) echo "--only expects gates|ts|ts-fast|ts-slow|java|java-fast|java-slow|python|csharp, got '${1:-}'" >&2; exit 2 ;;
esac ;;
-h|--help) awk 'NR==1{next} /^set -uo/{exit} {sub(/^# ?/,""); print}' "$0"; exit 0 ;;
*) echo "unknown arg: $1 (see --help)" >&2; exit 2 ;;
Expand Down Expand Up @@ -125,6 +130,9 @@ gate_fixture_lint() {
# bun_install first: under `--only ts` this gate runs without fixture-lint
# (whose install it historically piggybacked on), so it must install itself.
gate_ts_build_typecheck() { bun_install && bun run --filter '*' build && bun run --filter '*' typecheck; }
# Build only (no typecheck) — the ts-slow lane needs the workspace dist/ to run the
# integration tests, but the typecheck already runs in ts-fast, so don't repeat it.
gate_ts_build() { bun_install && bun run --filter '*' build; }

# ── conformance.yml — per-port conformance corpora (exact CI commands) ────────
gate_conf_ts() {
Expand Down Expand Up @@ -232,9 +240,15 @@ fi
if want gates; then step "leak-scan (security)" gate_leak_scan; fi
if want gates; then step "pom-version parity" gate_pom_versions; fi
if want gates; then step_if bun "fixture-lint" gate_fixture_lint; fi
if want ts; then step_if bun "ts build + typecheck" gate_ts_build_typecheck; fi
if want ts; then step_if bun "conformance: typescript" gate_conf_ts; fi
if want ts; then step_if bun "completeness-gate (mutation)" gate_completeness; fi
# The ts port is split into two lanes so CI can run them as separate jobs (see
# .github/workflows/local-ci.yml): a FAST lane (build+typecheck, conformance,
# completeness — the pure-code correctness signal, no docker) and a SLOW lane
# (docker/sidecar integration). Isolating integration means a docker/sidecar
# hiccup no longer fails the code signal, and vice versa. `--only ts` (and a plain
# local run) still runs both lanes, so it stays byte-equivalent to before.
if want_any ts ts-fast; then step_if bun "ts build + typecheck" gate_ts_build_typecheck; fi
if want_any ts ts-fast; then step_if bun "conformance: typescript" gate_conf_ts; fi
if want_any ts ts-fast; then step_if bun "completeness-gate (mutation)" gate_completeness; fi
if want gates; then step_if bun "doc-template drift" gate_doc_template_drift; fi
if want gates; then step_if bun "embedded-library drift" gate_embedded_library_drift; fi

Expand Down Expand Up @@ -270,7 +284,11 @@ else
FAIL+=("integration-tests (docker down)")
fi
else
want ts && run_integration_for ts ts
# ts-slow needs the workspace dist/ to run integration. When the fast lane also
# runs (umbrella `ts` / local full), its build already produced it — only build
# here when ts-slow runs in isolation (the CI ts-slow job).
if want_any ts ts-slow && ! want_any ts ts-fast; then step_if bun "ts build (for integration)" gate_ts_build; fi
want_any ts ts-slow && run_integration_for ts ts
want_any java java-slow && run_integration_for java java kotlin
want python && run_integration_for python python
want csharp && run_integration_for csharp csharp
Expand Down
Loading