diff --git a/Dockerfile b/Dockerfile index 309ba1d8f..d25924e6f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -134,7 +134,11 @@ RUN openclaw doctor --fix > /dev/null 2>&1 || true \ # The writable state lives in .openclaw-data, reached via the symlinks. # hadolint ignore=DL3002 USER root -RUN chown root:root /sandbox/.openclaw \ +RUN mkdir -p /sandbox/.openclaw-data/telegram \ + && chown -R sandbox:sandbox /sandbox/.openclaw-data/telegram \ + && rm -rf /sandbox/.openclaw/telegram \ + && ln -sfn /sandbox/.openclaw-data/telegram /sandbox/.openclaw/telegram \ + && chown root:root /sandbox/.openclaw \ && find /sandbox/.openclaw -mindepth 1 -maxdepth 1 -exec chown -h root:root {} + \ && chmod 755 /sandbox/.openclaw \ && chmod 444 /sandbox/.openclaw/openclaw.json diff --git a/test/dockerfile-telegram-state.test.js b/test/dockerfile-telegram-state.test.js new file mode 100644 index 000000000..fcf148f95 --- /dev/null +++ b/test/dockerfile-telegram-state.test.js @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { describe, it, expect } from "vitest"; +import fs from "node:fs"; +import path from "node:path"; + +const ROOT = path.resolve(import.meta.dirname, ".."); +const DOCKERFILE = fs.readFileSync(path.join(ROOT, "Dockerfile"), "utf-8"); + +describe("Dockerfile telegram state layout (#975)", () => { + it("precreates writable telegram state under .openclaw-data", () => { + expect(DOCKERFILE.includes("mkdir -p /sandbox/.openclaw-data/telegram")).toBeTruthy(); + expect(DOCKERFILE.includes("chown -R sandbox:sandbox /sandbox/.openclaw-data/telegram")).toBeTruthy(); + }); + + it("symlinks .openclaw/telegram into .openclaw-data before locking .openclaw", () => { + const symlink = DOCKERFILE.indexOf("ln -sfn /sandbox/.openclaw-data/telegram /sandbox/.openclaw/telegram"); + const lockStep = DOCKERFILE.indexOf("chown root:root /sandbox/.openclaw"); + const cleanupBeforeSymlink = DOCKERFILE.indexOf("rm -rf /sandbox/.openclaw/telegram"); + + expect(symlink).toBeGreaterThan(-1); + expect(lockStep).toBeGreaterThan(symlink); + expect(cleanupBeforeSymlink).toBeGreaterThan(-1); + expect(cleanupBeforeSymlink).toBeLessThan(symlink); + }); +});