fix(ci): preserve imported dist chunks after install

This commit is contained in:
Peter Steinberger
2026-04-29 01:12:59 +01:00
parent 054b2e1b7e
commit 03b1731d0f
5 changed files with 110 additions and 4 deletions

View File

@@ -7,7 +7,10 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { LOCAL_BUILD_METADATA_DIST_PATHS } from "./lib/local-build-metadata-paths.mjs";
import { collectPackageDistImportErrors } from "./lib/package-dist-imports.mjs";
import {
collectPackageDistImportErrors,
expandPackageDistImportClosure,
} from "./lib/package-dist-imports.mjs";
function usage() {
return "Usage: node scripts/check-openclaw-package-tarball.mjs <openclaw.tgz>";
@@ -186,6 +189,8 @@ if (entrySet.has("dist/postinstall-inventory.json")) {
if (!Array.isArray(inventory) || inventory.some((entry) => typeof entry !== "string")) {
errors.push("invalid dist/postinstall-inventory.json");
} else {
const normalizedInventory = inventory.map((entry) => entry.replace(/\\/gu, "/"));
const normalizedInventorySet = new Set(normalizedInventory);
for (const inventoryEntry of inventory) {
const normalizedEntry = inventoryEntry.replace(/\\/gu, "/");
if (!entrySet.has(normalizedEntry)) {
@@ -201,6 +206,16 @@ if (entrySet.has("dist/postinstall-inventory.json")) {
errors.push(`inventory references missing tar entry ${normalizedEntry}`);
}
}
const expandedInventory = expandPackageDistImportClosure({
files: normalized,
seedFiles: normalizedInventory,
readText: readTarEntry,
});
for (const importedEntry of expandedInventory) {
if (!normalizedInventorySet.has(importedEntry)) {
errors.push(`inventory omits imported dist file ${importedEntry}`);
}
}
}
} catch (error) {
errors.push(

View File

@@ -113,6 +113,22 @@ export function collectPackageDistImportErrors(params) {
const fileSet = new Set(files);
const errors = [];
for (const { importerPath, importedPath } of collectPackageDistImports({
files,
readText: params.readText,
})) {
if (!fileSet.has(importedPath)) {
errors.push(`${importerPath} imports missing ${importedPath}`);
}
}
return errors;
}
export function collectPackageDistImports(params) {
const files = [...new Set(params.files.map(normalizePackagePath))];
const imports = [];
for (const importerPath of files.toSorted((left, right) => left.localeCompare(right))) {
if (!JS_DIST_FILE_RE.test(importerPath) || importerPath.includes("/node_modules/")) {
continue;
@@ -120,12 +136,35 @@ export function collectPackageDistImportErrors(params) {
const source = params.readText(importerPath);
for (const specifier of collectImportSpecifiers(source)) {
const importedPath = resolveDistImportPath(importerPath, specifier);
if (!importedPath || fileSet.has(importedPath)) {
if (!importedPath) {
continue;
}
errors.push(`${importerPath} imports missing ${importedPath}`);
imports.push({ importerPath, importedPath });
}
}
return errors;
return imports;
}
export function expandPackageDistImportClosure(params) {
const files = [...new Set(params.files.map(normalizePackagePath))];
const fileSet = new Set(files);
const expectedSet = new Set(params.seedFiles.map(normalizePackagePath));
let changed = true;
while (changed) {
changed = false;
for (const { importedPath } of collectPackageDistImports({
files: [...expectedSet].filter((file) => fileSet.has(file)),
readText: params.readText,
})) {
if (!fileSet.has(importedPath) || expectedSet.has(importedPath)) {
continue;
}
expectedSet.add(importedPath);
changed = true;
}
}
return [...expectedSet].toSorted((left, right) => left.localeCompare(right));
}

View File

@@ -23,6 +23,7 @@ import {
} from "node:fs";
import { basename, dirname, isAbsolute, join, relative } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import { expandPackageDistImportClosure } from "./lib/package-dist-imports.mjs";
import { resolveNpmRunner } from "./npm-runner.mjs";
export const BUNDLED_PLUGIN_INSTALL_TARGETS = [];
@@ -292,6 +293,16 @@ export function pruneInstalledPackageDist(params = {}) {
}
}
const installedFiles = listInstalledDistFiles(params);
const readFile = params.readFileSync ?? readFileSync;
expectedFiles = new Set(
expandPackageDistImportClosure({
files: installedFiles,
seedFiles: [...expectedFiles],
readText(relativePath) {
return readFile(join(packageRoot, relativePath), "utf8");
},
}),
);
const removed = [];
for (const relativePath of installedFiles) {