diff --git a/.agents/skills/openclaw-ci-limits/SKILL.md b/.agents/skills/openclaw-ci-limits/SKILL.md index 5ec11cf1adff..c0ab185348e7 100644 --- a/.agents/skills/openclaw-ci-limits/SKILL.md +++ b/.agents/skills/openclaw-ci-limits/SKILL.md @@ -311,7 +311,12 @@ These are intentionally guarded by `test/scripts/ci-workflow-guards.test.ts`: routing, deadlines and all caps unchanged. This adds zero jobs or registrations. Compiler-only AWS evidence does not prove CI timing; validate the complete job through exact-head native CI before claiming an improvement. -- `build-artifacts` on `blacksmith-32vcpu-ubuntu-2404`. +- Current-target `build-artifacts` uses the existing 16-class after a complete + four-CPU/15.42-GiB compute proof, including the unchanged parallel verifier wave. + The SDK memory owner keeps declarations serial when two heaps do not fit. + Frozen or unclassified targets retain 32-class; hosted fallbacks, job counts, + concurrency and deadlines stay unchanged. Measured compute fit does not prove + queue savings; observe the next exact-head CI cycle. - Normal canonical hybrid first attempts use the existing four-part QA smoke plan, removing two repeated checkouts, setups and private runtime builds. Blacksmith profiles retain four parts; GitHub profiles and fresh hybrid diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbb0d49abacc..036534c156dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2126,10 +2126,9 @@ jobs: contents: read needs: [preflight] if: needs.preflight.outputs.run_build_artifacts == 'true' - # 32 vCPU: the dist build sits on the light-run critical path alongside - # check-lint/check-dependencies; tsdown parallelizes across the extra - # cores for roughly the same billed core-minutes. - runs-on: ${{ vars.OPENCLAW_CI_RUNNER_BACKEND == 'github' && 'ubuntu-24.04' || (vars.OPENCLAW_CI_RUNNER_BACKEND == 'hybrid' && github.run_attempt > 1) && 'ubuntu-24.04' || (github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && github.run_attempt > 1)) && 'ubuntu-24.04' || (github.repository == 'openclaw/openclaw' && (github.event_name != 'pull_request' || contains(fromJSON('["OWNER","MEMBER","COLLABORATOR","CONTRIBUTOR"]'), github.event.pull_request.author_association)) && 'blacksmith-32vcpu-ubuntu-2404' || 'ubuntu-24.04') }} + # Current targets fit the measured 16-class with serial SDK declarations. + # Keep frozen/unknown targets on their existing class; their compute was not proved. + runs-on: ${{ vars.OPENCLAW_CI_RUNNER_BACKEND == 'github' && 'ubuntu-24.04' || (vars.OPENCLAW_CI_RUNNER_BACKEND == 'hybrid' && github.run_attempt > 1) && 'ubuntu-24.04' || (github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && github.run_attempt > 1)) && 'ubuntu-24.04' || (github.repository == 'openclaw/openclaw' && (github.event_name != 'pull_request' || contains(fromJSON('["OWNER","MEMBER","COLLABORATOR","CONTRIBUTOR"]'), github.event.pull_request.author_association)) && (needs.preflight.outputs.frozen_target == 'false' && 'blacksmith-16vcpu-ubuntu-2404' || 'blacksmith-32vcpu-ubuntu-2404') || 'ubuntu-24.04') }} timeout-minutes: ${{ (vars.OPENCLAW_CI_RUNNER_BACKEND == 'github' || (vars.OPENCLAW_CI_RUNNER_BACKEND == 'hybrid' && github.run_attempt > 1) || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository)) && 35 || 20 }} steps: - *linux_node_checkout_step diff --git a/docs/ci/runners.md b/docs/ci/runners.md index 0bb2703d5012..fb1e057f45db 100644 --- a/docs/ci/runners.md +++ b/docs/ci/runners.md @@ -15,8 +15,8 @@ Runner choice follows contributor trust, not whether a pull request came from a | `ubuntu-24.04` | `openclaw/ci-gate` in every mode, `preflight` in hybrid mode, `check-docs` in every mode (its ClawHub mirror clone is unauthenticated by design), `security-fast` outside hybrid first attempts, manual CI dispatch and non-canonical repository fallbacks, CodeQL security and quality scans, workflow-sanity, labeler, auto-response, the standalone Docs workflow, the whole Install Smoke workflow, all configurable CI jobs in `github` mode, and the remaining light lanes plus rerun Blacksmith lanes in `hybrid` mode. The GitHub/hybrid planner profile expands the Node matrix, QA Smoke to six parts, core oxlint across five Programs (three jobs on ordinary non-frozen hybrid push/PR runs), and type checks across three jobs. Extension/scripts lint plus optional UI and format checks stay in `check-lint`; the last core type batch shares `check-test-types` with the extensions/root/scripts tail. | | `blacksmith-4vcpu-ubuntu-2404` | `preflight` when the backend is unset or `blacksmith`, hybrid first-attempt `security-fast`, `pnpm-store-warmup`, `native-i18n`, `checks-fast-core` except QA Smoke CI, plugin/channel contract shards, most bundled/lower-weight Linux Node shards, `check-*` lanes except `check-lint`, selected `check-additional-*` shards, and `skills-python` | | `blacksmith-8vcpu-ubuntu-2404` | Retained heavy Linux Node suites, compact-small queue-tail bins 2, 5, and 8, the `checks-ui-e2e` browser-extension row, boundary/extension-heavy `check-additional-*` shards except runtime topology architecture, and `android` | -| `blacksmith-16vcpu-ubuntu-2404` | Automatic QA Smoke CI shards and eligible compact bins containing the full CLI suite | -| `blacksmith-32vcpu-ubuntu-2404` | Eligible ordinary multi-group compact bins, numbered tooling bins, agent-support, the Docker seed job, `checks-ui-e2e` Control UI rows, eligible `checks-ui-e2e-real-gateway` jobs, `build-artifacts`, `check-lint`, `check-dependencies`, `check-test-types`, the two `check-test-types-core-*` rows, `check-additional-extension-package-boundary`, `check-additional-runtime-topology-architecture`, and npm release preflight; these CPU-heavy lanes need the measured capacity described below | +| `blacksmith-16vcpu-ubuntu-2404` | Current-target `build-artifacts`, automatic QA Smoke CI shards and eligible compact bins containing the full CLI suite | +| `blacksmith-32vcpu-ubuntu-2404` | Eligible ordinary multi-group compact bins, numbered tooling bins, agent-support, the Docker seed job, `checks-ui-e2e` Control UI rows, eligible `checks-ui-e2e-real-gateway` jobs, frozen/unclassified `build-artifacts` targets, `check-lint`, `check-dependencies`, `check-test-types`, the two `check-test-types-core-*` rows, `check-additional-extension-package-boundary`, `check-additional-runtime-topology-architecture`, and npm release preflight; these CPU-heavy lanes need the measured capacity described below | | `blacksmith-8vcpu-windows-2025` | `checks-windows` | | `blacksmith-6vcpu-macos-15` | `macos-node` on `openclaw/openclaw` when the backend is unset or `blacksmith`; hybrid and existing fallback routes use `macos-15` | | `macos-26` | All selected `macos-swift` and iOS build phases, both full-manual screenshot shards, and all four Periphery scans always use GitHub-hosted capacity. | @@ -58,6 +58,8 @@ preserves existing worker limits, explicit budgets, matrix sizes, and existing jobs adds no runner registrations. Repeat the capacity probe and reassess sizing after Blacksmith's allocation changes. +Current-target `build-artifacts` uses the existing 16-class. A [controlled Testbox proof](https://github.com/openclaw/openclaw/actions/runs/34669346942) at `3ccc3710bd6` completed all eight job compute steps in 229.3 seconds (252.8 seconds including payload setup) on four CPUs and 15.42 GiB RAM, with a 12.59 GiB cgroup peak and no recorded OOM events. The proof retained the complete parallel verifier wave and passed final source, worker-generation cleanup, and memory-event checks. The existing SDK memory gate keeps declarations serial below the capacity needed for both compiler heaps. Frozen targets and missing target classifications retain the 32-class; hosted fallbacks, job counts, concurrency, and deadlines are unchanged. These measurements establish compute fit, not a guaranteed queue reduction or full Actions duration. + Eligible `checks-ui-e2e-real-gateway` jobs request the 32-class so their private artifact build can overlap the two canonical SDK cache misses. Each compiler keeps its 12-GiB heap: overlap requires at least two available CPUs and 25.5 GiB of diff --git a/test/scripts/ci-workflow-guards.test.ts b/test/scripts/ci-workflow-guards.test.ts index 660cd2e9779a..9b9ce23afac9 100644 --- a/test/scripts/ci-workflow-guards.test.ts +++ b/test/scripts/ci-workflow-guards.test.ts @@ -5992,7 +5992,7 @@ setImmediate(() => { ...expectedHostedRunners, "security-fast": "blacksmith-4vcpu-ubuntu-2404", android: "blacksmith-8vcpu-ubuntu-2404", - "build-artifacts": "blacksmith-32vcpu-ubuntu-2404", + "build-artifacts": "blacksmith-16vcpu-ubuntu-2404", "checks-node-core-test-nondist-shard": "blacksmith-32vcpu-ubuntu-2404", "checks-ui-e2e": "blacksmith-8vcpu-ubuntu-2404", "checks-ui-e2e-real-gateway": "blacksmith-32vcpu-ubuntu-2404", @@ -8276,7 +8276,37 @@ server.listen(0, "127.0.0.1", () => { const source = readFileSync(".github/workflows/ci.yml", "utf8"); expect(source).toContain("createNodeTestShardBundles"); - expect(workflow.jobs["build-artifacts"]["runs-on"]).toContain("blacksmith-32vcpu-ubuntu-2404"); + const artifactRunner = workflow.jobs["build-artifacts"]["runs-on"]; + for (const [frozenTarget, expected] of [ + ["false", "blacksmith-16vcpu-ubuntu-2404"], + ["true", "blacksmith-32vcpu-ubuntu-2404"], + ["", "blacksmith-32vcpu-ubuntu-2404"], + ] as const) { + const context = { + eventName: "push", + repository: "openclaw/openclaw", + runAttempt: 1, + preflightOutputs: { frozen_target: frozenTarget }, + } as const; + for (const runnerBackend of ["", "blacksmith", "hybrid"] as const) { + for (const eventName of ["push", "pull_request"] as const) { + expect( + evaluateWorkflowExpression(artifactRunner, { ...context, runnerBackend, eventName }), + `build-artifacts: ${runnerBackend || "default"}/${eventName}/frozen=${frozenTarget}`, + ).toBe(expected); + } + } + for (const override of [ + { runnerBackend: "github" }, + { runnerBackend: "hybrid", runAttempt: 2 }, + { eventName: "workflow_dispatch" }, + { eventName: "pull_request", authorAssociation: "NONE", headRepository: "fork/openclaw" }, + ] as const) { + expect(evaluateWorkflowExpression(artifactRunner, { ...context, ...override })).toBe( + "ubuntu-24.04", + ); + } + } expect(workflow.jobs["build-artifacts"]["timeout-minutes"]).toBe( "${{ (vars.OPENCLAW_CI_RUNNER_BACKEND == 'github' || (vars.OPENCLAW_CI_RUNNER_BACKEND == 'hybrid' && github.run_attempt > 1) || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository)) && 35 || 20 }}", );