diff --git a/CHANGELOG.md b/CHANGELOG.md index f02c77f5b0fc..540f9f963d2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ Docs: https://docs.openclaw.ai - Telegram/doctor: keep top-level access-control fallback in place during multi-account normalization while still promoting legacy default auth into `accounts.default`, so existing named bots keep inherited allowlists without dropping the legacy default bot. (#62263) Thanks @obviyus. - Agents/subagents: honor `sessions_spawn(lightContext: true)` for spawned subagent runs by preserving lightweight bootstrap context through the gateway and embedded runner instead of silently falling back to full workspace bootstrap injection. (#62264) Thanks @theSamPadilla. - Slack/media: keep attachment downloads on the SSRF-guarded dispatcher path so Slack media fetching works on Node 22 without dropping pinned transport enforcement. (#62239) Thanks @openperf. +- Docker/plugins: stop forcing bundled plugin discovery to `/app/extensions` in runtime images so packaged installs use compiled `dist/extensions` artifacts again and Node 24 containers do not boot through source-only plugin entry paths. Fixes #62044. (#62316) Thanks @gumadeiras. ## 2026.4.5 diff --git a/Dockerfile b/Dockerfile index 7aacb4347974..a431c3616876 100644 --- a/Dockerfile +++ b/Dockerfile @@ -160,10 +160,6 @@ COPY --from=runtime-assets --chown=node:node /app/skills ./skills COPY --from=runtime-assets --chown=node:node /app/docs ./docs COPY --from=runtime-assets --chown=node:node /app/qa ./qa -# In npm-installed Docker images, prefer the copied source extension tree for -# bundled discovery so package metadata that points at source entries stays valid. -ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/${OPENCLAW_BUNDLED_PLUGIN_DIR} - # Keep pnpm available in the runtime image for container-local workflows. # Use a shared Corepack home so the non-root `node` user does not need a # first-run network fetch when invoking pnpm. diff --git a/src/dockerfile.test.ts b/src/dockerfile.test.ts index f23c06fe8bba..1384942866ca 100644 --- a/src/dockerfile.test.ts +++ b/src/dockerfile.test.ts @@ -7,6 +7,10 @@ import { BUNDLED_PLUGIN_ROOT_DIR } from "../test/helpers/bundled-plugin-paths.js const repoRoot = resolve(fileURLToPath(new URL(".", import.meta.url)), ".."); const dockerfilePath = join(repoRoot, "Dockerfile"); +function collapseDockerContinuations(dockerfile: string): string { + return dockerfile.replace(/\\\r?\n[ \t]*/g, " "); +} + describe("Dockerfile", () => { it("uses shared multi-arch base image refs for all root Node stages", async () => { const dockerfile = await readFile(dockerfilePath, "utf8"); @@ -50,12 +54,10 @@ describe("Dockerfile", () => { ); }); - it("pins bundled plugin discovery to copied source extensions in runtime images", async () => { - const dockerfile = await readFile(dockerfilePath, "utf8"); + it("does not override bundled plugin discovery in runtime images", async () => { + const dockerfile = collapseDockerContinuations(await readFile(dockerfilePath, "utf8")); expect(dockerfile).toContain(`ARG OPENCLAW_BUNDLED_PLUGIN_DIR=${BUNDLED_PLUGIN_ROOT_DIR}`); - expect(dockerfile).toContain( - "ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/${OPENCLAW_BUNDLED_PLUGIN_DIR}", - ); + expect(dockerfile).not.toMatch(/^\s*ENV\b[^\n]*\bOPENCLAW_BUNDLED_PLUGINS_DIR\b/m); }); it("normalizes plugin and agent paths permissions in image layers", async () => {