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:
commit
ef24f98478
@ -1,5 +1,5 @@
|
||||
language: go
|
||||
go: 1.8
|
||||
go: 1.8.1
|
||||
install:
|
||||
- make setup
|
||||
- gem install fpm
|
||||
|
52
Gopkg.toml
52
Gopkg.toml
@ -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"
|
||||
|
47
README.md
47
README.md
@ -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:
|
||||
|
@ -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:"-"`
|
||||
|
@ -33,6 +33,7 @@ type Context struct {
|
||||
Version string
|
||||
Validate bool
|
||||
Publish bool
|
||||
Snapshot bool
|
||||
}
|
||||
|
||||
var lock sync.Mutex
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
20
main.go
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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=")
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
4
pipeline/env/env.go
vendored
@ -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
|
||||
|
38
pipeline/env/env_test.go
vendored
38
pipeline/env/env_test.go
vendored
@ -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))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user