Skip to main content

devimint/
version_constants.rs

1use std::env;
2use std::sync::LazyLock;
3
4use semver::{BuildMetadata, Version};
5
6use crate::envs::FM_EXPECTED_FEDIMINTD_VENDOR_ENV;
7
8/// Add the exact expected vendor identity to a fedimintd release version.
9pub fn version_with_vendor(mut version: Version, vendor: Option<&str>) -> anyhow::Result<Version> {
10    version.build = match vendor {
11        Some(vendor) => {
12            anyhow::ensure!(!vendor.is_empty(), "Fedimintd vendor must not be empty");
13            BuildMetadata::new(vendor)?
14        }
15        None => BuildMetadata::EMPTY,
16    };
17    Ok(version)
18}
19
20/// Check a reported fedimintd version against this devimint invocation.
21pub fn ensure_expected_fedimintd_version(
22    reported_version: &str,
23    version: Version,
24) -> anyhow::Result<()> {
25    let expected_vendor = match env::var(FM_EXPECTED_FEDIMINTD_VENDOR_ENV) {
26        Ok(vendor) => Some(vendor),
27        Err(env::VarError::NotPresent) => None,
28        Err(error) => return Err(error.into()),
29    };
30    let expected_version = version_with_vendor(version, expected_vendor.as_deref())?;
31    let reported_version = Version::parse(reported_version)?;
32
33    anyhow::ensure!(
34        reported_version == expected_version,
35        "Fedimintd reported version {reported_version}, expected {expected_version}"
36    );
37    Ok(())
38}
39
40pub static VERSION_0_10_0_ALPHA: LazyLock<Version> =
41    LazyLock::new(|| Version::parse("0.10.0-alpha").expect("version is parsable"));
42pub static VERSION_0_11_0_ALPHA: LazyLock<Version> =
43    LazyLock::new(|| Version::parse("0.11.0-alpha").expect("version is parsable"));
44pub static VERSION_0_12_0_ALPHA: LazyLock<Version> =
45    LazyLock::new(|| Version::parse("0.12.0-alpha").expect("version is parsable"));
46pub static VERSION_0_13_0_ALPHA: LazyLock<Version> =
47    LazyLock::new(|| Version::parse("0.13.0-alpha").expect("version is parsable"));
48
49#[cfg(test)]
50mod tests {
51    use super::version_with_vendor;
52
53    #[test]
54    fn version_with_vendor_requires_exact_optional_identity() {
55        let upstream = semver::Version::parse("0.11.1-rc.1").expect("valid version");
56        let reported_upstream = semver::Version::parse("0.11.1-rc.1").expect("valid version");
57        let reported_fedi = semver::Version::parse("0.11.1-rc.1+fedi").expect("valid version");
58        let reported_acme = semver::Version::parse("0.11.1-rc.1+acme").expect("valid version");
59
60        assert_eq!(
61            version_with_vendor(upstream.clone(), None).expect("valid upstream version"),
62            reported_upstream
63        );
64        assert_eq!(
65            version_with_vendor(upstream.clone(), Some("fedi")).expect("valid vendor"),
66            reported_fedi
67        );
68        assert_ne!(
69            version_with_vendor(upstream, Some("fedi")).expect("valid vendor"),
70            reported_acme
71        );
72    }
73
74    #[test]
75    fn version_with_vendor_rejects_invalid_build_metadata() {
76        let upstream = semver::Version::parse("0.11.1").expect("valid version");
77
78        assert!(version_with_vendor(upstream.clone(), Some("")).is_err());
79        assert!(version_with_vendor(upstream, Some("not valid")).is_err());
80    }
81}