semver

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 4, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package semver wraps github.com/Masterminds/semver/v3 with the bump-level abstraction monorel uses everywhere it touches versions.

Version strings always carry the leading "v" required by Go module tags (e.g. "v1.6.2", "v1.0.0-rc.3"). Functions that produce versions emit the "v" form; functions that accept versions require it. Inputs without a leading "v" are rejected as invalid; this matches what `git tag --list` returns and what `go get` accepts, and catches caller bugs at the boundary instead of letting them propagate.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrInvalidVersion = errors.New("invalid semver version")

ErrInvalidVersion is returned when a version string does not parse as a Go module version (must start with "v" and follow SemVer 2.0).

Functions

func Apply

func Apply(current string, level BumpLevel) (string, error)

Apply bumps current by level. current must be a valid Go module version ("vX.Y.Z" or "vX.Y.Z-pre"). For pre-release inputs (e.g. "v1.0.0-rc.3"), Apply strips the pre-release suffix first and bumps from the canonical version: this matches the changesets convention where exiting pre-release mode yields a clean stable bump from the last stable version, not the last rc.

Returns ErrInvalidVersion if current is not parseable.

Example

ExampleApply demonstrates the basic version-bump operation: take a current version string (with the leading "v") and a bump level, return the next version (also with the "v"). Inputs without the "v" are rejected — Go module tags always carry it.

package main

import (
	"fmt"

	"monorel.disaresta.com/semver"
)

func main() {
	for _, level := range []semver.BumpLevel{semver.Patch, semver.Minor, semver.Major} {
		next, _ := semver.Apply("v1.6.2", level)
		fmt.Printf("%s + %s = %s\n", "v1.6.2", level, next)
	}
}
Output:
v1.6.2 + patch = v1.6.3
v1.6.2 + minor = v1.7.0
v1.6.2 + major = v2.0.0

func ApplyPrerelease

func ApplyPrerelease(base, channel string, counter int) (string, error)

ApplyPrerelease appends a pre-release suffix to base, with the given channel and counter. Yields e.g. "v1.0.0-rc.3" from base "v1.0.0", channel "rc", counter 3.

channel must be a non-empty identifier matching SemVer 2.0's pre-release rules (alphanumerics + hyphens). counter must be >= 0.

func Compare

func Compare(a, b string) (int, error)

Compare returns -1 if a < b, 0 if a == b, +1 if a > b. Pre-releases sort before their canonical version (v1.0.0-rc.1 < v1.0.0).

Returns a non-nil error if either input fails to parse as a valid version. Callers that want to silently skip unparseable values should IsValid-guard the inputs first; the previous "return 0 on parse failure" silently-equal behavior was a footgun that hid bad inputs from a caller computing a max.

func InitialFromBump

func InitialFromBump(level BumpLevel) (string, error)

InitialFromBump returns the version a never-released package gets on its first release with the given bump level. Major maps to v1.0.0 (the natural "first stable release" version), minor maps to v0.1.0, patch to v0.0.1.

Returns an error if level is None or unrecognized.

Example

ExampleInitialFromBump shows the rule for a never-released package's first release: major→1.0.0, minor→0.1.0, patch→0.0.1. The leading "v" is included.

package main

import (
	"fmt"

	"monorel.disaresta.com/semver"
)

func main() {
	for _, level := range []semver.BumpLevel{semver.Patch, semver.Minor, semver.Major} {
		v, _ := semver.InitialFromBump(level)
		fmt.Printf("%s → %s\n", level, v)
	}
}
Output:
patch → v0.0.1
minor → v0.1.0
major → v1.0.0

func IsPrerelease

func IsPrerelease(v string) bool

IsPrerelease reports whether v carries a pre-release suffix ("v1.0.0-rc.1" -> true, "v1.0.0" -> false).

func IsValid

func IsValid(v string) bool

IsValid reports whether v parses as a Go module semver version (leading "v", SemVer 2.0).

Types

type BumpLevel

type BumpLevel int

BumpLevel encodes the kind of version bump a changeset requests.

The zero value is None — useful when accumulating "max bump across changesets affecting this package" because absence is the natural identity. Higher values dominate lower ones in Max.

const (
	// None means no bump (no changesets affect this package).
	None BumpLevel = iota
	// Patch is for backwards-compatible bug fixes.
	Patch
	// Minor is for backwards-compatible feature additions.
	Minor
	// Major is for breaking changes.
	Major
)

func Max

func Max(a, b BumpLevel) BumpLevel

Max returns the higher of two bump levels. Used to combine multiple changesets affecting the same package: the strongest bump wins.

Example

ExampleMax shows how monorel collapses multiple changesets that name the same package into a single bump: take the maximum bump level across all of them.

package main

import (
	"fmt"

	"monorel.disaresta.com/semver"
)

func main() {
	bumps := []semver.BumpLevel{semver.Patch, semver.Minor, semver.Patch}
	winner := semver.None
	for _, b := range bumps {
		winner = semver.Max(winner, b)
	}
	fmt.Println("winning bump:", winner)
}
Output:
winning bump: minor

func ParseBumpLevel

func ParseBumpLevel(s string) (BumpLevel, error)

ParseBumpLevel converts a changeset-frontmatter string to a BumpLevel. Accepts "major"/"minor"/"patch" case-insensitively. "none" is rejected: a changeset that says "none" for a package shouldn't list that package at all.

func (BumpLevel) String

func (b BumpLevel) String() string

String returns the lowercase canonical name ("none", "patch", "minor", "major"). Matches the form used in changeset frontmatter.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL