fix(ci): shard fast extension checks

This commit is contained in:
Vincent Koc
2026-03-31 15:58:50 +09:00
parent a6046c94f7
commit 2feb83babb
4 changed files with 38 additions and 3 deletions

View File

@@ -302,11 +302,17 @@ jobs:
- name: Run ${{ matrix.task }} (${{ matrix.runtime }})
env:
TASK: ${{ matrix.task }}
SHARD_COUNT: ${{ matrix.shard_count || '' }}
SHARD_INDEX: ${{ matrix.shard_index || '' }}
shell: bash
run: |
set -euo pipefail
case "$TASK" in
extensions)
if [ -n "$SHARD_COUNT" ] && [ -n "$SHARD_INDEX" ]; then
export OPENCLAW_TEST_SHARDS="$SHARD_COUNT"
export OPENCLAW_TEST_SHARD_INDEX="$SHARD_INDEX"
fi
pnpm test:extensions
;;
contracts|contracts-protocol)

View File

@@ -53,6 +53,10 @@ OpenClaw has three public release lanes:
- npm release preflight fails closed unless the tarball includes both
`dist/control-ui/index.html` and a non-empty `dist/control-ui/assets/` payload
so we do not ship an empty browser dashboard again
- If the release work touched CI planning, extension timing manifests, or fast
test matrices, regenerate and review the planner-owned `checks-fast-extensions`
shard plan via `node scripts/ci-write-manifest-outputs.mjs --workflow ci`
before approval so release notes do not describe a stale CI layout
- Stable macOS release readiness also includes the updater surfaces:
- the GitHub release must end up with the packaged `.zip`, `.dmg`, and `.dSYM.zip`
- `appcast.xml` on `main` must point at the new stable zip after publish

View File

@@ -1223,6 +1223,9 @@ export function buildCIExecutionManifest(scopeInput = {}, options = {}) {
const channelCandidateFiles = context.catalog.allKnownTestFiles.filter((file) =>
context.catalog.channelTestPrefixes.some((prefix) => file.startsWith(prefix)),
);
const extensionCandidateFiles = context.catalog.allKnownTestFiles.filter((file) =>
file.startsWith(BUNDLED_PLUGIN_PATH_PREFIX),
);
const unitShardCount = resolveDynamicShardCount({
estimatedDurationMs: sumKnownManifestDurationsMs(context.unitTimingManifest),
fileCount: context.catalog.allKnownUnitFiles.length,
@@ -1256,15 +1259,24 @@ export function buildCIExecutionManifest(scopeInput = {}, options = {}) {
maxShards: 9,
});
const bunShardCount = windowsShardCount;
const extensionFastShardCount = resolveDynamicShardCount({
estimatedDurationMs: sumKnownManifestDurationsMs(context.extensionTimingManifest),
fileCount: extensionCandidateFiles.length,
targetDurationMs: 120_000,
targetFilesPerShard: 140,
minShards: 4,
maxShards: 5,
});
const checksFastInclude = nodeEligible
? [
{
check_name: "checks-fast-extensions",
...createShardMatrixEntries({
checkNamePrefix: "checks-fast-extensions",
runtime: "node",
task: "extensions",
command: "pnpm test:extensions",
},
shardCount: extensionFastShardCount,
}),
{
check_name: "checks-fast-contracts-protocol",
runtime: "node",
@@ -1395,6 +1407,7 @@ export function buildCIExecutionManifest(scopeInput = {}, options = {}) {
shardCounts: {
unit: unitShardCount,
channels: channelShardCount,
extensionFast: extensionFastShardCount,
windows: windowsShardCount,
macosNode: macosNodeShardCount,
bun: bunShardCount,

View File

@@ -574,6 +574,8 @@ describe("test planner", () => {
expect(manifest.jobs.buildArtifacts.enabled).toBe(true);
expect(manifest.shardCounts.unit).toBe(4);
expect(manifest.shardCounts.channels).toBe(3);
expect(manifest.shardCounts.extensionFast).toBeGreaterThanOrEqual(4);
expect(manifest.shardCounts.extensionFast).toBeLessThanOrEqual(5);
expect(manifest.shardCounts.windows).toBe(6);
expect(manifest.shardCounts.macosNode).toBe(9);
expect(manifest.shardCounts.bun).toBe(6);
@@ -581,6 +583,16 @@ describe("test planner", () => {
expect(manifest.jobs.checksWindows.matrix.include).toHaveLength(6);
expect(manifest.jobs.bunChecks.matrix.include).toHaveLength(6);
expect(manifest.jobs.macosNode.matrix.include).toHaveLength(9);
expect(manifest.jobs.checksFast.matrix.include).toHaveLength(
manifest.shardCounts.extensionFast + 1,
);
expect(
manifest.jobs.checksFast.matrix.include
.filter((entry) => entry.task === "extensions")
.every(
(entry) => typeof entry.shard_count === "number" && typeof entry.shard_index === "number",
),
).toBe(true);
expect(manifest.jobs.macosSwift.enabled).toBe(true);
expect(manifest.requiredCheckNames).toContain("macos-swift");
expect(manifest.requiredCheckNames).not.toContain("macos-swift-lint");