2025-12-16 21:20:27 +01:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
if [ -z "${BASH_VERSION:-}" ]; then
|
|
|
|
|
exec bash "$0" "$@"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# shellcheck disable=SC1091
|
2025-12-18 17:26:02 +01:00
|
|
|
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../lib/common.sh"
|
2025-12-16 21:20:27 +01:00
|
|
|
|
|
|
|
|
build_test_image::usage() {
|
|
|
|
|
cat <<'USAGE'
|
2025-12-18 17:26:02 +01:00
|
|
|
Usage: scripts/build/build_test_image.sh [options]
|
2025-12-16 21:20:27 +01:00
|
|
|
|
2026-01-26 08:26:15 +01:00
|
|
|
Builds the compose/k8s test image (bakes in binaries).
|
2025-12-16 21:20:27 +01:00
|
|
|
|
|
|
|
|
Options:
|
|
|
|
|
--tag TAG Docker image tag (default: logos-blockchain-testing:local; or env IMAGE_TAG)
|
2026-01-26 08:26:15 +01:00
|
|
|
--version VERSION Bundle version tag (default: versions.env VERSION)
|
2026-02-02 07:19:22 +01:00
|
|
|
--dockerfile PATH Dockerfile path (default: logos/infra/assets/stack/Dockerfile.runtime)
|
2025-12-18 09:58:47 +01:00
|
|
|
--base-tag TAG Base image tag (default: logos-blockchain-testing:base)
|
2026-01-26 16:36:51 +01:00
|
|
|
--bundle-tar PATH Bundle tar containing artifacts/{nomos-*} (default: .tmp/nomos-binaries-linux-<version>.tar.gz; or env LOGOS_BLOCKCHAIN_BINARIES_TAR)
|
2026-01-26 08:26:15 +01:00
|
|
|
--no-restore Do not restore binaries from bundle tar (forces Dockerfile to build/download as needed)
|
2025-12-16 21:20:27 +01:00
|
|
|
--print-config Print resolved configuration and exit
|
|
|
|
|
-h, --help Show this help and exit
|
|
|
|
|
|
|
|
|
|
Env (legacy/compatible):
|
2026-01-26 16:36:51 +01:00
|
|
|
IMAGE_TAG, VERSION, LOGOS_BLOCKCHAIN_BINARIES_TAR
|
2025-12-16 21:20:27 +01:00
|
|
|
USAGE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_test_image::fail() {
|
|
|
|
|
common::die "$1"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_test_image::load_env() {
|
|
|
|
|
if [ -n "${ROOT_DIR:-}" ] && [ -f "${ROOT_DIR}/versions.env" ]; then
|
|
|
|
|
: # Use provided ROOT_DIR.
|
|
|
|
|
else
|
|
|
|
|
ROOT_DIR="$(common::repo_root)"
|
|
|
|
|
fi
|
|
|
|
|
export ROOT_DIR
|
|
|
|
|
|
|
|
|
|
common::require_file "${ROOT_DIR}/versions.env"
|
|
|
|
|
# shellcheck disable=SC1091
|
|
|
|
|
. "${ROOT_DIR}/versions.env"
|
|
|
|
|
common::maybe_source "${ROOT_DIR}/paths.env"
|
|
|
|
|
|
2026-02-02 07:19:22 +01:00
|
|
|
DOCKERFILE_PATH_DEFAULT="${ROOT_DIR}/logos/infra/assets/stack/Dockerfile.runtime"
|
|
|
|
|
BASE_DOCKERFILE_PATH_DEFAULT="${ROOT_DIR}/logos/infra/assets/stack/Dockerfile.base"
|
2025-12-16 21:20:27 +01:00
|
|
|
IMAGE_TAG_DEFAULT="logos-blockchain-testing:local"
|
2025-12-18 09:58:47 +01:00
|
|
|
BASE_IMAGE_TAG_DEFAULT="logos-blockchain-testing:base"
|
2025-12-16 21:20:27 +01:00
|
|
|
|
|
|
|
|
VERSION_DEFAULT="${VERSION:?Missing VERSION in versions.env}"
|
2026-01-26 16:36:51 +01:00
|
|
|
LOGOS_BLOCKCHAIN_NODE_REV="${LOGOS_BLOCKCHAIN_NODE_REV:?Missing LOGOS_BLOCKCHAIN_NODE_REV in versions.env}"
|
2025-12-16 21:20:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_test_image::parse_args() {
|
|
|
|
|
IMAGE_TAG="${IMAGE_TAG:-${IMAGE_TAG_DEFAULT}}"
|
|
|
|
|
VERSION_OVERRIDE=""
|
|
|
|
|
DOCKERFILE_PATH="${DOCKERFILE_PATH_DEFAULT}"
|
2025-12-18 09:58:47 +01:00
|
|
|
BASE_DOCKERFILE_PATH="${BASE_DOCKERFILE_PATH_DEFAULT}"
|
|
|
|
|
BASE_IMAGE_TAG="${BASE_IMAGE_TAG:-${BASE_IMAGE_TAG_DEFAULT}}"
|
2026-01-26 16:36:51 +01:00
|
|
|
BUNDLE_TAR_PATH="${LOGOS_BLOCKCHAIN_BINARIES_TAR:-}"
|
2025-12-16 21:20:27 +01:00
|
|
|
NO_RESTORE=0
|
|
|
|
|
PRINT_CONFIG=0
|
|
|
|
|
|
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
|
|
|
case "$1" in
|
|
|
|
|
-h|--help) build_test_image::usage; exit 0 ;;
|
|
|
|
|
--tag=*) IMAGE_TAG="${1#*=}"; shift ;;
|
|
|
|
|
--tag) IMAGE_TAG="${2:-}"; shift 2 ;;
|
|
|
|
|
--version=*) VERSION_OVERRIDE="${1#*=}"; shift ;;
|
|
|
|
|
--version) VERSION_OVERRIDE="${2:-}"; shift 2 ;;
|
|
|
|
|
--dockerfile=*) DOCKERFILE_PATH="${1#*=}"; shift ;;
|
|
|
|
|
--dockerfile) DOCKERFILE_PATH="${2:-}"; shift 2 ;;
|
2025-12-18 09:58:47 +01:00
|
|
|
--base-tag=*) BASE_IMAGE_TAG="${1#*=}"; shift ;;
|
|
|
|
|
--base-tag) BASE_IMAGE_TAG="${2:-}"; shift 2 ;;
|
2025-12-16 21:20:27 +01:00
|
|
|
--bundle-tar=*) BUNDLE_TAR_PATH="${1#*=}"; shift ;;
|
|
|
|
|
--bundle-tar) BUNDLE_TAR_PATH="${2:-}"; shift 2 ;;
|
|
|
|
|
--no-restore) NO_RESTORE=1; shift ;;
|
|
|
|
|
--print-config) PRINT_CONFIG=1; shift ;;
|
|
|
|
|
*) build_test_image::fail "Unknown argument: $1" ;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
if [ -n "${VERSION_OVERRIDE}" ]; then
|
|
|
|
|
VERSION="${VERSION_OVERRIDE}"
|
|
|
|
|
else
|
|
|
|
|
VERSION="${VERSION_DEFAULT}"
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-02 07:19:22 +01:00
|
|
|
BIN_DST="${ROOT_DIR}/logos/infra/assets/stack/bin"
|
2025-12-16 21:20:27 +01:00
|
|
|
|
|
|
|
|
DEFAULT_LINUX_TAR="${ROOT_DIR}/.tmp/nomos-binaries-linux-${VERSION}.tar.gz"
|
|
|
|
|
TAR_PATH="${BUNDLE_TAR_PATH:-${DEFAULT_LINUX_TAR}}"
|
2026-02-02 07:19:22 +01:00
|
|
|
|
|
|
|
|
LOGOS_BLOCKCHAIN_NODE_PATH="${LOGOS_BLOCKCHAIN_NODE_PATH:-}"
|
|
|
|
|
if [ -z "${LOGOS_BLOCKCHAIN_NODE_PATH}" ]; then
|
|
|
|
|
# Prefer local checkout when available: this repo currently depends on
|
|
|
|
|
# lb-framework from nomos-node/tests/testing_framework.
|
|
|
|
|
local sibling_node_path="${ROOT_DIR}/../nomos-node"
|
|
|
|
|
if [ -d "${sibling_node_path}/tests/testing_framework" ]; then
|
|
|
|
|
LOGOS_BLOCKCHAIN_NODE_PATH="${sibling_node_path}"
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
if [ -n "${LOGOS_BLOCKCHAIN_NODE_PATH}" ] && [ ! -d "${LOGOS_BLOCKCHAIN_NODE_PATH}" ]; then
|
|
|
|
|
build_test_image::fail "LOGOS_BLOCKCHAIN_NODE_PATH does not exist: ${LOGOS_BLOCKCHAIN_NODE_PATH}"
|
|
|
|
|
fi
|
2025-12-16 21:20:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_test_image::print_config() {
|
|
|
|
|
echo "Workspace root: ${ROOT_DIR}"
|
|
|
|
|
echo "Image tag: ${IMAGE_TAG}"
|
|
|
|
|
echo "Dockerfile: ${DOCKERFILE_PATH}"
|
2025-12-18 09:58:47 +01:00
|
|
|
echo "Base image tag: ${BASE_IMAGE_TAG}"
|
|
|
|
|
echo "Base Dockerfile: ${BASE_DOCKERFILE_PATH}"
|
2026-01-26 16:36:51 +01:00
|
|
|
echo "Logos node rev: ${LOGOS_BLOCKCHAIN_NODE_REV}"
|
2026-02-02 07:19:22 +01:00
|
|
|
echo "Logos node path: ${LOGOS_BLOCKCHAIN_NODE_PATH:-<unset>}"
|
2025-12-16 21:20:27 +01:00
|
|
|
echo "Binaries dir: ${BIN_DST}"
|
|
|
|
|
echo "Bundle tar (if used): ${TAR_PATH}"
|
|
|
|
|
echo "Restore from tar: $([ "${NO_RESTORE}" -eq 1 ] && echo "disabled" || echo "enabled")"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_test_image::have_host_binaries() {
|
2026-01-25 10:11:16 +02:00
|
|
|
# Preserve existing behavior: only require node on the host.
|
|
|
|
|
[ -x "${BIN_DST}/logos-blockchain-node" ]
|
2025-12-16 21:20:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_test_image::restore_from_bundle() {
|
|
|
|
|
[ -f "${TAR_PATH}" ] || build_test_image::fail "Prebuilt binaries missing and bundle tar not found at ${TAR_PATH}"
|
|
|
|
|
|
2026-01-26 08:26:15 +01:00
|
|
|
echo "==> Restoring binaries from ${TAR_PATH}"
|
2025-12-16 21:20:27 +01:00
|
|
|
local tmp_extract
|
|
|
|
|
tmp_extract="$(common::tmpdir nomos-bundle-extract.XXXXXX)"
|
2025-12-17 19:24:55 +01:00
|
|
|
trap "rm -rf -- '${tmp_extract}'" RETURN
|
2025-12-16 21:20:27 +01:00
|
|
|
|
|
|
|
|
tar -xzf "${TAR_PATH}" -C "${tmp_extract}"
|
|
|
|
|
local artifacts="${tmp_extract}/artifacts"
|
|
|
|
|
|
2026-01-26 08:26:15 +01:00
|
|
|
[ -f "${artifacts}/logos-blockchain-node" ] || build_test_image::fail \
|
|
|
|
|
"Bundle ${TAR_PATH} missing artifacts/logos-blockchain-node"
|
2025-12-16 21:20:27 +01:00
|
|
|
|
|
|
|
|
mkdir -p "${BIN_DST}"
|
2026-01-26 08:26:15 +01:00
|
|
|
cp "${artifacts}/logos-blockchain-node" "${BIN_DST}/"
|
|
|
|
|
chmod +x "${BIN_DST}/logos-blockchain-node" || true
|
|
|
|
|
|
2025-12-16 21:20:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_test_image::maybe_restore_assets() {
|
|
|
|
|
if [ "${NO_RESTORE}" -eq 1 ]; then
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
if build_test_image::have_host_binaries; then
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
build_test_image::restore_from_bundle
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_test_image::docker_build() {
|
|
|
|
|
command -v docker >/dev/null 2>&1 || build_test_image::fail "docker not found in PATH"
|
|
|
|
|
[ -f "${DOCKERFILE_PATH}" ] || build_test_image::fail "Dockerfile not found: ${DOCKERFILE_PATH}"
|
|
|
|
|
|
2025-12-18 09:58:47 +01:00
|
|
|
[ -f "${BASE_DOCKERFILE_PATH}" ] || build_test_image::fail "Base Dockerfile not found: ${BASE_DOCKERFILE_PATH}"
|
|
|
|
|
|
2026-01-22 05:57:59 +01:00
|
|
|
local host_platform=""
|
|
|
|
|
local target_platform=""
|
|
|
|
|
case "$(uname -m)" in
|
|
|
|
|
x86_64) host_platform="linux/amd64" ;;
|
|
|
|
|
arm64|aarch64) host_platform="linux/arm64" ;;
|
|
|
|
|
esac
|
2026-01-26 08:26:15 +01:00
|
|
|
|
|
|
|
|
if [ -n "${DOCKER_PLATFORM:-}" ]; then
|
|
|
|
|
target_platform="${DOCKER_PLATFORM}"
|
|
|
|
|
elif [ -n "${COMPOSE_CIRCUITS_PLATFORM:-}" ] || [ -n "${CIRCUITS_PLATFORM:-}" ]; then
|
|
|
|
|
case "${COMPOSE_CIRCUITS_PLATFORM:-${CIRCUITS_PLATFORM}}" in
|
|
|
|
|
linux-x86_64) target_platform="linux/amd64" ;;
|
|
|
|
|
linux-aarch64) target_platform="linux/arm64" ;;
|
|
|
|
|
esac
|
|
|
|
|
fi
|
2026-02-02 07:19:22 +01:00
|
|
|
if [ -z "${target_platform}" ] && [ -n "${host_platform}" ]; then
|
|
|
|
|
# Prefer native builds to avoid emulation issues in rapidsnark/prover.
|
|
|
|
|
target_platform="${host_platform}"
|
|
|
|
|
fi
|
2026-01-22 05:57:59 +01:00
|
|
|
|
2025-12-18 09:58:47 +01:00
|
|
|
local -a base_build_args=(
|
|
|
|
|
-f "${BASE_DOCKERFILE_PATH}"
|
|
|
|
|
-t "${BASE_IMAGE_TAG}"
|
2026-01-26 16:36:51 +01:00
|
|
|
--build-arg "LOGOS_BLOCKCHAIN_NODE_REV=${LOGOS_BLOCKCHAIN_NODE_REV}"
|
2026-02-02 07:19:22 +01:00
|
|
|
--build-arg "LOGOS_BLOCKCHAIN_NODE_USE_LOCAL_CONTEXT=$([ -n "${LOGOS_BLOCKCHAIN_NODE_PATH}" ] && echo 1 || echo 0)"
|
2025-12-16 21:20:27 +01:00
|
|
|
--build-arg "VERSION=${VERSION}"
|
|
|
|
|
)
|
2026-02-02 07:19:22 +01:00
|
|
|
local node_context_path="${LOGOS_BLOCKCHAIN_NODE_PATH:-${ROOT_DIR}}"
|
|
|
|
|
base_build_args+=(--build-context "nomos_node=${node_context_path}")
|
|
|
|
|
if [ -n "${LOGOS_BLOCKCHAIN_FORCE_BUILD:-}" ]; then
|
|
|
|
|
base_build_args+=(--build-arg "LOGOS_BLOCKCHAIN_FORCE_BUILD=${LOGOS_BLOCKCHAIN_FORCE_BUILD}")
|
|
|
|
|
fi
|
2026-01-22 05:57:59 +01:00
|
|
|
if [ -n "${host_platform}" ] && [ -n "${target_platform}" ] && [ "${host_platform}" != "${target_platform}" ]; then
|
|
|
|
|
base_build_args+=(--platform "${target_platform}")
|
|
|
|
|
fi
|
2026-02-02 07:19:22 +01:00
|
|
|
base_build_args+=("${ROOT_DIR}")
|
2025-12-16 21:20:27 +01:00
|
|
|
|
|
|
|
|
printf "Running:"
|
2025-12-18 09:58:47 +01:00
|
|
|
printf " %q" docker build "${base_build_args[@]}"
|
|
|
|
|
echo
|
2026-02-02 07:19:22 +01:00
|
|
|
build_test_image::docker_build_with_retry "${base_build_args[@]}"
|
2025-12-18 09:58:47 +01:00
|
|
|
|
|
|
|
|
local -a final_build_args=(
|
|
|
|
|
-f "${DOCKERFILE_PATH}"
|
|
|
|
|
-t "${IMAGE_TAG}"
|
|
|
|
|
--build-arg "BASE_IMAGE=${BASE_IMAGE_TAG}"
|
|
|
|
|
"${ROOT_DIR}"
|
|
|
|
|
)
|
2026-01-22 05:57:59 +01:00
|
|
|
if [ -n "${host_platform}" ] && [ -n "${target_platform}" ] && [ "${host_platform}" != "${target_platform}" ]; then
|
|
|
|
|
final_build_args+=(--platform "${target_platform}")
|
|
|
|
|
fi
|
2025-12-18 09:58:47 +01:00
|
|
|
printf "Running:"
|
|
|
|
|
printf " %q" docker build "${final_build_args[@]}"
|
2025-12-16 21:20:27 +01:00
|
|
|
echo
|
2026-02-02 07:19:22 +01:00
|
|
|
build_test_image::docker_build_with_retry "${final_build_args[@]}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_test_image::docker_build_with_retry() {
|
|
|
|
|
local max_attempts=3
|
|
|
|
|
local attempt
|
|
|
|
|
for attempt in $(seq 1 "${max_attempts}"); do
|
|
|
|
|
if docker build "$@"; then
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
if [ "${attempt}" -lt "${max_attempts}" ]; then
|
|
|
|
|
local backoff=$((attempt * 5))
|
|
|
|
|
echo "docker build failed (attempt ${attempt}/${max_attempts}); retrying in ${backoff}s..."
|
|
|
|
|
sleep "${backoff}"
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
build_test_image::fail "docker build failed after ${max_attempts} attempts"
|
2025-12-16 21:20:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
build_test_image::main() {
|
|
|
|
|
build_test_image::load_env
|
|
|
|
|
build_test_image::parse_args "$@"
|
|
|
|
|
|
|
|
|
|
if [ "${PRINT_CONFIG}" -eq 1 ]; then
|
|
|
|
|
build_test_image::print_config
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
build_test_image::print_config
|
|
|
|
|
build_test_image::maybe_restore_assets
|
|
|
|
|
build_test_image::docker_build
|
|
|
|
|
|
|
|
|
|
cat <<EOF
|
|
|
|
|
|
|
|
|
|
Build complete.
|
2026-01-26 16:36:51 +01:00
|
|
|
- Use this image in k8s/compose by exporting LOGOS_BLOCKCHAIN_TESTNET_IMAGE=${IMAGE_TAG}
|
2025-12-16 21:20:27 +01:00
|
|
|
EOF
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
|
|
|
|
build_test_image::main "$@"
|
|
|
|
|
fi
|