fix: stabilize release smoke reruns

This commit is contained in:
Peter Steinberger
2026-04-19 09:04:58 +01:00
parent 6682b12563
commit 8c4ecf42df
4 changed files with 65 additions and 3 deletions

View File

@@ -2349,6 +2349,7 @@ run_fresh_main_lane() {
FRESH_MAIN_VERSION="$(extract_last_version "$(phase_log_path "$install_log_phase")")"
phase_run "fresh.verify-main-version" "$TIMEOUT_VERIFY_S" verify_target_version || return $?
phase_run "fresh.onboard-ref" "$TIMEOUT_ONBOARD_PHASE_S" run_ref_onboard || return $?
phase_run "fresh.gateway-restart" "$TIMEOUT_GATEWAY_S" restart_gateway || return $?
phase_run "fresh.gateway-status" "$TIMEOUT_GATEWAY_S" verify_gateway_reachable || return $?
FRESH_GATEWAY_STATUS="pass"
phase_run "fresh.first-agent-turn" "$TIMEOUT_AGENT_S" verify_turn || return $?

View File

@@ -241,12 +241,14 @@ function collectInstalledRuntimeDependencyRoots(
rootNodeModulesDir,
dependencySpecs,
directDependencyPackageRoot = null,
optionalDependencyNames = new Set(),
) {
const packageCache = new Map();
const directRoots = [];
const allRoots = [];
const queue = Object.entries(dependencySpecs).map(([depName, spec]) => ({
depName,
optional: optionalDependencyNames.has(depName),
spec,
parentPackageRoot: directDependencyPackageRoot,
direct: true,
@@ -263,6 +265,9 @@ function collectInstalledRuntimeDependencyRoots(
rootNodeModulesDir,
});
if (depRoot === null) {
if (current.optional) {
continue;
}
return null;
}
const canonicalDepRoot = fs.realpathSync(depRoot);
@@ -285,6 +290,7 @@ function collectInstalledRuntimeDependencyRoots(
for (const [childName, childSpec] of Object.entries(packageJson.dependencies ?? {})) {
queue.push({
depName: childName,
optional: false,
spec: childSpec,
parentPackageRoot: depRoot,
direct: false,
@@ -293,6 +299,7 @@ function collectInstalledRuntimeDependencyRoots(
for (const [childName, childSpec] of Object.entries(packageJson.optionalDependencies ?? {})) {
queue.push({
depName: childName,
optional: true,
spec: childSpec,
parentPackageRoot: depRoot,
direct: false,
@@ -391,6 +398,7 @@ function resolveInstalledDirectDependencyNames(
rootNodeModulesDir,
dependencySpecs,
directDependencyPackageRoot = null,
optionalDependencyNames = new Set(),
) {
const directDependencyNames = [];
for (const [depName, spec] of Object.entries(dependencySpecs)) {
@@ -401,6 +409,9 @@ function resolveInstalledDirectDependencyNames(
rootNodeModulesDir,
});
if (depRoot === null) {
if (optionalDependencyNames.has(depName)) {
continue;
}
return null;
}
const installedVersion = readInstalledDependencyVersionFromRoot(depRoot);
@@ -463,6 +474,7 @@ function resolveInstalledRuntimeClosureFingerprint(params) {
params.rootNodeModulesDir,
dependencySpecs,
params.directDependencyPackageRoot,
new Set(Object.keys(params.packageJson.optionalDependencies ?? {})),
);
if (resolution === null) {
return null;
@@ -890,6 +902,7 @@ function stageInstalledRootRuntimeDeps(params) {
...packageJson.dependencies,
...packageJson.optionalDependencies,
};
const optionalDependencyNames = new Set(Object.keys(packageJson.optionalDependencies ?? {}));
const rootNodeModulesDir = path.join(repoRoot, "node_modules");
if (Object.keys(dependencySpecs).length === 0 || !fs.existsSync(rootNodeModulesDir)) {
return false;
@@ -899,6 +912,7 @@ function stageInstalledRootRuntimeDeps(params) {
rootNodeModulesDir,
dependencySpecs,
directDependencyPackageRoot,
optionalDependencyNames,
);
if (directDependencyNames === null) {
return false;
@@ -907,15 +921,25 @@ function stageInstalledRootRuntimeDeps(params) {
rootNodeModulesDir,
dependencySpecs,
directDependencyPackageRoot,
optionalDependencyNames,
);
if (resolution === null) {
return false;
}
const rootsToCopy = selectRuntimeDependencyRootsToCopy(resolution);
const allowedRealRoots = rootsToCopy.map((record) => record.realRoot);
const nodeModulesDir = path.join(pluginDir, "node_modules");
const stampPath = resolveRuntimeDepsStampPath(pluginDir);
if (rootsToCopy.length === 0) {
assertPathIsNotSymlink(nodeModulesDir, "remove runtime deps");
removePathIfExists(nodeModulesDir);
writeJsonAtomically(stampPath, {
fingerprint,
generatedAt: new Date().toISOString(),
});
return true;
}
const allowedRealRoots = rootsToCopy.map((record) => record.realRoot);
const stagedNodeModulesDir = path.join(
makePluginOwnedTempDir(pluginDir, "stage"),
"node_modules",

View File

@@ -362,6 +362,43 @@ describe("stageBundledPluginRuntimeDeps", () => {
expect(fs.existsSync(path.join(pluginDir, ".openclaw-runtime-deps-stamp.json"))).toBe(true);
});
it("skips missing optional runtime deps when copying the installed closure", () => {
const { pluginDir, repoRoot } = createBundledPluginFixture({
packageJson: {
name: "@openclaw/fixture-plugin",
version: "1.0.0",
dependencies: { direct: "1.0.0" },
optionalDependencies: { missingOptional: "1.0.0" },
openclaw: { bundle: { stageRuntimeDependencies: true } },
},
});
const directDir = path.join(repoRoot, "node_modules", "direct");
fs.mkdirSync(directDir, { recursive: true });
fs.writeFileSync(
path.join(directDir, "package.json"),
'{ "name": "direct", "version": "1.0.0", "optionalDependencies": { "native-extra": "1.0.0" } }\n',
"utf8",
);
fs.writeFileSync(path.join(directDir, "index.js"), "module.exports = 1;\n", "utf8");
let installCount = 0;
stageBundledPluginRuntimeDeps({
cwd: repoRoot,
installPluginRuntimeDepsImpl: () => {
installCount += 1;
},
});
expect(installCount).toBe(0);
expect(
fs.readFileSync(path.join(pluginDir, "node_modules", "direct", "index.js"), "utf8"),
).toBe("module.exports = 1;\n");
expect(fs.existsSync(path.join(pluginDir, "node_modules", "missingOptional"))).toBe(false);
expect(
fs.existsSync(path.join(pluginDir, "node_modules", "direct", "node_modules", "native-extra")),
).toBe(false);
});
it("prunes staged test cargo from copied runtime dependencies", () => {
const { pluginDir, repoRoot } = createBundledPluginFixture({
packageJson: {

View File

@@ -611,7 +611,7 @@ function normalizePersistedDeliveryChannel(
return channel;
}
function buildFailureAlert(form: CronFormState, existingChannel?: string | undefined) {
function buildFailureAlert(form: CronFormState, existingChannel?: string) {
if (form.failureAlertMode === "disabled") {
return false as const;
}