Skip to content

Commit c0f1646

Browse files
committed
ci(release): smoke Docker runtime templates in full validation
1 parent 11ca150 commit c0f1646

2 files changed

Lines changed: 51 additions & 3 deletions

File tree

.github/workflows/full-release-validation.yml

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ jobs:
225225
} >> "$GITHUB_STEP_SUMMARY"
226226
227227
docker_runtime_assets_preflight:
228-
name: Verify Docker runtime-assets prune path
228+
name: Verify Docker runtime image assets
229229
needs: [resolve_target]
230230
if: inputs.rerun_group == 'all'
231231
runs-on: ubuntu-24.04
@@ -240,15 +240,48 @@ jobs:
240240
fetch-depth: 1
241241
persist-credentials: true
242242

243-
- name: Verify Docker runtime-assets prune path
243+
- name: Build and smoke test final Docker runtime image
244244
env:
245245
DOCKER_BUILDKIT: "1"
246+
TARGET_SHA: ${{ needs.resolve_target.outputs.sha }}
246247
run: |
247248
set -euo pipefail
249+
image_ref="openclaw-release-runtime-smoke:${TARGET_SHA}"
248250
timeout --kill-after=30s 35m docker build \
249-
--target runtime-assets \
250251
--build-arg OPENCLAW_EXTENSIONS="diagnostics-otel,codex" \
252+
-t "${image_ref}" \
251253
.
254+
docker run --rm --entrypoint /bin/sh "${image_ref}" -lc '
255+
set -eu
256+
test -f /app/src/agents/templates/HEARTBEAT.md
257+
temp_root="$(mktemp -d)"
258+
trap "rm -rf \"${temp_root}\"" EXIT
259+
mkdir -p "${temp_root}/home" "${temp_root}/cwd"
260+
cd "${temp_root}/cwd"
261+
set +e
262+
HOME="${temp_root}/home" \
263+
USERPROFILE="${temp_root}/home" \
264+
OPENCLAW_HOME="${temp_root}/home" \
265+
OPENCLAW_NO_ONBOARD=1 \
266+
OPENCLAW_SUPPRESS_NOTES=1 \
267+
OPENCLAW_DISABLE_BUNDLED_PLUGINS=1 \
268+
OPENCLAW_DISABLE_BUNDLED_ENTRY_SOURCE_FALLBACK=1 \
269+
AWS_EC2_METADATA_DISABLED=true \
270+
AWS_SHARED_CREDENTIALS_FILE="${temp_root}/home/.aws/credentials" \
271+
AWS_CONFIG_FILE="${temp_root}/home/.aws/config" \
272+
node /app/openclaw.mjs agent --message "workspace bootstrap smoke" --session-id "workspace-bootstrap-smoke" --local --timeout 1 --json \
273+
>"${temp_root}/out.log" 2>&1
274+
status="$?"
275+
set -e
276+
if grep -F "Missing workspace template:" "${temp_root}/out.log"; then
277+
cat "${temp_root}/out.log"
278+
exit 1
279+
fi
280+
test -f "${temp_root}/home/.openclaw/workspace/HEARTBEAT.md"
281+
if [ "${status}" -ne 0 ]; then
282+
cat "${temp_root}/out.log"
283+
fi
284+
'
252285
253286
normal_ci:
254287
name: Run normal full CI

src/dockerfile.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import YAML from "yaml";
88
const repoRoot = resolve(fileURLToPath(new URL(".", import.meta.url)), "..");
99
const dockerfilePath = join(repoRoot, "Dockerfile");
1010
const dockerReleaseWorkflowPath = join(repoRoot, ".github/workflows/docker-release.yml");
11+
const fullReleaseValidationWorkflowPath = join(
12+
repoRoot,
13+
".github/workflows/full-release-validation.yml",
14+
);
1115
const dockerSetupDockerfilePaths = ["Dockerfile", "scripts/docker/sandbox/Dockerfile"] as const;
1216
const pnpmWorkspacePath = join(repoRoot, "pnpm-workspace.yaml");
1317

@@ -301,6 +305,17 @@ describe("Dockerfile", () => {
301305
expect(workflow).toContain('test -f "${temp_root}/home/.openclaw/workspace/HEARTBEAT.md"');
302306
});
303307

308+
it("keeps runtime workspace template smoke in full release validation", async () => {
309+
const workflow = await readFile(fullReleaseValidationWorkflowPath, "utf8");
310+
311+
expect(workflow).toContain("Build and smoke test final Docker runtime image");
312+
expect(workflow).toContain('-t "${image_ref}"');
313+
expect(workflow).toContain("test -f /app/src/agents/templates/HEARTBEAT.md");
314+
expect(workflow).toContain('grep -F "Missing workspace template:"');
315+
expect(workflow).toContain('test -f "${temp_root}/home/.openclaw/workspace/HEARTBEAT.md"');
316+
expect(workflow).not.toContain("scripts/docker/runtime-workspace-template-smoke.sh");
317+
});
318+
304319
it("does not override bundled plugin discovery in runtime images", async () => {
305320
const dockerfile = collapseDockerContinuations(await readFile(dockerfilePath, "utf8"));
306321
expect(dockerfile).toContain(`ARG OPENCLAW_BUNDLED_PLUGIN_DIR=${BUNDLED_PLUGIN_ROOT_DIR}`);

0 commit comments

Comments
 (0)