fix(ci): align docker smoke cache tests and reuse built dist

This commit is contained in:
Vincent Koc
2026-04-15 12:12:51 +01:00
parent bb4498cef7
commit 890e299e30
5 changed files with 50 additions and 19 deletions

View File

@@ -211,4 +211,6 @@ jobs:
OPENCLAW_INSTALL_NONROOT_SKIP_IMAGE_BUILD: ${{ github.event_name == 'pull_request' && '0' || '1' }}
OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT: ${{ github.event_name == 'pull_request' && '1' || '0' }}
OPENCLAW_INSTALL_SMOKE_SKIP_PREVIOUS: "1"
OPENCLAW_INSTALL_SMOKE_UPDATE_DIST_IMAGE: openclaw-dockerfile-smoke:local
OPENCLAW_INSTALL_SMOKE_UPDATE_SKIP_LOCAL_BUILD: "1"
run: bash scripts/test-install-sh-docker.sh

View File

@@ -150,6 +150,7 @@ SKIP_UPDATE="${OPENCLAW_INSTALL_SMOKE_SKIP_UPDATE:-0}"
SKIP_NPM_GLOBAL="${OPENCLAW_INSTALL_SMOKE_SKIP_NPM_GLOBAL:-0}"
UPDATE_BASELINE_VERSION="${OPENCLAW_INSTALL_SMOKE_UPDATE_BASELINE:-2026.4.10}"
UPDATE_PACKAGE_SPEC="${OPENCLAW_INSTALL_SMOKE_UPDATE_PACKAGE_SPEC:-}"
UPDATE_DIST_IMAGE="${OPENCLAW_INSTALL_SMOKE_UPDATE_DIST_IMAGE:-}"
UPDATE_SKIP_LOCAL_BUILD="${OPENCLAW_INSTALL_SMOKE_UPDATE_SKIP_LOCAL_BUILD:-0}"
UPDATE_HOST_ALIAS="${OPENCLAW_INSTALL_SMOKE_UPDATE_HOST:-host.docker.internal}"
UPDATE_PORT="${OPENCLAW_INSTALL_SMOKE_UPDATE_PORT:-}"
@@ -191,6 +192,20 @@ allocate_host_port() {
'
}
restore_local_dist_from_image() {
local image="$1"
local container_id=""
echo "==> Reuse local dist/ from Docker image: $image"
container_id="$(docker create "$image")"
rm -rf "$ROOT_DIR/dist"
if ! docker cp "${container_id}:/app/dist" "$ROOT_DIR/dist"; then
docker rm -f "$container_id" >/dev/null 2>&1 || true
return 1
fi
docker rm -f "$container_id" >/dev/null
}
prepare_update_tarball() {
local pack_json
local baseline_pack_json
@@ -204,7 +219,9 @@ prepare_update_tarball() {
quiet_npm pack "$UPDATE_PACKAGE_SPEC" --json --pack-destination "$UPDATE_DIR" >"$pack_json_file"
else
echo "==> Build local release artifacts for update smoke"
if [[ "$UPDATE_SKIP_LOCAL_BUILD" != "1" ]]; then
if [[ -n "$UPDATE_DIST_IMAGE" ]]; then
restore_local_dist_from_image "$UPDATE_DIST_IMAGE"
elif [[ "$UPDATE_SKIP_LOCAL_BUILD" != "1" ]]; then
pnpm build
pnpm ui:build
fi

View File

@@ -111,7 +111,7 @@ describe("docker build cache layout", () => {
expectPatternBeforeInstall(/^COPY(?:\s+--chown=\S+)?\s+extensions \.\/extensions$/m);
expectPatternBeforeInstall(/^COPY(?:\s+--chown=\S+)?\s+patches \.\/patches$/m);
expectPatternBeforeInstall(
/^COPY(?:\s+--chown=\S+)?\s+scripts\/postinstall-bundled-plugins\.mjs scripts\/npm-runner\.mjs scripts\/windows-cmd-helpers\.mjs \.\/scripts\/$/m,
/^COPY(?:\s+--chown=\S+)?\s+scripts\/postinstall-bundled-plugins\.mjs scripts\/preinstall-package-manager-warning\.mjs scripts\/npm-runner\.mjs scripts\/windows-cmd-helpers\.mjs \.\/scripts\/$/m,
);
expectPatternAfterInstall(
/^COPY(?:\s+--chown=\S+)?\s+tsconfig\.json tsconfig\.plugin-sdk\.dts\.json tsdown\.config\.ts vitest\.config\.ts openclaw\.mjs \.\/$/m,

View File

@@ -46,25 +46,17 @@ function bundledEntry(pluginId: string): string {
}
function unifiedDistGraph(): TsdownConfigEntry | undefined {
return asConfigArray(tsdownConfig).find((config) => entryKeys(config).includes("index"));
return asConfigArray(tsdownConfig).find((config) =>
entryKeys(config).includes("plugins/runtime/index"),
);
}
describe("tsdown config", () => {
it("keeps core, plugin runtime, plugin-sdk, bundled plugins, and bundled hooks in one dist graph", () => {
const configs = asConfigArray(tsdownConfig);
const distGraphs = configs.filter((config) => {
const keys = entryKeys(config);
return (
keys.includes("index") ||
keys.includes("plugins/runtime/index") ||
keys.includes("plugin-sdk/index") ||
keys.includes(bundledEntry("openai")) ||
keys.includes("bundled/boot-md/handler")
);
});
it("keeps core, plugin runtime, plugin-sdk, bundled root plugins, and bundled hooks in one dist graph", () => {
const distGraph = unifiedDistGraph();
expect(distGraphs).toHaveLength(1);
expect(entryKeys(distGraphs[0])).toEqual(
expect(distGraph).toBeDefined();
expect(entryKeys(distGraph as TsdownConfigEntry)).toEqual(
expect.arrayContaining([
"agents/auth-profiles.runtime",
"agents/model-catalog.runtime",
@@ -79,14 +71,25 @@ describe("tsdown config", () => {
"plugin-sdk/compat",
"plugin-sdk/index",
bundledEntry("openai"),
bundledEntry("matrix"),
bundledEntry("msteams"),
bundledEntry("whatsapp"),
"bundled/boot-md/handler",
]),
);
});
it("emits staged bundled plugins as separate extension graphs", () => {
const stagedGraphs = asConfigArray(tsdownConfig).filter(
(config) => typeof config.outDir === "string" && config.outDir.startsWith("dist/extensions/"),
);
expect(stagedGraphs.length).toBeGreaterThan(0);
expect(stagedGraphs.every((config) => entryKeys(config).includes("index"))).toBe(true);
expect(stagedGraphs.every((config) => !entryKeys(config).includes("plugin-sdk/index"))).toBe(
true,
);
expect(stagedGraphs.some((config) => config.outDir === "dist/extensions/discord")).toBe(true);
});
it("does not emit plugin-sdk or hooks from a separate dist graph", () => {
const configs = asConfigArray(tsdownConfig);

View File

@@ -27,6 +27,15 @@ describe("test-install-sh-docker", () => {
);
});
it("can reuse dist from the already-built root Docker smoke image", () => {
const script = readFileSync(SCRIPT_PATH, "utf8");
expect(script).toContain('UPDATE_DIST_IMAGE="${OPENCLAW_INSTALL_SMOKE_UPDATE_DIST_IMAGE:-}"');
expect(script).toContain("restore_local_dist_from_image");
expect(script).toContain('docker cp "${container_id}:/app/dist" "$ROOT_DIR/dist"');
expect(script).toContain('echo "==> Reuse local dist/ from Docker image: $image"');
});
it("prints package size audits for release smoke tarballs", () => {
const script = readFileSync(SCRIPT_PATH, "utf8");