From 024592fb1de4780e05ca1f5e159bfba83144bf6e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 22 Apr 2026 18:10:02 +0100 Subject: [PATCH] Revert "ci: reuse build artifacts for gateway topology" This reverts commit be317769e6cf0e09737197272d1966e80bdecfbc. --- .github/workflows/ci.yml | 137 ++------------------- docs/ci.md | 62 +++++----- scripts/check-gateway-watch-regression.mjs | 33 +---- 3 files changed, 43 insertions(+), 189 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51ab5844ef1..20285e1ac52 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -544,12 +544,6 @@ jobs: include-hidden-files: true retention-days: 1 - - name: Cache dist-runtime build - uses: actions/cache@v5 - with: - path: dist-runtime/ - key: ${{ runner.os }}-dist-runtime-build-${{ github.sha }} - checks-fast-core: permissions: contents: read @@ -1612,6 +1606,8 @@ jobs: group: extension-bundled - check_name: check-additional-extension-package-boundary group: extension-package-boundary + - check_name: check-additional-runtime-topology-gateway + group: runtime-topology-gateway - check_name: check-additional-runtime-topology-architecture group: runtime-topology-architecture steps: @@ -1710,6 +1706,7 @@ jobs: - name: Run additional check shard env: ADDITIONAL_CHECK_GROUP: ${{ matrix.group }} + RUN_CONTROL_UI_I18N: ${{ needs.preflight.outputs.run_control_ui_i18n }} OPENCLAW_EXTENSION_BOUNDARY_CONCURRENCY: 6 shell: bash run: | @@ -1762,6 +1759,12 @@ jobs: run_check "test:extensions:package-boundary:compile" pnpm run test:extensions:package-boundary:compile run_check "test:extensions:package-boundary:canary" pnpm run test:extensions:package-boundary:canary ;; + runtime-topology-gateway) + if [ "$RUN_CONTROL_UI_I18N" = "true" ]; then + run_check "ui:i18n:check" pnpm ui:i18n:check + fi + run_check "gateway-watch-regression" pnpm test:gateway:watch-regression + ;; runtime-topology-architecture) run_check "check:architecture" pnpm check:architecture ;; @@ -1773,121 +1776,8 @@ jobs: exit "$failures" - check-additional-runtime-topology-gateway: - permissions: - contents: read - name: "check-additional-runtime-topology-gateway" - needs: [preflight, build-artifacts] - if: ${{ !cancelled() && always() && needs.preflight.outputs.run_check_additional == 'true' && needs.build-artifacts.result == 'success' }} - runs-on: ubuntu-24.04 - timeout-minutes: 20 - steps: - - name: Checkout - shell: bash - env: - CHECKOUT_REPO: ${{ github.repository }} - CHECKOUT_SHA: ${{ github.sha }} - CHECKOUT_TOKEN: ${{ github.token }} - run: | - set -euo pipefail - - workdir="$GITHUB_WORKSPACE" - auth_header="$(printf 'x-access-token:%s' "$CHECKOUT_TOKEN" | base64 | tr -d '\n')" - - reset_checkout_dir() { - mkdir -p "$workdir" - find "$workdir" -mindepth 1 -maxdepth 1 -exec rm -rf {} + - } - - checkout_attempt() { - local attempt="$1" - - reset_checkout_dir - git init "$workdir" >/dev/null - git config --global --add safe.directory "$workdir" - git -C "$workdir" remote add origin "https://github.com/${CHECKOUT_REPO}" - git -C "$workdir" config gc.auto 0 - - timeout --signal=TERM 30s git -C "$workdir" \ - -c protocol.version=2 \ - -c "http.https://github.com/.extraheader=AUTHORIZATION: basic ${auth_header}" \ - fetch --no-tags --prune --no-recurse-submodules --depth=1 origin \ - "+${CHECKOUT_SHA}:refs/remotes/origin/ci-target" || return 1 - - git -C "$workdir" checkout --force --detach "$CHECKOUT_SHA" || return 1 - test -f "$workdir/.github/actions/setup-node-env/action.yml" || return 1 - echo "checkout attempt ${attempt}/2 succeeded" - } - - for attempt in 1 2; do - if checkout_attempt "$attempt"; then - exit 0 - fi - echo "checkout attempt ${attempt}/2 failed" - sleep $((attempt * 5)) - done - - echo "checkout failed after 2 attempts" >&2 - exit 1 - - - name: Setup Node environment - uses: ./.github/actions/setup-node-env - with: - install-bun: "false" - - - name: Restore dist cache - id: gateway-dist-cache - uses: actions/cache@v5 - with: - path: dist/ - key: ${{ runner.os }}-dist-build-${{ github.sha }} - - - name: Download dist artifact - if: steps.gateway-dist-cache.outputs.cache-hit != 'true' - uses: actions/download-artifact@v8 - with: - name: dist-build - path: dist/ - - - name: Restore dist-runtime cache - id: gateway-dist-runtime-cache - uses: actions/cache@v5 - with: - path: dist-runtime/ - key: ${{ runner.os }}-dist-runtime-build-${{ github.sha }} - - - name: Run runtime topology gateway checks - env: - RUN_CONTROL_UI_I18N: ${{ needs.preflight.outputs.run_control_ui_i18n }} - shell: bash - run: | - set -euo pipefail - - failures=0 - - run_check() { - local label="$1" - shift - - echo "::group::${label}" - if "$@"; then - echo "[ok] ${label}" - else - echo "::error title=${label} failed::${label} failed" - failures=1 - fi - echo "::endgroup::" - } - - if [ "$RUN_CONTROL_UI_I18N" = "true" ]; then - run_check "ui:i18n:check" pnpm ui:i18n:check - fi - run_check "gateway-watch-regression" node scripts/check-gateway-watch-regression.mjs --skip-build - - exit "$failures" - - name: Upload gateway watch regression artifacts - if: always() + if: always() && matrix.group == 'runtime-topology-gateway' uses: actions/upload-artifact@v7 with: name: gateway-watch-regression @@ -1898,7 +1788,7 @@ jobs: permissions: contents: read name: "check-additional" - needs: [preflight, check-additional-shard, check-additional-runtime-topology-gateway] + needs: [preflight, check-additional-shard] if: ${{ !cancelled() && always() && needs.preflight.outputs.run_check_additional == 'true' }} runs-on: ubuntu-24.04 timeout-minutes: 5 @@ -1906,16 +1796,11 @@ jobs: - name: Verify additional check shards env: SHARD_RESULT: ${{ needs.check-additional-shard.result }} - GATEWAY_RESULT: ${{ needs.check-additional-runtime-topology-gateway.result }} run: | if [ "$SHARD_RESULT" != "success" ]; then echo "Additional check shards failed: $SHARD_RESULT" >&2 exit 1 fi - if [ "$GATEWAY_RESULT" != "success" ]; then - echo "Runtime topology gateway check failed: $GATEWAY_RESULT" >&2 - exit 1 - fi build-smoke: permissions: diff --git a/docs/ci.md b/docs/ci.md index 99ea1e07bfd..731e47d2bfc 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -12,28 +12,28 @@ The CI runs on every push to `main` and every pull request. It uses smart scopin ## Job Overview -| Job | Purpose | When it runs | -| -------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------- | -| `preflight` | Detect docs-only changes, changed scopes, changed extensions, and build the CI manifest | Always on non-draft pushes and PRs | -| `security-scm-fast` | Private key detection and workflow audit via `zizmor` | Always on non-draft pushes and PRs | -| `security-dependency-audit` | Dependency-free production lockfile audit against npm advisories | Always on non-draft pushes and PRs | -| `security-fast` | Required aggregate for the fast security jobs | Always on non-draft pushes and PRs | -| `build-artifacts` | Build `dist/` and the Control UI once, upload reusable artifacts for downstream jobs | Node-relevant changes | -| `checks-fast-core` | Fast Linux correctness lanes such as bundled/plugin-contract/protocol checks | Node-relevant changes | -| `checks-fast-contracts-channels` | Sharded channel contract checks with a stable aggregate check result | Node-relevant changes | -| `checks-node-extensions` | Full bundled-plugin test shards across the extension suite | Node-relevant changes | -| `checks-node-core-test` | Core Node test shards, excluding channel, bundled, contract, and extension lanes | Node-relevant changes | -| `extension-fast` | Focused tests for only the changed bundled plugins | When extension changes are detected | -| `check` | Sharded main local gate equivalent: prod types, lint, guards, test types, and strict smoke | Node-relevant changes | -| `check-additional` | Architecture, boundary, extension-surface guards, package-boundary, and built-artifact gateway-watch checks | Node-relevant changes | -| `build-smoke` | Built-CLI smoke tests and startup-memory smoke | Node-relevant changes | -| `checks` | Remaining Linux Node lanes: channel tests and push-only Node 22 compatibility | Node-relevant changes | -| `check-docs` | Docs formatting, lint, and broken-link checks | Docs changed | -| `skills-python` | Ruff + pytest for Python-backed skills | Python-skill-relevant changes | -| `checks-windows` | Windows-specific test lanes | Windows-relevant changes | -| `macos-node` | macOS TypeScript test lane using the shared built artifacts | macOS-relevant changes | -| `macos-swift` | Swift lint, build, and tests for the macOS app | macOS-relevant changes | -| `android` | Android build and test matrix | Android-relevant changes | +| Job | Purpose | When it runs | +| -------------------------------- | -------------------------------------------------------------------------------------------- | ----------------------------------- | +| `preflight` | Detect docs-only changes, changed scopes, changed extensions, and build the CI manifest | Always on non-draft pushes and PRs | +| `security-scm-fast` | Private key detection and workflow audit via `zizmor` | Always on non-draft pushes and PRs | +| `security-dependency-audit` | Dependency-free production lockfile audit against npm advisories | Always on non-draft pushes and PRs | +| `security-fast` | Required aggregate for the fast security jobs | Always on non-draft pushes and PRs | +| `build-artifacts` | Build `dist/` and the Control UI once, upload reusable artifacts for downstream jobs | Node-relevant changes | +| `checks-fast-core` | Fast Linux correctness lanes such as bundled/plugin-contract/protocol checks | Node-relevant changes | +| `checks-fast-contracts-channels` | Sharded channel contract checks with a stable aggregate check result | Node-relevant changes | +| `checks-node-extensions` | Full bundled-plugin test shards across the extension suite | Node-relevant changes | +| `checks-node-core-test` | Core Node test shards, excluding channel, bundled, contract, and extension lanes | Node-relevant changes | +| `extension-fast` | Focused tests for only the changed bundled plugins | When extension changes are detected | +| `check` | Sharded main local gate equivalent: prod types, lint, guards, test types, and strict smoke | Node-relevant changes | +| `check-additional` | Architecture, boundary, extension-surface guards, package-boundary, and gateway-watch shards | Node-relevant changes | +| `build-smoke` | Built-CLI smoke tests and startup-memory smoke | Node-relevant changes | +| `checks` | Remaining Linux Node lanes: channel tests and push-only Node 22 compatibility | Node-relevant changes | +| `check-docs` | Docs formatting, lint, and broken-link checks | Docs changed | +| `skills-python` | Ruff + pytest for Python-backed skills | Python-skill-relevant changes | +| `checks-windows` | Windows-specific test lanes | Windows-relevant changes | +| `macos-node` | macOS TypeScript test lane using the shared built artifacts | macOS-relevant changes | +| `macos-swift` | Swift lint, build, and tests for the macOS app | macOS-relevant changes | +| `android` | Android build and test matrix | Android-relevant changes | ## Fail-Fast Order @@ -52,21 +52,21 @@ Local changed-lane logic lives in `scripts/changed-lanes.mjs` and is executed by On pushes, the `checks` matrix adds the push-only `compat-node22` lane. On pull requests, that lane is skipped and the matrix stays focused on the normal test/channel lanes. -The slowest Node test families are split or balanced so each job stays small: channel contracts split registry and core coverage into eight weighted shards each, auto-reply reply tests split by prefix group, and agentic gateway/plugin configs are spread across the existing source-only agentic Node jobs instead of waiting on built artifacts. `check-additional` keeps package-boundary compile/canary work together, keeps architecture checks independent, and runs the runtime-topology gateway check from the shared `build-artifacts` output instead of rebuilding `dist/`. +The slowest Node test families are split or balanced so each job stays small: channel contracts split registry and core coverage into eight weighted shards each, auto-reply reply tests split by prefix group, and agentic gateway/plugin configs are spread across the existing source-only agentic Node jobs instead of waiting on built artifacts. `check-additional` keeps package-boundary compile/canary work together and separates it from runtime topology gateway/architecture work. GitHub may mark superseded jobs as `cancelled` when a newer push lands on the same PR or `main` ref. Treat that as CI noise unless the newest run for the same ref is also failing. Aggregate shard checks use `!cancelled() && always()` so they still report normal shard failures but do not queue after the whole workflow has already been superseded. The CI concurrency key is versioned (`CI-v2-*`) so a GitHub-side zombie in an old queue group cannot indefinitely block newer main runs. ## Runners -| Runner | Jobs | -| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `ubuntu-24.04` | `preflight`, fast security jobs and aggregates (`security-scm-fast`, `security-dependency-audit`, `security-fast`), fast protocol/contract/bundled checks, sharded channel contract checks, `check` shards except lint, `check-additional` shards/aggregate and the artifact-backed runtime-topology gateway check, docs checks, Python skills, workflow-sanity, labeler, auto-response; install-smoke preflight also uses GitHub-hosted Ubuntu so the Blacksmith matrix can queue earlier | -| `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`, build-smoke, Linux Node test shards, bundled plugin test shards, remaining built-artifact consumers, `android` | -| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`, which remains CPU-sensitive enough that 8 vCPU cost more than it saved | -| `blacksmith-16vcpu-windows-2025` | `checks-windows` | -| `blacksmith-6vcpu-macos-latest` | `macos-node` on `openclaw/openclaw`; forks fall back to `macos-latest` | -| `blacksmith-12vcpu-macos-latest` | `macos-swift` on `openclaw/openclaw`; forks fall back to `macos-latest` | +| Runner | Jobs | +| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ubuntu-24.04` | `preflight`, fast security jobs and aggregates (`security-scm-fast`, `security-dependency-audit`, `security-fast`), fast protocol/contract/bundled checks, sharded channel contract checks, `check` shards except lint, `check-additional` shards and aggregates, docs checks, Python skills, workflow-sanity, labeler, auto-response; install-smoke preflight also uses GitHub-hosted Ubuntu so the Blacksmith matrix can queue earlier | +| `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`, build-smoke, Linux Node test shards, bundled plugin test shards, remaining built-artifact consumers, `android` | +| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`, which remains CPU-sensitive enough that 8 vCPU cost more than it saved | +| `blacksmith-16vcpu-windows-2025` | `checks-windows` | +| `blacksmith-6vcpu-macos-latest` | `macos-node` on `openclaw/openclaw`; forks fall back to `macos-latest` | +| `blacksmith-12vcpu-macos-latest` | `macos-swift` on `openclaw/openclaw`; forks fall back to `macos-latest` | ## Local Equivalents diff --git a/scripts/check-gateway-watch-regression.mjs b/scripts/check-gateway-watch-regression.mjs index d8d01802d6e..6d17469826b 100644 --- a/scripts/check-gateway-watch-regression.mjs +++ b/scripts/check-gateway-watch-regression.mjs @@ -7,9 +7,8 @@ import os from "node:os"; import path from "node:path"; import process from "node:process"; import { pathToFileURL } from "node:url"; -import { resolveGitHead, writeBuildStamp } from "./build-stamp.mjs"; +import { writeBuildStamp } from "./build-stamp.mjs"; import { resolveBuildRequirement } from "./run-node.mjs"; -import { runRuntimePostBuild } from "./runtime-postbuild.mjs"; const DEFAULTS = { outputDir: path.join(process.cwd(), ".local", "gateway-watch-regression"), @@ -43,9 +42,6 @@ function parseArgs(argv) { for (let i = 0; i < argv.length; i += 1) { const arg = argv[i]; const next = argv[i + 1]; - if (arg === "--") { - continue; - } const readValue = () => { if (!next) { throw new Error(`Missing value for ${arg}`); @@ -583,31 +579,6 @@ function buildRunNodeDeps(env) { }; } -function writeRuntimePostBuildStamp(cwd) { - const stampPath = path.join(cwd, "dist", ".runtime-postbuildstamp"); - fs.mkdirSync(path.dirname(stampPath), { recursive: true }); - const head = resolveGitHead({ cwd, spawnSync }); - fs.writeFileSync( - stampPath, - `${JSON.stringify( - { - syncedAt: Date.now(), - ...(head ? { head } : {}), - }, - null, - 2, - )}\n`, - "utf8", - ); -} - -function prepareSkippedBuildRuntimeArtifacts() { - const cwd = process.cwd(); - runRuntimePostBuild({ cwd, env: process.env }); - writeBuildStamp({ cwd }); - writeRuntimePostBuildStamp(cwd); -} - async function main() { const options = parseArgs(process.argv.slice(2)); ensureDir(options.outputDir); @@ -617,8 +588,6 @@ async function main() { // Refresh the build stamp after the CI artifact build finishes so run-node // does not spuriously rebuild inside the bounded watch window. writeBuildStamp({ cwd: process.cwd() }); - } else { - prepareSkippedBuildRuntimeArtifacts(); } const preflightBuildRequirement = resolveBuildRequirement(buildRunNodeDeps(process.env));