Skip to content

Semver

semver

Semantic versioning — parse commits and compute next version.

VersionBump dataclass

Result of a semver computation.

Attributes:

Name Type Description
current str

Current tag (e.g. "v0.7.0").

next str

Next tag (e.g. "v0.8.0").

bump str

Bump type ("major", "minor", or "patch").

commits list[str]

One-line commit summaries since last tag.

breaking bool

Whether a breaking change was detected.

Source code in packages/axm-git/src/axm_git/core/semver.py
@dataclass(frozen=True)
class VersionBump:
    """Result of a semver computation.

    Attributes:
        current: Current tag (e.g. ``"v0.7.0"``).
        next: Next tag (e.g. ``"v0.8.0"``).
        bump: Bump type (``"major"``, ``"minor"``, or ``"patch"``).
        commits: One-line commit summaries since last tag.
        breaking: Whether a breaking change was detected.
    """

    current: str
    next: str
    bump: str
    commits: list[str]
    breaking: bool

compute_bump(commits, current_tag)

Compute the next semver version from commit messages.

Rules (pre-1.0, i.e. major == 0): - feat!: or BREAKING CHANGE:minor bump - feat:minor bump - everything else → patch bump

Rules (post-1.0): - feat!: or BREAKING CHANGE:major bump - feat:minor bump - everything else → patch bump

Parameters:

Name Type Description Default
commits list[str]

One-line commit messages (e.g. from git log --oneline).

required
current_tag str

Current version tag (e.g. "v0.7.0").

required

Returns:

Type Description
VersionBump

VersionBump with computed next version.

Source code in packages/axm-git/src/axm_git/core/semver.py
def compute_bump(commits: list[str], current_tag: str) -> VersionBump:
    """Compute the next semver version from commit messages.

    Rules (pre-1.0, i.e. major == 0):
        - ``feat!:`` or ``BREAKING CHANGE:`` → **minor** bump
        - ``feat:`` → **minor** bump
        - everything else → **patch** bump

    Rules (post-1.0):
        - ``feat!:`` or ``BREAKING CHANGE:`` → **major** bump
        - ``feat:`` → **minor** bump
        - everything else → **patch** bump

    Args:
        commits: One-line commit messages (e.g. from ``git log --oneline``).
        current_tag: Current version tag (e.g. ``"v0.7.0"``).

    Returns:
        VersionBump with computed next version.
    """
    logger.info("Computing version bump from %s", current_tag)
    major, minor, patch = parse_tag(current_tag)
    has_breaking, has_feat = _classify_commits(commits)
    bump, next_version = _next_version(
        major, minor, patch, has_breaking=has_breaking, has_feat=has_feat
    )

    return VersionBump(
        current=current_tag,
        next=next_version,
        bump=bump,
        commits=commits,
        breaking=has_breaking,
    )

parse_tag(tag)

Parse a semver tag string into (major, minor, patch).

Parameters:

Name Type Description Default
tag str

Version string, with or without v prefix.

required

Returns:

Type Description
tuple[int, int, int]

Tuple of (major, minor, patch).

Raises:

Type Description
ValueError

If the tag doesn't match semver format.

Source code in packages/axm-git/src/axm_git/core/semver.py
def parse_tag(tag: str) -> tuple[int, int, int]:
    """Parse a semver tag string into ``(major, minor, patch)``.

    Args:
        tag: Version string, with or without ``v`` prefix.

    Returns:
        Tuple of (major, minor, patch).

    Raises:
        ValueError: If the tag doesn't match semver format.
    """
    m = _TAG_RE.match(tag)
    if not m:
        msg = f"Invalid semver tag: {tag!r}"
        raise ValueError(msg)
    return int(m.group(1)), int(m.group(2)), int(m.group(3))