mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
119 lines
3.3 KiB
JavaScript
119 lines
3.3 KiB
JavaScript
// Plans grouped targeted Docker lane matrix entries without installed dependencies.
|
|
import { fileURLToPath } from "node:url";
|
|
import { parsePositiveInt } from "./lib/numeric-options.mjs";
|
|
|
|
const BASELINE_SHARDED_LANES = new Set(["published-upgrade-survivor", "update-migration"]);
|
|
|
|
function splitTokens(raw) {
|
|
return [
|
|
...new Set(
|
|
String(raw ?? "")
|
|
.split(/[,\s]+/u)
|
|
.map((token) => token.trim())
|
|
.filter(Boolean),
|
|
),
|
|
];
|
|
}
|
|
|
|
function sanitizeLabel(value) {
|
|
return (
|
|
String(value)
|
|
.replace(/^openclaw@/u, "")
|
|
.replace(/[^A-Za-z0-9._-]+/g, "-")
|
|
.replace(/^-+|-+$/g, "") || "targeted"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Groups selected Docker lanes and expands sharded upgrade-survivor baselines.
|
|
*
|
|
* @param {{
|
|
* groupSize?: number | string;
|
|
* lanes?: string;
|
|
* upgradeSurvivorBaselines?: string;
|
|
* upgradeSurvivorScenarios?: string;
|
|
* }} [options]
|
|
* @returns {{
|
|
* docker_lanes: string;
|
|
* label: string;
|
|
* published_upgrade_survivor_baselines?: string;
|
|
* timeout_minutes?: number;
|
|
* }[]}
|
|
*/
|
|
export function planTargetedDockerLaneGroups({
|
|
groupSize = 1,
|
|
lanes,
|
|
upgradeSurvivorBaselines = "",
|
|
upgradeSurvivorScenarios = "",
|
|
} = {}) {
|
|
const selectedLanes = splitTokens(lanes);
|
|
if (selectedLanes.length === 0) {
|
|
throw new Error("docker_lanes is required when planning targeted Docker lane groups.");
|
|
}
|
|
|
|
const parsedGroupSize = parsePositiveInt(groupSize, "groupSize");
|
|
const baselineSpecs = splitTokens(upgradeSurvivorBaselines);
|
|
const hasExpandedSurvivorScenarios = splitTokens(upgradeSurvivorScenarios).length > 0;
|
|
const groups = [];
|
|
let pendingLanes = [];
|
|
|
|
const addGroup = (group) => {
|
|
const groupLanes = splitTokens(group.docker_lanes);
|
|
if (
|
|
hasExpandedSurvivorScenarios &&
|
|
groupLanes.some((lane) => BASELINE_SHARDED_LANES.has(lane))
|
|
) {
|
|
group.timeout_minutes = 90;
|
|
}
|
|
groups.push(group);
|
|
};
|
|
|
|
const flushPending = () => {
|
|
if (pendingLanes.length === 0) {
|
|
return;
|
|
}
|
|
const first = sanitizeLabel(pendingLanes[0]);
|
|
const last = sanitizeLabel(pendingLanes[pendingLanes.length - 1]);
|
|
const label = pendingLanes.length === 1 ? first : `${first}--${last}`;
|
|
addGroup({ docker_lanes: pendingLanes.join(" "), label });
|
|
pendingLanes = [];
|
|
};
|
|
|
|
for (const lane of selectedLanes) {
|
|
if (BASELINE_SHARDED_LANES.has(lane) && baselineSpecs.length > 1) {
|
|
flushPending();
|
|
for (const baselineSpec of baselineSpecs) {
|
|
addGroup({
|
|
docker_lanes: lane,
|
|
label: `${sanitizeLabel(lane)}-${sanitizeLabel(baselineSpec)}`,
|
|
published_upgrade_survivor_baselines: baselineSpec,
|
|
});
|
|
}
|
|
continue;
|
|
}
|
|
|
|
pendingLanes.push(lane);
|
|
if (pendingLanes.length >= parsedGroupSize) {
|
|
flushPending();
|
|
}
|
|
}
|
|
|
|
flushPending();
|
|
return groups;
|
|
}
|
|
|
|
const isMain = process.argv[1] ? fileURLToPath(import.meta.url) === process.argv[1] : false;
|
|
|
|
if (isMain) {
|
|
process.stdout.write(
|
|
JSON.stringify(
|
|
planTargetedDockerLaneGroups({
|
|
groupSize: process.env.GROUP_SIZE,
|
|
lanes: process.env.LANES,
|
|
upgradeSurvivorBaselines: process.env.OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS,
|
|
upgradeSurvivorScenarios: process.env.OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS,
|
|
}),
|
|
),
|
|
);
|
|
}
|