Giter Club home page Giter Club logo

autotag's Introduction

AutoTag

CI Coverage Status Go Report Card Actively Maintained

Automatically increment version tags to a git repo based on commit messages.

Dependencies

Version v1.0.0+ depends on the Git CLI, install Git with your distribution's package management system.

Versions prior to v1.0.0 use cgo libgit or native golang Git, the binary will work standalone.

Installing

Pre-built binaries

OS Arch binary
macOS amd64 autotag
Linux amd64 autotag

Docker images

Arch Images
amd64 quay.io/pantheon-public/autotag:latest, vX.Y.Z, vX.Y, vX

One-liner

An install script generated by godownloader is available for all supported platforms. This is often a convenient option for CI pipelines.

Examples:

Download and install latest version of autotag at ./bin/autotag:

curl -sL https://git.io/autotag-install | sh --

Install to a different location using -b flag:

curl -sL https://git.io/autotag-install | sh -s -- -b /usr/bin

Install a specific version of autotag:

curl -sL https://git.io/autotag-install | sh -- v1.2.1

Only versions v1.2.0+ are supported by the install script.

Usage

The autotag utility will use the current state of the git repository to determine what the next tag should be and then creates the tag by executing git tag. The -n flag will print the next tag but not apply it.

autotag scans the main branch for commits by default. If no main branch is found, it will fall back to the master branch. Use -b/--branch to scan a different branch. The utility first looks to find the most-recent reachable tag that matches a supported versioning scheme. If no tags can be found the utility bails-out, so you do need to create a v0.0.0 tag before using autotag.

Once the last reachable tag has been found, the autotag utility inspects each commit between the tag and HEAD of the branch to determine how to increment the version.

Commit messages are parsed for keywords via schemes. Schemes influence the tag selection according to a set of rules.

Schemes are specified using the -s/--scheme flag:

Scheme: Autotag (default)

The autotag scheme implements SemVer style versioning vMajor.Minor.Patch (e.g., v1.2.3).

Before using autotag for the first time create an initial SemVer tag, eg: git tag v0.0.0 -m'initial tag'

The next version tag is calculated based on the contents of commit message according to these rules:

  • Bump the major version by including [major] or #major in a commit message, eg:
[major] breaking change
  • Bump the minor version by including [minor] or #minor in a commit message, eg:
[minor] new feature added
  • Bump the patch version by including [patch] or #patch in a commit message, eg:
[patch] bug fixed

If no keywords are specified a Patch bump is applied.

Scheme: Conventional Commits

Specify the Conventional Commits v1.0.0 scheme by passing --scheme=conventional to autotag.

Conventional Commits implements SemVer style versioning vMajor.Minor.Patch similar to the autotag scheme, but with a different commit message format.

Examples of Conventional Commits:

  • A commit message footer containing BREAKING CHANGE: will bump the major version:
feat: allow provided config object to extend other configs

BREAKING CHANGE: `extends` key in config file is now used for extending other config files
  • A commit message header containing a type of feat will bump the minor version:
feat(lang): add polish language
  • A commit message header containg a ! after the type is considered a breaking change and will bump the major version:
refactor!: drop support for Node 6

If no keywords are specified a Patch bump is applied.

Pre-Release Tags

autotag supports appending additional test to the calculated next version string:

  • Use -p/--pre-release-name= to append a pre-release name to the version. Pre-release names are subject to the rules outlined in the SemVer spec.

  • Use -T/--pre-release-timestmap= to append timestamp to the version. Allowed timetstamp formats are datetime (YYYYMMDDHHMMSS) or epoch (UNIX epoch timestamp in seconds).

Build metadata

Optional SemVer build metadata can be appended to the version string after a + character using the -m/--build-metadata flag. eg: v1.2.3+foo

Build metadata is subject to the rules outlined in the SemVer spec.

A common uses might be the current git reference: git rev-parse --short HEAD.

Multiple metadata items should be seperated by a ., eg: foo.bar

Examples

$ autotag
3.2.1
$ autotag -p pre
3.2.1-pre

$ autotag -T epoch
3.2.1-1499320004

$ autotag -T datetime
3.2.1-20170706054703

$ autotag -p pre -T epoch
3.2.1-pre.1499319951

$ autotag -p rc -T datetime
3.2.1-rc.20170706054528

$ autotag -m g$(git rev-parse --short HEAD)
3.2.1+ge92b825

$ autotag -p dev -m g$(git rev-parse --short HEAD)
3.2.1-dev+ge92b825

$ autotag -m $(date +%Y%M%d)
3.2.1-dev+20200518

$ autotag  -m g$(git rev-parse --short HEAD).$(date +%s)
3.2.1+g11492a8.1589860151

For additional help information use the -h/--help flag:

autotag -h

Goreleaser

autotag works well with goreleaser for automating the process of creating new versions and releases from CI.

An example of a Circle-CI job utilizing both autotag and goreleaser:

jobs:
  release:
    steps:
      - run:
          name: install autotag binary
          command: |
            curl -sL https://git.io/autotag-install | sudo sh -s -- -b /usr/bin
      - run:
          name: increment version
          command: |
           autotag
      - run:
          name: build and push releases
          command: |
            curl -sL https://git.io/goreleaser | bash -s -- --parallelism=2 --rm-dist

workflows:
  version: 2
  build-test-release:
    jobs:
      - release
          requires:
            - build
          filters:
            branches:
              only:
                - master

Troubleshooting

error getting head commit: object does not exist [id: refs/heads/master, rel_path: ]

error getting head commit: object does not exist [id: refs/heads/master, rel_path: ]

You may run into this error on certain CI platforms such as Github Actions or Azure DevOps Pipelines. These platforms tend to make shallow clones of the git repo leaving out important data that autotag expects to find. This can be solved by adding the following commands prior to running autotag:

# fetch all tags and history:
git fetch --tags --unshallow --prune

if [ $(git rev-parse --abbrev-ref HEAD) != "master" ]; then
  # ensure a local 'master' branch exists at 'refs/heads/master'
  git branch --track master origin/master
fi

Build from Source

Assuming you have Go 1.5+ installed you can checkout and run make deps build to compile the binary at ./autotag/autotag.

git clone [email protected]:pantheon-systems/autotag.git

cd autotag

make test
make build

Release information

Autotag itself uses autotag to increment releases. The default autotag scheme is used for version selection.

autotag's People

Contributors

carsonoid avatar defgenx avatar dependabot[bot] avatar dfreilich avatar djschaap avatar fujin avatar joemiller avatar kporras07 avatar kwilliams312 avatar mjhipp avatar pwtyler avatar spheromak avatar theckman avatar vtopc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

autotag's Issues

Loop for version assignment does not apply biggest bump

This issue, I think, is related if not the reason #72 was discovered.

It appears that the logic for determining versions, particularly in the context of !, is not working as intended when that ! commit is not the most recent.

In the screenshots below, the last tag was 3.0.0 so the expectation for these tests is that the version bump should be 4.0.0.

Screen Shot 2022-02-10 at 9 35 23 AM

If commit 3fd23e8f5482f0ad0027a624ff6682492f45dc64 were the last commit, autotag would output 4.0.0 as intended.

The Bug

autotag/autotag.go

Lines 381 to 394 in 408aa18

for i := len(l) - 1; i >= 0; i-- {
commit := l[i] // getting the reverse order element
if commit == nil {
return fmt.Errorf("commit pointed to nil object. This should not happen.")
}
v, nerr := r.parseCommit(commit)
if nerr != nil {
log.Fatal(err)
}
if v != nil {
r.newVersion = v
}

It looks like in this loop the version bump is being set on each iteration, so long as as the bump is not nil. This will overwrite a major bump with a minor depending on the order of parsing. I believe this is what was causing the bug as well in #72, the order itself actually was not the issue. There just exists a possibility where a minor bump overwrites the major bump.

Possible Fix

I think in the loop above, just need to compare the current version to the previous version and somehow compare whether the current bump is greater than the previous and apply the biggest bump rather than applying the bump on non-nil (L392).

Can you also ensure that this fixes the ! mirror, IE BREAKING in the body?

support SemVer "+" build metadata

We currently support SemVer pre-release builds with the - separator. The SemVer 2.0.0 spec also specifies a + for embedding metadata such as git hashes.

https://semver.org/
https://semver.org/#spec-item-10

Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphen [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85.

<valid semver> ::= <version core>
                 | <version core> "-" <pre-release>
                 | <version core> "+" <build>
                 | <version core> "-" <pre-release> "+" <build>

We could support +. A couple ideas come to mind:

  1. A flag to add the short git sha ref, eg v1.0.0+g01aabbcc
  2. A flag to add the full git sha ref, eg v1.0.0+g01aabbccddeeff11223344
  3. A flag to add a posix strftime date format. The flag should let the user pass a valid strftime string such as %Y%m%d, eg: v1.0.0+20200408

Maybe a flag to add arbitrary data as well? That might simplify # 3 by allowing the user to use shell expansions instead of having to parse the strftime string in autotag, eg: autotag -flagname $(date +%Y%m%d)

make a github action for autotag

Autotag is generally used in CI/CD pipelines. We should see about providing a GitHub Action that makes it as easy as possible to integrate.

Bonus points: Make it easy to combine with goreleaser. Not sure if that means documenting how to combine the autotag GH-action with goreleaser's own GH-action, or adding an optional step that supports goreleaser manually in our GH-action.

Allow skipping tags when calculating the next version

Hi, first of all thanks for this cool project.

I have a somewhat specific usecase where I would need to ignore some tags following a pattern when calculating the next version.
My approach would be to add build metadata to those commits so that they can be ignored later.

Example:
image
With this git log I would like to be able to run autotag and ignore the commits with meta so the next version in this example would be "v0.1.0".

My idea would be to add a "--ignore" option ("-i" for short) which allows specifying a pattern like "*meta*" to match the tag name against.

What do you think of it, would this be possible?
Thanks in advance :)

Consider moving project to its own org

There are folks outside of Pantheon that would be willing to keep improving this project and reviewing security patches.

We could take this burden off of Pantheon's hands. Please consider moving this project to its own org, eg github.com/autotag/autotag.

autotag is currently not go-gettable

Hi,

Currently, If I do a go get github.com/pantheon-systems/autotag/autotag it will fail with this message:

go: found github.com/pantheon-systems/autotag/autotag in github.com/pantheon-systems/autotag v1.3.6
go get: github.com/pantheon-systems/[email protected] requires
        github.com/Unknwon/[email protected]: parsing go.mod:
        module declares its path as: github.com/unknwon/com
                but was required as: github.com/Unknwon/com

This is because replace directives are not honored by go get, and they will probably never will.

Removing the replace directive gives this error:

david$ go mod tidy
go: github.com/Unknwon/[email protected]: parsing go.mod:
        module declares its path as: github.com/unknwon/com
                but was required as: github.com/Unknwon/com

And this is caused by an old version of git-module which requires package github.com/Unknwon/com with an uppercase U.

go: finding module for package github.com/Unknwon/com
go: found github.com/Unknwon/com in github.com/Unknwon/com v1.0.1
go: github.com/pantheon-systems/autotag imports
        github.com/gogits/git-module imports
        github.com/Unknwon/com: github.com/Unknwon/[email protected]: parsing go.mod:
        module declares its path as: github.com/unknwon/com
                but was required as: github.com/Unknwon/com

If interested, I have a small PR that brings the github.com/gogs/git-module (formerly github.com/gogits/git-module) to v0.8.3 and removes the need for a replace directive.

Support subsequent pre-releases

This is somewhat related to #18

Our dev preview tags look like X.Y.Z-dev.A

Sometimes we tag multiple dev previews before releasing the final version. I guess the same could be true for alpha, beta, rc and other pre release methods.

I opened a separate PR for this, as it seems less trivial than #18

Autotag is not able to bump from v0.9.x to v0.10.0

It looks like autotag is unable to move from v0.9.x to v0.10.0. Whatever you're using conventional or autotag, the bug exists for both.

if v != nil && v.String() > r.newVersion.String() { this code compares string lexicographically. That's why "0.9.0" is greater than "0.10.0".

support main branch by default

From our readme:

autotag scans the master branch for commits by default. Use -b/--branch to scan a different branch.

It should look for both master and main.

We also need to change this repo to use main instead of master and since autotag's CI uses autotag it might be worthwhile to do these things at the same time.

Multiple tags for 1 commit

I noticed that everytime I ran autotag, it adds an incremented tag to the commit, even if that commit already has a semver tag.

Possible to make it check for a semver tag first and skip if one already exists?

Support tag per subdirectory

In a monorepo containing multiple go modules, versioning of each module is possible using the subdirectory prefix.

This way go get will use the version specific to the module of the monorepo, if the repo is tagged with the module directory.

Example:

Monorepo:
github.com/sermojohn/go-monorepo-importer
Module 1:
github.com/sermojohn/go-monorepo/mod1
Module 2:
github.com/sermojohn/go-monorepo/mod2

autotag could be provided with a flag referring to the subdirectory of a go module in a monorepo, in order to:

  • find the last tag of the subdirectory, e.g. mod1/v0.1.1
  • write the new tag for the subdirectory, e.g. mod1/v0.1.2

This way autotag can create tags that are compatible with Go modules.
reference: https://go.dev/ref/mod#vcs-version

We are in need for this feature, so I have capacity to work on it and contribute to autotag, if you think this feature is valuable to this project.

Potential case-insensitive import collision

Due to GitHub handle change (to lowercase) for long term purpose, go get may fail fetching github.com/Unknwon/com.
Please consider take some time to update it to github.com/unknwon/com in the go.mod file.
I truly apology for the inconvenience and unintended troubles caused.

autotag tagging same commit over and over again

(truncating shas)

git rev-parse HEAD: deac9d...

but:
autotag -v:

2019/01/09 23:36:39 Opening repo at /volume/repo/.git                                                                                              
2019/01/09 23:36:39 Parsing repository tags                                                                                                                         
2019/01/09 23:36:39 Checking commits from 3a1901b... to 3a1901b...                                      
2019/01/09 23:36:39 Writing Tag v0.1.10 

3a1901b... - is 10 commits old and keeps getting tagged with every new commit to master

Tag a bare repository

I wasn't able to tag a bare repository which looks like this:

./
../
branches/
config
description
HEAD
hooks/
info/
objects/
refs/

Latest release does not recognize "!" in commit message

Issue
Fails to recognize "!" as a breaking change and does not follow Semantic Versioning scheme. Results in MINOR bump instead of MAJOR. Introduced to this issue using the latest release but after further investigation tracked the genesis of the issue to release 1.3.14. The final 2 screenshots show release 1.3.13 working as expected.

To Reproduce
I created a dummy repo and attempted to replicate commits that helped discover the issue in the first place.

Expected Behavior
MAJOR version bump when the commit in question, latest commit, contains "!" in the message indicating a breaking change as in v.1.3.13 and prior.

Screenshots/Logs
In order to replicate I did a series of basic and more complicated commits with different keywords that may trigger a particular versioning rule.

Screen Shot 2022-01-20 at 10 49 42 AM

The simple, 1 commit squash and merge PRs seem to be working correct. The commit at the top mimics the squash and merge PR that first introduced the issue. The expectation is that the tag should be 4.0.0, not 3.1.0. The tagging for the git log above was using the latest release of autotag.

Commit parsing in 1.3.14

Screen Shot 2022-01-20 at 11 12 06 AM

Commit parsing in 1.3.13

Screen Shot 2022-01-20 at 11 15 08 AM

It appears the sequential order of parsing commits in v1.3.14 is reverse that of v1.3.13, potentially making the versioning bump not use the latest commit?

System
macOS using latest release as the introduction to bug

Not working in Drone CI, but works locally with same repo

Hello,

I'm trying to use Autotag in one of my pipelines in Drone CI.

I always get the following error message:

2021/12/10 10:14:26 Error initializing: no stable (non pre-release) version tags found

Here's my pipeline configuration:

kind: pipeline
type: kubernetes
name: tag-repo

steps:
  - name: autotag
    image: node:14
    commands:
      - curl -sL https://git.io/autotag-install | sh -s -- -b /usr/bin
      - git --version
      - autotag -n -b dev

trigger:
  branch:
    - dev-ci
  event:
    - push

I'm adding git --version to make sure that I have git 2.X+ available in the PATH.
And I'm using the -n option just to validate if Autotag is working correctly for now.

Here's the output:

1	+ curl -sL https://git.io/autotag-install | sh -s -- -b /usr/bin
2	pantheon-systems/autotag info checking GitHub for latest tag
3	pantheon-systems/autotag info found version: 1.3.13 for v1.3.13/linux/amd64
4	pantheon-systems/autotag info installed /usr/bin/autotag
32	+ git --version
33	git version 2.11.0
34	+ autotag -n -b dev
35	2021/12/10 10:14:26 Error initializing: no stable (non pre-release) version tags found

If I run the same command locally in the same repository it manages to compute the next tag normaly.

Is there any trick or extra configuration that I need to make this work in Drone CI?

Autotag container image are not working

You're building our golang app in desbian and you copy it in alpine.

You need to build it in alpine if you want to expose a alpine image

FROM golang:alpine AS autotag

ARG AUTOTAG_VERSION=v1.1.4

RUN apk add --no-cache git make

WORKDIR /home

RUN git clone https://github.com/pantheon-systems/autotag.git

WORKDIR /home/autotag

RUN git checkout $AUTOTAG_VERSION

RUN make build

use golang:alpine instead of the one by circleci

Support of `v`-prefixed tags?

Hey,

Are v-prefixed tags supported?
With a little experiment I did (with the latest version of autotag), this didn't seem to work for me:
My latest tag was v1.0.4, so I'd expect my next (patch) tag would be v1.0.5. From some reason, I've got 1.0.5 (without v):

❯ git describe --abbrev=0 --tags
v1.0.4

and when running autotag:

❯ ./bin/autotag -n
1.0.5

I even saw there is a flag that let you disable it (-e, --empty-version-prefix Do not prepend v to version tag), so that hints it should work by default, no?

Is it on purpose? If yes, what am I doing wrong and how can I config it to work with v-prefixed tags?

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.