Files
openclaw/scripts/e2e/Dockerfile
Peter Steinberger f6131a4fbf build(deps): remove npm shrinkwrap; mirror pnpm lock into transient package locks (#114006)
* build(deps): remove npm shrinkwrap; mirror pnpm lock into transient package locks

npm 12 removed shrinkwrap (command + tarball/root loading). Delete all 82
committed npm-shrinkwrap.json files and stop publishing lockfiles; keep
pnpm-lock.yaml as the single reviewed dependency boundary. The generator
becomes scripts/generate-npm-package-lock.mjs and feeds plugin bundling via
a transient package-lock.json + npm ci (works on npm 11 and 12). Tarball
validation treats the published 2026.7.2 beta train as a shrinkwrap
transition; self-update npm detection now uses install topology instead of
the shipped shrinkwrap.

* fix(deps): repair lint, deadcode, and test-type lanes for the npm 12 migration

- sort integrity comparisons with an explicit comparator (oxlint)
- keep resolveBunGlobalNodeModules module-local (knip unused-export gate)
- model npm pack --json as npm<=11 array / npm 12 name-keyed object
- default calver destructuring in the tarball test fixture
2026-07-26 01:29:55 -04:00

105 lines
4.3 KiB
Docker

# syntax=docker/dockerfile:1.7
#
# Shared Docker E2E image.
# `bare` is a clean Node/Git runner for install/update lanes. `functional`
# installs the prepared OpenClaw npm tarball into /app for built-app lanes.
FROM node:24-bookworm-slim@sha256:6f7b03f7c2c8e2e784dcf9295400527b9b1270fd37b7e9a7285cf83b6951452d AS e2e-runner
# openssl provisions short-lived fixture certificates for HTTPS-only provider
# routes. python3 covers package/plugin install paths that execute helper scripts.
# procps provides pgrep for E2E watchdogs that assert no package-manager work is
# still running after Gateway readiness.
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates git openssl procps python3 \
&& rm -rf /var/lib/apt/lists/*
RUN corepack enable
RUN npm install -g tsx@4.21.0 --no-fund --no-audit
RUN useradd --create-home --shell /bin/bash appuser \
&& mkdir -p /app \
&& chown appuser:appuser /app
ENV HOME="/home/appuser"
ENV PATH="/home/appuser/.local/bin:${PATH}"
ENV NODE_OPTIONS="--disable-warning=ExperimentalWarning"
# Docker E2E lanes start many loopback gateways concurrently; mDNS advertising
# is unrelated to those checks and can flap under container CPU/network load.
ENV OPENCLAW_DISABLE_BONJOUR="1"
USER appuser
WORKDIR /app
FROM e2e-runner AS bare
CMD ["bash"]
FROM bare AS build
CMD ["bash"]
FROM bare AS functional-manifest
# Per-PR tarballs differ only in built app bytes. Extract the dependency
# manifest alone so the expensive install layer below is keyed on it and stays
# a warm-cache hit until dependencies actually change.
COPY --from=openclaw_package --chown=appuser:appuser openclaw-current.tgz /tmp/openclaw-current.tgz
# Bundled dependencies ship inside the tarball, and the packaged lifecycle
# scripts reference files outside this manifest-only tree. Drop both plus dev
# dependencies so the install below reifies registry dependencies only.
RUN <<'PREPARE_MANIFEST'
set -eu
mkdir -p /tmp/openclaw-deps
tar -xzf /tmp/openclaw-current.tgz -C /tmp/openclaw-deps --strip-components=1 \
package/package.json
node - <<'NODE'
const fs = require("node:fs");
const manifestPath = "/tmp/openclaw-deps/package.json";
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
for (const name of manifest.bundleDependencies ?? []) {
delete manifest.dependencies?.[name];
}
delete manifest.bundleDependencies;
delete manifest.devDependencies;
delete manifest.scripts;
fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
NODE
PREPARE_MANIFEST
FROM bare AS functional-deps
# Cache key: normalized manifest contents only, so unchanged dependencies skip
# the full reify.
COPY --from=functional-manifest --chown=appuser:appuser /tmp/openclaw-deps /tmp/openclaw-deps
# Drop npm's hidden tree manifest so the copied node_modules matches a plain
# package install.
# The pinned Node image owns uid 1000, so useradd assigns appuser uid/gid 1001.
RUN --mount=type=cache,target=/home/appuser/.npm,uid=1001,gid=1001,sharing=locked \
cd /tmp/openclaw-deps \
&& npm install --omit=dev --no-fund --no-audit \
&& rm -f node_modules/.package-lock.json
FROM bare AS functional
# The app under test enters through the named BuildKit context, not by copying
# checkout sources into the image.
COPY --from=openclaw_package --chown=appuser:appuser openclaw-current.tgz /tmp/openclaw-current.tgz
COPY --from=functional-deps --chown=appuser:appuser /tmp/openclaw-deps/node_modules /app/node_modules
# Extract the package over the prebuilt dependency tree (bundled deps ship in
# the tarball), then run its packaged postinstall. Functional E2E lanes exercise
# private bundled plugins too, so skip the production migration's intentionally
# curated persisted registry in this test image. The /app/node_modules/openclaw
# self-link preserves package self-reference imports such as
# openclaw/plugin-sdk/*; create it after postinstall so its prune walks cannot
# cycle through the link.
RUN tar -xzf /tmp/openclaw-current.tgz -C /app --strip-components=1 \
&& chmod +x /app/openclaw.mjs \
&& node --input-type=module -e "import { runBundledPluginPostinstall } from '/app/scripts/postinstall-bundled-plugins.mjs'; runBundledPluginPostinstall();" \
&& ln -sfn /app /app/node_modules/openclaw \
&& mkdir -p "$HOME/.local/bin" \
&& ln -sf /app/openclaw.mjs "$HOME/.local/bin/openclaw" \
&& rm -f /tmp/openclaw-current.tgz
CMD ["bash"]