use anodizer_core::artifact::ArtifactKind;
use anodizer_core::config::Config;
use anodizer_core::context::Context;
use anodizer_core::log::StageLogger;
use anyhow::{Context as _, Result};
pub fn write_effective_config(config: &Config, log: &StageLogger) -> Result<()> {
let dist = &config.dist;
std::fs::create_dir_all(dist)
.with_context(|| format!("failed to create dist directory: {}", dist.display()))?;
let effective_path = dist.join("config.yaml");
let mut value: serde_yaml_ng::Value =
serde_yaml_ng::to_value(config).context("failed to serialize effective config")?;
sort_yaml_mapping(&mut value);
let yaml = serde_yaml_ng::to_string(&value).context("failed to serialize effective config")?;
std::fs::write(&effective_path, &yaml)
.with_context(|| format!("failed to write {}", effective_path.display()))?;
log.verbose(&format!(
"wrote effective config to {}",
effective_path.display()
));
Ok(())
}
pub(super) fn sort_yaml_mapping(value: &mut serde_yaml_ng::Value) {
use serde_yaml_ng::{Mapping, Value};
match value {
Value::Mapping(map) => {
let mut entries: Vec<(Value, Value)> = std::mem::take(map).into_iter().collect();
entries.sort_by_key(|(a, _)| yaml_key_sort_key(a));
let mut sorted = Mapping::with_capacity(entries.len());
for (k, mut v) in entries {
sort_yaml_mapping(&mut v);
sorted.insert(k, v);
}
*map = sorted;
}
Value::Sequence(seq) => {
for v in seq.iter_mut() {
sort_yaml_mapping(v);
}
}
Value::Tagged(tagged) => sort_yaml_mapping(&mut tagged.value),
_ => {}
}
}
pub(super) fn yaml_key_sort_key(v: &serde_yaml_ng::Value) -> String {
match v {
serde_yaml_ng::Value::String(s) => s.clone(),
other => format!("{:?}", other),
}
}
pub fn run_report_sizes(ctx: &mut Context, config: &Config, log: &StageLogger) {
if config.report_sizes.unwrap_or(false) {
anodizer_core::artifact::print_size_report(&mut ctx.artifacts, log);
}
}
pub fn write_metadata_json(
ctx: &Context,
config: &Config,
log: &StageLogger,
) -> Result<std::path::PathBuf> {
let dist = &ctx.config.dist;
std::fs::create_dir_all(dist)
.with_context(|| format!("failed to create dist directory: {}", dist.display()))?;
let metadata_path = dist.join(anodizer_core::dist::METADATA_JSON);
let goos = anodizer_core::context::map_os_to_goos(std::env::consts::OS);
let goarch = anodizer_core::context::map_arch_to_goarch(std::env::consts::ARCH);
let tag = ctx.template_vars().get("Tag").cloned().unwrap_or_default();
let previous_tag = ctx
.template_vars()
.get("PreviousTag")
.cloned()
.unwrap_or_default();
let version = ctx.version();
let commit = ctx
.template_vars()
.get("FullCommit")
.cloned()
.unwrap_or_default();
let date = ctx.template_vars().get("Date").cloned().unwrap_or_default();
let release_url = ctx
.template_vars()
.get("ReleaseURL")
.cloned()
.unwrap_or_default();
let project_metadata = serde_json::json!({
"project_name": config.project_name,
"tag": tag,
"previous_tag": previous_tag,
"version": version,
"commit": commit,
"date": date,
"release_url": release_url,
"runtime": {
"goos": goos,
"goarch": goarch,
}
});
let json_str = serde_json::to_string_pretty(&project_metadata)
.context("failed to serialize project metadata JSON")?;
std::fs::write(&metadata_path, &json_str)
.with_context(|| format!("failed to write {}", metadata_path.display()))?;
log.status(&format!("wrote {}", metadata_path.display()));
Ok(metadata_path)
}
const _: &str = anodizer_core::determinism::ARTIFACTS_MANIFEST_AGGREGATE_ID;
pub fn write_metadata_and_artifacts(
ctx: &mut Context,
config: &Config,
log: &StageLogger,
) -> Result<()> {
let dist = ctx.config.dist.clone();
let metadata_path = write_metadata_json(ctx, config, log)?;
ctx.artifacts.add(anodizer_core::artifact::Artifact {
kind: ArtifactKind::Metadata,
name: anodizer_core::dist::METADATA_JSON.to_string(),
path: metadata_path.clone(),
target: None,
crate_name: config.project_name.clone(),
metadata: Default::default(),
size: None,
});
let artifacts_path = dist.join(anodizer_core::dist::ARTIFACTS_JSON);
let artifacts_json = ctx
.artifacts
.to_artifacts_json()
.context("failed to serialize artifact list")?;
let json_str = serde_json::to_string_pretty(&artifacts_json)
.context("failed to serialize artifacts JSON")?;
std::fs::write(&artifacts_path, &json_str)
.with_context(|| format!("failed to write {}", artifacts_path.display()))?;
log.status(&format!("wrote {}", artifacts_path.display()));
if let Some(ref meta) = config.metadata
&& let Some(ref ts_tmpl) = meta.mod_timestamp
{
let rendered = ctx
.render_template(ts_tmpl)
.context("failed to render metadata.mod_timestamp template")?;
if !rendered.is_empty() {
let mtime = anodizer_core::util::parse_mod_timestamp(&rendered)
.with_context(|| format!("invalid metadata.mod_timestamp value: {:?}", rendered))?;
anodizer_core::util::set_file_mtime(&metadata_path, mtime)?;
anodizer_core::util::set_file_mtime(&artifacts_path, mtime)?;
log.status(&format!(
"set mtime on metadata.json and artifacts.json to {}",
rendered
));
}
}
Ok(())
}