From f6653b9b354869a98cde44eed5f81fe0e1329162 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 2 Jun 2026 02:08:13 +0100 Subject: [PATCH] fix(ci): retry live Docker image pulls --- scripts/test-live-build-docker.sh | 29 +++++++++++++++++-- test/scripts/docker-build-helper.test.ts | 5 +++- .../package-acceptance-workflow.test.ts | 3 +- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/scripts/test-live-build-docker.sh b/scripts/test-live-build-docker.sh index 563fa27fe8a7..fb1d461044e5 100755 --- a/scripts/test-live-build-docker.sh +++ b/scripts/test-live-build-docker.sh @@ -6,10 +6,21 @@ ROOT_DIR="${OPENCLAW_LIVE_DOCKER_REPO_ROOT:-$SCRIPT_ROOT_DIR}" ROOT_DIR="$(cd "$ROOT_DIR" && pwd)" source "$SCRIPT_ROOT_DIR/scripts/lib/docker-build.sh" source "$SCRIPT_ROOT_DIR/scripts/lib/docker-e2e-container.sh" -DOCKER_COMMAND_TIMEOUT="${DOCKER_COMMAND_TIMEOUT:-${OPENCLAW_LIVE_DOCKER_PULL_TIMEOUT:-600s}}" +DOCKER_COMMAND_TIMEOUT="${DOCKER_COMMAND_TIMEOUT:-${OPENCLAW_LIVE_DOCKER_PULL_TIMEOUT:-180s}}" IMAGE_NAME="${OPENCLAW_IMAGE:-openclaw:local}" LIVE_IMAGE_NAME="${OPENCLAW_LIVE_IMAGE:-${IMAGE_NAME}-live}" DOCKER_BUILD_EXTENSIONS="${OPENCLAW_DOCKER_BUILD_EXTENSIONS:-${OPENCLAW_EXTENSIONS:-}}" +LIVE_IMAGE_PULL_ATTEMPTS="${OPENCLAW_LIVE_DOCKER_PULL_ATTEMPTS:-3}" +LIVE_IMAGE_PULL_RETRY_DELAY_SECONDS="${OPENCLAW_LIVE_DOCKER_PULL_RETRY_DELAY_SECONDS:-5}" + +if ! [[ "$LIVE_IMAGE_PULL_ATTEMPTS" =~ ^[1-9][0-9]*$ ]]; then + echo "OPENCLAW_LIVE_DOCKER_PULL_ATTEMPTS must be a positive integer, got: $LIVE_IMAGE_PULL_ATTEMPTS" >&2 + exit 2 +fi +if ! [[ "$LIVE_IMAGE_PULL_RETRY_DELAY_SECONDS" =~ ^[0-9]+$ ]]; then + echo "OPENCLAW_LIVE_DOCKER_PULL_RETRY_DELAY_SECONDS must be a non-negative integer, got: $LIVE_IMAGE_PULL_RETRY_DELAY_SECONDS" >&2 + exit 2 +fi case " ${DOCKER_BUILD_EXTENSIONS} " in *" matrix "*) @@ -24,13 +35,27 @@ if [[ -n "${DOCKER_BUILD_EXTENSIONS}" ]]; then DOCKER_BUILD_ARGS+=(--build-arg "OPENCLAW_EXTENSIONS=${DOCKER_BUILD_EXTENSIONS}") fi +pull_live_image() { + local attempt + for attempt in $(seq 1 "$LIVE_IMAGE_PULL_ATTEMPTS"); do + echo "==> Pull live-test image attempt ${attempt}/${LIVE_IMAGE_PULL_ATTEMPTS}: $LIVE_IMAGE_NAME" + if docker_e2e_docker_cmd pull "$LIVE_IMAGE_NAME"; then + return 0 + fi + if [[ "$attempt" -lt "$LIVE_IMAGE_PULL_ATTEMPTS" && "$LIVE_IMAGE_PULL_RETRY_DELAY_SECONDS" -gt 0 ]]; then + sleep "$LIVE_IMAGE_PULL_RETRY_DELAY_SECONDS" + fi + done + return 1 +} + if [[ "${OPENCLAW_SKIP_DOCKER_BUILD:-}" == "1" ]]; then echo "==> Reuse live-test image: $LIVE_IMAGE_NAME" if docker_e2e_docker_cmd image inspect "$LIVE_IMAGE_NAME" >/dev/null 2>&1; then exit 0 fi echo "==> Live-test image not found locally; pulling: $LIVE_IMAGE_NAME" - if docker_e2e_docker_cmd pull "$LIVE_IMAGE_NAME"; then + if pull_live_image; then exit 0 fi if ! docker_build_on_missing_enabled; then diff --git a/test/scripts/docker-build-helper.test.ts b/test/scripts/docker-build-helper.test.ts index 01de29e8881c..3f934b96593a 100644 --- a/test/scripts/docker-build-helper.test.ts +++ b/test/scripts/docker-build-helper.test.ts @@ -166,7 +166,10 @@ describe("docker build helper", () => { expect(e2eImageHelper).toContain('docker_e2e_docker_cmd pull "$image_name"'); expect(liveBuild).toContain('source "$SCRIPT_ROOT_DIR/scripts/lib/docker-e2e-container.sh"'); expect(liveBuild).toContain( - 'DOCKER_COMMAND_TIMEOUT="${DOCKER_COMMAND_TIMEOUT:-${OPENCLAW_LIVE_DOCKER_PULL_TIMEOUT:-600s}}"', + 'DOCKER_COMMAND_TIMEOUT="${DOCKER_COMMAND_TIMEOUT:-${OPENCLAW_LIVE_DOCKER_PULL_TIMEOUT:-180s}}"', + ); + expect(liveBuild).toContain( + 'LIVE_IMAGE_PULL_ATTEMPTS="${OPENCLAW_LIVE_DOCKER_PULL_ATTEMPTS:-3}"', ); expect(liveBuild).toContain('docker_e2e_docker_cmd image inspect "$LIVE_IMAGE_NAME"'); expect(liveBuild).toContain('docker_e2e_docker_cmd pull "$LIVE_IMAGE_NAME"'); diff --git a/test/scripts/package-acceptance-workflow.test.ts b/test/scripts/package-acceptance-workflow.test.ts index 0af050ad1d2b..280221680db5 100644 --- a/test/scripts/package-acceptance-workflow.test.ts +++ b/test/scripts/package-acceptance-workflow.test.ts @@ -885,8 +885,9 @@ describe("package artifact reuse", () => { expect(build).toContain('source "$SCRIPT_ROOT_DIR/scripts/lib/docker-build.sh"'); expect(build).toContain('source "$SCRIPT_ROOT_DIR/scripts/lib/docker-e2e-container.sh"'); expect(build).toContain( - 'DOCKER_COMMAND_TIMEOUT="${DOCKER_COMMAND_TIMEOUT:-${OPENCLAW_LIVE_DOCKER_PULL_TIMEOUT:-600s}}"', + 'DOCKER_COMMAND_TIMEOUT="${DOCKER_COMMAND_TIMEOUT:-${OPENCLAW_LIVE_DOCKER_PULL_TIMEOUT:-180s}}"', ); + expect(build).toContain('LIVE_IMAGE_PULL_ATTEMPTS="${OPENCLAW_LIVE_DOCKER_PULL_ATTEMPTS:-3}"'); expect(build).toContain('docker_e2e_docker_cmd pull "$LIVE_IMAGE_NAME"'); expect(build).not.toContain('docker pull "$LIVE_IMAGE_NAME"'); expect(stage).toContain(