use crate::release::publish::tag::CrateTag;
use crate::release::version::Ybf;
use std::collections::BTreeMap;
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum CrateResult {
Published { tag: String },
AlreadyPublished,
Failed { reason: String },
Skipped { reason: String },
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub(crate) struct PublishReport {
pub(crate) transaction_id: String,
pub(crate) commit: String,
pub(crate) results: BTreeMap<String, CrateResult>,
pub(crate) all_published: bool,
}
impl PublishReport {
#[allow(dead_code)]
pub(crate) fn published_count(&self) -> usize {
self.results
.values()
.filter(|r| matches!(r, CrateResult::Published { .. }))
.count()
}
#[allow(dead_code)]
pub(crate) fn already_published_count(&self) -> usize {
self.results
.values()
.filter(|r| matches!(r, CrateResult::AlreadyPublished))
.count()
}
#[allow(dead_code)]
pub(crate) fn failed_count(&self) -> usize {
self.results
.values()
.filter(|r| matches!(r, CrateResult::Failed { .. }))
.count()
}
#[allow(dead_code)]
pub(crate) fn skipped_count(&self) -> usize {
self.results
.values()
.filter(|r| matches!(r, CrateResult::Skipped { .. }))
.count()
}
}
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct PublishStep {
pub(crate) crate_name: String,
pub(crate) version: Ybf,
pub(crate) order: usize,
pub(crate) tag: String,
}
pub(crate) fn build_publish_steps(crate_name: &str, version: &Ybf, order: usize) -> PublishStep {
let tag = CrateTag::render(crate_name, version);
PublishStep {
crate_name: crate_name.to_string(),
version: *version,
order,
tag,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn build_step_has_correct_tag() {
let v = Ybf::parse("2026.1.7").unwrap();
let step = build_publish_steps("arcature-auth", &v, 1);
assert_eq!(step.crate_name, "arcature-auth");
assert_eq!(step.version, v);
assert_eq!(step.order, 1);
assert_eq!(step.tag, "arcature-auth-v2026.1.7");
}
#[test]
fn report_counts_published() {
let mut results = BTreeMap::new();
results.insert(
"arcature-auth".to_string(),
CrateResult::Published {
tag: "arcature-auth-v2026.1.7".to_string(),
},
);
results.insert("arcature-cli".to_string(), CrateResult::AlreadyPublished);
results.insert(
"arcature-jobs".to_string(),
CrateResult::Failed {
reason: "build error".to_string(),
},
);
results.insert(
"arcature-pages".to_string(),
CrateResult::Skipped {
reason: "prior failure".to_string(),
},
);
let report = PublishReport {
transaction_id: "2026-08-15.01".to_string(),
commit: "abc".to_string(),
results,
all_published: false,
};
assert_eq!(report.published_count(), 1);
assert_eq!(report.already_published_count(), 1);
assert_eq!(report.failed_count(), 1);
assert_eq!(report.skipped_count(), 1);
}
#[test]
fn report_all_published_true() {
let mut results = BTreeMap::new();
results.insert(
"arcature-auth".to_string(),
CrateResult::Published {
tag: "arcature-auth-v2026.1.7".to_string(),
},
);
results.insert("arcature-cli".to_string(), CrateResult::AlreadyPublished);
let report = PublishReport {
transaction_id: "2026-08-15.01".to_string(),
commit: "abc".to_string(),
results,
all_published: true,
};
assert!(report.all_published);
}
}