Skip to main content

intentional_core/
model.rs

1// ---
2// relationships:
3//   implements: intent-driven-polyglot-release
4// ---
5
6//! Shared release domain values.
7
8use serde::{Deserialize, Serialize};
9use std::fmt;
10use std::str::FromStr;
11
12/// Semantic version change declared by an intent.
13#[derive(
14    Debug, Clone, Copy, Default, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash,
15)]
16#[serde(rename_all = "lowercase")]
17pub enum Bump {
18    /// No change.
19    #[default]
20    None,
21    /// Backwards-compatible bug fix.
22    Patch,
23    /// Backwards-compatible feature.
24    Minor,
25    /// Breaking change.
26    Major,
27}
28
29impl fmt::Display for Bump {
30    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
31        formatter.write_str(match self {
32            Self::None => "none",
33            Self::Patch => "patch",
34            Self::Minor => "minor",
35            Self::Major => "major",
36        })
37    }
38}
39
40impl FromStr for Bump {
41    type Err = String;
42
43    fn from_str(value: &str) -> std::result::Result<Self, Self::Err> {
44        match value {
45            "patch" => Ok(Self::Patch),
46            "minor" => Ok(Self::Minor),
47            "major" => Ok(Self::Major),
48            _ => Err(format!("expected major, minor, or patch; got {value}")),
49        }
50    }
51}
52
53/// How a version projection is materialized.
54#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
55#[serde(rename_all = "lowercase")]
56pub enum ProjectionMode {
57    /// Version is written for a source-controlled release commit.
58    Committed,
59    /// Version is written only for build-time stamping.
60    Injected,
61    /// No manifest version is written.
62    None,
63}
64
65/// How bump names are interpreted before semantic version 1.0.0.
66#[derive(Debug, Clone, Copy, Default, Deserialize, Serialize, PartialEq, Eq)]
67#[serde(rename_all = "lowercase")]
68pub enum Pre1BumpMapping {
69    /// Bump the named semantic-version component, matching Changesets.
70    Component,
71    /// Treat bump names as compatibility significance.
72    #[default]
73    Compatibility,
74}
75
76/// Whether a discovered release unit participates in releases.
77#[derive(Debug, Clone, Copy, Default, Deserialize, Serialize, PartialEq, Eq)]
78#[serde(rename_all = "lowercase")]
79pub enum ReleaseUnitDisposition {
80    /// The release unit is configured and eligible for release.
81    #[default]
82    Managed,
83    /// The release unit remains configured, but any release requiring it is blocked.
84    Suspended,
85}
86
87/// Version-authority role of a release-unit tag.
88#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
89#[serde(rename_all = "lowercase")]
90pub enum TagRole {
91    /// The single tag stream used to discover the release unit's current version.
92    Primary,
93    /// An additional release record carrying the same logical version.
94    Projection,
95}
96
97/// Executor-declared phase required to create a configured tag.
98#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
99#[serde(rename_all = "kebab-case")]
100pub enum TagPhase {
101    /// The executor declares that publication has not begun.
102    BeforePublication,
103    /// The executor declares that publication has completed.
104    AfterPublication,
105}
106
107impl fmt::Display for TagPhase {
108    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
109        formatter.write_str(match self {
110            Self::BeforePublication => "before-publication",
111            Self::AfterPublication => "after-publication",
112        })
113    }
114}
115
116/// Manifest or generic format adapter used by a projection.
117#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Hash)]
118#[serde(rename_all = "lowercase")]
119pub enum Adapter {
120    /// npm `package.json`.
121    Npm,
122    /// Cargo `Cargo.toml`.
123    Cargo,
124    /// Dart/Flutter `pubspec.yaml`.
125    Pub,
126    /// PEP 621 `pyproject.toml`.
127    Python,
128    /// MSBuild project file.
129    Msbuild,
130    /// Go module file.
131    Go,
132    /// Generic JSON file.
133    Json,
134    /// Generic TOML file.
135    Toml,
136    /// Generic YAML file.
137    Yaml,
138}
139
140impl Adapter {
141    /// Whether the adapter requires an explicit pointer.
142    pub fn requires_pointer(self) -> bool {
143        matches!(self, Self::Json | Self::Toml | Self::Yaml)
144    }
145
146    /// Whether the projection participates in dependency range rewriting.
147    pub fn ecosystem(self) -> Option<&'static str> {
148        match self {
149            Self::Npm => Some("npm"),
150            Self::Cargo => Some("cargo"),
151            Self::Pub => Some("pub"),
152            Self::Python => Some("python"),
153            Self::Msbuild => Some("msbuild"),
154            Self::Go => Some("go"),
155            Self::Json | Self::Toml | Self::Yaml => None,
156        }
157    }
158}