Skip to main content

release_tool/
domain.rs

1use crate::tag::CalendarTag;
2
3#[derive(Clone, Copy, Debug, Eq, PartialEq)]
4pub enum ReleaseIntent {
5    Existing,
6    New,
7}
8
9#[derive(Clone, Debug, Eq, PartialEq)]
10pub struct ReleaseCandidate {
11    pub repository: String,
12    pub commit: String,
13    pub tag: CalendarTag,
14    pub intent: ReleaseIntent,
15    pub tag_already_sealed: bool,
16}
17
18#[derive(Clone, Debug, Eq, PartialEq)]
19pub struct SealedRelease {
20    pub release: ReleaseCandidate,
21    pub tag_object: String,
22}
23
24#[derive(Clone, Debug, Eq, Hash, PartialEq)]
25pub enum ArtifactIdentity {
26    GithubReleaseAsset {
27        name: String,
28    },
29    MavenPackage {
30        group_id: String,
31        artifact_id: String,
32        version: String,
33        extension: String,
34        classifier: Option<String>,
35    },
36    OciImage {
37        repository: String,
38        tag: String,
39        platform: String,
40    },
41}
42
43impl ArtifactIdentity {
44    pub(crate) fn maven_file_name(&self) -> anyhow::Result<String> {
45        let Self::MavenPackage {
46            artifact_id,
47            version,
48            extension,
49            classifier,
50            ..
51        } = self
52        else {
53            anyhow::bail!("expected a Maven artifact identity");
54        };
55        let suffix = match classifier {
56            Some(classifier) => {
57                validate_maven_attachment(classifier, extension)?;
58                format!("-{classifier}")
59            }
60            None => String::new(),
61        };
62        Ok(format!("{artifact_id}-{version}{suffix}.{extension}"))
63    }
64}
65
66pub(crate) fn validate_maven_attachment(classifier: &str, extension: &str) -> anyhow::Result<()> {
67    if !classifier
68        .as_bytes()
69        .first()
70        .is_some_and(u8::is_ascii_alphanumeric)
71        || !classifier
72            .bytes()
73            .all(|byte| byte.is_ascii_alphanumeric() || b"._-".contains(&byte))
74    {
75        anyhow::bail!(
76            "Maven attachment classifier must be a nonempty safe identifier: `{classifier}`"
77        );
78    }
79    if !matches!(extension, "jar" | "zip") {
80        anyhow::bail!("Maven attachment extension must be jar or zip: `{extension}`");
81    }
82    Ok(())
83}
84
85#[derive(Clone, Debug, Eq, PartialEq)]
86pub struct TargetPlan {
87    pub name: String,
88    pub publisher: String,
89    pub release: ReleaseCandidate,
90    pub artifacts: Vec<ArtifactIdentity>,
91}
92
93#[derive(Clone, Debug, Eq, PartialEq)]
94pub struct PreparedArtifact {
95    pub identity: ArtifactIdentity,
96    pub path: std::path::PathBuf,
97    pub sha256: String,
98}
99
100#[derive(Clone, Debug, Eq, PartialEq)]
101pub struct ArtifactManifest {
102    pub target: String,
103    pub publisher: String,
104    pub release: ReleaseCandidate,
105    pub artifacts: Vec<PreparedArtifact>,
106}
107
108#[derive(Clone, Debug, Eq, PartialEq)]
109pub struct ReleasePlan {
110    pub tool_version: String,
111    pub release: ReleaseCandidate,
112    pub targets: Vec<TargetPlan>,
113}