From cbcf9c8d455000c59af4a2143c4ba3d32a29b083 Mon Sep 17 00:00:00 2001 From: Wisaroot Lertthaweedech Date: Sat, 8 Nov 2025 08:32:31 +0700 Subject: [PATCH 01/52] refactor: clean presets code --- src/schema/components.rs | 63 ++++++++++ src/schema/mod.rs | 8 +- src/schema/names.rs | 27 +++++ src/schema/presets.rs | 247 +++++++++++++-------------------------- 4 files changed, 176 insertions(+), 169 deletions(-) create mode 100644 src/schema/components.rs create mode 100644 src/schema/names.rs diff --git a/src/schema/components.rs b/src/schema/components.rs new file mode 100644 index 00000000..ad159183 --- /dev/null +++ b/src/schema/components.rs @@ -0,0 +1,63 @@ +use crate::utils::constants::timestamp_patterns; +use crate::version::zerv::{ + Component, + Var, +}; + +pub fn standard_core() -> Vec { + vec![ + Component::Var(Var::Major), + Component::Var(Var::Minor), + Component::Var(Var::Patch), + ] +} + +pub fn calver_core() -> Vec { + vec![ + Component::Var(Var::Timestamp(timestamp_patterns::YYYY.to_string())), + Component::Var(Var::Timestamp(timestamp_patterns::MM.to_string())), + Component::Var(Var::Timestamp(timestamp_patterns::DD.to_string())), + Component::Var(Var::Patch), + ] +} + +pub fn prerelease_core() -> Vec { + vec![Component::Var(Var::Epoch), Component::Var(Var::PreRelease)] +} + +pub fn prerelease_post_core() -> Vec { + vec![ + Component::Var(Var::Epoch), + Component::Var(Var::PreRelease), + Component::Var(Var::Post), + ] +} + +pub fn prerelease_post_dev_core() -> Vec { + vec![ + Component::Var(Var::Epoch), + Component::Var(Var::PreRelease), + Component::Var(Var::Post), + Component::Var(Var::Dev), + ] +} + +pub fn build_context() -> Vec { + vec![ + Component::Var(Var::BumpedBranch), + Component::Var(Var::Distance), + Component::Var(Var::BumpedCommitHashShort), + ] +} + +pub fn build_if_enabled(with_context: bool) -> Vec { + if with_context { + build_context() + } else { + vec![] + } +} + +pub fn epoch_extra_core() -> Vec { + vec![Component::Var(Var::Epoch)] +} diff --git a/src/schema/mod.rs b/src/schema/mod.rs index ec3dae77..8c17699f 100644 --- a/src/schema/mod.rs +++ b/src/schema/mod.rs @@ -1,8 +1,8 @@ +mod components; +mod names; mod presets; -pub use presets::{ - ZervSchemaPreset, - schema_preset_names, -}; +pub use names::schema_preset_names; +pub use presets::ZervSchemaPreset; pub use crate::version::zerv::schema::parse_ron_schema; diff --git a/src/schema/names.rs b/src/schema/names.rs new file mode 100644 index 00000000..c970255f --- /dev/null +++ b/src/schema/names.rs @@ -0,0 +1,27 @@ +pub mod schema_preset_names { + pub const STANDARD: &str = "standard"; + pub const STANDARD_NO_CONTEXT: &str = "standard-no-context"; + pub const STANDARD_BASE: &str = "standard-base"; + pub const STANDARD_BASE_PRERELEASE: &str = "standard-base-prerelease"; + pub const STANDARD_BASE_PRERELEASE_POST: &str = "standard-base-prerelease-post"; + pub const STANDARD_BASE_PRERELEASE_POST_DEV: &str = "standard-base-prerelease-post-dev"; + pub const STANDARD_BASE_CONTEXT: &str = "standard-base-context"; + pub const STANDARD_BASE_PRERELEASE_CONTEXT: &str = "standard-base-prerelease-context"; + pub const STANDARD_BASE_PRERELEASE_POST_CONTEXT: &str = "standard-base-prerelease-post-context"; + pub const STANDARD_BASE_PRERELEASE_POST_DEV_CONTEXT: &str = + "standard-base-prerelease-post-dev-context"; + pub const STANDARD_CONTEXT: &str = "standard-context"; + + pub const CALVER: &str = "calver"; + pub const CALVER_NO_CONTEXT: &str = "calver-no-context"; + pub const CALVER_BASE: &str = "calver-base"; + pub const CALVER_BASE_PRERELEASE: &str = "calver-base-prerelease"; + pub const CALVER_BASE_PRERELEASE_POST: &str = "calver-base-prerelease-post"; + pub const CALVER_BASE_PRERELEASE_POST_DEV: &str = "calver-base-prerelease-post-dev"; + pub const CALVER_BASE_CONTEXT: &str = "calver-base-context"; + pub const CALVER_BASE_PRERELEASE_CONTEXT: &str = "calver-base-prerelease-context"; + pub const CALVER_BASE_PRERELEASE_POST_CONTEXT: &str = "calver-base-prerelease-post-context"; + pub const CALVER_BASE_PRERELEASE_POST_DEV_CONTEXT: &str = + "calver-base-prerelease-post-dev-context"; + pub const CALVER_CONTEXT: &str = "calver-context"; +} diff --git a/src/schema/presets.rs b/src/schema/presets.rs index 221c3e59..80f235ff 100644 --- a/src/schema/presets.rs +++ b/src/schema/presets.rs @@ -1,105 +1,45 @@ use std::str::FromStr; +pub use super::components::{ + build_context, + build_if_enabled, + calver_core, + epoch_extra_core, + prerelease_core, + prerelease_post_core, + prerelease_post_dev_core, + standard_core, +}; +pub use super::names::schema_preset_names::{ + CALVER, + CALVER_BASE, + CALVER_BASE_CONTEXT, + CALVER_BASE_PRERELEASE, + CALVER_BASE_PRERELEASE_CONTEXT, + CALVER_BASE_PRERELEASE_POST, + CALVER_BASE_PRERELEASE_POST_CONTEXT, + CALVER_BASE_PRERELEASE_POST_DEV, + CALVER_BASE_PRERELEASE_POST_DEV_CONTEXT, + CALVER_CONTEXT, + CALVER_NO_CONTEXT, + STANDARD, + STANDARD_BASE, + STANDARD_BASE_CONTEXT, + STANDARD_BASE_PRERELEASE, + STANDARD_BASE_PRERELEASE_CONTEXT, + STANDARD_BASE_PRERELEASE_POST, + STANDARD_BASE_PRERELEASE_POST_CONTEXT, + STANDARD_BASE_PRERELEASE_POST_DEV, + STANDARD_BASE_PRERELEASE_POST_DEV_CONTEXT, + STANDARD_CONTEXT, + STANDARD_NO_CONTEXT, +}; use crate::error::ZervError; use crate::version::zerv::{ ZervSchema, ZervVars, }; -mod schema_preset_components { - use crate::utils::constants::timestamp_patterns; - use crate::version::zerv::{ - Component, - Var, - }; - - pub fn standard_core() -> Vec { - vec![ - Component::Var(Var::Major), - Component::Var(Var::Minor), - Component::Var(Var::Patch), - ] - } - - pub fn calver_core() -> Vec { - vec![ - Component::Var(Var::Timestamp(timestamp_patterns::YYYY.to_string())), - Component::Var(Var::Timestamp(timestamp_patterns::MM.to_string())), - Component::Var(Var::Timestamp(timestamp_patterns::DD.to_string())), - Component::Var(Var::Patch), - ] - } - - pub fn prerelease_core() -> Vec { - vec![Component::Var(Var::Epoch), Component::Var(Var::PreRelease)] - } - - pub fn prerelease_post_core() -> Vec { - vec![ - Component::Var(Var::Epoch), - Component::Var(Var::PreRelease), - Component::Var(Var::Post), - ] - } - - pub fn prerelease_post_dev_core() -> Vec { - vec![ - Component::Var(Var::Epoch), - Component::Var(Var::PreRelease), - Component::Var(Var::Post), - Component::Var(Var::Dev), - ] - } - - pub fn build_context() -> Vec { - vec![ - Component::Var(Var::BumpedBranch), - Component::Var(Var::Distance), - Component::Var(Var::BumpedCommitHashShort), - ] - } - - pub fn build_if_enabled(with_context: bool) -> Vec { - if with_context { - build_context() - } else { - vec![] - } - } - - pub fn epoch_extra_core() -> Vec { - vec![Component::Var(Var::Epoch)] - } -} - -pub mod schema_preset_names { - pub const STANDARD: &str = "standard"; - pub const STANDARD_NO_CONTEXT: &str = "standard-no-context"; - pub const STANDARD_BASE: &str = "standard-base"; - pub const STANDARD_BASE_PRERELEASE: &str = "standard-base-prerelease"; - pub const STANDARD_BASE_PRERELEASE_POST: &str = "standard-base-prerelease-post"; - pub const STANDARD_BASE_PRERELEASE_POST_DEV: &str = "standard-base-prerelease-post-dev"; - pub const STANDARD_BASE_CONTEXT: &str = "standard-base-context"; - pub const STANDARD_BASE_PRERELEASE_CONTEXT: &str = "standard-base-prerelease-context"; - pub const STANDARD_BASE_PRERELEASE_POST_CONTEXT: &str = "standard-base-prerelease-post-context"; - pub const STANDARD_BASE_PRERELEASE_POST_DEV_CONTEXT: &str = - "standard-base-prerelease-post-dev-context"; - pub const STANDARD_CONTEXT: &str = "standard-context"; - - pub const CALVER: &str = "calver"; - pub const CALVER_NO_CONTEXT: &str = "calver-no-context"; - pub const CALVER_BASE: &str = "calver-base"; - pub const CALVER_BASE_PRERELEASE: &str = "calver-base-prerelease"; - pub const CALVER_BASE_PRERELEASE_POST: &str = "calver-base-prerelease-post"; - pub const CALVER_BASE_PRERELEASE_POST_DEV: &str = "calver-base-prerelease-post-dev"; - pub const CALVER_BASE_CONTEXT: &str = "calver-base-context"; - pub const CALVER_BASE_PRERELEASE_CONTEXT: &str = "calver-base-prerelease-context"; - pub const CALVER_BASE_PRERELEASE_POST_CONTEXT: &str = "calver-base-prerelease-post-context"; - pub const CALVER_BASE_PRERELEASE_POST_DEV_CONTEXT: &str = - "calver-base-prerelease-post-dev-context"; - pub const CALVER_CONTEXT: &str = "calver-context"; -} - #[derive(Debug, Clone, PartialEq, Eq)] pub enum ZervSchemaPreset { Standard, @@ -227,9 +167,9 @@ impl ZervSchemaPreset { fn standard_base_schema(&self, with_context: bool) -> ZervSchema { ZervSchema::new_with_precedence( - schema_preset_components::standard_core(), - schema_preset_components::epoch_extra_core(), - schema_preset_components::build_if_enabled(with_context), + standard_core(), + epoch_extra_core(), + build_if_enabled(with_context), Default::default(), ) .unwrap() @@ -237,9 +177,9 @@ impl ZervSchemaPreset { fn standard_base_prerelease_schema(&self, with_context: bool) -> ZervSchema { ZervSchema::new_with_precedence( - schema_preset_components::standard_core(), - schema_preset_components::prerelease_core(), - schema_preset_components::build_if_enabled(with_context), + standard_core(), + prerelease_core(), + build_if_enabled(with_context), Default::default(), ) .unwrap() @@ -247,9 +187,9 @@ impl ZervSchemaPreset { fn standard_base_prerelease_post_schema(&self, with_context: bool) -> ZervSchema { ZervSchema::new_with_precedence( - schema_preset_components::standard_core(), - schema_preset_components::prerelease_post_core(), - schema_preset_components::build_if_enabled(with_context), + standard_core(), + prerelease_post_core(), + build_if_enabled(with_context), Default::default(), ) .unwrap() @@ -257,9 +197,9 @@ impl ZervSchemaPreset { fn standard_base_prerelease_post_dev_schema(&self, with_context: bool) -> ZervSchema { ZervSchema::new_with_precedence( - schema_preset_components::standard_core(), - schema_preset_components::prerelease_post_dev_core(), - schema_preset_components::build_if_enabled(with_context), + standard_core(), + prerelease_post_dev_core(), + build_if_enabled(with_context), Default::default(), ) .unwrap() @@ -267,9 +207,9 @@ impl ZervSchemaPreset { fn calver_base_schema(&self, with_context: bool) -> ZervSchema { ZervSchema::new_with_precedence( - schema_preset_components::calver_core(), - schema_preset_components::epoch_extra_core(), - schema_preset_components::build_if_enabled(with_context), + calver_core(), + epoch_extra_core(), + build_if_enabled(with_context), Default::default(), ) .unwrap() @@ -277,9 +217,9 @@ impl ZervSchemaPreset { fn calver_base_prerelease_schema(&self, with_context: bool) -> ZervSchema { ZervSchema::new_with_precedence( - schema_preset_components::calver_core(), - schema_preset_components::prerelease_core(), - schema_preset_components::build_if_enabled(with_context), + calver_core(), + prerelease_core(), + build_if_enabled(with_context), Default::default(), ) .unwrap() @@ -287,9 +227,9 @@ impl ZervSchemaPreset { fn calver_base_prerelease_post_schema(&self, with_context: bool) -> ZervSchema { ZervSchema::new_with_precedence( - schema_preset_components::calver_core(), - schema_preset_components::prerelease_post_core(), - schema_preset_components::build_if_enabled(with_context), + calver_core(), + prerelease_post_core(), + build_if_enabled(with_context), Default::default(), ) .unwrap() @@ -297,9 +237,9 @@ impl ZervSchemaPreset { fn calver_base_prerelease_post_dev_schema(&self, with_context: bool) -> ZervSchema { ZervSchema::new_with_precedence( - schema_preset_components::calver_core(), - schema_preset_components::prerelease_post_dev_core(), - schema_preset_components::build_if_enabled(with_context), + calver_core(), + prerelease_post_dev_core(), + build_if_enabled(with_context), Default::default(), ) .unwrap() @@ -307,9 +247,7 @@ impl ZervSchemaPreset { fn with_build_context(&self, schema: ZervSchema) -> ZervSchema { let mut result = schema; - result - .set_build(schema_preset_components::build_context()) - .unwrap(); + result.set_build(build_context()).unwrap(); result } @@ -328,59 +266,39 @@ impl FromStr for ZervSchemaPreset { fn from_str(s: &str) -> Result { match s { // Standard Schema Family - self::schema_preset_names::STANDARD => Ok(ZervSchemaPreset::Standard), - self::schema_preset_names::STANDARD_NO_CONTEXT => { - Ok(ZervSchemaPreset::StandardNoContext) - } - self::schema_preset_names::STANDARD_BASE => Ok(ZervSchemaPreset::StandardBase), - self::schema_preset_names::STANDARD_BASE_PRERELEASE => { - Ok(ZervSchemaPreset::StandardBasePrerelease) - } - self::schema_preset_names::STANDARD_BASE_PRERELEASE_POST => { - Ok(ZervSchemaPreset::StandardBasePrereleasePost) - } - self::schema_preset_names::STANDARD_BASE_PRERELEASE_POST_DEV => { + STANDARD => Ok(ZervSchemaPreset::Standard), + STANDARD_NO_CONTEXT => Ok(ZervSchemaPreset::StandardNoContext), + STANDARD_BASE => Ok(ZervSchemaPreset::StandardBase), + STANDARD_BASE_PRERELEASE => Ok(ZervSchemaPreset::StandardBasePrerelease), + STANDARD_BASE_PRERELEASE_POST => Ok(ZervSchemaPreset::StandardBasePrereleasePost), + STANDARD_BASE_PRERELEASE_POST_DEV => { Ok(ZervSchemaPreset::StandardBasePrereleasePostDev) } - self::schema_preset_names::STANDARD_BASE_CONTEXT => { - Ok(ZervSchemaPreset::StandardBaseContext) - } - self::schema_preset_names::STANDARD_BASE_PRERELEASE_CONTEXT => { - Ok(ZervSchemaPreset::StandardBasePrereleaseContext) - } - self::schema_preset_names::STANDARD_BASE_PRERELEASE_POST_CONTEXT => { + STANDARD_BASE_CONTEXT => Ok(ZervSchemaPreset::StandardBaseContext), + STANDARD_BASE_PRERELEASE_CONTEXT => Ok(ZervSchemaPreset::StandardBasePrereleaseContext), + STANDARD_BASE_PRERELEASE_POST_CONTEXT => { Ok(ZervSchemaPreset::StandardBasePrereleasePostContext) } - self::schema_preset_names::STANDARD_BASE_PRERELEASE_POST_DEV_CONTEXT => { + STANDARD_BASE_PRERELEASE_POST_DEV_CONTEXT => { Ok(ZervSchemaPreset::StandardBasePrereleasePostDevContext) } - self::schema_preset_names::STANDARD_CONTEXT => Ok(ZervSchemaPreset::StandardContext), - - self::schema_preset_names::CALVER => Ok(ZervSchemaPreset::Calver), - self::schema_preset_names::CALVER_NO_CONTEXT => Ok(ZervSchemaPreset::CalverNoContext), - self::schema_preset_names::CALVER_BASE => Ok(ZervSchemaPreset::CalverBase), - self::schema_preset_names::CALVER_BASE_PRERELEASE => { - Ok(ZervSchemaPreset::CalverBasePrerelease) - } - self::schema_preset_names::CALVER_BASE_PRERELEASE_POST => { - Ok(ZervSchemaPreset::CalverBasePrereleasePost) - } - self::schema_preset_names::CALVER_BASE_PRERELEASE_POST_DEV => { - Ok(ZervSchemaPreset::CalverBasePrereleasePostDev) - } - self::schema_preset_names::CALVER_BASE_CONTEXT => { - Ok(ZervSchemaPreset::CalverBaseContext) - } - self::schema_preset_names::CALVER_BASE_PRERELEASE_CONTEXT => { - Ok(ZervSchemaPreset::CalverBasePrereleaseContext) - } - self::schema_preset_names::CALVER_BASE_PRERELEASE_POST_CONTEXT => { + STANDARD_CONTEXT => Ok(ZervSchemaPreset::StandardContext), + + CALVER => Ok(ZervSchemaPreset::Calver), + CALVER_NO_CONTEXT => Ok(ZervSchemaPreset::CalverNoContext), + CALVER_BASE => Ok(ZervSchemaPreset::CalverBase), + CALVER_BASE_PRERELEASE => Ok(ZervSchemaPreset::CalverBasePrerelease), + CALVER_BASE_PRERELEASE_POST => Ok(ZervSchemaPreset::CalverBasePrereleasePost), + CALVER_BASE_PRERELEASE_POST_DEV => Ok(ZervSchemaPreset::CalverBasePrereleasePostDev), + CALVER_BASE_CONTEXT => Ok(ZervSchemaPreset::CalverBaseContext), + CALVER_BASE_PRERELEASE_CONTEXT => Ok(ZervSchemaPreset::CalverBasePrereleaseContext), + CALVER_BASE_PRERELEASE_POST_CONTEXT => { Ok(ZervSchemaPreset::CalverBasePrereleasePostContext) } - self::schema_preset_names::CALVER_BASE_PRERELEASE_POST_DEV_CONTEXT => { + CALVER_BASE_PRERELEASE_POST_DEV_CONTEXT => { Ok(ZervSchemaPreset::CalverBasePrereleasePostDevContext) } - self::schema_preset_names::CALVER_CONTEXT => Ok(ZervSchemaPreset::CalverContext), + CALVER_CONTEXT => Ok(ZervSchemaPreset::CalverContext), _ => Err(ZervError::UnknownSchema(s.to_string())), } @@ -389,7 +307,6 @@ impl FromStr for ZervSchemaPreset { #[cfg(test)] mod tests { - use super::schema_preset_names::*; use super::*; use crate::version::zerv::ZervVars; From b435c7d7e29984efb930439cb5ac09c4d84beab6 Mon Sep 17 00:00:00 2001 From: Wisaroot Lertthaweedech Date: Sat, 8 Nov 2025 09:15:11 +0700 Subject: [PATCH 02/52] test: imporove test_flow_pipeline_with_fixture --- src/cli/flow/pipeline.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/cli/flow/pipeline.rs b/src/cli/flow/pipeline.rs index ed515f3a..5771f133 100644 --- a/src/cli/flow/pipeline.rs +++ b/src/cli/flow/pipeline.rs @@ -128,11 +128,10 @@ mod tests { test_flow_pipeline_with_fixture(&fixture_path, "1.0.0", "1.0.0"); - // Test template creation (rendering test disabled for now) - let _feature_1_hash: Template = - Template::new("{{ hash_int(value='feature-1', length=5) }}".to_string()); - let rendered_feature_1_hash = _feature_1_hash.render_unwrap(None); - test_info!("{}", rendered_feature_1_hash); + let branch_feature_1_hash = + Template::::new("{{ hash_int(value='feature-1', length=5) }}".to_string()) + .render_unwrap(None); + assert_eq!(branch_feature_1_hash, "42954"); fixture .make_dirty() @@ -140,8 +139,12 @@ mod tests { test_flow_pipeline_with_fixture( &fixture_path, - "1.0.0-alpha.42954.post.0.dev.{timestamp:now}+feature.1.0.{hex:7}", - "1.0.0a42954.post0.dev{timestamp:now}+feature.1.0.{hex:7}", + &format!( + "1.0.0-alpha.{branch_feature_1_hash}.post.0.dev.{{timestamp:now}}+feature.1.0.{{hex:7}}" + ), + &format!( + "1.0.0a{branch_feature_1_hash}.post0.dev{{timestamp:now}}+feature.1.0.{{hex:7}}" + ), ); } } From a940b70a436ccfd36f1a5e5c5e46aefce3d89941 Mon Sep 17 00:00:00 2001 From: Wisaroot Lertthaweedech Date: Sat, 8 Nov 2025 14:43:41 +0700 Subject: [PATCH 03/52] feat: implement schema arg for zerv flow --- .../plan/33-zerv-flow-cli-command-design.md | 132 ++++-- .../39-implement-zerv-flow-schema-system.md | 389 ++++++++++++++++++ src/cli/flow/args/main.rs | 373 ++++++----------- src/cli/flow/pipeline.rs | 7 +- 4 files changed, 613 insertions(+), 288 deletions(-) create mode 100644 .claude/plan/39-implement-zerv-flow-schema-system.md diff --git a/.claude/plan/33-zerv-flow-cli-command-design.md b/.claude/plan/33-zerv-flow-cli-command-design.md index d6b85d84..4696301a 100644 --- a/.claude/plan/33-zerv-flow-cli-command-design.md +++ b/.claude/plan/33-zerv-flow-cli-command-design.md @@ -39,17 +39,62 @@ zerv flow [OPTIONS] --bumped-branch Override branch name for pre-release resolution (same as zerv version) --bumped-branch-hash-length Branch hash length for pre-release numbers [default: 5] [range: 4..16] --post-mode Post calculation mode [default: tag] [possible values: tag, commit] - --build-context Include build context (+branch.commit) in output [default: true] - --no-build-context Exclude build context from output - --dev-ts Include dev timestamp for dirty working directory [default: auto-detect] - --no-dev-ts Exclude dev timestamp from output - --with-pre-release Include pre-release/post-release but no build context - --base-only Base version only (major.minor.patch) + --schema Schema variant for output components [default: standard] [possible values: standard, standard-no-context, standard-context, standard-base, standard-base-prerelease, standard-base-prerelease-post, standard-base-prerelease-post-dev] -v, --verbose Show verbose output including version resolution details -h, --help Print help -V, --version Print version ``` +### Schema System + +**zerv flow uses the flexible schema system from zerv version but restricted to standard schema family only.** + +#### Available Standard Schema Variants + +- **`standard`** (default) - Smart context: includes context only for dirty/distance states, excludes for clean tagged +- **`standard-no-context`** - Never includes build context (branch.commit info) +- **`standard-context`** - Always includes build context +- **`standard-base`** - Base version only (e.g., `1.2.3`) +- **`standard-base-prerelease`** - Base + prerelease (e.g., `1.2.3-alpha.1`) +- **`standard-base-prerelease-post`** - Base + prerelease + post (e.g., `1.2.3-alpha.1.post.2`) +- **`standard-base-prerelease-post-dev`** - Base + prerelease + post + dev (e.g., `1.2.3-alpha.1.post.2.dev.123`) + +#### Schema Behavior Examples + +**Smart Context (`standard` - default):** + +- Clean tagged commit: `1.0.1-rc.1.post.1` +- Dirty working directory: `1.0.1-rc.1.post.1.dev.1729924622+feature.auth.1.a1b2c3d` +- Distance from tag: `1.0.1-rc.1.post.2+feature.auth.2.c2d3e4f` + +**No Context (`standard-no-context`):** + +- Any state: `1.0.1-rc.1.post.1` (never includes +branch.commit) + +**Always Context (`standard-context`):** + +- Any state: `1.0.1-rc.1.post.1+feature.auth.1.a1b2c3d` (always includes context) + +**Base Components:** + +- `standard-base`: `1.2.3` +- `standard-base-prerelease`: `1.2.3-alpha.1` +- `standard-base-prerelease-post`: `1.2.3-alpha.1.post.2` +- `standard-base-prerelease-post-dev`: `1.2.3-alpha.1.post.2.dev.123` + +#### Schema Validation + +**Only standard schema family supported in zerv flow:** + +- ✅ **Valid**: `standard`, `standard-no-context`, `standard-context`, `standard-base`, `standard-base-prerelease`, `standard-base-prerelease-post`, `standard-base-prerelease-post-dev` +- ❌ **Invalid**: Any `calver*` schema variants will produce error +- ❌ **Invalid**: Any deprecated tier-based schemas will produce error + +**Error handling:** + +- Non-standard schemas will result in: `Error: zerv flow only supports standard schema variants, got: 'calver'` +- Invalid schema names will result in: `Error: Unknown schema variant: 'invalid-schema'` + ## Pre-release Resolution Logic ### Default Behavior (no flags) @@ -162,17 +207,21 @@ zerv flow --branch-rules ### Manual Override -**Mutually exclusive with `--pre-release-from-branch`:** +**Schema can be combined with manual pre-release overrides:** ```bash -# Force specific pre-release type and number -zerv flow --pre-release-label beta --pre-release-num 1 +# Force specific pre-release type and number with context +zerv flow --pre-release-label beta --pre-release-num 1 --schema standard-context + +# Force rc for release-like branches, no context +zerv flow --pre-release-label rc --pre-release-num 2 --schema standard-base-prerelease-post -# Force rc for release-like branches -zerv flow --pre-release-label rc --pre-release-num 2 +# Force alpha for feature branches with full context +zerv flow --pre-release-label alpha --schema standard-base-prerelease-post-dev-context -# Force alpha for feature branches (uses hash by default) -zerv flow --pre-release-label alpha +# Manual overrides with different schema levels +zerv flow --pre-release-label beta --schema standard-base-prerelease +zerv flow --pre-release-label rc --schema standard-base ``` ### Branch Override @@ -180,25 +229,32 @@ zerv flow --pre-release-label alpha **Test different branch scenarios without switching branches:** ```bash -zerv flow --bumped-branch develop --pre-release-from-branch -zerv flow --bumped-branch release/1 --pre-release-from-branch +# Test develop branch with different schemas +zerv flow --bumped-branch develop --schema standard +zerv flow --bumped-branch develop --schema standard-no-context + +# Test release branch with specific schema +zerv flow --bumped-branch release/1 --schema standard-base-prerelease-post-context + +# Test feature branch scenarios +zerv flow --bumped-branch feature/auth --schema standard-base-prerelease-post-dev ``` ## Output Modes -### Full Output (default) +### Full Output (default - `standard` schema) ``` 1.0.1-alpha.12345.post.2.dev.1729924622+feature.auth.2.a1b2c3d ``` -### Pre-release Output (`--with-pre-release`) +### Pre-release Output (`--schema standard-base-prerelease-post`) ``` 1.0.1-alpha.12345.post.2 ``` -### Base-Only Output (`--base-only`) +### Base-Only Output (`--schema standard-base`) ``` 1.0.1 @@ -235,36 +291,42 @@ zerv flow --bumped-branch release/1 --pre-release-from-branch ### Basic Usage ```bash -# Generate flow version with automatic pre-release +# Generate flow version with smart context (default schema) zerv flow -# Enable branch pattern detection (GitFlow) -zerv flow --pre-release-from-branch - # Force specific pre-release type zerv flow --pre-release-label beta # Include pre-release/post-release but no build context -zerv flow --with-pre-release +zerv flow --schema standard-base-prerelease-post # Base version only -zerv flow --base-only +zerv flow --schema standard-base + +# Never include build context +zerv flow --schema standard-no-context + +# Always include build context +zerv flow --schema standard-context ``` ### Advanced Usage ```bash -# Complete control over pre-release -zerv flow --bumped-branch release/1 --pre-release-from-branch +# Complete control over pre-release with schema +zerv flow --bumped-branch release/1 --schema standard-base-prerelease-post-context -# Custom template output -zerv flow --output-template "v{{version}}-{{pre_release}}" +# Custom template output with specific schema +zerv flow --schema standard-base --output-template "v{{version}}-{{pre_release}}" # Different repository directory -zerv flow --directory ../other-repo +zerv flow --directory ../other-repo --schema standard # Verbose output -zerv flow --verbose +zerv flow --verbose --schema standard-base-prerelease-post-dev + +# Error case - this will fail with calver schema +zerv flow --schema calver # Error: zerv flow only supports standard schema variants ``` ## Future Configuration @@ -291,11 +353,11 @@ zerv flow --config .zerv.ron ## Key Design Principles -1. **Mirror zerv version**: Same output/input options structure -2. **Intelligent defaults**: Smart branch-based pre-release detection -3. **Flexible overrides**: Manual control when needed -4. **Honest versioning**: Never hides Git state, always accurate -5. **Clean alternatives**: `--with-pre-release` and `--base-only` for simplified output +1. **Mirror zerv version**: Same output/input options structure with shared schema system +2. **Intelligent defaults**: Smart branch-based pre-release detection with smart context schema +3. **Flexible overrides**: Manual control when needed, including schema selection +4. **Honest versioning**: Never hides Git state, always accurate (unless explicitly requested via schema) +5. **Schema-based flexibility**: Single `--schema` argument replaces multiple context/control flags --- diff --git a/.claude/plan/39-implement-zerv-flow-schema-system.md b/.claude/plan/39-implement-zerv-flow-schema-system.md new file mode 100644 index 00000000..f1584022 --- /dev/null +++ b/.claude/plan/39-implement-zerv-flow-schema-system.md @@ -0,0 +1,389 @@ +# Implement Zerv Flow Schema System + +**Status**: Planned +**Priority**: High +**Context**: Refactor zerv flow CLI arguments to use flexible schema system, consolidating multiple context/control flags into a single `--schema` argument that leverages the existing schema system from zerv version. + +## Current State Analysis + +### Existing Flow Arguments (src/cli/flow/args/main.rs) + +```rust +// Currently implemented context flags to be replaced +--dev-ts / --no-dev-ts // Controls dev timestamp inclusion ✅ IMPLEMENTED + +// Context flags from design doc that were never implemented +--build-context / --no-build-context // Controls build context inclusion ❌ NOT IMPLEMENTED +--with-pre-release // Include prerelease/post only ❌ NOT IMPLEMENTED +--base-only // Base version only ❌ NOT IMPLEMENTED + +// Context flags to be replaced (that are actually implemented) +--no-pre-release // Disable pre-release entirely ✅ IMPLEMENTED + +// Existing arguments to keep +--pre-release-label