mirror of
https://github.com/imjasonh/krust
synced 2026-07-08 06:45:32 +00:00
commit
d9bef924aa
1 changed files with 100 additions and 71 deletions
171
src/main.rs
171
src/main.rs
|
|
@ -91,91 +91,120 @@ async fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build for each platform
|
// Build for each platform concurrently
|
||||||
let mut manifest_descriptors = Vec::new();
|
let mut tasks = Vec::new();
|
||||||
|
|
||||||
for platform_str in &platforms {
|
for platform_str in platforms.clone() {
|
||||||
info!("Building for platform: {}", platform_str);
|
let project_path = project_path.clone();
|
||||||
|
let base_image = base_image.clone();
|
||||||
|
let target_repo = target_repo.clone();
|
||||||
|
let cargo_args = cargo_args.clone();
|
||||||
|
let no_push_flag = no_push;
|
||||||
|
|
||||||
// Build the Rust binary for this platform
|
let task = tokio::spawn(async move {
|
||||||
let target = get_rust_target_triple(platform_str)?;
|
info!("Building for platform: {}", platform_str);
|
||||||
let builder =
|
|
||||||
RustBuilder::new(&project_path, &target).with_cargo_args(cargo_args.clone());
|
|
||||||
|
|
||||||
let build_result = builder.build()?;
|
// Build the Rust binary for this platform
|
||||||
|
let target = get_rust_target_triple(&platform_str)?;
|
||||||
|
let builder =
|
||||||
|
RustBuilder::new(&project_path, &target).with_cargo_args(cargo_args);
|
||||||
|
|
||||||
// Build container image for this platform
|
let build_result = builder.build()?;
|
||||||
let image_builder = ImageBuilder::new(
|
|
||||||
build_result.binary_path,
|
|
||||||
base_image.clone(),
|
|
||||||
platform_str.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Always use layered approach - registry layer will handle cross-registry blob copying
|
// Build container image for this platform
|
||||||
let base_auth = resolve_auth(&base_image)?;
|
let image_builder = ImageBuilder::new(
|
||||||
let (config_data, layer_data, manifest) = image_builder
|
build_result.binary_path,
|
||||||
.build(&mut registry_client, &base_auth)
|
base_image.clone(),
|
||||||
.await?;
|
platform_str.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
// Push platform-specific image if not --no-push
|
// Create a registry client for this task
|
||||||
if !no_push {
|
let mut registry_client = RegistryClient::new()?;
|
||||||
info!("Pushing image for platform: {}", platform_str);
|
|
||||||
|
|
||||||
// Get auth for the target registry
|
// Always use layered approach - registry layer will handle cross-registry blob copying
|
||||||
let push_auth = resolve_auth(&target_repo)?;
|
let base_auth = resolve_auth(&base_image)?;
|
||||||
|
let (config_data, layer_data, manifest) = image_builder
|
||||||
// Get the media type of the application layer (last layer in manifest)
|
.build(&mut registry_client, &base_auth)
|
||||||
let app_layer_media_type = manifest
|
|
||||||
.layers
|
|
||||||
.last()
|
|
||||||
.map(|l| l.media_type.clone())
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
"application/vnd.docker.image.rootfs.diff.tar.gzip".to_string()
|
|
||||||
});
|
|
||||||
|
|
||||||
// Push layered image by digest only (no tag)
|
|
||||||
// This will be referenced by digest in the final manifest list
|
|
||||||
let (digest_ref, manifest_size) = registry_client
|
|
||||||
.push_layered_image(
|
|
||||||
&target_repo,
|
|
||||||
config_data,
|
|
||||||
layer_data,
|
|
||||||
app_layer_media_type,
|
|
||||||
&manifest,
|
|
||||||
&push_auth,
|
|
||||||
&base_image,
|
|
||||||
&base_auth,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Parse platform string
|
// Push platform-specific image if not --no-push
|
||||||
let parts: Vec<&str> = platform_str.split('/').collect();
|
let manifest_descriptor = if !no_push_flag {
|
||||||
let (os, arch) = if parts.len() >= 2 {
|
info!("Pushing image for platform: {}", platform_str);
|
||||||
(parts[0].to_string(), parts[1].to_string())
|
|
||||||
|
// Get auth for the target registry
|
||||||
|
let push_auth = resolve_auth(&target_repo)?;
|
||||||
|
|
||||||
|
// Get the media type of the application layer (last layer in manifest)
|
||||||
|
let app_layer_media_type = manifest
|
||||||
|
.layers
|
||||||
|
.last()
|
||||||
|
.map(|l| l.media_type.clone())
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
"application/vnd.docker.image.rootfs.diff.tar.gzip".to_string()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Push layered image by digest only (no tag)
|
||||||
|
// This will be referenced by digest in the final manifest list
|
||||||
|
let (digest_ref, manifest_size) = registry_client
|
||||||
|
.push_layered_image(
|
||||||
|
&target_repo,
|
||||||
|
config_data,
|
||||||
|
layer_data,
|
||||||
|
app_layer_media_type,
|
||||||
|
&manifest,
|
||||||
|
&push_auth,
|
||||||
|
&base_image,
|
||||||
|
&base_auth,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// Parse platform string
|
||||||
|
let parts: Vec<&str> = platform_str.split('/').collect();
|
||||||
|
let (os, arch) = if parts.len() >= 2 {
|
||||||
|
(parts[0].to_string(), parts[1].to_string())
|
||||||
|
} else {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"Invalid platform format: {}",
|
||||||
|
platform_str
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extract just the digest from the full reference
|
||||||
|
let digest = digest_ref.split('@').next_back().unwrap_or("").to_string();
|
||||||
|
|
||||||
|
info!("Pushed platform image to: {}", digest_ref);
|
||||||
|
|
||||||
|
// Return manifest descriptor
|
||||||
|
info!(
|
||||||
|
"Adding manifest to list - platform: {}/{}, digest: {}, size: {}",
|
||||||
|
os, arch, digest, manifest_size
|
||||||
|
);
|
||||||
|
Some(ManifestDescriptor {
|
||||||
|
media_type: "application/vnd.oci.image.manifest.v1+json".to_string(),
|
||||||
|
size: manifest_size as i64,
|
||||||
|
digest,
|
||||||
|
platform: Platform {
|
||||||
|
architecture: arch,
|
||||||
|
os,
|
||||||
|
variant: None,
|
||||||
|
},
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
return Err(anyhow::anyhow!("Invalid platform format: {}", platform_str));
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract just the digest from the full reference
|
Ok::<_, anyhow::Error>(manifest_descriptor)
|
||||||
let digest = digest_ref.split('@').next_back().unwrap_or("").to_string();
|
});
|
||||||
|
|
||||||
info!("Pushed platform image to: {}", digest_ref);
|
tasks.push(task);
|
||||||
|
}
|
||||||
|
|
||||||
// Add to manifest list
|
// Wait for all builds to complete
|
||||||
info!(
|
let mut manifest_descriptors = Vec::new();
|
||||||
"Adding manifest to list - platform: {}/{}, digest: {}, size: {}",
|
for task in tasks {
|
||||||
os, arch, digest, manifest_size
|
let result = task.await.context("Build task panicked")??;
|
||||||
);
|
if let Some(descriptor) = result {
|
||||||
manifest_descriptors.push(ManifestDescriptor {
|
manifest_descriptors.push(descriptor);
|
||||||
media_type: "application/vnd.oci.image.manifest.v1+json".to_string(),
|
|
||||||
size: manifest_size as i64,
|
|
||||||
digest,
|
|
||||||
platform: Platform {
|
|
||||||
architecture: arch,
|
|
||||||
os,
|
|
||||||
variant: None,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue