1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-03-17 20:47:50 +02:00

Merge branch 'master' into ignore-builds2

This commit is contained in:
Carlos Alexandro Becker 2017-05-01 11:41:30 -03:00 committed by GitHub
commit ef24f98478
17 changed files with 475 additions and 92 deletions

View File

@ -1,5 +1,5 @@
language: go
go: 1.8
go: 1.8.1
install:
- make setup
- gem install fpm

View File

@ -1,4 +1,56 @@
## Gopkg.toml example (these lines may be deleted)
## "required" lists a set of packages (not projects) that must be included in
## Gopkg.lock. This list is merged with the set of packages imported by the current
## project. Use it when your project needs a package it doesn't explicitly import -
## including "main" packages.
# required = ["github.com/user/thing/cmd/thing"]
## "ignored" lists a set of packages (not projects) that are ignored when
## dep statically analyzes source code. Ignored packages can be in this project,
## or in a dependency.
# ignored = ["github.com/user/project/badpkg"]
## Dependencies define constraints on dependent projects. They are respected by
## dep whether coming from the Gopkg.toml of the current project or a dependency.
# [[dependencies]]
## Required: the root import path of the project being constrained.
# name = "github.com/user/project"
#
## Recommended: the version constraint to enforce for the project.
## Only one of "branch", "version" or "revision" can be specified.
# version = "1.0.0"
# branch = "master"
# revision = "abc123"
#
## Optional: an alternate location (URL or import path) for the project's source.
# source = "https://github.com/myfork/package.git"
## Overrides have the same structure as [[dependencies]], but supercede all
## [[dependencies]] declarations from all projects. Only the current project's
## [[overrides]] are applied.
##
## Overrides are a sledgehammer. Use them only as a last resort.
# [[overrides]]
## Required: the root import path of the project being constrained.
# name = "github.com/user/project"
#
## Optional: specifying a version constraint override will cause all other
## constraints on this project to be ignored; only the overriden constraint
## need be satisfied.
## Again, only one of "branch", "version" or "revision" can be specified.
# version = "1.0.0"
# branch = "master"
# revision = "abc123"
#
## Optional: specifying an alternate source location as an override will
## enforce that the alternate location is used for that project, regardless of
## what source location any dependent projects specify.
# source = "https://github.com/myfork/package.git"
[[dependencies]]
name = "github.com/stretchr/testify"
version = "^1.1.4"

View File

@ -9,6 +9,7 @@
<a href="https://codecov.io/gh/goreleaser/goreleaser"><img alt="Codecov branch" src="https://img.shields.io/codecov/c/github/goreleaser/goreleaser/master.svg?style=flat-square"></a>
<a href="https://goreportcard.com/report/github.com/goreleaser/goreleaser"><img alt="Go Report Card" src="https://goreportcard.com/badge/github.com/goreleaser/goreleaser?style=flat-square"></a>
<a href="http://godoc.org/github.com/goreleaser/goreleaser"><img alt="Go Doc" src="https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square"></a>
<a href="https://beerpay.io/goreleaser/goreleaser"><img src="https://beerpay.io/goreleaser/goreleaser/badge.svg?style=flat-square" /></a>
<a href="https://saythanks.io/to/caarlos0"><img alt="SayThanks.io" src="https://img.shields.io/badge/SayThanks.io-%E2%98%BC-1EAEDB.svg?style=flat-square"></a>
<a href="https://github.com/goreleaser"><img alt="Powered By: GoReleaser" src="https://img.shields.io/badge/powered%20by-goreleaser-green.svg?style=flat-square"></a>
</p>
@ -56,7 +57,7 @@ func main() {
}
```
By default GoReleaser will build the **main.go** file located in your current directory, but you can change the build package path in the GoReleaser configuration file.
By default GoReleaser will build the your current directory, but you can change the build package path in the GoReleaser configuration file.
```yml
# goreleaser.yml
@ -94,9 +95,6 @@ build:
# Archive customization
archive:
format: tar.gz
format_overrides:
- goos: windows
format: zip
replacements:
amd64: 64-bit
darwin: macOS
@ -129,6 +127,8 @@ are not enforcing it though. We do remove the `v` prefix and then enforce
that the next character is a number. So, `v0.1.0` and `0.1.0` are virtually the
same and are both accepted, while `version0.1.0` is not.
If you don't want to create a tag yet but instead simply create a package based on the latest commit, then you can also use the `--snapshot` flag.
Now you can run GoReleaser at the root of your repository:
```console
@ -163,11 +163,15 @@ func main() {
}
```
`version` will always be the name of the current Git tag.
`version` will be the current Git tag (with `v` prefix stripped) or the name of the snapshot if you're using the `--snapshot` flag.
## Release customization
## GoReleaser customization
GoReleaser provides multiple customizations. We will cover them with the help of `goreleaser.yml`:
GoReleaser provides multiple customizations via the `goreleaser.yml` file.
You can generate it by running `goreleaser init` or start from scratch. The
defaults are sensible and fit for most projects.
We'll cover all customizations available bellow:
### Build customization
@ -189,9 +193,10 @@ build:
# Custom ldflags template.
# This is parsed with Golang template engine and the following variables
# are available:
# - Version
# - Date
# - Commit
# - Tag
# - Version (Tag with the `v` prefix stripped)
# The default is `-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}`
# Date format is `2006-01-02_15:04:05`
ldflags: -s -w -X main.build={{.Version}}
@ -256,6 +261,13 @@ archive:
# Default is `tar.gz`
format: zip
# Can be used to archive on different formats for specific GOOSs.
# Most common use case is to archive as zip on Windows.
# Default is empty
format_overrides:
- goos: windows
format: zip
# Replacements for GOOS and GOARCH on the archive name.
# The keys should be valid GOOS or GOARCH values followed by your custom
# replacements.
@ -295,6 +307,20 @@ release:
You can also specify a release notes file in markdown format using the
`--release-notes` flag.
### Snapshot customization
```yml
# goreleaser.yml
snapshot:
# Allows you to change the name of the generated snapshot
# releases. The following variables are available:
# - Commit
# - Tag
# - Timestamp
# Default: SNAPSHOT-{{.Commit}}
name_template: SNAPSHOT-{{.Commit}}
```
### Homebrew tap customization
The brew section specifies how the formula should be created.
@ -412,6 +438,11 @@ fpm:
Note that GoReleaser will not install `fpm` nor any of its dependencies for you.
### Custom release notes
You can have a markdown file previously created with the release notes, and
pass it down to goreleaser with the `--release-notes=FILE` flag.
## Integration with CI
You may want to wire this to auto-deploy your new tags on [Travis](https://travis-ci.org), for example:

View File

@ -10,8 +10,8 @@ import (
// Repo represents any kind of repo (github, gitlab, etc)
type Repo struct {
Owner string
Name string
Owner string `yaml:",omitempty"`
Name string `yaml:",omitempty"`
}
// String of the repo, e.g. owner/name
@ -21,21 +21,21 @@ func (r Repo) String() string {
// Homebrew contains the brew section
type Homebrew struct {
GitHub Repo
Folder string
Caveats string
Plist string
Install string
Dependencies []string
Conflicts []string
Description string
Homepage string
GitHub Repo `yaml:",omitempty"`
Folder string `yaml:",omitempty"`
Caveats string `yaml:",omitempty"`
Plist string `yaml:",omitempty"`
Install string `yaml:",omitempty"`
Dependencies []string `yaml:",omitempty"`
Conflicts []string `yaml:",omitempty"`
Description string `yaml:",omitempty"`
Homepage string `yaml:",omitempty"`
}
// Hooks define actions to run before and/or after something
type Hooks struct {
Pre string
Post string
Pre string `yaml:",omitempty"`
Post string `yaml:",omitempty"`
}
// IgnoredBuild represents a build ignored by the user
@ -45,57 +45,63 @@ type IgnoredBuild struct {
// Build contains the build configuration section
type Build struct {
Goos []string
Goarch []string
Goarm []string
Ignore []IgnoredBuild
Main string
Ldflags string
Flags string
Binary string
Hooks Hooks
Goos []string `yaml:",omitempty"`
Goarch []string `yaml:",omitempty"`
Goarm []string `yaml:",omitempty"`
Ignore []IgnoredBuild `yaml:",omitempty"`
Main string `yaml:",omitempty"`
Ldflags string `yaml:",omitempty"`
Flags string `yaml:",omitempty"`
Binary string `yaml:",omitempty"`
Hooks Hooks `yaml:",omitempty"`
}
// FormatOverride is used to specify a custom format for a specific GOOS.
type FormatOverride struct {
Goos string
Format string
Goos string `yaml:",omitempty"`
Format string `yaml:",omitempty"`
}
// Archive config used for the archive
type Archive struct {
Format string
FormatOverrides []FormatOverride `yaml:"format_overrides"`
NameTemplate string `yaml:"name_template"`
Replacements map[string]string
Files []string
Format string `yaml:",omitempty"`
FormatOverrides []FormatOverride `yaml:"format_overrides,omitempty"`
NameTemplate string `yaml:"name_template,omitempty"`
Replacements map[string]string `yaml:",omitempty"`
Files []string `yaml:",omitempty"`
}
// Release config used for the GitHub release
type Release struct {
GitHub Repo
Draft bool
GitHub Repo `yaml:",omitempty"`
Draft bool `yaml:",omitempty"`
}
// FPM config
type FPM struct {
Formats []string
Dependencies []string
Conflicts []string
Vendor string
Homepage string
Maintainer string
Description string
License string
Formats []string `yaml:",omitempty"`
Dependencies []string `yaml:",omitempty"`
Conflicts []string `yaml:",omitempty"`
Vendor string `yaml:",omitempty"`
Homepage string `yaml:",omitempty"`
Maintainer string `yaml:",omitempty"`
Description string `yaml:",omitempty"`
License string `yaml:",omitempty"`
}
// Snapshot config
type Snapshot struct {
NameTemplate string `yaml:"name_template,omitempty"`
}
// Project includes all project configuration
type Project struct {
Release Release
Brew Homebrew
Build Build
Archive Archive
FPM FPM `yaml:"fpm"`
Release Release `yaml:",omitempty"`
Brew Homebrew `yaml:",omitempty"`
Build Build `yaml:",omitempty"`
Archive Archive `yaml:",omitempty"`
FPM FPM `yaml:",omitempty"`
Snapshot Snapshot `yaml:",omitempty"`
// test only property indicating the path to the dist folder
Dist string `yaml:"-"`

View File

@ -33,6 +33,7 @@ type Context struct {
Version string
Validate bool
Publish bool
Snapshot bool
}
var lock sync.Mutex

View File

@ -5,6 +5,10 @@ import (
"log"
"os"
yaml "gopkg.in/yaml.v1"
"fmt"
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/pipeline"
@ -66,6 +70,11 @@ func Release(flags Flags) error {
log.Println("Loaded custom release notes from", notes)
ctx.ReleaseNotes = string(bts)
}
ctx.Snapshot = flags.Bool("snapshot")
if ctx.Snapshot {
log.Println("Publishing disabled in snapshot mode")
ctx.Publish = false
}
for _, pipe := range pipes {
log.Println(pipe.Description())
log.SetPrefix(" -> ")
@ -77,3 +86,25 @@ func Release(flags Flags) error {
log.Println("Done!")
return nil
}
// InitProject creates an example goreleaser.yml in the current directory
func InitProject(filename string) error {
if _, err := os.Stat(filename); !os.IsNotExist(err) {
if err != nil {
return err
}
return fmt.Errorf("%s already exists", filename)
}
var ctx = context.New(config.Project{})
var pipe = defaults.Pipe{}
if err := pipe.Run(ctx); err != nil {
return err
}
out, err := yaml.Marshal(ctx.Config)
if err != nil {
return err
}
return ioutil.WriteFile(filename, out, 0644)
}

View File

@ -8,6 +8,9 @@ import (
"path/filepath"
"testing"
yaml "gopkg.in/yaml.v1"
"github.com/goreleaser/goreleaser/config"
"github.com/stretchr/testify/assert"
)
@ -28,6 +31,18 @@ func TestRelease(t *testing.T) {
assert.NoError(Release(flags))
}
func TestSnapshotRelease(t *testing.T) {
var assert = assert.New(t)
_, back := setup(t)
defer back()
var flags = fakeFlags{
flags: map[string]string{
"snapshot": "true",
},
}
assert.NoError(Release(flags))
}
func TestConfigFileIsSetAndDontExist(t *testing.T) {
var assert = assert.New(t)
var flags = fakeFlags{
@ -78,6 +93,40 @@ func TestBrokenPipe(t *testing.T) {
assert.Error(Release(flags))
}
func TestInitProject(t *testing.T) {
var assert = assert.New(t)
_, back := setup(t)
defer back()
var filename = "test_goreleaser.yml"
assert.NoError(InitProject(filename))
file, err := os.Open(filename)
assert.NoError(err)
out, err := ioutil.ReadAll(file)
assert.NoError(err)
var config = config.Project{}
assert.NoError(yaml.Unmarshal(out, &config))
}
func TestInitProjectFileExist(t *testing.T) {
var assert = assert.New(t)
_, back := setup(t)
defer back()
var filename = "test_goreleaser.yml"
createFile(t, filename, "")
assert.Error(InitProject(filename))
}
func TestInitProjectDefaultPipeFails(t *testing.T) {
var assert = assert.New(t)
_, back := setup(t)
defer back()
var filename = "test_goreleaser.yml"
assert.NoError(os.RemoveAll(".git"))
assert.Error(InitProject(filename))
}
// fakeFlags is a mock of the cli flags
type fakeFlags struct {
flags map[string]string

20
main.go
View File

@ -38,6 +38,10 @@ func main() {
Name: "skip-publish",
Usage: "Skip all publishing pipes of the release",
},
cli.BoolFlag{
Name: "snapshot",
Usage: "Generate an unversioned snapshot release",
},
}
app.Action = func(c *cli.Context) error {
log.Printf("Running goreleaser %v\n", version)
@ -46,6 +50,22 @@ func main() {
}
return nil
}
app.Commands = []cli.Command{
{
Name: "init",
Aliases: []string{"i"},
Usage: "generate goreleaser.yml",
Action: func(c *cli.Context) error {
var filename = "goreleaser.yml"
if err := goreleaserlib.InitProject(filename); err != nil {
return cli.NewExitError(err.Error(), 1)
}
log.Printf("%s created. Please edit accordingly to your needs.", filename)
return nil
},
},
}
if err := app.Run(os.Args); err != nil {
log.Fatalln(err)
}

View File

@ -10,6 +10,7 @@ import (
type ldflagsData struct {
Date string
Tag string
Commit string
Version string
}
@ -17,7 +18,8 @@ type ldflagsData struct {
func ldflags(ctx *context.Context) (string, error) {
var data = ldflagsData{
Commit: ctx.Git.Commit,
Version: ctx.Git.CurrentTag,
Tag: ctx.Git.CurrentTag,
Version: ctx.Version,
Date: time.Now().UTC().Format(time.RFC3339),
}
var out bytes.Buffer

View File

@ -12,7 +12,7 @@ func TestLdFlagsFullTemplate(t *testing.T) {
assert := assert.New(t)
var config = config.Project{
Build: config.Build{
Ldflags: "-s -w -X main.version={{.Version}} -X main.date={{.Date}} -X main.commit={{.Commit}}",
Ldflags: "-s -w -X main.version={{.Version}} -X main.tag={{.Tag}} -X main.date={{.Date}} -X main.commit={{.Commit}}",
},
}
var ctx = &context.Context{
@ -20,12 +20,14 @@ func TestLdFlagsFullTemplate(t *testing.T) {
CurrentTag: "v1.2.3",
Commit: "123",
},
Config: config,
Version: "1.2.3",
Config: config,
}
flags, err := ldflags(ctx)
assert.NoError(err)
assert.Contains(flags, "-s -w")
assert.Contains(flags, "-X main.version=v1.2.3")
assert.Contains(flags, "-X main.version=1.2.3")
assert.Contains(flags, "-X main.tag=v1.2.3")
assert.Contains(flags, "-X main.commit=123")
assert.Contains(flags, "-X main.date=")
}

View File

@ -81,9 +81,9 @@ func TestNameDefaltTemplate(t *testing.T) {
Version: "1.2.3",
}
for key, target := range map[string]buildTarget{
"test_darwin_amd64": buildTarget{"darwin", "amd64", ""},
"test_linux_arm64": buildTarget{"linux", "arm64", ""},
"test_linux_armv7": buildTarget{"linux", "arm", "7"},
"test_darwin_amd64": {"darwin", "amd64", ""},
"test_linux_arm64": {"linux", "arm64", ""},
"test_linux_armv7": {"linux", "arm", "7"},
} {
t.Run(key, func(t *testing.T) {
name, err := nameFor(ctx, target)

View File

@ -3,7 +3,7 @@
package defaults
import (
"errors"
"fmt"
"io/ioutil"
"strings"
@ -15,6 +15,9 @@ var defaultFiles = []string{"licence", "license", "readme", "changelog"}
// NameTemplate default name_template for the archive.
const NameTemplate = "{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
// SnapshotNameTemplate represents the default format for snapshot release names.
const SnapshotNameTemplate = "SNAPSHOT-{{ .Commit }}"
// Pipe for brew deployment
type Pipe struct{}
@ -25,13 +28,36 @@ func (Pipe) Description() string {
// Run the pipe
func (Pipe) Run(ctx *context.Context) error {
if ctx.Config.Release.GitHub.Name == "" {
repo, err := remoteRepo()
ctx.Config.Release.GitHub = repo
if err != nil {
return errors.New("failed reading repo from git: " + err.Error())
}
ctx.Config.Dist = "dist"
if ctx.Config.Snapshot.NameTemplate == "" {
ctx.Config.Snapshot.NameTemplate = SnapshotNameTemplate
}
if err := setReleaseDefaults(ctx); err != nil {
return err
}
setBuildDefaults(ctx)
if ctx.Config.Brew.Install == "" {
ctx.Config.Brew.Install = fmt.Sprintf(
`bin.install "%s"`,
ctx.Config.Build.Binary,
)
}
return setArchiveDefaults(ctx)
}
func setReleaseDefaults(ctx *context.Context) error {
if ctx.Config.Release.GitHub.Name != "" {
return nil
}
repo, err := remoteRepo()
if err != nil {
return fmt.Errorf("failed reading repo from git: %v", err.Error())
}
ctx.Config.Release.GitHub = repo
return nil
}
func setBuildDefaults(ctx *context.Context) {
if ctx.Config.Build.Binary == "" {
ctx.Config.Build.Binary = ctx.Config.Release.GitHub.Name
}
@ -50,7 +76,9 @@ func (Pipe) Run(ctx *context.Context) error {
if ctx.Config.Build.Ldflags == "" {
ctx.Config.Build.Ldflags = "-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}"
}
}
func setArchiveDefaults(ctx *context.Context) error {
if ctx.Config.Archive.NameTemplate == "" {
ctx.Config.Archive.NameTemplate = NameTemplate
}
@ -76,10 +104,6 @@ func (Pipe) Run(ctx *context.Context) error {
}
ctx.Config.Archive.Files = files
}
if ctx.Config.Brew.Install == "" {
ctx.Config.Brew.Install = "bin.install \"" + ctx.Config.Build.Binary + "\""
}
ctx.Config.Dist = "dist"
return nil
}

View File

@ -41,6 +41,22 @@ func TestFillBasicData(t *testing.T) {
)
}
func TestFillPartial(t *testing.T) {
assert := assert.New(t)
var ctx = &context.Context{
Config: config.Project{
Release: config.Release{
GitHub: config.Repo{
Owner: "goreleaser",
Name: "test",
},
},
},
}
assert.NoError(Pipe{}.Run(ctx))
}
func TestFilesFilled(t *testing.T) {
assert := assert.New(t)

4
pipeline/env/env.go vendored
View File

@ -24,6 +24,10 @@ func (Pipe) Description() string {
// Run the pipe
func (Pipe) Run(ctx *context.Context) (err error) {
ctx.Token = os.Getenv("GITHUB_TOKEN")
if !ctx.Publish {
log.Println("GITHUB_TOKEN not validated because publishing has been disabled")
return nil
}
if !ctx.Validate {
log.Println("Skipped validations because --skip-validate is set")
return nil

View File

@ -1,6 +1,7 @@
package env
import (
"fmt"
"os"
"testing"
@ -19,6 +20,7 @@ func TestValidEnv(t *testing.T) {
var ctx = &context.Context{
Config: config.Project{},
Validate: true,
Publish: true,
}
assert.NoError(Pipe{}.Run(ctx))
}
@ -29,15 +31,37 @@ func TestInvalidEnv(t *testing.T) {
var ctx = &context.Context{
Config: config.Project{},
Validate: true,
Publish: true,
}
assert.Error(Pipe{}.Run(ctx))
}
func TestSkipValidate(t *testing.T) {
assert := assert.New(t)
var ctx = &context.Context{
Config: config.Project{},
Validate: false,
}
assert.NoError(Pipe{}.Run(ctx))
type flags struct {
Validate, Publish, Snapshot bool
}
func TestInvalidEnvChecksSkipped(t *testing.T) {
for _, flag := range []flags{
{
Validate: false,
Publish: true,
}, {
Validate: true,
Publish: false,
}, {
Validate: true,
},
} {
t.Run(fmt.Sprintf("%v", flag), func(t *testing.T) {
var assert = assert.New(t)
assert.NoError(os.Unsetenv("GITHUB_TOKEN"))
var ctx = &context.Context{
Config: config.Project{},
Validate: flag.Validate,
Publish: flag.Publish,
Snapshot: flag.Snapshot,
}
assert.NoError(Pipe{}.Run(ctx))
})
}
}

View File

@ -3,10 +3,14 @@
package git
import (
"bytes"
"fmt"
"log"
"regexp"
"strings"
"time"
"text/template"
"github.com/goreleaser/goreleaser/context"
)
@ -38,6 +42,10 @@ func (e ErrWrongRef) Error() string {
return fmt.Sprintf("git tag %v was not made against commit %v", e.tag, e.commit)
}
// ErrNoTag happens if the underlying git repository doesn't contain any tags
// but no snapshot-release was requested.
var ErrNoTag = fmt.Errorf("git doesn't contain any tags. Either add a tag or use --snapshot")
// Pipe for brew deployment
type Pipe struct{}
@ -52,35 +60,89 @@ func (Pipe) Run(ctx *context.Context) (err error) {
if err != nil {
return
}
if tag == "" && !ctx.Snapshot {
return ErrNoTag
}
ctx.Git = context.GitInfo{
CurrentTag: tag,
Commit: commit,
}
if ctx.ReleaseNotes == "" {
log, err := getChangelog(tag)
if err != nil {
return err
}
ctx.ReleaseNotes = fmt.Sprintf("## Changelog\n\n%v", log)
if err = setLog(ctx, tag, commit); err != nil {
return
}
if err = setVersion(ctx, tag, commit); err != nil {
return
}
// removes usual `v` prefix
ctx.Version = strings.TrimPrefix(tag, "v")
if !ctx.Validate {
log.Println("Skipped validations because --skip-validate is set")
return nil
}
return validate(commit, tag, ctx.Version)
return validate(ctx, commit, tag)
}
func validate(commit, tag, version string) error {
matches, err := regexp.MatchString("^[0-9.]+", version)
if err != nil || !matches {
return ErrInvalidVersionFormat{version}
func setVersion(ctx *context.Context, tag, commit string) (err error) {
if ctx.Snapshot {
snapshotName, err := getSnapshotName(ctx, tag, commit)
if err != nil {
return fmt.Errorf("failed to generate snapshot name: %s", err.Error())
}
ctx.Version = snapshotName
return nil
}
// removes usual `v` prefix
ctx.Version = strings.TrimPrefix(tag, "v")
return
}
func setLog(ctx *context.Context, tag, commit string) (err error) {
if ctx.ReleaseNotes != "" {
return
}
var log string
if tag == "" {
log, err = getChangelog(commit)
} else {
log, err = getChangelog(tag)
}
if err != nil {
return err
}
ctx.ReleaseNotes = fmt.Sprintf("## Changelog\n\n%v", log)
return nil
}
type snapshotNameData struct {
Commit string
Tag string
Timestamp int64
}
func getSnapshotName(ctx *context.Context, tag, commit string) (string, error) {
tmpl, err := template.New("snapshot").Parse(ctx.Config.Snapshot.NameTemplate)
var out bytes.Buffer
if err != nil {
return "", err
}
var data = snapshotNameData{
Commit: commit,
Tag: tag,
Timestamp: time.Now().Unix(),
}
err = tmpl.Execute(&out, data)
return out.String(), err
}
func validate(ctx *context.Context, commit, tag string) error {
out, err := git("status", "-s")
if strings.TrimSpace(out) != "" || err != nil {
return ErrDirty{out}
}
if ctx.Snapshot {
return nil
}
if !regexp.MustCompile("^[0-9.]+").MatchString(ctx.Version) {
return ErrInvalidVersionFormat{ctx.Version}
}
_, err = cleanGit("describe", "--exact-match", "--tags", "--match", tag)
if err != nil {
return ErrWrongRef{commit, tag}
@ -108,7 +170,7 @@ func gitLog(refs ...string) (string, error) {
func getInfo() (tag, commit string, err error) {
tag, err = cleanGit("describe", "--tags", "--abbrev=0")
if err != nil {
return
log.Printf("Failed to retrieve current tag: %s", err.Error())
}
commit, err = cleanGit("show", "--format='%H'", "HEAD")
return

View File

@ -8,6 +8,7 @@ import (
"github.com/goreleaser/goreleaser/config"
"github.com/goreleaser/goreleaser/context"
"github.com/goreleaser/goreleaser/pipeline/defaults"
"github.com/stretchr/testify/assert"
)
@ -50,6 +51,64 @@ func TestNewRepository(t *testing.T) {
assert.Error(Pipe{}.Run(ctx))
}
func TestNoTagsSnapshot(t *testing.T) {
assert := assert.New(t)
_, back := createAndChdir(t)
defer back()
gitInit(t)
gitCommit(t, "first")
var ctx = &context.Context{
Config: config.Project{
Snapshot: config.Snapshot{
NameTemplate: defaults.SnapshotNameTemplate,
},
},
Snapshot: true,
Publish: false,
}
assert.NoError(Pipe{}.Run(ctx))
assert.Contains(ctx.Version, "SNAPSHOT-")
}
func TestNoTagsSnapshotInvalidTemplate(t *testing.T) {
assert := assert.New(t)
_, back := createAndChdir(t)
defer back()
gitInit(t)
gitCommit(t, "first")
var ctx = &context.Context{
Config: config.Project{
Snapshot: config.Snapshot{
NameTemplate: "{{",
},
},
Snapshot: true,
Publish: false,
}
assert.Error(Pipe{}.Run(ctx))
}
// TestNoTagsNoSnapshot covers the situation where a repository
// only contains simple commits and no tags. In this case you have
// to set the --snapshot flag otherwise an error is returned.
func TestNoTagsNoSnapshot(t *testing.T) {
assert := assert.New(t)
_, back := createAndChdir(t)
defer back()
gitInit(t)
gitCommit(t, "first")
var ctx = &context.Context{
Config: config.Project{
Snapshot: config.Snapshot{
NameTemplate: defaults.SnapshotNameTemplate,
},
},
Snapshot: false,
Publish: false,
}
assert.Error(Pipe{}.Run(ctx))
}
func TestInvalidTagFormat(t *testing.T) {
var assert = assert.New(t)
_, back := createAndChdir(t)