From 038c75c2fb00e8f6a26b20bbe5bd1776237b1a4f Mon Sep 17 00:00:00 2001 From: Alon Gubkin Date: Wed, 26 Aug 2026 19:00:14 -0700 Subject: [PATCH] fix: support local multi-arch image releases --- Cargo.lock | 8 +-- Cargo.toml | 2 +- .../tests/registry_proxy_test.rs | 51 +++++++++++++++++-- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 085a4cf51..0048b825b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -241,7 +241,7 @@ dependencies = [ "base64 0.22.1", "bytes", "chrono", - "container-registry 0.3.1 (git+https://github.com/alienplatform/container_registry-rs.git?rev=f0d0fe6)", + "container-registry 0.3.1 (git+https://github.com/alienplatform/container_registry-rs.git?rev=fd28e7c)", "dotenvy", "futures", "hex", @@ -801,7 +801,7 @@ dependencies = [ "bollard", "bytes", "chrono", - "container-registry 0.3.1 (git+https://github.com/alienplatform/container_registry-rs.git?rev=f0d0fe6)", + "container-registry 0.3.1 (git+https://github.com/alienplatform/container_registry-rs.git?rev=fd28e7c)", "cron", "dockdash", "futures", @@ -864,7 +864,7 @@ dependencies = [ "bytes", "chrono", "clap", - "container-registry 0.3.1 (git+https://github.com/alienplatform/container_registry-rs.git?rev=f0d0fe6)", + "container-registry 0.3.1 (git+https://github.com/alienplatform/container_registry-rs.git?rev=fd28e7c)", "dockdash", "dotenvy", "form_urlencoded", @@ -3092,7 +3092,7 @@ dependencies = [ [[package]] name = "container-registry" version = "0.3.1" -source = "git+https://github.com/alienplatform/container_registry-rs.git?rev=f0d0fe6#f0d0fe697838152e81258edeb323e8bc73b130dd" +source = "git+https://github.com/alienplatform/container_registry-rs.git?rev=fd28e7c#fd28e7cd0e0af5f888fa93e3a4e1b22878ed0f19" dependencies = [ "axum 0.7.9", "base64 0.21.7", diff --git a/Cargo.toml b/Cargo.toml index fd6ba0ffe..d46fb7ecc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -115,7 +115,7 @@ chrono = "0.4.40" clap = "4.5.35" cloudevents-sdk = "0.9" config = "0.15" -container-registry = { git = "https://github.com/alienplatform/container_registry-rs.git", rev = "f0d0fe6" } +container-registry = { git = "https://github.com/alienplatform/container_registry-rs.git", rev = "fd28e7c" } dashmap = "6" derive_more = "2" dirs = "6" diff --git a/crates/alien-manager/tests/registry_proxy_test.rs b/crates/alien-manager/tests/registry_proxy_test.rs index 23437ec8a..a45e1b5dd 100644 --- a/crates/alien-manager/tests/registry_proxy_test.rs +++ b/crates/alien-manager/tests/registry_proxy_test.rs @@ -17,6 +17,7 @@ use std::time::Duration; use bollard::image::CreateImageOptions; use bollard::Docker; +use container_registry::ContainerRegistry; use futures_util::StreamExt; use alien_core::{Platform, ReadinessProbe, ResourceLifecycle, Stack, Worker, WorkerCode}; @@ -90,9 +91,10 @@ fn empty_stack(stack_id: &str) -> Stack { /// Start a local OCI registry on a random port (no auth — matches production). /// The real security boundary is the manager's registry proxy (deployment tokens). async fn start_local_registry() -> (String, tokio::task::JoinHandle<()>) { - let (running, host) = dockdash::test_utils::setup_local_registry() - .await - .expect("Failed to start local registry"); + let running = ContainerRegistry::builder() + .build_for_testing() + .run_in_background(); + let host = format!("localhost:{}", running.bound_addr().port()); let handle = tokio::spawn(async move { let _guard = running; @@ -901,6 +903,49 @@ async fn test_proxy_push_then_pull() { println!("End-to-end push→pull through proxy succeeded!"); } +/// OCI indexes must pass through the manager proxy to the embedded local +/// registry. `alien dev release` publishes one whenever a worker has multiple +/// Linux targets. +#[tokio::test] +async fn test_proxy_push_image_index() { + let s = setup().await; + let index = serde_json::json!({ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.index.v1+json", + "manifests": [{ + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "size": 7143, + "digest": "sha256:e4c58958181a5925816faa528ce959e487632f4cfd192f8132f71b32df2744b4", + "platform": { + "architecture": "amd64", + "os": "linux" + } + }] + }); + + let response = reqwest::Client::new() + .put(format!( + "{}/v2/artifacts/proxy-index/manifests/latest", + s.manager_url + )) + .bearer_auth(&s.admin_token) + .header( + reqwest::header::CONTENT_TYPE, + "application/vnd.oci.image.index.v1+json", + ) + .json(&index) + .send() + .await + .expect("image index request should reach the manager"); + let status = response.status(); + let body = response + .text() + .await + .expect("image index response body should be readable"); + + assert_eq!(status, reqwest::StatusCode::CREATED, "{body}"); +} + /// End-to-end: push a large, poorly-compressible layer through the local /// registry proxy. This catches body-size limits in the proxy path while /// staying fully local.