Skip to main content

Adding Version Strategies

Adding Version Strategies

Internal Extension

Extend tag generation while preserving explicit-tag priority, typed CLI choices, and workflow integration.

Commandapp/core/git_ops/tag_strategy/

Category

Developer Guide

Quick Command

strategy.get_next_tag() -> str

TagStrategyStrategyChoicesWorkflowEngine

Overview

Custy currently provides SemVer, PEP 440, Commitizen, date, and Git-count generation. Each strategy returns the next tag string, but active selection is implemented explicitly in WorkflowEngine.prepare_version_tag() rather than through a strategy factory.


Current Strategy Responsibilities

Properties

PropertyTypeDescriptionDefaultRequired
SemverStrategyGit-awareReads the latest tag and applies semantic bump, prerelease, and build metadata behavior.-No
PEP440StrategyGit-awareReads the latest tag and applies PEP 440 bump, pre, post, dev, local, and epoch behavior.-No
CommitizenStrategyExternal toolUses cz bump --dry-run to infer a bump and delegates final construction to SemverStrategy.-No
DateStrategyClock-basedReturns the current date in vYYYY.MM.DD form by default.-No
GitCountStrategyRepository countReturns v followed by the repository commit count.-No

Implement the Protocol

Strategy shape
python
from app.core.git_ops.tag_strategy.base import TagStrategy

class BuildNumberStrategy:
"""Generate a tag from a validated build number."""

  def __init__(self, build_number: int) -> None:
      """Store the positive build number used for generation."""
      if build_number < 1:
          raise ValueError("build_number must be positive")
      self.build_number = build_number

  def get_next_tag(self) -> str:
      """Return the next build-number tag."""
      return f"vbuild.{self.build_number}"

TagStrategy is a structural Protocol, so a concrete class does not need to inherit it explicitly. The class must still satisfy the documented get_next_tag() -> str behavior and report invalid inputs or unavailable dependencies clearly.


Integration Checklist

Before You Begin

  • Add the strategy moduleRequired

    Create a documented class under app/core/git_ops/tag_strategy and export it when package-level imports require that.

  • Extend StrategyChoicesRequired

    Add the public string value in app/cli/constants/enums.py so Typer can validate version and Run inputs.

  • Update CLI helpRequired

    Describe the value and its required companion options in both version and Run option declarations where supported.

  • Carry required inputsRequired

    Extend option declarations, argument models, configuration resolution, WorkflowConfig, and WorkflowEngineBuilder only for data the strategy truly needs.

  • Add workflow dispatchRequired

    Instantiate the strategy from prepare_version_tag() after explicit-tag handling and before the invalid-configuration branch.

  • Update detection if applicableRequired

    Change project auto-detection only when there is a reliable, tested signal for selecting the strategy.

  • Document configurationRequired

    Update allowed values, requirements, examples, generated configuration comments, and public strategy guidance.


Testing Checklist

  • Construct the strategy with default and explicit supported values.
  • Verify the exact returned tag format at important boundaries.
  • Mock the clock, Git service, environment, or subprocess dependency rather than relying on a contributor machine.
  • Verify malformed prior tags, invalid input, missing tools, and command failures produce intentional exceptions.
  • Verify WorkflowEngine.prepare_version_tag() selects the new strategy and still gives an explicit tag higher priority.
  • Verify Typer accepts the new StrategyChoices value in every supported command path.
  • Add integration coverage when the generated tag affects file updates, changelog content, commit messages, or tag creation.


Continue