mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
fix(e2e): clean functional Docker build inputs
This commit is contained in:
@@ -67,20 +67,39 @@ docker_e2e_build_or_reuse() {
|
||||
|
||||
echo "Building Docker image: $image_name"
|
||||
local build_args=()
|
||||
local package_tgz=""
|
||||
local package_context=""
|
||||
local package_pack_dir=""
|
||||
if [ -n "$target" ]; then
|
||||
build_args+=(--target "$target")
|
||||
fi
|
||||
if [ "$target" = "functional" ]; then
|
||||
local package_tgz
|
||||
local package_context
|
||||
package_tgz="$(docker_e2e_prepare_package_tgz "$label")"
|
||||
package_context="$(docker_e2e_prepare_package_context "$package_tgz")"
|
||||
if [ -z "${OPENCLAW_CURRENT_PACKAGE_TGZ:-}" ]; then
|
||||
package_pack_dir="$(dirname "$package_tgz")"
|
||||
fi
|
||||
local context_status=0
|
||||
package_context="$(docker_e2e_prepare_package_context "$package_tgz")" || context_status="$?"
|
||||
if [ "$context_status" -ne 0 ]; then
|
||||
if [ -n "$package_pack_dir" ]; then
|
||||
rm -rf "$package_pack_dir"
|
||||
fi
|
||||
return "$context_status"
|
||||
fi
|
||||
# The Dockerfile never sees repo sources as app input; functional installs
|
||||
# exactly this tarball through a named BuildKit context.
|
||||
build_args+=(--build-context "openclaw_package=$package_context")
|
||||
fi
|
||||
build_args+=(-t "$image_name" -f "$dockerfile" "$context")
|
||||
docker_build_run "$label-build" "${build_args[@]}"
|
||||
local build_status=0
|
||||
docker_build_run "$label-build" "${build_args[@]}" || build_status="$?"
|
||||
if [ -n "$package_context" ]; then
|
||||
rm -rf "$package_context"
|
||||
fi
|
||||
if [ -n "$package_pack_dir" ]; then
|
||||
rm -rf "$package_pack_dir"
|
||||
fi
|
||||
return "$build_status"
|
||||
}
|
||||
|
||||
docker_e2e_test_state_shell_b64() {
|
||||
|
||||
@@ -31,13 +31,19 @@ docker_e2e_prepare_package_tgz() {
|
||||
|
||||
local pack_dir
|
||||
pack_dir="$(mktemp -d "${TMPDIR:-/tmp}/openclaw-docker-e2e-pack.XXXXXX")"
|
||||
local pack_status=0
|
||||
package_tgz="$(
|
||||
node "$ROOT_DIR/scripts/package-openclaw-for-docker.mjs" \
|
||||
--output-dir "$pack_dir" \
|
||||
--output-name openclaw-current.tgz
|
||||
)"
|
||||
)" || pack_status="$?"
|
||||
if [ "$pack_status" -ne 0 ]; then
|
||||
rm -rf "$pack_dir"
|
||||
return "$pack_status"
|
||||
fi
|
||||
if [ -z "$package_tgz" ]; then
|
||||
echo "missing packed OpenClaw tarball" >&2
|
||||
rm -rf "$pack_dir"
|
||||
return 1
|
||||
fi
|
||||
docker_e2e_abs_path "$package_tgz"
|
||||
@@ -49,7 +55,12 @@ docker_e2e_prepare_package_context() {
|
||||
context_dir="$(mktemp -d "${TMPDIR:-/tmp}/openclaw-docker-e2e-package-context.XXXXXX")"
|
||||
# BuildKit named contexts must be directories, so expose the tarball as a
|
||||
# stable filename inside a tiny temporary context.
|
||||
cp "$package_tgz" "$context_dir/openclaw-current.tgz"
|
||||
local copy_status=0
|
||||
cp "$package_tgz" "$context_dir/openclaw-current.tgz" || copy_status="$?"
|
||||
if [ "$copy_status" -ne 0 ]; then
|
||||
rm -rf "$context_dir"
|
||||
return "$copy_status"
|
||||
fi
|
||||
printf '%s\n' "$context_dir"
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,10 @@ const CENTRALIZED_BUILD_SCRIPTS = [
|
||||
"scripts/test-live-build-docker.sh",
|
||||
] as const;
|
||||
|
||||
function shellQuote(value: string): string {
|
||||
return `'${value.replace(/'/gu, `'\\''`)}'`;
|
||||
}
|
||||
|
||||
describe("docker build helper", () => {
|
||||
it("forces BuildKit for centralized Docker builds", () => {
|
||||
const helper = readFileSync(HELPER_PATH, "utf8");
|
||||
@@ -109,6 +113,148 @@ describe("docker build helper", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("removes functional Docker build package inputs after the build", () => {
|
||||
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-build-cleanup-"));
|
||||
|
||||
try {
|
||||
const rootDir = process.cwd();
|
||||
const script = `
|
||||
set -euo pipefail
|
||||
ROOT_DIR=${shellQuote(rootDir)}
|
||||
TMPDIR=${shellQuote(workDir)}
|
||||
export ROOT_DIR TMPDIR
|
||||
|
||||
node() {
|
||||
local script="$1"
|
||||
shift
|
||||
if [[ "$script" != "$ROOT_DIR/scripts/package-openclaw-for-docker.mjs" ]]; then
|
||||
command node "$script" "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
local output_dir=""
|
||||
local output_name=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--output-dir)
|
||||
output_dir="$2"
|
||||
shift 2
|
||||
;;
|
||||
--output-name)
|
||||
output_name="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
mkdir -p "$output_dir"
|
||||
printf fixture >"$output_dir/$output_name"
|
||||
printf "%s\\n" "$output_dir/$output_name"
|
||||
}
|
||||
export -f node
|
||||
|
||||
source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh"
|
||||
|
||||
docker_build_run() {
|
||||
local build_context=""
|
||||
local arg
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
openclaw_package=*)
|
||||
build_context="\${arg#openclaw_package=}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -n "$build_context"
|
||||
test -f "$build_context/openclaw-current.tgz"
|
||||
printf "%s\\n" "$build_context" >"$TMPDIR/build-context-seen"
|
||||
}
|
||||
|
||||
docker_e2e_build_or_reuse \\
|
||||
openclaw-test-image \\
|
||||
cleanup-proof \\
|
||||
"$ROOT_DIR/scripts/e2e/Dockerfile" \\
|
||||
"$ROOT_DIR" \\
|
||||
functional
|
||||
|
||||
test -f "$TMPDIR/build-context-seen"
|
||||
leftovers="$(find "$TMPDIR" -maxdepth 1 \\( \\
|
||||
-name 'openclaw-docker-e2e-pack.*' \\
|
||||
-o -name 'openclaw-docker-e2e-package-context.*' \\
|
||||
\\) -print)"
|
||||
if [[ -n "$leftovers" ]]; then
|
||||
printf 'leftover functional build inputs:\\n%s\\n' "$leftovers" >&2
|
||||
exit 1
|
||||
fi
|
||||
`;
|
||||
|
||||
execFileSync("bash", ["-lc", script], { encoding: "utf8" });
|
||||
} finally {
|
||||
rmSync(workDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps caller-provided functional Docker build packages", () => {
|
||||
const workDir = mkdtempSync(join(tmpdir(), "openclaw-docker-build-external-package-"));
|
||||
|
||||
try {
|
||||
const rootDir = process.cwd();
|
||||
const script = `
|
||||
set -euo pipefail
|
||||
ROOT_DIR=${shellQuote(rootDir)}
|
||||
TMPDIR=${shellQuote(workDir)}
|
||||
export ROOT_DIR TMPDIR
|
||||
|
||||
external_dir="$TMPDIR/external-package"
|
||||
mkdir -p "$external_dir"
|
||||
printf fixture >"$external_dir/openclaw-current.tgz"
|
||||
OPENCLAW_CURRENT_PACKAGE_TGZ="$external_dir/openclaw-current.tgz"
|
||||
export OPENCLAW_CURRENT_PACKAGE_TGZ
|
||||
|
||||
source "$ROOT_DIR/scripts/lib/docker-e2e-image.sh"
|
||||
|
||||
docker_build_run() {
|
||||
local build_context=""
|
||||
local arg
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
openclaw_package=*)
|
||||
build_context="\${arg#openclaw_package=}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -n "$build_context"
|
||||
test -f "$build_context/openclaw-current.tgz"
|
||||
printf "%s\\n" "$build_context" >"$TMPDIR/build-context-seen"
|
||||
}
|
||||
|
||||
docker_e2e_build_or_reuse \\
|
||||
openclaw-test-image \\
|
||||
external-package-proof \\
|
||||
"$ROOT_DIR/scripts/e2e/Dockerfile" \\
|
||||
"$ROOT_DIR" \\
|
||||
functional
|
||||
|
||||
test -f "$TMPDIR/build-context-seen"
|
||||
test -f "$OPENCLAW_CURRENT_PACKAGE_TGZ"
|
||||
leftovers="$(find "$TMPDIR" -maxdepth 1 -name 'openclaw-docker-e2e-package-context.*' -print)"
|
||||
if [[ -n "$leftovers" ]]; then
|
||||
printf 'leftover functional build context:\\n%s\\n' "$leftovers" >&2
|
||||
exit 1
|
||||
fi
|
||||
`;
|
||||
|
||||
execFileSync("bash", ["-lc", script], { encoding: "utf8" });
|
||||
} finally {
|
||||
rmSync(workDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("includes procps in the shared Docker E2E image for process watchdogs", () => {
|
||||
const dockerfile = readFileSync("scripts/e2e/Dockerfile", "utf8");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user