Skip to content

Commit 7db737a

Browse files
committed
feat(boil): Provide more build args
1 parent 2dab4c1 commit 7db737a

File tree

6 files changed

+161
-68
lines changed

6 files changed

+161
-68
lines changed

boil.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ DELETE_CACHES = "true"
88
documentation = "https://docs.stackable.tech/home/stable/"
99
source = "https://github.com/stackabletech/docker-images/"
1010
authors = "Stackable GmbH <info@stackable.tech>"
11+
vendor-tag-prefix = "stackable"
1112
vendor = "Stackable GmbH"
1213
licenses = "Apache-2.0"
1314

rust/boil/src/build/bakefile.rs

Lines changed: 112 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ use crate::{
2424
image::{Image, ImageConfig, ImageConfigError, ImageOptions, VersionOptionsPair},
2525
platform::TargetPlatform,
2626
},
27-
config::{self, Config},
28-
utils::{format_image_manifest_uri, format_image_repository_uri},
27+
config::{self, Config, Metadata},
28+
utils,
2929
};
3030

3131
pub const COMMON_TARGET_NAME: &str = "common--target";
@@ -272,23 +272,28 @@ impl Bakefile {
272272
}
273273

274274
/// Creates the common target, containing shared data, which will be inherited by other targets.
275-
fn common_target(args: &cli::BuildArguments, config: Config) -> Result<BakefileTarget, Error> {
275+
fn common_target(
276+
args: &cli::BuildArguments,
277+
build_arguments: BuildArguments,
278+
metadata: &Metadata,
279+
) -> Result<BakefileTarget, Error> {
276280
let revision = Self::git_head_revision().context(GetRevisionSnafu)?;
277281
let date_time = Self::now()?;
278282

279283
// Load build arguments from a file if the user requested it
280-
let mut build_arguments = args.build_arguments.clone();
284+
let mut user_build_arguments = args.build_arguments.clone();
281285
if let Some(path) = &args.build_arguments_file {
282286
let build_arguments_from_file =
283287
BuildArguments::from_file(path).context(ParseBuildArgumentsSnafu)?;
284-
build_arguments.extend(build_arguments_from_file);
288+
user_build_arguments.extend(build_arguments_from_file);
285289
}
286290

287291
let target = BakefileTarget::common(
288292
date_time,
289293
revision,
290-
config,
291294
build_arguments,
295+
metadata,
296+
user_build_arguments,
292297
args.image_version.base_prerelease(),
293298
);
294299

@@ -303,12 +308,46 @@ impl Bakefile {
303308
let mut bakefile_targets = BTreeMap::new();
304309
let mut groups: BTreeMap<String, BakefileGroup> = BTreeMap::new();
305310

311+
// Destructure config so that we can move and borrow fields separately.
312+
let Config {
313+
build_arguments,
314+
metadata,
315+
} = config;
316+
306317
// Create a common target, which contains shared data, like annotations, arguments, labels, etc...
307-
let common_target = Self::common_target(args, config)?;
318+
let common_target = Self::common_target(args, build_arguments, &metadata)?;
308319
bakefile_targets.insert(COMMON_TARGET_NAME.to_owned(), common_target);
309320

321+
// The image registry, eg. `oci.stackable.tech` or `localhost`
322+
let image_registry = if args.use_localhost_registry {
323+
&HostPort::localhost()
324+
} else {
325+
&args.registry
326+
};
327+
310328
for (image_name, image_versions) in targets.into_iter() {
311329
for (image_version, (image_options, is_entry)) in image_versions {
330+
let image_repository_uri = utils::format_image_repository_uri(
331+
image_registry,
332+
&args.registry_namespace,
333+
&image_name,
334+
);
335+
336+
let image_index_manifest_tag = utils::format_image_index_manifest_tag(
337+
&image_version,
338+
&metadata.vendor_tag_prefix,
339+
&args.image_version,
340+
);
341+
342+
let image_manifest_tag = utils::format_image_manifest_tag(
343+
&image_index_manifest_tag,
344+
args.target_platform.architecture(),
345+
args.strip_architecture,
346+
);
347+
348+
let image_manifest_uri =
349+
utils::format_image_manifest_uri(&image_repository_uri, &image_manifest_tag);
350+
312351
// TODO (@Techassi): Clean this up
313352
// TODO (@Techassi): Move the arg formatting into functions
314353
let mut build_arguments = BuildArguments::new();
@@ -317,11 +356,8 @@ impl Bakefile {
317356
.local_images
318357
.iter()
319358
.map(|(image_name, image_version)| {
320-
BuildArgument::new(
321-
format!(
322-
"{image_name}_VERSION",
323-
image_name = image_name.to_uppercase().replace('-', "_")
324-
),
359+
BuildArgument::local_image_version(
360+
image_name.to_string(),
325361
image_version.to_string(),
326362
)
327363
})
@@ -334,27 +370,22 @@ impl Bakefile {
334370
"PRODUCT_VERSION".to_owned(),
335371
image_version.to_string(),
336372
));
337-
338-
// The image registry, eg. `oci.stackable.tech` or `localhost`
339-
let image_registry = if args.use_localhost_registry {
340-
&HostPort::localhost()
341-
} else {
342-
&args.registry
343-
};
344-
345-
let image_repository_uri = format_image_repository_uri(
346-
image_registry,
347-
&args.registry_namespace,
348-
&image_name,
349-
);
350-
351-
let image_manifest_uri = format_image_manifest_uri(
352-
&image_repository_uri,
353-
&image_version,
354-
&args.image_version,
355-
args.target_platform.architecture(),
356-
args.strip_architecture,
357-
);
373+
build_arguments.insert(BuildArgument::new(
374+
"IMAGE_REPOSITORY_URI".to_owned(),
375+
image_repository_uri,
376+
));
377+
build_arguments.insert(BuildArgument::new(
378+
"IMAGE_INDEX_MANIFEST_TAG".to_owned(),
379+
image_index_manifest_tag,
380+
));
381+
build_arguments.insert(BuildArgument::new(
382+
"IMAGE_MANIFEST_TAG".to_owned(),
383+
image_manifest_tag,
384+
));
385+
build_arguments.insert(BuildArgument::new(
386+
"IMAGE_MANIFEST_URI".to_owned(),
387+
image_manifest_uri.clone(),
388+
));
358389

359390
// By using a cap-std Dir, we can ensure that the paths provided must be relative to
360391
// the appropriate image folder and wont escape it by providing absolute or relative
@@ -399,8 +430,11 @@ impl Bakefile {
399430
})
400431
.collect();
401432

402-
let annotations =
403-
BakefileTarget::image_version_annotation(&image_version, &args.image_version);
433+
let annotations = BakefileTarget::image_version_annotation(
434+
&image_version,
435+
&metadata.vendor_tag_prefix,
436+
&args.image_version,
437+
);
404438

405439
let target = BakefileTarget {
406440
tags: vec![image_manifest_uri],
@@ -533,31 +567,50 @@ impl BakefileTarget {
533567
fn common(
534568
date_time: String,
535569
revision: String,
536-
config: Config,
537-
build_arguments: Vec<BuildArgument>,
570+
build_arguments: BuildArguments,
571+
metadata: &Metadata,
572+
user_build_arguments: Vec<BuildArgument>,
538573
release_version: String,
539574
) -> Self {
540575
let config::Metadata {
541-
documentation,
576+
documentation: docs,
542577
licenses,
543578
authors,
544579
source,
545580
vendor,
546-
} = config.metadata;
581+
..
582+
} = metadata;
547583

548584
// Annotations describe OCI image components.
549-
let annotations = vec![
585+
// Add annotations which are always present.
586+
let mut annotations = vec![
550587
format!("{ANNOTATION_CREATED}={date_time}"),
551-
format!("{ANNOTATION_AUTHORS}={authors}"),
552-
format!("{ANNOTATION_DOCUMENTATION}={documentation}"),
553-
format!("{ANNOTATION_SOURCE}={source}"),
554588
format!("{ANNOTATION_REVISION}={revision}"),
555-
format!("{ANNOTATION_VENDOR}={vendor}"),
556-
format!("{ANNOTATION_LICENSES}={licenses}"),
557589
];
558590

559-
let mut arguments = config.build_arguments;
560-
arguments.extend(build_arguments);
591+
// Add optional annotations.
592+
if let Some(authors) = authors {
593+
annotations.push(format!("{ANNOTATION_AUTHORS}={authors}"));
594+
}
595+
596+
if let Some(docs) = docs {
597+
annotations.push(format!("{ANNOTATION_DOCUMENTATION}={docs}"));
598+
}
599+
600+
if let Some(source) = source {
601+
annotations.push(format!("{ANNOTATION_SOURCE}={source}"));
602+
}
603+
604+
if let Some(licenses) = licenses {
605+
annotations.push(format!("{ANNOTATION_LICENSES}={licenses}"));
606+
}
607+
608+
if let Some(vendor) = vendor {
609+
annotations.push(format!("{ANNOTATION_VENDOR}={vendor}"));
610+
}
611+
612+
let mut arguments = build_arguments;
613+
arguments.extend(user_build_arguments);
561614
arguments.insert(BuildArgument::new(
562615
"RELEASE_VERSION".to_owned(),
563616
release_version,
@@ -580,12 +633,18 @@ impl BakefileTarget {
580633
}
581634
}
582635

583-
fn image_version_annotation(image_version: &str, sdp_image_version: &Version) -> Vec<String> {
584-
vec![
585-
// TODO (@Techassi): Move this version formatting into a function
586-
// TODO (@Techassi): Make this vendor agnostic, don't hard-code stackable here
587-
format!("{ANNOTATION_VERSION}={image_version}-stackable{sdp_image_version}"),
588-
]
636+
fn image_version_annotation(
637+
image_version: &str,
638+
vendor_tag_prefix: &str,
639+
vendor_image_version: &Version,
640+
) -> Vec<String> {
641+
let image_index_manifest_tag = utils::format_image_index_manifest_tag(
642+
image_version,
643+
vendor_tag_prefix,
644+
vendor_image_version,
645+
);
646+
647+
vec![format!("{ANNOTATION_VERSION}={image_index_manifest_tag}")]
589648
}
590649
}
591650

rust/boil/src/build/cli.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ pub struct BuildArguments {
2222
#[arg(help_heading = "Image Options", required = true)]
2323
pub images: Vec<Image>,
2424

25-
// The action currently does the wrong thing here. It includes the
26-
// architecture even though it should come from the --target-platform arg.
27-
// The release arg is NOT needed, because this version IS the release version.
25+
// NOTE (@Techassi): Should this maybe be renamed to vendor_version?
2826
/// The image version being built.
2927
#[arg(
3028
short, long,

rust/boil/src/build/docker.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ impl BuildArgument {
3030
Self((key, value))
3131
}
3232

33+
pub fn local_image_version(image_name: String, image_version: String) -> Self {
34+
Self::new(format!("{image_name}_VERSION"), image_version)
35+
}
36+
3337
fn format_key(key: impl AsRef<str>) -> String {
3438
key.as_ref().replace(['-', '/'], "_").to_uppercase()
3539
}

rust/boil/src/config.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,28 @@ impl Config {
3030
// NOTE (@Techassi): Think about if these metadata fields should be required or optional. If they
3131
// are optional, the appropriate annotations are only emitted if set.
3232
#[derive(Debug, Deserialize)]
33+
#[serde(rename_all = "kebab-case")]
3334
pub struct Metadata {
34-
pub documentation: Url,
35-
pub licenses: String,
36-
pub authors: String,
37-
pub vendor: String,
38-
pub source: Url,
35+
/// The URL to the documentation page.
36+
pub documentation: Option<Url>,
37+
38+
/// One ore more licenses used for images using the SPDX format.
39+
pub licenses: Option<String>,
40+
41+
/// One or more authors of images.
42+
///
43+
/// It is recommended to use the "NAME <EMAIL>" format.
44+
pub authors: Option<String>,
45+
46+
/// The vendor who builds the images.
47+
pub vendor: Option<String>,
48+
49+
/// The vendor prefix used in the image (index) manifest tag.
50+
///
51+
/// Defaults to an empty string.
52+
#[serde(default)]
53+
pub vendor_tag_prefix: String,
54+
55+
/// The version control source of the images.
56+
pub source: Option<Url>,
3957
}

rust/boil/src/utils.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,32 @@ pub fn format_image_repository_uri(
1414
}
1515

1616
/// Formats and returns the image manifest URI, eg. `oci.stackable.tech/sdp/opa:1.4.2-stackable25.7.0-amd64`.
17-
pub fn format_image_manifest_uri(
18-
image_repository_uri: &str,
17+
pub fn format_image_manifest_uri(image_repository_uri: &str, image_manifest_tag: &str) -> String {
18+
format!("{image_repository_uri}:{image_manifest_tag}")
19+
}
20+
21+
/// Formats and returns the image index manifest tag, eg. `1.4.2-stackable25.7.0`.
22+
pub fn format_image_index_manifest_tag(
1923
image_version: &str,
20-
sdp_image_version: &Version,
24+
vendor_tag_prefix: &str,
25+
vendor_image_version: &Version,
26+
) -> String {
27+
format!("{image_version}-{vendor_tag_prefix}{vendor_image_version}")
28+
}
29+
30+
/// Formats and returns the image manifest tag, eg. `1.4.2-stackable25.7.0-amd64`.
31+
///
32+
/// The `strip_architecture` parameter controls if the architecture is included in the tag.
33+
pub fn format_image_manifest_tag(
34+
image_index_manifest_tag: &str,
35+
// TODO (@Techassi): Maybe turn this into an Option to get rid of the bool
2136
architecture: &Architecture,
2237
strip_architecture: bool,
2338
) -> String {
2439
if strip_architecture {
25-
format!("{image_repository_uri}:{image_version}-stackable{sdp_image_version}")
40+
image_index_manifest_tag.to_owned()
2641
} else {
27-
format!(
28-
"{image_repository_uri}:{image_version}-stackable{sdp_image_version}-{architecture}"
29-
)
42+
format!("{image_index_manifest_tag}-{architecture}")
3043
}
3144
}
3245

0 commit comments

Comments
 (0)