ci: keep heavy plugin sweeps release-only

This commit is contained in:
Peter Steinberger
2026-04-29 06:49:00 +01:00
parent cfcb8f4eda
commit fda8cc2a9d
5 changed files with 30 additions and 7 deletions
+5 -4
View File
@@ -143,10 +143,11 @@ artifact reuse, and sharding instead. The parent verifier job appends
slowest-job tables for child runs; rerun only that verifier after a child rerun
turns green.
Standalone manual `CI` dispatches do not run the plugin prerelease suite. That
suite is intentionally reserved for the Full Release Validation CI child so PRs,
main pushes, and ad hoc broad CI checks do not spend Docker/package time on
release-only plugin product coverage.
Standalone manual `CI` dispatches do not run the plugin prerelease suite, the
extension batch sweep, or the release-only `agentic-plugins` Vitest shard. Those
lanes are intentionally reserved for the Full Release Validation CI child so
PRs, main pushes, and ad hoc broad CI checks do not spend Docker/package time or
all-plugin runtime time on release-only product coverage.
If a full run is already active on a newer `origin/main`, prefer watching that
run over dispatching a duplicate. If you accidentally dispatch a stale duplicate,
+6 -2
View File
@@ -199,6 +199,8 @@ jobs:
: process.env.OPENCLAW_CI_CHECKOUT_REVISION;
let runPluginPrereleaseSuite =
isFullReleaseValidationCiRun && runNodeFull && isCanonicalRepository;
const runReleaseOnlyPluginSuites =
isFullReleaseValidationCiRun && runNodeFull && isCanonicalRepository;
let pluginPrereleasePlan = { staticChecks: [], dockerLanes: [] };
if (runPluginPrereleaseSuite) {
try {
@@ -228,7 +230,7 @@ jobs:
? DEFAULT_EXTENSION_TEST_SHARD_COUNT
: Math.max(DEFAULT_EXTENSION_TEST_SHARD_COUNT, 36);
const extensionShardMatrix = createMatrix(
runNodeFull
runReleaseOnlyPluginSuites
? createExtensionTestShards({
shardCount: extensionTestShardCount,
}).map((shard) => ({
@@ -271,7 +273,9 @@ jobs:
}
const nodeTestShards = runNodeFull
? createNodeTestShards().map((shard) => ({
? createNodeTestShards({
includeReleaseOnlyPluginShards: runReleaseOnlyPluginSuites,
}).map((shard) => ({
check_name: shard.checkName,
runtime: "node",
task: "test-shard",
+1
View File
@@ -408,6 +408,7 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
- Import-light unit tests from agents, commands, plugins, auto-reply helpers, `plugin-sdk`, and similar pure utility areas route through the `unit-fast` lane, which skips `test/setup-openclaw-runtime.ts`; stateful/runtime-heavy files stay on the existing lanes.
- Selected `plugin-sdk` and `commands` helper source files also map changed-mode runs to explicit sibling tests in those light lanes, so helper edits avoid rerunning the full heavy suite for that directory.
- `auto-reply` has dedicated buckets for top-level core helpers, top-level `reply.*` integration tests, and the `src/auto-reply/reply/**` subtree. CI further splits the reply subtree into agent-runner, dispatch, and commands/state-routing shards so one import-heavy bucket does not own the full Node tail.
- Normal PR/main CI intentionally skips the extension batch sweep and release-only `agentic-plugins` shard. Full Release Validation dispatches the CI child with `full_release_validation=true`, which turns those plugin/extension-heavy suites back on for release candidates.
</Accordion>
+11 -1
View File
@@ -10,6 +10,7 @@ const EXCLUDED_FULL_SUITE_SHARDS = new Set([
]);
const EXCLUDED_PROJECT_CONFIGS = new Set(["test/vitest/vitest.channels.config.ts"]);
const RELEASE_ONLY_PLUGIN_SHARDS = new Set(["agentic-plugins"]);
function listTestFiles(rootDir) {
if (!existsSync(rootDir)) {
return [];
@@ -288,7 +289,9 @@ function formatNodeTestShardCheckName(shardName) {
return `checks-node-${normalizedShardName}`;
}
export function createNodeTestShards() {
export function createNodeTestShards(options = {}) {
const includeReleaseOnlyPluginShards = options.includeReleaseOnlyPluginShards ?? true;
return fullSuiteVitestShards.flatMap((shard) => {
if (EXCLUDED_FULL_SUITE_SHARDS.has(shard.config)) {
return [];
@@ -302,6 +305,13 @@ export function createNodeTestShards() {
const splitShards = SPLIT_NODE_SHARDS.get(shard.name);
if (splitShards) {
return splitShards.flatMap((splitShard) => {
if (
RELEASE_ONLY_PLUGIN_SHARDS.has(splitShard.shardName) &&
!includeReleaseOnlyPluginShards
) {
return [];
}
const splitConfigs = splitShard.includeExternalConfigs
? splitShard.configs
: splitShard.configs.filter((config) => configs.includes(config));
+7
View File
@@ -276,6 +276,13 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => {
);
});
it("keeps expensive plugin shards release-only when normal CI asks for the cheaper plan", () => {
const shards = createNodeTestShards({ includeReleaseOnlyPluginShards: false });
expect(shards.some((shard) => shard.shardName === "agentic-plugins")).toBe(false);
expect(shards.some((shard) => shard.shardName === "agentic-plugin-sdk")).toBe(true);
});
it("splits auto-reply into balanced core/top-level and reply subtree shards", () => {
const shards = createNodeTestShards();
const autoReplyShards = shards