

















@@ -41,11 +41,32 @@ env:
4141FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
42424343jobs:
44+# Keep the canonical main queue quiet long enough for a follow-up push to
45+# cancel this run before it registers the Blacksmith matrix.
46+runner-admission:
47+permissions:
48+contents: read
49+runs-on: ubuntu-24.04
50+timeout-minutes: 3
51+env:
52+OPENCLAW_MAIN_CI_DEBOUNCE_SECONDS: "90"
53+steps:
54+ - name: Debounce canonical main pushes
55+if: github.event_name == 'push' && github.repository == 'openclaw/openclaw' && github.ref == 'refs/heads/main'
56+run: |
57+ set -euo pipefail
58+ echo "Waiting ${OPENCLAW_MAIN_CI_DEBOUNCE_SECONDS}s for a superseding main push before Blacksmith admission"
59+ sleep "${OPENCLAW_MAIN_CI_DEBOUNCE_SECONDS}"
60+ - name: Admit non-main CI runs immediately
61+if: github.event_name != 'push' || github.repository != 'openclaw/openclaw' || github.ref != 'refs/heads/main'
62+run: echo "No canonical main debounce required"
63+4464# Preflight: establish routing truth and job matrices once, then let real
4565# work fan out from a single source of truth.
4666preflight:
4767permissions:
4868contents: read
69+needs: [runner-admission]
4970if: github.event_name != 'pull_request' || !github.event.pull_request.draft
5071runs-on: ${{ github.event_name == 'workflow_dispatch' && 'ubuntu-24.04' || (github.repository == 'openclaw/openclaw' && 'blacksmith-4vcpu-ubuntu-2404' || 'ubuntu-24.04') }}
5172timeout-minutes: 20
@@ -272,18 +293,22 @@ jobs:
272293 }
273294 }
274295296+ const compactPullRequest = isCanonicalRepository && eventName === "pull_request";
275297 const nodeTestShards = runNodeFull
276298 ? createNodeTestShardBundles({
277299 includeReleaseOnlyPluginShards: false,
300+ compact: compactPullRequest,
278301 }).map((shard) => ({
279302 check_name: shard.checkName,
280303 runtime: "node",
281304 task: "test-shard",
282305 shard_name: shard.shardName,
306+ groups: shard.groups,
283307 configs: shard.configs,
284308 includePatterns: shard.includePatterns,
285309 requires_dist: shard.requiresDist,
286310 runner: shard.runner,
311+ timeout_minutes: shard.timeoutMinutes,
287312 }))
288313 : [];
289314 const nodeTestNonDistShards = nodeTestShards.filter((shard) => !shard.requires_dist);
@@ -361,6 +386,7 @@ jobs:
361386security-fast:
362387permissions:
363388contents: read
389+needs: [runner-admission]
364390if: github.event_name != 'pull_request' || !github.event.pull_request.draft
365391runs-on: ${{ github.event_name == 'workflow_dispatch' && 'ubuntu-24.04' || (github.repository == 'openclaw/openclaw' && 'blacksmith-4vcpu-ubuntu-2404' || 'ubuntu-24.04') }}
366392timeout-minutes: 20
@@ -826,7 +852,7 @@ jobs:
826852timeout-minutes: 60
827853strategy:
828854fail-fast: false
829-max-parallel: 4
855+max-parallel: 8
830856matrix: ${{ fromJson(needs.preflight.outputs.checks_fast_core_matrix) }}
831857steps:
832858 - name: Checkout
@@ -916,7 +942,7 @@ jobs:
916942timeout-minutes: 60
917943strategy:
918944fail-fast: false
919-max-parallel: 4
945+max-parallel: 8
920946matrix: ${{ fromJson(needs.preflight.outputs.plugin_contracts_matrix) }}
921947steps:
922948 - name: Checkout
@@ -997,7 +1023,7 @@ jobs:
9971023timeout-minutes: 60
9981024strategy:
9991025fail-fast: false
1000-max-parallel: 4
1026+max-parallel: 8
10011027matrix: ${{ fromJson(needs.preflight.outputs.channel_contracts_matrix) }}
10021028steps:
10031029 - name: Checkout
@@ -1147,10 +1173,10 @@ jobs:
11471173needs: [preflight]
11481174if: needs.preflight.outputs.run_checks_node_core_nondist == 'true'
11491175runs-on: ${{ github.event_name == 'workflow_dispatch' && 'ubuntu-24.04' || (github.repository == 'openclaw/openclaw' && (matrix.runner || 'blacksmith-4vcpu-ubuntu-2404') || 'ubuntu-24.04') }}
1150-timeout-minutes: 60
1176+timeout-minutes: ${{ matrix.timeout_minutes || 60 }}
11511177strategy:
11521178fail-fast: false
1153-max-parallel: 6
1179+max-parallel: 12
11541180matrix: ${{ fromJson(needs.preflight.outputs.checks_node_core_nondist_matrix) }}
11551181steps:
11561182 - name: Checkout
@@ -1209,6 +1235,7 @@ jobs:
12091235 - name: Run Node test shard
12101236env:
12111237NODE_OPTIONS: --max-old-space-size=8192
1238+OPENCLAW_NODE_TEST_GROUPS_JSON: ${{ toJson(matrix.groups || null) }}
12121239OPENCLAW_NODE_TEST_CONFIGS_JSON: ${{ toJson(matrix.configs) }}
12131240OPENCLAW_NODE_TEST_INCLUDE_PATTERNS_JSON: ${{ toJson(matrix.includePatterns) }}
12141241OPENCLAW_VITEST_SHARD_NAME: ${{ matrix.shard_name }}
@@ -1223,28 +1250,47 @@ jobs:
12231250 import { writeFileSync } from "node:fs";
12241251 import { join } from "node:path";
122512521226- const configs = JSON.parse(process.env.OPENCLAW_NODE_TEST_CONFIGS_JSON ?? "[]");
1227- if (!Array.isArray(configs) || configs.length === 0) {
1228- console.error("Missing node test shard configs");
1229- process.exit(1);
1230- }
1231- const includePatterns = JSON.parse(process.env.OPENCLAW_NODE_TEST_INCLUDE_PATTERNS_JSON ?? "null");
1232- const childEnv = { ...process.env };
1233- if (Array.isArray(includePatterns) && includePatterns.length > 0) {
1234- const includeFile = join(
1235- process.env.RUNNER_TEMP ?? ".",
1236- `node-test-include-${process.env.GITHUB_JOB ?? "local"}-${Date.now()}.json`,
1253+ const groups = JSON.parse(process.env.OPENCLAW_NODE_TEST_GROUPS_JSON ?? "null");
1254+ const plans = Array.isArray(groups) && groups.length > 0
1255+ ? groups
1256+ : [{
1257+ configs: JSON.parse(process.env.OPENCLAW_NODE_TEST_CONFIGS_JSON ?? "[]"),
1258+ includePatterns: JSON.parse(
1259+ process.env.OPENCLAW_NODE_TEST_INCLUDE_PATTERNS_JSON ?? "null",
1260+ ),
1261+ shard_name: process.env.OPENCLAW_VITEST_SHARD_NAME,
1262+ }];
1263+ for (const plan of plans) {
1264+ const configs = plan.configs;
1265+ if (!Array.isArray(configs) || configs.length === 0) {
1266+ console.error("Missing node test shard configs");
1267+ process.exit(1);
1268+ }
1269+ const childEnv = {
1270+ ...process.env,
1271+ ...(plan.shard_name ? { OPENCLAW_VITEST_SHARD_NAME: plan.shard_name } : {}),
1272+ };
1273+ if (Array.isArray(plan.includePatterns) && plan.includePatterns.length > 0) {
1274+ const includeFile = join(
1275+ process.env.RUNNER_TEMP ?? ".",
1276+ `node-test-include-${process.env.GITHUB_JOB ?? "local"}-${Date.now()}.json`,
1277+ );
1278+ writeFileSync(includeFile, JSON.stringify(plan.includePatterns), "utf8");
1279+ childEnv.OPENCLAW_VITEST_INCLUDE_FILE = includeFile;
1280+ } else {
1281+ delete childEnv.OPENCLAW_VITEST_INCLUDE_FILE;
1282+ }
1283+ const result = spawnSync(
1284+ "pnpm",
1285+ ["exec", "node", "scripts/test-projects.mjs", ...configs],
1286+ {
1287+ env: childEnv,
1288+ stdio: "inherit",
1289+ },
12371290 );
1238- writeFileSync(includeFile, JSON.stringify(includePatterns), "utf8");
1239- childEnv.OPENCLAW_VITEST_INCLUDE_FILE = includeFile;
1240- }
1241-1242- const result = spawnSync("pnpm", ["exec", "node", "scripts/test-projects.mjs", ...configs], {
1243- env: childEnv,
1244- stdio: "inherit",
1245- });
1246- if ((result.status ?? 1) !== 0) {
1247- process.exit(result.status ?? 1);
1291+ if ((result.status ?? 1) !== 0) {
1292+ process.exit(result.status ?? 1);
1293+ }
12481294 }
12491295 EOF
12501296@@ -1259,7 +1305,7 @@ jobs:
12591305timeout-minutes: 20
12601306strategy:
12611307fail-fast: false
1262-max-parallel: 4
1308+max-parallel: 8
12631309matrix:
12641310include:
12651311 - check_name: check-guards
@@ -1401,7 +1447,7 @@ jobs:
14011447timeout-minutes: 20
14021448strategy:
14031449fail-fast: false
1404-max-parallel: 4
1450+max-parallel: 8
14051451matrix:
14061452include:
14071453 - check_name: check-additional-boundaries-a
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。