mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-25 00:42:24 +00:00
ci: rebalance sharded test lanes
This commit is contained in:
32
.github/workflows/ci-bun.yml
vendored
32
.github/workflows/ci-bun.yml
vendored
@@ -12,7 +12,32 @@ env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
build-bun-artifacts:
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Build A2UI bundle
|
||||
run: pnpm canvas:a2ui:bundle
|
||||
|
||||
- name: Upload A2UI bundle artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: canvas-a2ui-bundle
|
||||
path: src/canvas-host/a2ui/
|
||||
|
||||
bun-checks:
|
||||
needs: [build-bun-artifacts]
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
@@ -37,8 +62,11 @@ jobs:
|
||||
install-bun: "true"
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Build A2UI bundle
|
||||
run: pnpm canvas:a2ui:bundle
|
||||
- name: Download A2UI bundle artifact
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: canvas-a2ui-bundle
|
||||
path: src/canvas-host/a2ui/
|
||||
|
||||
- name: Run Bun test shard
|
||||
run: ${{ matrix.command }}
|
||||
|
||||
9
.github/workflows/ci.yml
vendored
9
.github/workflows/ci.yml
vendored
@@ -257,7 +257,7 @@ jobs:
|
||||
- runtime: node
|
||||
task: channels
|
||||
shard_index: 1
|
||||
shard_count: 2
|
||||
shard_count: 3
|
||||
command: pnpm test:channels
|
||||
- runtime: node
|
||||
task: contracts
|
||||
@@ -265,7 +265,12 @@ jobs:
|
||||
- runtime: node
|
||||
task: channels
|
||||
shard_index: 2
|
||||
shard_count: 2
|
||||
shard_count: 3
|
||||
command: pnpm test:channels
|
||||
- runtime: node
|
||||
task: channels
|
||||
shard_index: 3
|
||||
shard_count: 3
|
||||
command: pnpm test:channels
|
||||
- runtime: node
|
||||
task: protocol
|
||||
|
||||
@@ -807,6 +807,53 @@ const targetedEntries = (() => {
|
||||
return [createTargetedEntry(owner, false, uniqueFilters)];
|
||||
}).flat();
|
||||
})();
|
||||
const estimateTopLevelEntryDurationMs = (entry) => {
|
||||
const filters = getExplicitEntryFilters(entry.args);
|
||||
if (filters.length === 0) {
|
||||
return unitTimingManifest.defaultDurationMs;
|
||||
}
|
||||
return filters.reduce((totalMs, file) => {
|
||||
if (isUnitConfigTestFile(file)) {
|
||||
return totalMs + estimateUnitDurationMs(file);
|
||||
}
|
||||
if (channelTestPrefixes.some((prefix) => file.startsWith(prefix))) {
|
||||
return totalMs + 3_000;
|
||||
}
|
||||
if (file.startsWith("extensions/")) {
|
||||
return totalMs + 2_000;
|
||||
}
|
||||
return totalMs + 1_000;
|
||||
}, 0);
|
||||
};
|
||||
const topLevelSingleShardAssignments = (() => {
|
||||
if (shardIndexOverride === null || shardCount <= 1) {
|
||||
return new Map();
|
||||
}
|
||||
|
||||
// Single-file and other non-shardable explicit lanes would otherwise run on
|
||||
// every shard. Assign them to one top-level shard instead.
|
||||
const entriesNeedingAssignment = runs.filter((entry) => {
|
||||
const explicitFilterCount = countExplicitEntryFilters(entry.args);
|
||||
if (explicitFilterCount === null) {
|
||||
return false;
|
||||
}
|
||||
const effectiveShardCount = Math.min(shardCount, Math.max(1, explicitFilterCount - 1));
|
||||
return effectiveShardCount <= 1;
|
||||
});
|
||||
|
||||
const assignmentMap = new Map();
|
||||
const buckets = packFilesByDuration(
|
||||
entriesNeedingAssignment,
|
||||
shardCount,
|
||||
estimateTopLevelEntryDurationMs,
|
||||
);
|
||||
for (const [bucketIndex, bucket] of buckets.entries()) {
|
||||
for (const entry of bucket) {
|
||||
assignmentMap.set(entry, bucketIndex + 1);
|
||||
}
|
||||
}
|
||||
return assignmentMap;
|
||||
})();
|
||||
// Node 25 local runs still show cross-process worker shutdown contention even
|
||||
// after moving the known heavy files into singleton lanes.
|
||||
const topLevelParallelEnabled =
|
||||
@@ -1258,6 +1305,13 @@ const runOnce = (entry, extraArgs = []) =>
|
||||
|
||||
const run = async (entry, extraArgs = []) => {
|
||||
const explicitFilterCount = countExplicitEntryFilters(entry.args);
|
||||
const topLevelAssignedShard = topLevelSingleShardAssignments.get(entry);
|
||||
if (topLevelAssignedShard !== undefined) {
|
||||
if (shardIndexOverride !== null && shardIndexOverride !== topLevelAssignedShard) {
|
||||
return 0;
|
||||
}
|
||||
return runOnce(entry, extraArgs);
|
||||
}
|
||||
// Vitest requires the shard count to stay strictly below the number of
|
||||
// resolved test files, so explicit-filter lanes need a `< fileCount` cap.
|
||||
const effectiveShardCount =
|
||||
|
||||
Reference in New Issue
Block a user