1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2024-12-31 01:53:50 +02:00

fix: improved semver parsing

This commit is contained in:
Carlos Alexandro Becker 2019-01-19 16:57:58 -02:00 committed by Carlos Alexandro Becker
parent a43c653254
commit df831077e5
9 changed files with 161 additions and 35 deletions

View File

@ -580,6 +580,11 @@ func TestRunPipe(t *testing.T) {
CurrentTag: "v1.0.0",
Commit: "a1b2c3d4",
}
ctx.Semver = context.Semver{
Major: 1,
Minor: 0,
Patch: 0,
}
for _, os := range []string{"linux", "darwin"} {
for _, arch := range []string{"amd64", "386"} {
for _, bin := range []string{"mybin", "anotherbin"} {
@ -818,6 +823,11 @@ func Test_processImageTemplates(t *testing.T) {
CurrentTag: "v1.0.0",
Commit: "a1b2c3d4",
}
ctx.Semver = context.Semver{
Major: 1,
Minor: 0,
Patch: 0,
}
assert.NoError(t, Pipe{}.Default(ctx))
assert.Len(t, ctx.Config.Dockers, 1)

View File

@ -4,7 +4,6 @@ import (
"os"
"time"
"github.com/Masterminds/semver"
"github.com/apex/log"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/internal/client"
@ -40,12 +39,7 @@ func (Pipe) Default(ctx *context.Context) error {
// Check if we have to check the git tag for an indicator to mark as pre release
switch ctx.Config.Release.Prerelease {
case "auto":
sv, err := semver.NewVersion(ctx.Git.CurrentTag)
if err != nil {
return errors.Wrapf(err, "failed to parse tag %s as semver", ctx.Git.CurrentTag)
}
if sv.Prerelease() != "" {
if ctx.Semver.Prerelease != "" {
ctx.PreRelease = true
}
log.Debugf("pre-release was detected for tag %s: %v", ctx.Git.CurrentTag, ctx.PreRelease)

View File

@ -189,7 +189,11 @@ func TestDefaultPreReleaseAuto(t *testing.T) {
Prerelease: "auto",
},
})
ctx.Git.CurrentTag = "v1.0.0"
ctx.Semver = context.Semver{
Major: 1,
Minor: 0,
Patch: 0,
}
assert.NoError(t, Pipe{}.Default(ctx))
assert.Equal(t, false, ctx.PreRelease)
})
@ -200,12 +204,17 @@ func TestDefaultPreReleaseAuto(t *testing.T) {
Prerelease: "auto",
},
})
ctx.Git.CurrentTag = "v1.0.1-rc1"
ctx.Semver = context.Semver{
Major: 1,
Minor: 0,
Patch: 0,
Prerelease: "rc1",
}
assert.NoError(t, Pipe{}.Default(ctx))
assert.Equal(t, true, ctx.PreRelease)
})
t.Run("auto-rc", func(t *testing.T) {
t.Run("auto-rc-github-setup", func(t *testing.T) {
var ctx = context.New(config.Project{
Release: config.Release{
GitHub: config.Repo{
@ -215,7 +224,12 @@ func TestDefaultPreReleaseAuto(t *testing.T) {
Prerelease: "auto",
},
})
ctx.Git.CurrentTag = "v1.0.1-rc1"
ctx.Semver = context.Semver{
Major: 1,
Minor: 0,
Patch: 0,
Prerelease: "rc1",
}
assert.NoError(t, Pipe{}.Default(ctx))
assert.Equal(t, true, ctx.PreRelease)
})

View File

@ -0,0 +1,41 @@
package semver
import (
"github.com/Masterminds/semver"
"github.com/apex/log"
"github.com/goreleaser/goreleaser/internal/pipe"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/pkg/errors"
)
// Pipe is a global hook pipe
type Pipe struct{}
// String is the name of this pipe
func (Pipe) String() string {
return "Parsing tag"
}
// Run executes the hooks
func (Pipe) Run(ctx *context.Context) error {
sv, err := semver.NewVersion(ctx.Git.CurrentTag)
if err != nil {
if ctx.Snapshot {
return pipe.ErrSnapshotEnabled
}
if ctx.SkipValidate {
log.WithError(err).
WithField("tag", ctx.Git.CurrentTag).
Warn("current tag is not a semantic tag")
return pipe.ErrSkipValidateEnabled
}
return errors.Wrapf(err, "failed to parse tag %s as semver", ctx.Git.CurrentTag)
}
ctx.Semver = context.Semver{
Major: sv.Major(),
Minor: sv.Minor(),
Patch: sv.Patch(),
Prerelease: sv.Prerelease(),
}
return nil
}

View File

@ -0,0 +1,62 @@
package semver
import (
"testing"
"github.com/goreleaser/goreleaser/internal/pipe"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDescription(t *testing.T) {
assert.NotEmpty(t, Pipe{}.String())
}
func TestValidSemver(t *testing.T) {
var ctx = context.New(config.Project{})
ctx.Git.CurrentTag = "v1.5.2-rc1"
require.NoError(t, Pipe{}.Run(ctx))
require.Equal(t, context.Semver{
Major: 1,
Minor: 5,
Patch: 2,
Prerelease: "rc1",
}, ctx.Semver)
}
func TestInvalidSemver(t *testing.T) {
var ctx = context.New(config.Project{})
ctx.Git.CurrentTag = "aaaav1.5.2-rc1"
var err = Pipe{}.Run(ctx)
require.Error(t, err)
require.Contains(t, err.Error(), "failed to parse tag aaaav1.5.2-rc1 as semver")
}
func TestInvalidSemverOnSnapshots(t *testing.T) {
var ctx = context.New(config.Project{})
ctx.Git.CurrentTag = "aaaav1.5.2-rc1"
ctx.Snapshot = true
require.EqualError(t, Pipe{}.Run(ctx), pipe.ErrSnapshotEnabled.Error())
require.Equal(t, context.Semver{
Major: 0,
Minor: 0,
Patch: 0,
Prerelease: "",
}, ctx.Semver)
}
func TestInvalidSemverSkipValidate(t *testing.T) {
var ctx = context.New(config.Project{})
ctx.Git.CurrentTag = "aaaav1.5.2-rc1"
ctx.SkipValidate = true
require.EqualError(t, Pipe{}.Run(ctx), pipe.ErrSkipValidateEnabled.Error())
require.Equal(t, context.Semver{
Major: 0,
Minor: 0,
Patch: 0,
Prerelease: "",
}, ctx.Semver)
}

View File

@ -4,6 +4,8 @@ package pipeline
import (
"fmt"
"github.com/goreleaser/goreleaser/internal/pipe/semver"
"github.com/goreleaser/goreleaser/internal/pipe/archive"
"github.com/goreleaser/goreleaser/internal/pipe/before"
"github.com/goreleaser/goreleaser/internal/pipe/build"
@ -36,6 +38,7 @@ type Piper interface {
var Pipeline = []Piper{
before.Pipe{}, // run global hooks before build
git.Pipe{}, // get and validate git repo state
semver.Pipe{}, // parse current tag to a semver
defaults.Pipe{}, // load default configs
snapshot.Pipe{}, // snapshot version handling
dist.Pipe{}, // ensure ./dist is clean

View File

@ -6,10 +6,8 @@ import (
"text/template"
"time"
"github.com/Masterminds/semver"
"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/pkg/errors"
)
// Template holds data that can be applied to a template string
@ -57,6 +55,10 @@ func New(ctx *context.Context) *Template {
env: ctx.Env,
date: time.Now().UTC().Format(time.RFC3339),
timestamp: time.Now().UTC().Unix(),
major: ctx.Semver.Major,
minor: ctx.Semver.Minor,
patch: ctx.Semver.Patch,
// TODO: no reason not to add prerelease here too I guess
},
}
}
@ -90,14 +92,6 @@ func (t *Template) Apply(s string) (string, error) {
return "", err
}
sv, err := semver.NewVersion(t.fields[tag].(string))
if err != nil {
return "", errors.Wrap(err, "tmpl")
}
t.fields[major] = sv.Major()
t.fields[minor] = sv.Minor()
t.fields[patch] = sv.Patch()
err = tmpl.Execute(&out, t.fields)
return out.String(), err
}

View File

@ -16,8 +16,13 @@ func TestWithArtifact(t *testing.T) {
ctx.Env = map[string]string{
"FOO": "bar",
}
ctx.Version = "1.0.0"
ctx.Git.CurrentTag = "v1.0.0"
ctx.Version = "1.2.3"
ctx.Git.CurrentTag = "v1.2.3"
ctx.Semver = context.Semver{
Major: 1,
Minor: 2,
Patch: 3,
}
ctx.Git.Commit = "commit"
ctx.Git.FullCommit = "fullcommit"
ctx.Git.ShortCommit = "shortcommit"
@ -26,8 +31,9 @@ func TestWithArtifact(t *testing.T) {
"Linux": "{{.Os}}",
"amd64": "{{.Arch}}",
"6": "{{.Arm}}",
"1.0.0": "{{.Version}}",
"v1.0.0": "{{.Tag}}",
"1.2.3": "{{.Version}}",
"v1.2.3": "{{.Tag}}",
"1-2-3": "{{.Major}}-{{.Minor}}-{{.Patch}}",
"commit": "{{.Commit}}",
"fullcommit": "{{.FullCommit}}",
"shortcommit": "{{.ShortCommit}}",
@ -136,7 +142,9 @@ func TestFuncMap(t *testing.T) {
}
func TestInvalidTemplate(t *testing.T) {
_, err := New(context.New(config.Project{})).Apply("{{{.Foo}")
ctx := context.New(config.Project{})
ctx.Git.CurrentTag = "v1.1.1"
_, err := New(ctx).Apply("{{{.Foo}")
assert.EqualError(t, err, "template: tmpl:1: unexpected \"{\" in command")
}
@ -147,12 +155,3 @@ func TestEnvNotFound(t *testing.T) {
assert.Empty(t, result)
assert.EqualError(t, err, `template: tmpl:1:6: executing "tmpl" at <.Env.FOO>: map has no entry for key "FOO"`)
}
// This should actually never happen...
func TestInvalidSemver(t *testing.T) {
var ctx = context.New(config.Project{})
ctx.Git.CurrentTag = "v1_2_3"
result, err := New(ctx).Apply("{{.Major}}")
assert.Empty(t, result)
assert.EqualError(t, err, `tmpl: Invalid Semantic Version`)
}

View File

@ -43,6 +43,15 @@ type Context struct {
Debug bool
PreRelease bool
Parallelism int
Semver Semver
}
// Semver represents a semantic version
type Semver struct {
Major int64
Minor int64
Patch int64
Prerelease string
}
// New context