-
Notifications
You must be signed in to change notification settings - Fork 386
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
76302bb
commit c5b9ea0
Showing
4 changed files
with
320 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"group": { | ||
"default": { | ||
"targets": ["x86_64-unknown-linux-gnu", "x86_64-unknown-netbsd"] | ||
} | ||
}, | ||
"target": { | ||
"x86_64-unknown-linux-gnu": { | ||
"args": {}, | ||
"cache-from": [ | ||
"type=registry,ref=ghcr.io/cross-rs/x86_64-unknown-linux-gnu:main" | ||
], | ||
"context": null, | ||
"dockerfile": "/home/emil/workspace/cross/docker/Dockerfile.x86_64-unknown-linux-gnu", | ||
"labels": { | ||
"org.cross-rs.for-cross-target": "x86_64-unknown-linux-gnu" | ||
}, | ||
"no-cache": false, | ||
"platforms": ["linux/amd64"], | ||
"tags": ["ghcr.io/cross-rs/x86_64-unknown-linux-gnu:local"] | ||
}, | ||
"x86_64-unknown-netbsd": { | ||
"args": {}, | ||
"cache-from": [ | ||
"type=registry,ref=ghcr.io/cross-rs/x86_64-unknown-netbsd:main" | ||
], | ||
"context": null, | ||
"dockerfile": "/home/emil/workspace/cross/docker/Dockerfile.x86_64-unknown-netbsd", | ||
"labels": { | ||
"org.cross-rs.for-cross-target": "x86_64-unknown-netbsd" | ||
}, | ||
"no-cache": false, | ||
"platforms": ["linux/amd64"], | ||
"tags": ["ghcr.io/cross-rs/x86_64-unknown-netbsd:local"] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
use std::{collections::BTreeMap, path::Path}; | ||
|
||
use clap::Args; | ||
use cross::docker; | ||
use serde::Serialize; | ||
|
||
use crate::build_docker_image::{get_tags, locate_dockerfile}; | ||
|
||
#[derive(Args, Debug)] | ||
pub struct BakeDockerImage { | ||
#[clap(long, hide = true, env = "GITHUB_REF_TYPE")] | ||
ref_type: Option<String>, | ||
#[clap(long, hide = true, env = "GITHUB_REF_NAME")] | ||
ref_name: Option<String>, | ||
#[clap(long, hide = true, env = "IS_LATEST")] | ||
is_latest: Option<bool>, | ||
/// Specify a tag to use instead of the derived one, eg `local` | ||
#[clap(long)] | ||
tag: Option<String>, | ||
/// Repository name for image. | ||
#[clap(long, default_value = docker::CROSS_IMAGE)] | ||
repository: String, | ||
/// Newline separated labels | ||
#[clap(long, env = "LABELS")] | ||
labels: Option<String>, | ||
/// Provide verbose diagnostic output. | ||
#[clap(short, long)] | ||
pub verbose: bool, | ||
/// Print but do not execute the build commands. | ||
#[clap(long)] | ||
dry_run: bool, | ||
/// Force a push when `--push` is set, but not `--tag` | ||
#[clap(long, hide = true)] | ||
force: bool, | ||
/// Push build to registry. | ||
#[clap(short, long)] | ||
push: bool, | ||
/// Set output to /dev/null | ||
#[clap(short, long)] | ||
no_output: bool, | ||
/// Docker build progress output type. | ||
#[clap( | ||
long, | ||
value_parser = clap::builder::PossibleValuesParser::new(["auto", "plain", "tty"]), | ||
default_value = "auto" | ||
)] | ||
progress: String, | ||
/// Use a bake build | ||
#[clap(long)] | ||
bake: bool, | ||
/// Do not load from cache when building the image. | ||
#[clap(long)] | ||
no_cache: bool, | ||
/// Continue building images even if an image fails to build. | ||
#[clap(long)] | ||
no_fastfail: bool, | ||
/// Container engine (such as docker or podman). | ||
#[clap(long)] | ||
pub engine: Option<String>, | ||
/// If no target list is provided, parse list from CI. | ||
#[clap(long)] | ||
from_ci: bool, | ||
/// Additional build arguments to pass to Docker. | ||
#[clap(long)] | ||
build_arg: Vec<String>, | ||
/// Targets to build for | ||
#[clap()] | ||
targets: Vec<crate::ImageTarget>, | ||
} | ||
|
||
#[derive(Debug, Serialize)] | ||
#[serde(rename_all = "kebab-case")] | ||
pub struct BakeTarget { | ||
context: Option<String>, | ||
dockerfile: String, | ||
tags: Vec<String>, | ||
labels: BTreeMap<String, String>, | ||
platforms: Vec<String>, | ||
args: BTreeMap<String, String>, | ||
no_cache: bool, | ||
cache_from: Vec<String>, | ||
} | ||
|
||
pub fn bake_docker_image( | ||
BakeDockerImage { | ||
ref_type, | ||
ref_name, | ||
is_latest, | ||
tag: tag_override, | ||
repository, | ||
labels, | ||
verbose, | ||
push, | ||
no_output, | ||
no_cache, | ||
from_ci, | ||
build_arg, | ||
mut targets, | ||
.. | ||
}: BakeDockerImage, | ||
engine: &docker::Engine, | ||
) -> cross::Result<()> { | ||
let metadata = cross::cargo_metadata_with_args( | ||
Some(Path::new(env!("CARGO_MANIFEST_DIR"))), | ||
None, | ||
verbose, | ||
)? | ||
.ok_or_else(|| eyre::eyre!("could not find cross workspace and its current version"))?; | ||
let version = metadata | ||
.get_package("cross") | ||
.expect("cross expected in workspace") | ||
.version | ||
.clone(); | ||
if targets.is_empty() { | ||
if from_ci { | ||
targets = crate::util::get_matrix() | ||
.iter() | ||
.filter(|m| m.os.starts_with("ubuntu")) | ||
.map(|m| m.to_image_target()) | ||
.collect(); | ||
} else { | ||
targets = walkdir::WalkDir::new(metadata.workspace_root.join("docker")) | ||
.max_depth(1) | ||
.contents_first(true) | ||
.into_iter() | ||
.filter_map(|e| e.ok().filter(|f| f.file_type().is_file())) | ||
.filter_map(|f| { | ||
f.file_name() | ||
.to_string_lossy() | ||
.strip_prefix("Dockerfile.") | ||
.map(ToOwned::to_owned) | ||
.map(|s| s.parse().unwrap()) | ||
}) | ||
.collect(); | ||
} | ||
} | ||
let docker_root = metadata.workspace_root.join("docker"); | ||
let cross_toolchains_root = docker_root.join("cross-toolchains").join("docker"); | ||
let targets = targets | ||
.into_iter() | ||
.map(|t| locate_dockerfile(t, &docker_root, &cross_toolchains_root)) | ||
.collect::<cross::Result<Vec<_>>>()?; | ||
let build_args = build_arg | ||
.into_iter() | ||
.map(|s| -> cross::Result<_> { | ||
let s = s | ||
.split_once('=') | ||
.ok_or_else(|| eyre::eyre!("invalid build arg `{s}`"))?; | ||
Ok((s.0.to_string(), s.1.to_string())) | ||
}) | ||
.collect::<cross::Result<BTreeMap<_, _>>>()?; | ||
let labels = labels | ||
.into_iter() | ||
.map(|s| -> cross::Result<_> { | ||
let s = s | ||
.split_once('=') | ||
.ok_or_else(|| eyre::eyre!("invalid label `{s}`"))?; | ||
Ok((s.0.to_string(), s.1.to_string())) | ||
}) | ||
.collect::<cross::Result<BTreeMap<_, _>>>()?; | ||
let targets = targets | ||
.into_iter() | ||
.map(|(target, dockerfile)| -> cross::Result<_> { | ||
Ok(( | ||
target.to_string().replace('.', "-"), | ||
BakeTarget { | ||
context: None, | ||
dockerfile, | ||
tags: get_tags( | ||
&target, | ||
&repository, | ||
&version, | ||
is_latest.unwrap_or_default(), | ||
ref_type.as_deref(), | ||
ref_name.as_deref(), | ||
tag_override.as_deref(), | ||
)?, | ||
labels: { | ||
let mut labels = labels.clone(); | ||
labels.insert( | ||
format!("{}.for-cross-target", cross::CROSS_LABEL_DOMAIN), | ||
target.triplet.clone(), | ||
); | ||
labels | ||
}, | ||
platforms: vec!["linux/amd64".to_string()], | ||
args: build_args.clone(), | ||
no_cache, | ||
cache_from: if !no_cache { | ||
vec![format!( | ||
"type=registry,ref={}", | ||
target.image_name(&repository, "main") | ||
)] | ||
} else { | ||
vec![] | ||
}, | ||
}, | ||
)) | ||
}) | ||
.collect::<cross::Result<BTreeMap<_, _>>>()?; | ||
|
||
let mut docker_bake = docker::command(engine); | ||
docker_bake.args(&["buildx", "bake"]); | ||
docker_bake.current_dir(&docker_root); | ||
|
||
if push { | ||
docker_bake.arg("--push"); | ||
} else if no_output { | ||
docker_bake.args(&["--set", "*.output=type=tar,dest=/dev/null"]); | ||
} else { | ||
docker_bake.arg("--load"); | ||
} | ||
let defaults = targets | ||
.iter() | ||
.map(|(t, _)| t.clone()) | ||
.collect::<Vec<String>>(); | ||
println!( | ||
"{}", | ||
serde_json::to_string_pretty(&serde_json::json!({ | ||
"group": { | ||
"default": { | ||
"targets": defaults, | ||
} | ||
}, | ||
"target": targets, | ||
}))? | ||
); | ||
todo!() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.