From f6fc681a685af79bd0934f1cbd64f5806df7b55a Mon Sep 17 00:00:00 2001 From: m1saka Date: Thu, 15 Oct 2026 09:50:30 +0800 Subject: [PATCH] fix: normalize default arm64 v8 image platform --- internal/api/images_policy.go | 6 ++++++ internal/api/images_policy_test.go | 22 ++++++++++++++++++++++ internal/api/releases_test.go | 18 +++++++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/internal/api/images_policy.go b/internal/api/images_policy.go index 6097cf4..380f1bd 100644 --- a/internal/api/images_policy.go +++ b/internal/api/images_policy.go @@ -42,6 +42,12 @@ func (im inspectedImage) platform() string { return "" } p := im.Os + "/" + im.Architecture + // Docker can report the default ARM64 variant explicitly. Keep its + // identity consistent with build records and admission keys; preserve + // all other variants so incompatible images remain rejected. + if im.Architecture == "arm64" && im.Variant == "v8" { + return p + } if im.Variant != "" { p += "/" + im.Variant } diff --git a/internal/api/images_policy_test.go b/internal/api/images_policy_test.go index 723aa57..f12932d 100644 --- a/internal/api/images_policy_test.go +++ b/internal/api/images_policy_test.go @@ -13,6 +13,28 @@ import ( "testing" ) +func TestInspectedImagePlatform(t *testing.T) { + for _, tc := range []struct{ os, arch, variant, want string }{ + {"linux", "arm64", "", "linux/arm64"}, + {"linux", "arm64", "v8", "linux/arm64"}, + {"linux", "arm64", "v9", "linux/arm64/v9"}, + {"linux", "arm64", "v8.1", "linux/arm64/v8.1"}, + {"linux", "arm", "v7", "linux/arm/v7"}, + {"linux", "arm", "v8", "linux/arm/v8"}, + {"linux", "amd64", "", "linux/amd64"}, + {"linux", "amd64", "v8", "linux/amd64/v8"}, + {"", "arm64", "v8", ""}, + {"linux", "", "v8", ""}, + } { + t.Run(tc.os+"/"+tc.arch+"/"+tc.variant, func(t *testing.T) { + im := inspectedImage{Os: tc.os, Architecture: tc.arch, Variant: tc.variant} + if got := im.platform(); got != tc.want { + t.Fatalf("platform() = %q, want %q", got, tc.want) + } + }) + } +} + func TestImageLegacyMigrationNeverCertifies(t *testing.T) { a, sid := imageTestAPI(t, func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/v1.47/images/json" { diff --git a/internal/api/releases_test.go b/internal/api/releases_test.go index eb47fe5..11c8b71 100644 --- a/internal/api/releases_test.go +++ b/internal/api/releases_test.go @@ -161,6 +161,18 @@ func TestReleaseGitEnvironmentAndFailure(t *testing.T) { } func TestPinnedReleaseWorkerAdmissionAndBlock(t *testing.T) { + testPinnedReleaseWorkerAdmissionAndBlock(t, "") +} + +func TestPinnedReleaseWorkerARM64V8AdmissionAndBlock(t *testing.T) { + previous := imagePlatform + imagePlatform = "linux/arm64" + t.Cleanup(func() { imagePlatform = previous }) + testPinnedReleaseWorkerAdmissionAndBlock(t, "v8") +} + +func testPinnedReleaseWorkerAdmissionAndBlock(t *testing.T, variant string) { + t.Helper() info := releaseFixture() labels := map[string]string{"dsh-mgr.role": "runtime", "dsh-mgr.version": info.Version, "dsh-mgr.recipe": "7", "dsh-mgr.release": info.ReleaseID, "dsh-mgr.source": info.Repository, "dsh-mgr.commit": info.Commit} a, _ := imageTestAPI(t, func(w http.ResponseWriter, r *http.Request) { @@ -180,7 +192,7 @@ func TestPinnedReleaseWorkerAdmissionAndBlock(t *testing.T) { io.WriteString(w, `{"aux":{"ID":"sha256:release"}}`) case "/v1.47/images/sha256:release/json": parts := strings.Split(imagePlatform, "/") - writeJSON(w, map[string]any{"Id": "sha256:release", "Os": parts[0], "Architecture": parts[1], "Config": map[string]any{"Labels": labels}}) + writeJSON(w, map[string]any{"Id": "sha256:release", "Os": parts[0], "Architecture": parts[1], "Variant": variant, "Config": map[string]any{"Labels": labels}}) case "/v1.47/containers/create": var cfg struct { Image, User string @@ -235,6 +247,10 @@ func TestPinnedReleaseWorkerAdmissionAndBlock(t *testing.T) { if b.Status != "success" { t.Fatalf("%+v", b) } + records := []buildRecord{b} + if err = a.reconcileBuilds(context.Background(), records); err != nil || records[0].Status != "success" { + t.Fatalf("reconciliation: %+v %v", records, err) + } im, err := a.evaluateImage(context.Background(), b.ImageID) if err != nil || !im.Selectable { t.Fatalf("%+v %v", im, err)