mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:40:44 +00:00
ci: centralize docker build wrapper
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/lib/docker-build.sh"
|
||||
COMPOSE_FILE="$ROOT_DIR/docker-compose.yml"
|
||||
EXTRA_COMPOSE_FILE="$ROOT_DIR/docker-compose.extra.yml"
|
||||
IMAGE_NAME="${OPENCLAW_IMAGE:-openclaw:local}"
|
||||
@@ -27,7 +28,7 @@ require_cmd() {
|
||||
run_docker_build() {
|
||||
# Dockerfile uses BuildKit-only syntax (RUN --mount=type=cache). Force
|
||||
# BuildKit so hosts defaulting to the legacy builder do not fail.
|
||||
DOCKER_BUILDKIT=1 docker build "$@"
|
||||
docker_build_exec "$@"
|
||||
}
|
||||
|
||||
is_truthy_value() {
|
||||
|
||||
@@ -39,7 +39,7 @@ RUN apt-get update \\
|
||||
USER appuser
|
||||
EOF
|
||||
echo "Building Docker image: $IMAGE_NAME"
|
||||
run_logged browser-cdp-snapshot-build docker build -t "$IMAGE_NAME" -f "$build_dir/Dockerfile" "$build_dir"
|
||||
docker_build_run browser-cdp-snapshot-build -t "$IMAGE_NAME" -f "$build_dir/Dockerfile" "$build_dir"
|
||||
fi
|
||||
|
||||
echo "Starting browser CDP snapshot container..."
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
|
||||
source "$ROOT_DIR/scripts/lib/docker-build.sh"
|
||||
IMAGE_NAME="${OPENCLAW_QR_SMOKE_IMAGE:-openclaw-qr-smoke}"
|
||||
DOCKER_BUILD_ARGS=()
|
||||
|
||||
@@ -15,16 +15,11 @@ if [[ "${OPENCLAW_QR_SMOKE_FORCE_INSTALL:-0}" == "1" ]]; then
|
||||
fi
|
||||
|
||||
echo "Building Docker image..."
|
||||
DOCKER_BUILD_CMD=(docker build)
|
||||
if ((${#DOCKER_BUILD_ARGS[@]} > 0)); then
|
||||
DOCKER_BUILD_CMD+=("${DOCKER_BUILD_ARGS[@]}")
|
||||
fi
|
||||
DOCKER_BUILD_CMD+=(
|
||||
-t "$IMAGE_NAME"
|
||||
-f "$ROOT_DIR/scripts/e2e/Dockerfile.qr-import"
|
||||
docker_build_run qr-import-build \
|
||||
"${DOCKER_BUILD_ARGS[@]}" \
|
||||
-t "$IMAGE_NAME" \
|
||||
-f "$ROOT_DIR/scripts/e2e/Dockerfile.qr-import" \
|
||||
"$ROOT_DIR"
|
||||
)
|
||||
run_logged qr-import-build "${DOCKER_BUILD_CMD[@]}"
|
||||
|
||||
echo "Running qrcode-tui import smoke..."
|
||||
run_logged qr-import-run docker run --rm -t "$IMAGE_NAME" node -e "import('@vincentkoc/qrcode-tui').then(async (m)=>{process.stdout.write(await m.renderTerminal('qr-smoke',{small:true}))})"
|
||||
|
||||
40
scripts/lib/docker-build.sh
Normal file
40
scripts/lib/docker-build.sh
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
DOCKER_BUILD_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
if ! declare -F run_logged >/dev/null 2>&1; then
|
||||
source "$DOCKER_BUILD_LIB_DIR/docker-e2e-logs.sh"
|
||||
fi
|
||||
|
||||
docker_build_exec() {
|
||||
local build_cmd=(docker build)
|
||||
if [ "${OPENCLAW_DOCKER_BUILD_USE_BUILDX:-0}" = "1" ]; then
|
||||
build_cmd=(docker buildx build --load)
|
||||
if [ -n "${OPENCLAW_DOCKER_BUILD_CACHE_FROM:-}" ]; then
|
||||
build_cmd+=(--cache-from "${OPENCLAW_DOCKER_BUILD_CACHE_FROM}")
|
||||
fi
|
||||
if [ -n "${OPENCLAW_DOCKER_BUILD_CACHE_TO:-}" ]; then
|
||||
build_cmd+=(--cache-to "${OPENCLAW_DOCKER_BUILD_CACHE_TO}")
|
||||
fi
|
||||
fi
|
||||
|
||||
env DOCKER_BUILDKIT=1 "${build_cmd[@]}" "$@"
|
||||
}
|
||||
|
||||
docker_build_run() {
|
||||
local label="$1"
|
||||
shift
|
||||
|
||||
local build_cmd=(docker build)
|
||||
if [ "${OPENCLAW_DOCKER_BUILD_USE_BUILDX:-0}" = "1" ]; then
|
||||
build_cmd=(docker buildx build --load)
|
||||
if [ -n "${OPENCLAW_DOCKER_BUILD_CACHE_FROM:-}" ]; then
|
||||
build_cmd+=(--cache-from "${OPENCLAW_DOCKER_BUILD_CACHE_FROM}")
|
||||
fi
|
||||
if [ -n "${OPENCLAW_DOCKER_BUILD_CACHE_TO:-}" ]; then
|
||||
build_cmd+=(--cache-to "${OPENCLAW_DOCKER_BUILD_CACHE_TO}")
|
||||
fi
|
||||
fi
|
||||
|
||||
run_logged "$label" env DOCKER_BUILDKIT=1 "${build_cmd[@]}" "$@"
|
||||
}
|
||||
@@ -4,6 +4,7 @@ DOCKER_E2E_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="${ROOT_DIR:-$(cd "$DOCKER_E2E_LIB_DIR/../.." && pwd)}"
|
||||
|
||||
source "$DOCKER_E2E_LIB_DIR/docker-e2e-logs.sh"
|
||||
source "$DOCKER_E2E_LIB_DIR/docker-build.sh"
|
||||
|
||||
docker_e2e_resolve_image() {
|
||||
local default_image="$1"
|
||||
@@ -48,10 +49,10 @@ docker_e2e_build_or_reuse() {
|
||||
fi
|
||||
|
||||
echo "Building Docker image: $image_name"
|
||||
local build_cmd=(docker build)
|
||||
local build_args=()
|
||||
if [ -n "$target" ]; then
|
||||
build_cmd+=(--target "$target")
|
||||
build_args+=(--target "$target")
|
||||
fi
|
||||
build_cmd+=(-t "$image_name" -f "$dockerfile" "$context")
|
||||
run_logged "$label-build" "${build_cmd[@]}"
|
||||
build_args+=(-t "$image_name" -f "$dockerfile" "$context")
|
||||
docker_build_run "$label-build" "${build_args[@]}"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/lib/docker-build.sh"
|
||||
|
||||
IMAGE_NAME="openclaw-sandbox-browser:bookworm-slim"
|
||||
|
||||
docker build -t "${IMAGE_NAME}" -f Dockerfile.sandbox-browser .
|
||||
docker_build_exec -t "${IMAGE_NAME}" -f "$ROOT_DIR/Dockerfile.sandbox-browser" "$ROOT_DIR"
|
||||
echo "Built ${IMAGE_NAME}"
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/lib/docker-build.sh"
|
||||
|
||||
BASE_IMAGE="${BASE_IMAGE:-openclaw-sandbox:bookworm-slim}"
|
||||
TARGET_IMAGE="${TARGET_IMAGE:-openclaw-sandbox-common:bookworm-slim}"
|
||||
PACKAGES="${PACKAGES:-curl wget jq coreutils grep nodejs npm python3 git ca-certificates golang-go rustc cargo unzip pkg-config libasound2-dev build-essential file}"
|
||||
@@ -17,25 +20,14 @@ OPENCLAW_DOCKER_BUILD_CACHE_TO="${OPENCLAW_DOCKER_BUILD_CACHE_TO:-}"
|
||||
if ! docker image inspect "${BASE_IMAGE}" >/dev/null 2>&1; then
|
||||
echo "Base image missing: ${BASE_IMAGE}"
|
||||
echo "Building base image via scripts/sandbox-setup.sh..."
|
||||
scripts/sandbox-setup.sh
|
||||
"$ROOT_DIR/scripts/sandbox-setup.sh"
|
||||
fi
|
||||
|
||||
echo "Building ${TARGET_IMAGE} with: ${PACKAGES}"
|
||||
|
||||
build_cmd=(docker build)
|
||||
if [ "${OPENCLAW_DOCKER_BUILD_USE_BUILDX}" = "1" ]; then
|
||||
build_cmd=(docker buildx build --load)
|
||||
if [ -n "${OPENCLAW_DOCKER_BUILD_CACHE_FROM}" ]; then
|
||||
build_cmd+=(--cache-from "${OPENCLAW_DOCKER_BUILD_CACHE_FROM}")
|
||||
fi
|
||||
if [ -n "${OPENCLAW_DOCKER_BUILD_CACHE_TO}" ]; then
|
||||
build_cmd+=(--cache-to "${OPENCLAW_DOCKER_BUILD_CACHE_TO}")
|
||||
fi
|
||||
fi
|
||||
|
||||
"${build_cmd[@]}" \
|
||||
docker_build_exec \
|
||||
-t "${TARGET_IMAGE}" \
|
||||
-f Dockerfile.sandbox-common \
|
||||
-f "$ROOT_DIR/Dockerfile.sandbox-common" \
|
||||
--build-arg BASE_IMAGE="${BASE_IMAGE}" \
|
||||
--build-arg PACKAGES="${PACKAGES}" \
|
||||
--build-arg INSTALL_PNPM="${INSTALL_PNPM}" \
|
||||
@@ -44,7 +36,7 @@ fi
|
||||
--build-arg INSTALL_BREW="${INSTALL_BREW}" \
|
||||
--build-arg BREW_INSTALL_DIR="${BREW_INSTALL_DIR}" \
|
||||
--build-arg FINAL_USER="${FINAL_USER}" \
|
||||
.
|
||||
"$ROOT_DIR"
|
||||
|
||||
cat <<NOTE
|
||||
Built ${TARGET_IMAGE}.
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/lib/docker-build.sh"
|
||||
|
||||
IMAGE_NAME="openclaw-sandbox:bookworm-slim"
|
||||
|
||||
docker build -t "${IMAGE_NAME}" -f Dockerfile.sandbox .
|
||||
docker_build_exec -t "${IMAGE_NAME}" -f "$ROOT_DIR/Dockerfile.sandbox" "$ROOT_DIR"
|
||||
echo "Built ${IMAGE_NAME}"
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
|
||||
source "$ROOT_DIR/scripts/lib/docker-build.sh"
|
||||
IMAGE_NAME="${OPENCLAW_CLEANUP_SMOKE_IMAGE:-openclaw-cleanup-smoke:local}"
|
||||
PLATFORM="${OPENCLAW_CLEANUP_SMOKE_PLATFORM:-linux/amd64}"
|
||||
|
||||
echo "==> Build image: $IMAGE_NAME"
|
||||
run_logged cleanup-build docker build \
|
||||
docker_build_run cleanup-build \
|
||||
-t "$IMAGE_NAME" \
|
||||
-f "$ROOT_DIR/scripts/docker/cleanup-smoke/Dockerfile" \
|
||||
"$ROOT_DIR"
|
||||
|
||||
@@ -4,6 +4,7 @@ set -euo pipefail
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
# shellcheck source=./docker/install-sh-common/version-parse.sh
|
||||
source "$ROOT_DIR/scripts/docker/install-sh-common/version-parse.sh"
|
||||
source "$ROOT_DIR/scripts/lib/docker-build.sh"
|
||||
|
||||
resolve_default_smoke_platform() {
|
||||
local host_os
|
||||
@@ -358,7 +359,7 @@ if [[ "$SKIP_SMOKE_IMAGE_BUILD" == "1" ]]; then
|
||||
echo "==> Reuse prebuilt smoke image: $SMOKE_IMAGE"
|
||||
else
|
||||
echo "==> Build smoke image (upgrade, root, ${SMOKE_PLATFORM}): $SMOKE_IMAGE"
|
||||
docker build \
|
||||
docker_build_run install-smoke-build \
|
||||
--platform "$SMOKE_PLATFORM" \
|
||||
-t "$SMOKE_IMAGE" \
|
||||
-f "$ROOT_DIR/scripts/docker/install-sh-smoke/Dockerfile" \
|
||||
@@ -441,7 +442,7 @@ else
|
||||
echo "==> Reuse prebuilt non-root image: $NONROOT_IMAGE"
|
||||
else
|
||||
echo "==> Build non-root image (${NONROOT_PLATFORM}): $NONROOT_IMAGE"
|
||||
docker build \
|
||||
docker_build_run install-nonroot-build \
|
||||
--platform "$NONROOT_PLATFORM" \
|
||||
-t "$NONROOT_IMAGE" \
|
||||
-f "$ROOT_DIR/scripts/docker/install-sh-nonroot/Dockerfile" \
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/lib/docker-build.sh"
|
||||
IMAGE_NAME="${OPENCLAW_INSTALL_E2E_IMAGE:-openclaw-install-e2e:local}"
|
||||
INSTALL_URL="${OPENCLAW_INSTALL_URL:-https://openclaw.bot/install.sh}"
|
||||
|
||||
@@ -11,7 +12,7 @@ ANTHROPIC_API_TOKEN="${ANTHROPIC_API_TOKEN:-}"
|
||||
OPENCLAW_E2E_MODELS="${OPENCLAW_E2E_MODELS:-}"
|
||||
|
||||
echo "==> Build image: $IMAGE_NAME"
|
||||
docker build \
|
||||
docker_build_run install-e2e-build \
|
||||
-t "$IMAGE_NAME" \
|
||||
-f "$ROOT_DIR/scripts/docker/install-sh-e2e/Dockerfile" \
|
||||
"$ROOT_DIR/scripts/docker"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/lib/docker-e2e-logs.sh"
|
||||
source "$ROOT_DIR/scripts/lib/docker-build.sh"
|
||||
IMAGE_NAME="${OPENCLAW_IMAGE:-openclaw:local}"
|
||||
LIVE_IMAGE_NAME="${OPENCLAW_LIVE_IMAGE:-${IMAGE_NAME}-live}"
|
||||
DOCKER_BUILD_EXTENSIONS="${OPENCLAW_DOCKER_BUILD_EXTENSIONS:-${OPENCLAW_EXTENSIONS:-}}"
|
||||
@@ -27,4 +27,4 @@ fi
|
||||
|
||||
echo "==> Build live-test image: $LIVE_IMAGE_NAME (target=build)"
|
||||
echo "==> Bundled plugin deps: ${DOCKER_BUILD_EXTENSIONS}"
|
||||
run_logged live-build docker build "${DOCKER_BUILD_ARGS[@]}" --target build -t "$LIVE_IMAGE_NAME" -f "$ROOT_DIR/Dockerfile" "$ROOT_DIR"
|
||||
docker_build_run live-build "${DOCKER_BUILD_ARGS[@]}" --target build -t "$LIVE_IMAGE_NAME" -f "$ROOT_DIR/Dockerfile" "$ROOT_DIR"
|
||||
|
||||
38
test/scripts/docker-build-helper.test.ts
Normal file
38
test/scripts/docker-build-helper.test.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const HELPER_PATH = "scripts/lib/docker-build.sh";
|
||||
const CENTRALIZED_BUILD_SCRIPTS = [
|
||||
"scripts/docker/setup.sh",
|
||||
"scripts/e2e/browser-cdp-snapshot-docker.sh",
|
||||
"scripts/e2e/qr-import-docker.sh",
|
||||
"scripts/lib/docker-e2e-image.sh",
|
||||
"scripts/sandbox-browser-setup.sh",
|
||||
"scripts/sandbox-common-setup.sh",
|
||||
"scripts/sandbox-setup.sh",
|
||||
"scripts/test-cleanup-docker.sh",
|
||||
"scripts/test-install-sh-docker.sh",
|
||||
"scripts/test-install-sh-e2e-docker.sh",
|
||||
"scripts/test-live-build-docker.sh",
|
||||
] as const;
|
||||
|
||||
describe("docker build helper", () => {
|
||||
it("forces BuildKit for centralized Docker builds", () => {
|
||||
const helper = readFileSync(HELPER_PATH, "utf8");
|
||||
|
||||
expect(helper).toContain("DOCKER_BUILDKIT=1");
|
||||
expect(helper).toContain("docker_build_exec()");
|
||||
expect(helper).toContain("docker_build_run()");
|
||||
expect(helper).toContain("docker buildx build --load");
|
||||
});
|
||||
|
||||
it("keeps shell-script Docker builds behind the helper", () => {
|
||||
for (const path of CENTRALIZED_BUILD_SCRIPTS) {
|
||||
const script = readFileSync(path, "utf8");
|
||||
|
||||
expect(script, path).toMatch(/docker-build\.sh|docker-e2e-image\.sh/);
|
||||
expect(script, path).not.toMatch(/\bdocker build\b/);
|
||||
expect(script, path).not.toMatch(/run_logged\s+\S+\s+docker\s+build/);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user