gotagger

package module
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2023 License: Apache-2.0 Imports: 14 Imported by: 0

README

gotagger

Table of Contents

Overview

gotagger is a library and CLI for tagging releases in git repositories as part of a CI process.

gotagger looks through the git history of the current commit for the latest semantic version. This becomes the "base" version. Then gotagger examines all of the commit messages between the current commit and the latest tag, to determine if the most significant change was a feature, bug fix, or breaking change per the Conventional Commits format. gotagger then increments the base version accordingly and print the new version.

If the current commit type is release and the -release flag or GOTAGGER_RELEASE environment variable is set, then gotagger will tag the current commit with the new version. If there are no commits explicitly marked as a feature or a bug fix, then the patch version is incremented.

Installation

You can install gotagger by downloading a pre-built binary for your OS and architecture from our releases page.

Alternatively, you can install gotagger directly with go get. If you go this route, we recommend that you create a "fake" module, so you can ensure you build a supported release:

mkdir tmp
cd tmp
go mod init fake
go get github.com/sassoftware/gotagger

Getting started

Running

Run gotagger inside of a git repository to see what the current version is.

git clone https://github.com/sassoftware/gotagger.git
cd gotagger
make build
build/$(go env GOOS)/gotagger
v0.4.0

Note: The version reported may be different, depending on what unreleased changes exist.

To tag a release, make any changes needed to prepare your project for releasing (ie. update the change log, merge any feature branches). Then create a "release" commit and run gotagger again:

VERSION="$(gotagger)"
git commit -m "release: $VERSION"
gotagger -release

You can now perform any release builds, push the tag to your central git repository, or any other post-release tasks.

gotagger can also push any tags it creates, by using the -push flag.

gotagger -release -push
Configuration

Projects using gotagger can control some behaviors via a config file: gotagger.json. Check out the gotagger.json in this project to see an example configuration.

If a gotagger.json file exists in the working directory, Gotagger will use it. If no configuration is provided, Gotagger defaults to the current functionality, which is equivalent to what is defined in gotagger.json.

If you want to place your config file in a non-standard location, then you must use the -config flag to tell gotagger where it is:

gotagger -config path/to/gotagger.json
Default Increment

The defaultIncrement option controls how gotagger increments the version for commit types that are not listed in incrementMappings. Allowed values are "minor", "patch", and "none".

Increment Dirty Worktree

The incrementDirtyWorktree option controls how gotagger increments the version when there are no new commits, but the worktree is dirty. Allowed values are "minor", "patch", and "none".

Exclude Modules

The excludeModules option controls which modules gotagger will attempt to version.

Ignore Modules

The ignoreModules option toggles gotagger support for go modules. If you are using gotagger to version a project written in another language, then set this to "true":

{
  "ignoreModules": true
}
Increment Mappings

The incrementMappings option controls which part of the semantic version gotagger increments for a given commit type. This option contains a mapping of commit type to semver increment For example, if your project uses "f" for commits that implement features, and "b" for commits that fix bugs:

{
  "incrementMappings": {
    "f": "minor",
    "b": "patch"
  },
}
Pre-Release Incrementing

The incrementPreReleaseMinor option controls how gotagger increments pre-release versions for breaking changes. Normally, a breaking change will increment the MAJOR version. However, for pre-release versions, those with a MAJOR version of "0", some projects may want to increment the MINOR version instead. This is done by setting incrementPreReleaseMinor to "true".

Version Prefix

The versionPrefix option controls how gotagger prefixes the version it calculates. The default prefix is "v", as in "v2.3.4". Some projects may wish to have no prefix, which can be done by setting versionPrefix to the empty string:

{
  "versionPrefix": ""
}

Note: go has very particular requirements about how tags are named, so avoid changing the version prefix if you are versioning a go module.

Go Module Support

By default gotagger will enforce semantic import versioning on any project that has one or more go.mod files. This means gotagger will ignore tags whose major version does not match the major version of the module, as well as tags whose prefix does not match the path to the module's go.mod file.

For projects that are not written in go but do have a go.mod for build tooling, the -modules flag and GOTAGGER_MODULES environment variable can be used to disable this behavior.

gotagger can also tag go multi-module repositories. To tag one ore more modules, include a Modules footer in your commit message containing a comma-separated list of modules to tag:

release: the bar and baz modules

Modules: foo/bar, foo/baz

You can also use multiple Modules footers if you prefer:

release: the bar and baz modules in separate footers

Modules: foo/bar
Modules: foo/baz

To release the "root" module explicitly list it in the Modules footer:

release: foo and bar

Modules: foo, foo/bar

# "Modules: foo/bar, foo" also works

gotagger will print out all of the versions it tagged in the order they are specified in the Modules footer.

Path Filtering

gotagger supports versioning individual paths within a git repository using a path filter. Currently, only a single path filter is supported, and gotagger will return an error if a path filter is used in a repository that contains go modules without setting -modules=false.

Using gotagger as a library

import github.com/sassoftware/gotagger

Create a Gotagger instance

g, err := gotagger.New("path/to/repo")
if err != nil {
    return err
}

// get the current version of a repository
version, err := g.Version()
if err != nil {
    return err
}
fmt.Println("version:", version)

// Uncomment this to ignore the module example.com/bar or any modules under some/path
// g.Config.ExcludeModules = []string{"example.com/bar", "some/path"}

// get the version of module foo
fooVersion, err := g.ModuleVersion("foo")
if err != nil {
    return err
}
fmt.Println("foo version:", fooVersion)

// Check what versions will be tagged.
// If HEAD is not a release commit,
// then only the the main module version is returned.
versions, err := g.TagRepo()
if err != nil {
    return err
}

for _, v := range versions {
    fmt.Println(v)
}

// Create the tags
g.Config.CreateTag = true

// uncomment to push tags as well
// g.Config.PushTag = true

_, err := g.TagRepo()
if err != nil {
    return err
}

Contributing

We welcome your contributions! Please read CONTRIBUTING.md for details on how to submit contributions to this project.

License

This project is licensed under the Apache 2.0 License.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNoSubmodule = errors.New("no submodule found")
	ErrNotRelease  = errors.New("HEAD is not a release commit")
)

Functions

This section is empty.

Types

type Config

type Config struct {
	// CreateTag represents whether to create the tag.
	CreateTag bool

	// ExcludeModules is a list of module names or paths to exclude.
	ExcludeModules []string

	// IgnoreModules controls whether gotagger will ignore the existence of
	// go.mod files when determining how to version a project.
	IgnoreModules bool

	// RemoteName represents the name of the remote repository. Defaults to origin.
	RemoteName string

	// PreMajor controls whether gotagger will increase the major version from 0
	// to 1 for breaking changes.
	PreMajor bool

	// PushTag represents whether to push the tag to the remote git repository.
	PushTag bool

	// VersionPrefix is a string that will be added to the front of the version. Defaults to 'v'.
	VersionPrefix string

	// DirtyWorktreeIncrement is a string that sets how to increment the version
	// if there are no new commits, but the worktree is "dirty".
	DirtyWorktreeIncrement mapper.Increment

	// CommitTypeTable used for looking up version increments based on the commit type.
	CommitTypeTable mapper.Table

	// Force controls whether gotagger will create a tag even if HEAD is not a "release" commit.
	Force bool

	// Paths is a list of sub-paths within the repo to restrict the git
	// history used to calculate a version. The versions returned will be
	// prefixed with their path.
	Paths []string
}

Config represents how to tag a repo.

If no default is mentioned, the option defaults to go's zero-value.

func NewDefaultConfig

func NewDefaultConfig() Config

NewDefaultConfig returns a Config with default options set.

If an option is not mentioned, then the default is the zero-value for its type.

  • RemoteName origin
  • VersionPrefix v

func (*Config) ParseJSON added in v0.8.0

func (c *Config) ParseJSON(data []byte) error

ParseJSON unmarshals a byte slice containing mappings of commit type to semver increment. Mappings determine how much to increment the semver based on the commit type. The 'release' commit type has special meaning to gotagger and cannot be overridden in the config file. Unknown commit types will fall back to the config default. Invalid increments will throw an error. Duplicate type definitions will take the last entry.

type Gotagger

type Gotagger struct {
	Config Config
	// contains filtered or unexported fields
}

func New

func New(path string) (*Gotagger, error)

func (*Gotagger) ModuleVersions

func (g *Gotagger) ModuleVersions(names ...string) ([]string, error)

ModuleVersions returns the current version for all go modules in the repository in the order they were found by a depth-first, lexicographically sorted search.

For example, in a repository with a root go.mod and a submodule foo/bar, the slice returned would be: []string{"v0.1.0", "bar/v0.1.0"}

If module names are passed in, then only the versions for those modules are returned.

func (*Gotagger) SetLogger added in v0.9.0

func (g *Gotagger) SetLogger(l logr.Logger)

func (*Gotagger) TagRepo

func (g *Gotagger) TagRepo() ([]string, error)

TagRepo determines the current version of the repository by parsing the commit history since the previous release and returns that version. Depending on the CreateTag and PushTag configuration options tags may be created and pushed.

If the current commit contains one or more Modules footers, then tags are created for each module listed. In this case if the root module is not explicitly included in a Modules footer then it will not be included.

func (*Gotagger) Version

func (g *Gotagger) Version() (string, error)

Version returns the current version for the repository.

In a repository that contains multiple go modules, this returns the version of the first module found by a depth-first, lexicographically sorted search. Usually this is the root module, but possibly not if the repo is a monorepo with no root module.

Directories

Path Synopsis
cmd
internal
git
The git package contains functions for running git commands.
The git package contains functions for running git commands.

Jump to

Keyboard shortcuts

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