Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions deploy/offline/build_offline_package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -502,10 +502,24 @@ save_image_to_tar() {
if docker save "${save_args[@]}" "$image"; then
echo "✅ Saved: $output_file"
return 0
else
echo "❌ Failed to save image: $image"
return 1
fi

# Legacy single-platform images (e.g. supabase/postgres:15.8.1.060) carry a
# platform annotation that does not match linux/amd64 or linux/arm64 exactly,
# so `docker pull --platform` silently lands the only available variant while
# `docker save --platform` rejects it with "no suitable export target".
# Retry without the platform filter: the pull step already pinned the
# variant, so the local image is the one this package intends to ship.
if docker_supports_save_platform; then
echo "⚠️ Platform-filtered export failed, retrying without --platform: $image"
if docker save -o "$output_file" "$image"; then
echo "✅ Saved: $output_file"
return 0
fi
fi

echo "❌ Failed to save image: $image"
return 1
}

save_all_images() {
Expand Down
37 changes: 36 additions & 1 deletion test/backend/deploy/test_offline_image_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ def export_image(tmp_path):
if os.environ["FAKE_REQUIRE_PLATFORM"] == "true" and "--platform" not in arguments:
print("unable to create manifests file: amd64 content digest not found", file=sys.stderr)
sys.exit(1)
if os.environ["FAKE_PLATFORM_SAVE_FAILS"] == "true" and "--platform" in arguments:
print("no suitable export target found: image was found but does not provide the specified platform", file=sys.stderr)
sys.exit(1)
if int(os.environ["FAKE_SAVE_STATUS"]):
print("synthetic image export failure", file=sys.stderr)
sys.exit(int(os.environ["FAKE_SAVE_STATUS"]))
Expand All @@ -51,7 +54,8 @@ def export_image(tmp_path):
docker.chmod(0o755)

def run(platform="arm64", client_api="1.54", server_api="1.54", *,
version_status=0, save_status=0, require_platform=False):
version_status=0, save_status=0, require_platform=False,
platform_save_fails=False):
log_path = tmp_path / "docker.jsonl"
output = tmp_path / "offline images.tar"
environment = os.environ.copy()
Expand All @@ -63,6 +67,7 @@ def run(platform="arm64", client_api="1.54", server_api="1.54", *,
FAKE_VERSION_STATUS=str(version_status),
FAKE_SAVE_STATUS=str(save_status),
FAKE_REQUIRE_PLATFORM=str(require_platform).lower(),
FAKE_PLATFORM_SAVE_FAILS=str(platform_save_fails).lower(),
)
result = subprocess.run(
["bash", "-c", functions + '\nPLATFORM="$1"\nsave_image_to_tar "$2" "$3"',
Expand Down Expand Up @@ -141,3 +146,33 @@ def test_export_failure_is_reported_without_an_unrestricted_retry(export_image,
saves = [call for call in calls if call[0] == "save"]
assert len(saves) == 1
assert ("--platform" in saves[0]) is has_platform


@pytest.mark.parametrize("platform", ["arm64", "amd64"])
def test_platform_export_falls_back_to_unrestricted_save_for_legacy_images(export_image, platform):
# Legacy single-platform images (e.g. supabase/postgres:15.8.1.060) fail a
# platform-filtered export even though the pinned pull already landed the
# only available variant, so the save must fall back to an unfiltered export.
result, calls, output = export_image(platform, platform_save_fails=True)

assert result.returncode == 0, result.stdout + result.stderr
saves = [call for call in calls if call[0] == "save"]
assert len(saves) == 2
assert "--platform" in saves[0]
assert "--platform" not in saves[1]
assert saves[1][-1] == "nexent/nexent:v2.8.3"
assert "retrying without --platform" in result.stdout
assert output.read_bytes() == b"synthetic image tar"


def test_unrestricted_retry_does_not_run_on_unsupported_docker(export_image):
# On API versions without platform-filtered export there is nothing to
# fall back from: a failing save must stay a single, failed attempt.
result, calls, output = export_image(
client_api="1.39", server_api="1.39", save_status=1,
)

assert result.returncode != 0
saves = [call for call in calls if call[0] == "save"]
assert len(saves) == 1
assert "--platform" not in saves[0]
Loading