Use git tags to add (GoReleaser-compatible) semver to your go package.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
AJ ONeal 1638772379
docs: fix typo
il y a 1 an
examples update examples il y a 4 ans
gitver v2.0.0-pre1: make compatible with GoReleaser il y a 4 ans
.gitignore complete transition to v2 il y a 4 ans
.prettierrc v2.0.0-pre1: make compatible with GoReleaser il y a 4 ans
LICENSE Initial commit il y a 5 ans
README.md docs: fix typo il y a 1 an
gitver.go complete transition to v2 il y a 4 ans
go.mod add v2 to go.mod il y a 4 ans
go.sum update examples il y a 4 ans
version.go v2.0.0-pre1: make compatible with GoReleaser il y a 4 ans

README.md

Go GitVer

Use git tags to add (GoReleaser-compatible) semver to your go package in under 150 lines of code.

Goals:

      1. Use an exact `git tag` version, like v1.0.0, when clean
      2. Translate the `git describe` version  (v1.0.0-4-g0000000)
	     to semver (1.0.1-pre4+g0000000) in between releases
      3. Note when `dirty` (and have build timestamp)

      Fail gracefully when git repo isn't available.

GoDoc

See https://pkg.go.dev/git.rootprojects.org/root/go-gitver/v2.

How it works

  1. You define the fallback version and version printing in main.go:
//go:generate go run git.rootprojects.org/root/go-gitver/v2

package main

import (
	"fmt"
	"strings"
)

var (
	commit  = "0000000"
	version = "0.0.0-pre0+0000000"
	date    = "0000-00-00T00:00:00+0000"
)

func main() {
	if (len(os.Args) > 1 && "version" == strings.TrimLeft(os.Args[1], "-")) {
		fmt.Printf("Foobar v%s (%s) %s\n", version, commit[:7], date)
	}
	// ...
}
  1. You go generate or go run git.rootprojects.org/root/go-gitver/v2 to generate xversion.go:
package main

func init() {
    commit  = "0921ed1e"
    version = "1.1.2"
    date    = "2019-07-01T02:32:58-06:00"
}

Demo

Generate an xversion.go file:

go run git.rootprojects.org/root/go-gitver/v2
cat xversion.go
// Code generated by go generate; DO NOT EDIT.
package main

func init() {
	commit  = "6dace8255b52e123297a44629bc32c015add310a"
	version = "1.1.4-pre2+g6dace82"
	date    = "2020-07-16T20:48:15-06:00"
}

Note: The file is named xversion.go by default so that the generated file's init() will come later, and thus take priority, over most other files.

See go-gitvers self-generated version:

go run git.rootprojects.org/root/go-gitver/v2 version
6dace8255b52e123297a44629bc32c015add310a
v1.1.4-pre2+g6dace82
2020-07-16T20:48:15-06:00

QuickStart

Add this to the top of your main file, so that it runs with go generate:

//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2

Add a file that imports go-gitver (for versioning)

// +build tools

package example

import _ "git.rootprojects.org/root/go-gitver/v2"

Change you build instructions to be something like this:

go mod vendor
go generate -mod=vendor ./...
go build -mod=vendor -o example cmd/example/*.go

You don't have to use -mod=vendor, but I highly recommend it (just go mod tidy; go mod vendor to start).

Options

version           print version and exit
--fail            exit with non-zero status code on failure
--package <name>  will set the package name
--outfile <name>  will replace `xversion.go` with the given file path

ENVs

# Alias for --fail
GITVER_FAIL=true

For example:

//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --fail

go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 version

Usage

See examples/basic

  1. Create a tools package in your project
  2. Guard it against regular builds with // +build tools
  3. Include _ "git.rootprojects.org/root/go-gitver/v2" in the imports
  4. Declare var commit, version, date string in your package main
  5. Include //go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 as well

tools/tools.go:

// +build tools

// This is a dummy package for build tooling
package tools

import (
	_ "git.rootprojects.org/root/go-gitver/v2"
)

main.go:

//go:generate go run git.rootprojects.org/root/go-gitver/v2 --fail

package main

import "fmt"

var (
	commit  = "0000000"
	version = "0.0.0-pre0+0000000"
	date    = "0000-00-00T00:00:00+0000"
)

func main() {
  fmt.Println(commit)
  fmt.Println(version)
  fmt.Println(date)
}

If you're using go mod vendor (which I highly recommend that you do), you'd modify the go:generate ever so slightly:

//go:generate go run -mod=vendor git.rootprojects.org/root/go-gitver/v2 --fail

The only reason I didn't do that in the example is that I'd be included the repository in itself and that would be... weird.

Why a tools package?

import "git.rootprojects.org/root/go-gitver/v2" is a program, not an importable package

Having a tools package with a build tag that you don't use is a nice way to add exact versions of a command package used for tooling to your go.mod with go mod tidy, without getting the error above.

git: behind the curtain

These are the commands that are used under the hood to produce the versions.

Shows the git tag + description. Assumes that you're using the semver format v1.0.0 for your base tags.

git describe --tags --dirty --always
# v1.0.0
# v1.0.0-1-g0000000
# v1.0.0-dirty

Show the commit date (when the commit made it into the current tree). Internally we use the current date when the working tree is dirty.

git show v1.0.0-1-g0000000 --format=%cd --date=format:%Y-%m-%dT%H:%M:%SZ%z --no-patch
# 2010-01-01T20:30:00Z-0600
# fatal: ambiguous argument 'v1.0.0-1-g0000000-dirty': unknown revision or path not in the working tree.

Shows the most recent commit.

git rev-parse HEAD
# 0000000000000000000000000000000000000000

Errors

cannot find package "."

package git.rootprojects.org/root/go-gitver/v2: cannot find package "." in:
	/Users/me/go-example/vendor/git.rootprojects.org/root/go-gitver/v2
cmd/example/example.go:1: running "go": exit status 1

You forgot to update deps and re-vendor:

go mod tidy
go mod vendor