mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-01-24 04:16:27 +02:00
commit
3696f74606
167
README.md
167
README.md
@ -61,36 +61,36 @@ By default GoReleaser will build the current directory, but you can change the b
|
||||
```yml
|
||||
# goreleaser.yml
|
||||
# Build customization
|
||||
build:
|
||||
binary: drum-roll
|
||||
goos:
|
||||
- windows
|
||||
- darwin
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
builds:
|
||||
- binary: drum-roll
|
||||
goos:
|
||||
- windows
|
||||
- darwin
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
```
|
||||
|
||||
PS: Invalid GOOS/GOARCH combinations will automatically be skipped.
|
||||
|
||||
This configuration specifies the build operating systems to Windows, Linux and MacOS using 64bit architecture, the name of the binaries is `drum-roll`.
|
||||
|
||||
GoReleaser will then archive the result binaries of each Os/Arch into a separate file. The default format is `{{.Binary}}_{{.Os}}_{{.Arch}}`.
|
||||
GoReleaser will then archive the result binaries of each Os/Arch into a separate file. The default format is `{{.ProjectName}}_{{.Os}}_{{.Arch}}`.
|
||||
You can change the archives name and format. You can also replace the OS and the Architecture with your own.
|
||||
Another useful feature is to add files to archives, this is very useful for integrating assets like resource files.
|
||||
|
||||
```yml
|
||||
# goreleaser.yml
|
||||
# Build customization
|
||||
build:
|
||||
main: main.go
|
||||
binary: drum-roll
|
||||
goos:
|
||||
- windows
|
||||
- darwin
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
builds:
|
||||
- main: main.go
|
||||
binary: drum-roll
|
||||
goos:
|
||||
- windows
|
||||
- darwin
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
# Archive customization
|
||||
archive:
|
||||
format: tar.gz
|
||||
@ -172,76 +172,87 @@ defaults are sensible and fit for most projects.
|
||||
|
||||
We'll cover all customizations available bellow:
|
||||
|
||||
### Project name
|
||||
|
||||
```yml
|
||||
# goreleaser.yml
|
||||
# The name of the project. It is used in the name of the brew formula, archives,
|
||||
# etc. Defaults to the name of the git project.
|
||||
project_name: myproject
|
||||
```
|
||||
|
||||
### Build customization
|
||||
|
||||
```yml
|
||||
# goreleaser.yml
|
||||
build:
|
||||
# Path to main.go file or main package.
|
||||
# Default is `.`
|
||||
main: ./cmd/main.go
|
||||
builds:
|
||||
# You can have multiple builds, its a common yaml list
|
||||
-
|
||||
# Path to main.go file or main package.
|
||||
# Default is `.`
|
||||
main: ./cmd/main.go
|
||||
|
||||
# Name of the binary.
|
||||
# Default is the name of the project directory.
|
||||
binary: program
|
||||
# Name of the binary.
|
||||
# Default is the name of the project directory.
|
||||
binary: program
|
||||
|
||||
# Custom build tags.
|
||||
# Default is empty
|
||||
flags: -tags dev
|
||||
# Custom build tags.
|
||||
# Default is empty
|
||||
flags: -tags dev
|
||||
|
||||
# Custom ldflags template.
|
||||
# This is parsed with Golang template engine and the following variables
|
||||
# are available:
|
||||
# - 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}}
|
||||
# Custom ldflags template.
|
||||
# This is parsed with Golang template engine and the following variables
|
||||
# are available:
|
||||
# - 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}}
|
||||
|
||||
# Custom environment variables to be set durign the builds.
|
||||
# Default is empty
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
# Custom environment variables to be set durign the builds.
|
||||
# Default is empty
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
|
||||
# GOOS list to build in.
|
||||
# For more info refer to https://golang.org/doc/install/source#environment
|
||||
# Defaults are darwin and linux
|
||||
goos:
|
||||
- freebsd
|
||||
- windows
|
||||
# GOOS list to build in.
|
||||
# For more info refer to https://golang.org/doc/install/source#environment
|
||||
# Defaults are darwin and linux
|
||||
goos:
|
||||
- freebsd
|
||||
- windows
|
||||
|
||||
# GOARCH to build in.
|
||||
# For more info refer to https://golang.org/doc/install/source#environment
|
||||
# Defaults are 386 and amd64
|
||||
goarch:
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
# GOARCH to build in.
|
||||
# For more info refer to https://golang.org/doc/install/source#environment
|
||||
# Defaults are 386 and amd64
|
||||
goarch:
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
|
||||
# GOARM to build in when GOARCH is arm.
|
||||
# For more info refer to https://golang.org/doc/install/source#environment
|
||||
# Defaults are 6
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
# GOARM to build in when GOARCH is arm.
|
||||
# For more info refer to https://golang.org/doc/install/source#environment
|
||||
# Defaults are 6
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
|
||||
# List of combinations of GOOS + GOARCH + GOARM to ignore.
|
||||
# Default is empty.
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
- goos: linux
|
||||
goarch: arm
|
||||
goarm: 7
|
||||
# List of combinations of GOOS + GOARCH + GOARM to ignore.
|
||||
# Default is empty.
|
||||
ignore:
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
- goos: linux
|
||||
goarch: arm
|
||||
goarm: 7
|
||||
|
||||
# Hooks can be used to customize the final binary, for example, to run
|
||||
# generator or whatever you want.
|
||||
# Default is both hooks empty.
|
||||
hooks:
|
||||
pre: rice embed-go
|
||||
post: ./script.sh
|
||||
# Hooks can be used to customize the final binary, for example, to run
|
||||
# generator or whatever you want.
|
||||
# Default is both hooks empty.
|
||||
hooks:
|
||||
pre: rice embed-go
|
||||
post: ./script.sh
|
||||
```
|
||||
|
||||
### Archive customization
|
||||
@ -252,14 +263,14 @@ archive:
|
||||
# You can change the name of the archive.
|
||||
# This is parsed with Golang template engine and the following variables
|
||||
# are available:
|
||||
# - Binary
|
||||
# - ProjectName
|
||||
# - Tag
|
||||
# - Version (Tag with the `v` prefix stripped)
|
||||
# - Os
|
||||
# - Arch
|
||||
# - Arm (ARM version)
|
||||
# The default is `{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
|
||||
name_template: "{{.Binary}}_{{.Version}}_{{.Os}}_{{.Arch}}"
|
||||
# The default is `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`
|
||||
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||
|
||||
# Archive format. Valid options are `tar.gz` and `zip`.
|
||||
# Default is `tar.gz`
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/apex/log"
|
||||
yaml "gopkg.in/yaml.v1"
|
||||
)
|
||||
|
||||
@ -99,12 +100,16 @@ type Snapshot struct {
|
||||
|
||||
// Project includes all project configuration
|
||||
type Project struct {
|
||||
Release Release `yaml:",omitempty"`
|
||||
Brew Homebrew `yaml:",omitempty"`
|
||||
Build Build `yaml:",omitempty"`
|
||||
Archive Archive `yaml:",omitempty"`
|
||||
FPM FPM `yaml:",omitempty"`
|
||||
Snapshot Snapshot `yaml:",omitempty"`
|
||||
ProjectName string `yaml:"project_name,omitempty"`
|
||||
Release Release `yaml:",omitempty"`
|
||||
Brew Homebrew `yaml:",omitempty"`
|
||||
Builds []Build `yaml:",omitempty"`
|
||||
Archive Archive `yaml:",omitempty"`
|
||||
FPM FPM `yaml:",omitempty"`
|
||||
Snapshot Snapshot `yaml:",omitempty"`
|
||||
|
||||
// this is a hack ¯\_(ツ)_/¯
|
||||
SingleBuild Build `yaml:"build,omitempty"`
|
||||
|
||||
// test only property indicating the path to the dist folder
|
||||
Dist string `yaml:"-"`
|
||||
@ -126,5 +131,6 @@ func LoadReader(fd io.Reader) (config Project, err error) {
|
||||
return config, err
|
||||
}
|
||||
err = yaml.Unmarshal(data, &config)
|
||||
log.WithField("config", config).Debug("loaded config file")
|
||||
return
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ type Context struct {
|
||||
Config config.Project
|
||||
Token string
|
||||
Git GitInfo
|
||||
Archives map[string]string
|
||||
Folders map[string]string
|
||||
Artifacts []string
|
||||
ReleaseNotes string
|
||||
Version string
|
||||
@ -36,23 +36,32 @@ type Context struct {
|
||||
Snapshot bool
|
||||
}
|
||||
|
||||
var lock sync.Mutex
|
||||
var artifactsLock sync.Mutex
|
||||
var foldersLock sync.Mutex
|
||||
|
||||
// AddArtifact adds a file to upload list
|
||||
func (ctx *Context) AddArtifact(file string) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
artifactsLock.Lock()
|
||||
defer artifactsLock.Unlock()
|
||||
file = strings.TrimPrefix(file, ctx.Config.Dist)
|
||||
file = strings.Replace(file, "/", "", -1)
|
||||
ctx.Artifacts = append(ctx.Artifacts, file)
|
||||
log.WithField("artifact", file).Info("registered")
|
||||
log.WithField("artifact", file).Info("new artifact")
|
||||
}
|
||||
|
||||
// AddFolder adds a built binary to the current context
|
||||
func (ctx *Context) AddFolder(key, folder string) {
|
||||
foldersLock.Lock()
|
||||
defer foldersLock.Unlock()
|
||||
ctx.Folders[key] = folder
|
||||
log.WithField("key", key).WithField("folder", folder).Info("new folder")
|
||||
}
|
||||
|
||||
// New context
|
||||
func New(config config.Project) *Context {
|
||||
return &Context{
|
||||
Context: ctx.Background(),
|
||||
Config: config,
|
||||
Archives: map[string]string{},
|
||||
Context: ctx.Background(),
|
||||
Config: config,
|
||||
Folders: map[string]string{},
|
||||
}
|
||||
}
|
||||
|
@ -31,3 +31,27 @@ func TestMultipleArtifactAdds(t *testing.T) {
|
||||
assert.Len(ctx.Artifacts, len(list))
|
||||
assert.Contains(ctx.Artifacts, "a", "b", "c", "d")
|
||||
}
|
||||
|
||||
func TestMultipleFolderAdds(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
var list = map[string]string{
|
||||
"key-a": "folder/a",
|
||||
"key-b": "folder/b",
|
||||
"key-c": "folder/c",
|
||||
"key-d": "folder/d",
|
||||
}
|
||||
var ctx = New(config.Project{
|
||||
Dist: "dist",
|
||||
})
|
||||
var g errgroup.Group
|
||||
for k, f := range list {
|
||||
f := f
|
||||
k := k
|
||||
g.Go(func() error {
|
||||
ctx.AddFolder(k, f)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
assert.NoError(g.Wait())
|
||||
assert.Len(ctx.Folders, len(list))
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
homepage: &homepage http://goreleaser.github.io
|
||||
description: &description Deliver Go binaries as fast and easily as possible
|
||||
build:
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
- darwin
|
||||
- windows
|
||||
goarch:
|
||||
- 386
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
builds:
|
||||
-
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
- darwin
|
||||
- windows
|
||||
goarch:
|
||||
- 386
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
archive:
|
||||
name_template: '{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
|
||||
replacements:
|
||||
|
@ -36,7 +36,7 @@ func (c *githubClient) CreateFile(
|
||||
},
|
||||
Content: content.Bytes(),
|
||||
Message: github.String(
|
||||
ctx.Config.Build.Binary + " version " + ctx.Git.CurrentTag,
|
||||
ctx.Config.ProjectName + " version " + ctx.Git.CurrentTag,
|
||||
),
|
||||
}
|
||||
|
||||
|
49
internal/name/name.go
Normal file
49
internal/name/name.go
Normal file
@ -0,0 +1,49 @@
|
||||
// Package name provides name template logic for the final archive, formulae,
|
||||
// etc.
|
||||
package name
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"text/template"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
)
|
||||
|
||||
type nameData struct {
|
||||
Os string
|
||||
Arch string
|
||||
Arm string
|
||||
Version string
|
||||
Tag string
|
||||
Binary string // deprecated
|
||||
ProjectName string
|
||||
}
|
||||
|
||||
// For returns the name for the given context, goos, goarch and goarm.
|
||||
func For(ctx *context.Context, goos, goarch, goarm string) (string, error) {
|
||||
var data = nameData{
|
||||
Os: replace(ctx.Config.Archive.Replacements, goos),
|
||||
Arch: replace(ctx.Config.Archive.Replacements, goarch),
|
||||
Arm: replace(ctx.Config.Archive.Replacements, goarm),
|
||||
Version: ctx.Version,
|
||||
Tag: ctx.Git.CurrentTag,
|
||||
Binary: ctx.Config.ProjectName,
|
||||
ProjectName: ctx.Config.ProjectName,
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
t, err := template.New(data.Binary).Parse(ctx.Config.Archive.NameTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = t.Execute(&out, data)
|
||||
return out.String(), err
|
||||
}
|
||||
|
||||
func replace(replacements map[string]string, original string) string {
|
||||
result := replacements[original]
|
||||
if result == "" {
|
||||
return original
|
||||
}
|
||||
return result
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package build
|
||||
package name
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@ -20,9 +20,7 @@ func TestNameFor(t *testing.T) {
|
||||
"amd64": "x86_64",
|
||||
},
|
||||
},
|
||||
Build: config.Build{
|
||||
Binary: "test",
|
||||
},
|
||||
ProjectName: "test",
|
||||
}
|
||||
var ctx = &context.Context{
|
||||
Config: config,
|
||||
@ -32,30 +30,26 @@ func TestNameFor(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
name, err := nameFor(ctx, buildTarget{"darwin", "amd64", ""})
|
||||
name, err := For(ctx, "darwin", "amd64", "")
|
||||
assert.NoError(err)
|
||||
assert.Equal("test_Darwin_x86_64_v1.2.3_1.2.3", name)
|
||||
}
|
||||
|
||||
func TestInvalidNameTemplate(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var config = config.Project{
|
||||
Archive: config.Archive{
|
||||
NameTemplate: "{{.Binary}_{{.Os}}_{{.Arch}}_{{.Version}}",
|
||||
},
|
||||
Build: config.Build{
|
||||
Binary: "test",
|
||||
},
|
||||
}
|
||||
var assert = assert.New(t)
|
||||
var ctx = &context.Context{
|
||||
Config: config,
|
||||
Config: config.Project{
|
||||
Archive: config.Archive{
|
||||
NameTemplate: "{{.Binary}_{{.Os}}_{{.Arch}}_{{.Version}}",
|
||||
},
|
||||
ProjectName: "test",
|
||||
},
|
||||
Git: context.GitInfo{
|
||||
CurrentTag: "v1.2.3",
|
||||
},
|
||||
}
|
||||
|
||||
_, err := nameFor(ctx, buildTarget{"darwin", "amd64", ""})
|
||||
_, err := For(ctx, "darwin", "amd64", "")
|
||||
assert.Error(err)
|
||||
}
|
||||
|
||||
@ -66,19 +60,20 @@ func TestNameDefaltTemplate(t *testing.T) {
|
||||
Archive: config.Archive{
|
||||
NameTemplate: defaults.NameTemplate,
|
||||
},
|
||||
Build: config.Build{
|
||||
Binary: "test",
|
||||
},
|
||||
ProjectName: "test",
|
||||
},
|
||||
Version: "1.2.3",
|
||||
}
|
||||
type buildTarget struct {
|
||||
goos, goarch, goarm string
|
||||
}
|
||||
for key, target := range map[string]buildTarget{
|
||||
"test_1.2.3_darwin_amd64": {"darwin", "amd64", ""},
|
||||
"test_1.2.3_linux_arm64": {"linux", "arm64", ""},
|
||||
"test_1.2.3_linux_armv7": {"linux", "arm", "7"},
|
||||
} {
|
||||
t.Run(key, func(t *testing.T) {
|
||||
name, err := nameFor(ctx, target)
|
||||
name, err := For(ctx, target.goos, target.goarch, target.goarm)
|
||||
assert.NoError(err)
|
||||
assert.Equal(key, name)
|
||||
})
|
@ -4,6 +4,7 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@ -11,7 +12,6 @@ import (
|
||||
"github.com/goreleaser/archive"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/archiveformat"
|
||||
"github.com/goreleaser/goreleaser/internal/ext"
|
||||
"github.com/mattn/go-zglob"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
@ -27,11 +27,11 @@ func (Pipe) Description() string {
|
||||
// Run the pipe
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
var g errgroup.Group
|
||||
for platform, archive := range ctx.Archives {
|
||||
archive := archive
|
||||
for platform, folder := range ctx.Folders {
|
||||
folder := folder
|
||||
platform := platform
|
||||
g.Go(func() error {
|
||||
return create(ctx, platform, archive)
|
||||
return create(ctx, platform, folder)
|
||||
})
|
||||
}
|
||||
return g.Wait()
|
||||
@ -58,10 +58,16 @@ func create(ctx *context.Context, platform, name string) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var binary = ctx.Config.Build.Binary + ext.For(platform)
|
||||
if err := archive.Add(binary, filepath.Join(folder, binary)); err != nil {
|
||||
var path = filepath.Join(ctx.Config.Dist, name)
|
||||
binaries, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, binary := range binaries {
|
||||
if err := archive.Add(binary.Name(), filepath.Join(path, binary.Name())); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ctx.AddArtifact(file.Name())
|
||||
return nil
|
||||
}
|
||||
|
@ -27,23 +27,21 @@ func TestRunPipe(t *testing.T) {
|
||||
}()
|
||||
var dist = filepath.Join(folder, "dist")
|
||||
assert.NoError(os.Mkdir(dist, 0755))
|
||||
assert.NoError(os.Mkdir(filepath.Join(dist, "mybin"), 0755))
|
||||
_, err = os.Create(filepath.Join(dist, "mybin", "mybin"))
|
||||
assert.NoError(os.Mkdir(filepath.Join(dist, "mybin_darwin_amd64"), 0755))
|
||||
assert.NoError(os.Mkdir(filepath.Join(dist, "mybin_windows_amd64"), 0755))
|
||||
_, err = os.Create(filepath.Join(dist, "mybin_darwin_amd64", "mybin"))
|
||||
assert.NoError(err)
|
||||
_, err = os.Create(filepath.Join(dist, "mybin", "mybin.exe"))
|
||||
_, err = os.Create(filepath.Join(dist, "mybin_windows_amd64", "mybin.exe"))
|
||||
assert.NoError(err)
|
||||
_, err = os.Create(filepath.Join(folder, "README.md"))
|
||||
assert.NoError(err)
|
||||
var ctx = &context.Context{
|
||||
Archives: map[string]string{
|
||||
"darwinamd64": "mybin",
|
||||
"windowsamd64": "mybin",
|
||||
Folders: map[string]string{
|
||||
"darwinamd64": "mybin_darwin_amd64",
|
||||
"windowsamd64": "mybin_windows_amd64",
|
||||
},
|
||||
Config: config.Project{
|
||||
Dist: dist,
|
||||
Build: config.Build{
|
||||
Binary: "mybin",
|
||||
},
|
||||
Archive: config.Archive{
|
||||
Files: []string{
|
||||
"README.*",
|
||||
@ -68,9 +66,8 @@ func TestRunPipe(t *testing.T) {
|
||||
func TestRunPipeDistRemoved(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
var ctx = &context.Context{
|
||||
Archives: map[string]string{
|
||||
"darwinamd64": "mybin",
|
||||
"windowsamd64": "mybin",
|
||||
Folders: map[string]string{
|
||||
"darwinamd64": "whatever",
|
||||
},
|
||||
Config: config.Project{
|
||||
Dist: "/path/nope",
|
||||
@ -85,8 +82,8 @@ func TestRunPipeDistRemoved(t *testing.T) {
|
||||
func TestRunPipeInvalidGlob(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
var ctx = &context.Context{
|
||||
Archives: map[string]string{
|
||||
"windowsamd64": "mybin",
|
||||
Folders: map[string]string{
|
||||
"windowsamd64": "whatever",
|
||||
},
|
||||
Config: config.Project{
|
||||
Dist: "/tmp",
|
||||
@ -113,7 +110,7 @@ func TestRunPipeGlobFailsToAdd(t *testing.T) {
|
||||
assert.NoError(os.MkdirAll(filepath.Join(folder, "folder", "another"), 0755))
|
||||
|
||||
var ctx = &context.Context{
|
||||
Archives: map[string]string{
|
||||
Folders: map[string]string{
|
||||
"windows386": "mybin",
|
||||
},
|
||||
Config: config.Project{
|
||||
@ -127,18 +124,3 @@ func TestRunPipeGlobFailsToAdd(t *testing.T) {
|
||||
}
|
||||
assert.Error(Pipe{}.Run(ctx))
|
||||
}
|
||||
|
||||
func TestRunPipeBinaryDontExist(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
folder, err := ioutil.TempDir("", "archivetest")
|
||||
assert.NoError(err)
|
||||
var ctx = &context.Context{
|
||||
Archives: map[string]string{
|
||||
"windows386": "mybin",
|
||||
},
|
||||
Config: config.Project{
|
||||
Dist: folder,
|
||||
},
|
||||
}
|
||||
assert.Error(Pipe{}.Run(ctx))
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ import (
|
||||
// contain darwin and/or goarch doesn't contain amd64)
|
||||
var ErrNoDarwin64Build = errors.New("brew tap requires a darwin amd64 build")
|
||||
|
||||
const platform = "darwinamd64"
|
||||
|
||||
const formula = `class {{ .Name }} < Formula
|
||||
desc "{{ .Desc }}"
|
||||
homepage "{{ .Homepage }}"
|
||||
@ -70,7 +72,6 @@ type templateData struct {
|
||||
Repo config.Repo // FIXME: will not work for anything but github right now.
|
||||
Tag string
|
||||
Version string
|
||||
Binary string
|
||||
Caveats string
|
||||
File string
|
||||
SHA256 string
|
||||
@ -106,7 +107,7 @@ func doRun(ctx *context.Context, client client.Client) error {
|
||||
log.Warn("skipped because release is marked as draft")
|
||||
return nil
|
||||
}
|
||||
path := filepath.Join(ctx.Config.Brew.Folder, ctx.Config.Build.Binary+".rb")
|
||||
var path = filepath.Join(ctx.Config.Brew.Folder, ctx.Config.ProjectName+".rb")
|
||||
log.WithField("formula", path).
|
||||
WithField("repo", ctx.Config.Brew.GitHub.String()).
|
||||
Info("pushing")
|
||||
@ -127,7 +128,7 @@ func buildFormula(ctx *context.Context, client client.Client) (bytes.Buffer, err
|
||||
|
||||
func doBuildFormula(data templateData) (bytes.Buffer, error) {
|
||||
var out bytes.Buffer
|
||||
tmpl, err := template.New(data.Binary).Parse(formula)
|
||||
tmpl, err := template.New(data.Name).Parse(formula)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
@ -136,23 +137,22 @@ func doBuildFormula(data templateData) (bytes.Buffer, error) {
|
||||
}
|
||||
|
||||
func dataFor(ctx *context.Context, client client.Client) (result templateData, err error) {
|
||||
var folder = ctx.Archives["darwinamd64"]
|
||||
var folder = ctx.Folders[platform]
|
||||
if folder == "" {
|
||||
return result, ErrNoDarwin64Build
|
||||
}
|
||||
var file = folder + "." + archiveformat.For(ctx, "darwinamd64")
|
||||
var file = folder + "." + archiveformat.For(ctx, platform)
|
||||
sum, err := checksum.SHA256(filepath.Join(ctx.Config.Dist, file))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return templateData{
|
||||
Name: formulaNameFor(ctx.Config.Build.Binary),
|
||||
Name: formulaNameFor(ctx.Config.ProjectName),
|
||||
Desc: ctx.Config.Brew.Description,
|
||||
Homepage: ctx.Config.Brew.Homepage,
|
||||
Repo: ctx.Config.Release.GitHub,
|
||||
Tag: ctx.Git.CurrentTag,
|
||||
Version: ctx.Version,
|
||||
Binary: ctx.Config.Build.Binary,
|
||||
Caveats: ctx.Config.Brew.Caveats,
|
||||
File: file,
|
||||
SHA256: sum,
|
||||
|
@ -29,7 +29,6 @@ func TestSimpleName(t *testing.T) {
|
||||
}
|
||||
|
||||
var defaultTemplateData = templateData{
|
||||
Binary: "test",
|
||||
Desc: "Some desc",
|
||||
Homepage: "https://google.com",
|
||||
Name: "Test",
|
||||
@ -104,7 +103,7 @@ func TestRunPipe(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Archives: map[string]string{
|
||||
Folders: map[string]string{
|
||||
"darwinamd64": "bin",
|
||||
},
|
||||
Publish: true,
|
||||
@ -139,7 +138,7 @@ func TestRunPipeFormatOverride(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Archives: map[string]string{
|
||||
Folders: map[string]string{
|
||||
"darwinamd64": "bin",
|
||||
},
|
||||
Publish: true,
|
||||
@ -167,7 +166,7 @@ func TestRunPipeArchiveDoesntExist(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Archives: map[string]string{
|
||||
Folders: map[string]string{
|
||||
"darwinamd64": "bin",
|
||||
},
|
||||
Publish: true,
|
||||
|
@ -10,8 +10,10 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/ext"
|
||||
"github.com/goreleaser/goreleaser/internal/name"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
@ -25,31 +27,36 @@ func (Pipe) Description() string {
|
||||
|
||||
// Run the pipe
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
if err := runHook(ctx.Config.Build.Env, ctx.Config.Build.Hooks.Pre); err != nil {
|
||||
for _, build := range ctx.Config.Builds {
|
||||
log.WithField("build", build).Debug("building")
|
||||
if err := runPipeOnBuild(ctx, build); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runPipeOnBuild(ctx *context.Context, build config.Build) error {
|
||||
if err := runHook(build.Env, build.Hooks.Pre); err != nil {
|
||||
return err
|
||||
}
|
||||
sem := make(chan bool, 4)
|
||||
var g errgroup.Group
|
||||
for _, target := range buildTargets(ctx) {
|
||||
name, err := nameFor(ctx, target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.Archives[target.String()] = name
|
||||
|
||||
for _, target := range buildTargets(build) {
|
||||
sem <- true
|
||||
target := target
|
||||
build := build
|
||||
g.Go(func() error {
|
||||
defer func() {
|
||||
<-sem
|
||||
}()
|
||||
return build(ctx, name, target)
|
||||
return doBuild(ctx, build, target)
|
||||
})
|
||||
}
|
||||
if err := g.Wait(); err != nil {
|
||||
return err
|
||||
}
|
||||
return runHook(ctx.Config.Build.Env, ctx.Config.Build.Hooks.Post)
|
||||
return runHook(build.Env, build.Hooks.Post)
|
||||
}
|
||||
|
||||
func runHook(env []string, hook string) error {
|
||||
@ -61,23 +68,28 @@ func runHook(env []string, hook string) error {
|
||||
return run(runtimeTarget, cmd, env)
|
||||
}
|
||||
|
||||
func build(ctx *context.Context, name string, target buildTarget) error {
|
||||
output := filepath.Join(
|
||||
ctx.Config.Dist,
|
||||
name,
|
||||
ctx.Config.Build.Binary+ext.For(target.goos),
|
||||
)
|
||||
log.WithField("binary", output).Info("building")
|
||||
cmd := []string{"go", "build"}
|
||||
if ctx.Config.Build.Flags != "" {
|
||||
cmd = append(cmd, strings.Fields(ctx.Config.Build.Flags)...)
|
||||
}
|
||||
flags, err := ldflags(ctx)
|
||||
func doBuild(ctx *context.Context, build config.Build, target buildTarget) error {
|
||||
folder, err := name.For(ctx, target.goos, target.goarch, target.goarm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd = append(cmd, "-ldflags="+flags, "-o", output, ctx.Config.Build.Main)
|
||||
return run(target, cmd, ctx.Config.Build.Env)
|
||||
ctx.AddFolder(target.String(), folder)
|
||||
var binary = filepath.Join(
|
||||
ctx.Config.Dist,
|
||||
folder,
|
||||
build.Binary+ext.For(target.goos),
|
||||
)
|
||||
log.WithField("binary", binary).Info("building")
|
||||
cmd := []string{"go", "build"}
|
||||
if build.Flags != "" {
|
||||
cmd = append(cmd, strings.Fields(build.Flags)...)
|
||||
}
|
||||
flags, err := ldflags(ctx, build)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd = append(cmd, "-ldflags="+flags, "-o", binary, build.Main)
|
||||
return run(target, cmd, build.Env)
|
||||
}
|
||||
|
||||
func run(target buildTarget, command, env []string) error {
|
||||
|
@ -29,16 +29,19 @@ func TestRunInvalidCommand(t *testing.T) {
|
||||
func TestBuild(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
var config = config.Project{
|
||||
Build: config.Build{
|
||||
Binary: "testing",
|
||||
Flags: "-n",
|
||||
Env: []string{"BLAH=1"},
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Binary: "testing",
|
||||
Flags: "-n",
|
||||
Env: []string{"BLAH=1"},
|
||||
},
|
||||
},
|
||||
}
|
||||
var ctx = &context.Context{
|
||||
Config: config,
|
||||
Config: config,
|
||||
Folders: map[string]string{},
|
||||
}
|
||||
assert.NoError(build(ctx, "build_test", runtimeTarget))
|
||||
assert.NoError(doBuild(ctx, ctx.Config.Builds[0], runtimeTarget))
|
||||
}
|
||||
|
||||
func TestRunFullPipe(t *testing.T) {
|
||||
@ -50,25 +53,27 @@ func TestRunFullPipe(t *testing.T) {
|
||||
var post = filepath.Join(folder, "post")
|
||||
var config = config.Project{
|
||||
Dist: folder,
|
||||
Build: config.Build{
|
||||
Binary: "testing",
|
||||
Flags: "-v",
|
||||
Ldflags: "-X main.test=testing",
|
||||
Hooks: config.Hooks{
|
||||
Pre: "touch " + pre,
|
||||
Post: "touch " + post,
|
||||
},
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Binary: "testing",
|
||||
Flags: "-v",
|
||||
Ldflags: "-X main.test=testing",
|
||||
Hooks: config.Hooks{
|
||||
Pre: "touch " + pre,
|
||||
Post: "touch " + post,
|
||||
},
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var ctx = &context.Context{
|
||||
Config: config,
|
||||
Archives: map[string]string{},
|
||||
Config: config,
|
||||
Folders: map[string]string{},
|
||||
}
|
||||
assert.NoError(Pipe{}.Run(ctx))
|
||||
assert.True(exists(binary), binary)
|
||||
@ -83,25 +88,27 @@ func TestRunPipeArmBuilds(t *testing.T) {
|
||||
var binary = filepath.Join(folder, "armtesting")
|
||||
var config = config.Project{
|
||||
Dist: folder,
|
||||
Build: config.Build{
|
||||
Binary: "armtesting",
|
||||
Flags: "-v",
|
||||
Ldflags: "-X main.test=armtesting",
|
||||
Goos: []string{
|
||||
"linux",
|
||||
},
|
||||
Goarch: []string{
|
||||
"arm",
|
||||
"arm64",
|
||||
},
|
||||
Goarm: []string{
|
||||
"6",
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Binary: "armtesting",
|
||||
Flags: "-v",
|
||||
Ldflags: "-X main.test=armtesting",
|
||||
Goos: []string{
|
||||
"linux",
|
||||
},
|
||||
Goarch: []string{
|
||||
"arm",
|
||||
"arm64",
|
||||
},
|
||||
Goarm: []string{
|
||||
"6",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var ctx = &context.Context{
|
||||
Config: config,
|
||||
Archives: map[string]string{},
|
||||
Config: config,
|
||||
Folders: map[string]string{},
|
||||
}
|
||||
assert.NoError(Pipe{}.Run(ctx))
|
||||
assert.True(exists(binary), binary)
|
||||
@ -110,19 +117,21 @@ func TestRunPipeArmBuilds(t *testing.T) {
|
||||
func TestBuildFailed(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
var config = config.Project{
|
||||
Build: config.Build{
|
||||
Flags: "-flag-that-dont-exists-to-force-failure",
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Flags: "-flag-that-dont-exists-to-force-failure",
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var ctx = &context.Context{
|
||||
Config: config,
|
||||
Archives: map[string]string{},
|
||||
Config: config,
|
||||
Folders: map[string]string{},
|
||||
}
|
||||
assert.Error(Pipe{}.Run(ctx))
|
||||
}
|
||||
@ -130,19 +139,21 @@ func TestBuildFailed(t *testing.T) {
|
||||
func TestRunPipeWithInvalidOS(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
var config = config.Project{
|
||||
Build: config.Build{
|
||||
Flags: "-v",
|
||||
Goos: []string{
|
||||
"windows",
|
||||
},
|
||||
Goarch: []string{
|
||||
"arm",
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Flags: "-v",
|
||||
Goos: []string{
|
||||
"windows",
|
||||
},
|
||||
Goarch: []string{
|
||||
"arm",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var ctx = &context.Context{
|
||||
Config: config,
|
||||
Archives: map[string]string{},
|
||||
Config: config,
|
||||
Folders: map[string]string{},
|
||||
}
|
||||
assert.NoError(Pipe{}.Run(ctx))
|
||||
}
|
||||
@ -151,14 +162,16 @@ func TestRunInvalidNametemplate(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Build: config.Build{
|
||||
Binary: "nametest",
|
||||
Flags: "-v",
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Binary: "nametest",
|
||||
Flags: "-v",
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
},
|
||||
},
|
||||
},
|
||||
Archive: config.Archive{
|
||||
@ -172,17 +185,19 @@ func TestRunInvalidNametemplate(t *testing.T) {
|
||||
func TestRunInvalidLdflags(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
var ctx = &context.Context{
|
||||
Archives: map[string]string{},
|
||||
Folders: map[string]string{},
|
||||
Config: config.Project{
|
||||
Build: config.Build{
|
||||
Binary: "nametest",
|
||||
Flags: "-v",
|
||||
Ldflags: "-s -w -X main.version={{.Version}",
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Binary: "nametest",
|
||||
Flags: "-v",
|
||||
Ldflags: "-s -w -X main.version={{.Version}",
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -193,26 +208,28 @@ func TestRunInvalidLdflags(t *testing.T) {
|
||||
func TestRunPipeFailingHooks(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
var config = config.Project{
|
||||
Build: config.Build{
|
||||
Hooks: config.Hooks{},
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Hooks: config.Hooks{},
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var ctx = &context.Context{
|
||||
Config: config,
|
||||
Archives: map[string]string{},
|
||||
Config: config,
|
||||
Folders: map[string]string{},
|
||||
}
|
||||
t.Run("pre-hook", func(t *testing.T) {
|
||||
ctx.Config.Build.Hooks.Pre = "exit 1"
|
||||
ctx.Config.Builds[0].Hooks.Pre = "exit 1"
|
||||
assert.Error(Pipe{}.Run(ctx))
|
||||
})
|
||||
t.Run("post-hook", func(t *testing.T) {
|
||||
ctx.Config.Build.Hooks.Post = "exit 1"
|
||||
ctx.Config.Builds[0].Hooks.Post = "exit 1"
|
||||
assert.Error(Pipe{}.Run(ctx))
|
||||
})
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
)
|
||||
|
||||
@ -15,7 +16,7 @@ type ldflagsData struct {
|
||||
Version string
|
||||
}
|
||||
|
||||
func ldflags(ctx *context.Context) (string, error) {
|
||||
func ldflags(ctx *context.Context, build config.Build) (string, error) {
|
||||
var data = ldflagsData{
|
||||
Commit: ctx.Git.Commit,
|
||||
Tag: ctx.Git.CurrentTag,
|
||||
@ -23,7 +24,7 @@ func ldflags(ctx *context.Context) (string, error) {
|
||||
Date: time.Now().UTC().Format(time.RFC3339),
|
||||
}
|
||||
var out bytes.Buffer
|
||||
t, err := template.New("ldflags").Parse(ctx.Config.Build.Ldflags)
|
||||
t, err := template.New("ldflags").Parse(build.Ldflags)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -11,8 +11,10 @@ import (
|
||||
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.tag={{.Tag}} -X main.date={{.Date}} -X main.commit={{.Commit}}",
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Ldflags: "-s -w -X main.version={{.Version}} -X main.tag={{.Tag}} -X main.date={{.Date}} -X main.commit={{.Commit}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
var ctx = &context.Context{
|
||||
@ -23,7 +25,7 @@ func TestLdFlagsFullTemplate(t *testing.T) {
|
||||
Version: "1.2.3",
|
||||
Config: config,
|
||||
}
|
||||
flags, err := ldflags(ctx)
|
||||
flags, err := ldflags(ctx, ctx.Config.Builds[0])
|
||||
assert.NoError(err)
|
||||
assert.Contains(flags, "-s -w")
|
||||
assert.Contains(flags, "-X main.version=1.2.3")
|
||||
@ -35,14 +37,14 @@ func TestLdFlagsFullTemplate(t *testing.T) {
|
||||
func TestInvalidTemplate(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
var config = config.Project{
|
||||
Build: config.Build{
|
||||
Ldflags: "{invalid{.Template}}}{{}}}",
|
||||
Builds: []config.Build{
|
||||
{Ldflags: "{invalid{.Template}}}{{}}}"},
|
||||
},
|
||||
}
|
||||
var ctx = &context.Context{
|
||||
Config: config,
|
||||
}
|
||||
flags, err := ldflags(ctx)
|
||||
flags, err := ldflags(ctx, ctx.Config.Builds[0])
|
||||
assert.Error(err)
|
||||
assert.Equal(flags, "")
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"text/template"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
)
|
||||
|
||||
type nameData struct {
|
||||
Os string
|
||||
Arch string
|
||||
Arm string
|
||||
Version string
|
||||
Tag string
|
||||
Binary string
|
||||
}
|
||||
|
||||
func nameFor(ctx *context.Context, target buildTarget) (string, error) {
|
||||
var data = nameData{
|
||||
Os: replace(ctx.Config.Archive.Replacements, target.goos),
|
||||
Arch: replace(ctx.Config.Archive.Replacements, target.goarch),
|
||||
Arm: replace(ctx.Config.Archive.Replacements, target.goarm),
|
||||
Version: ctx.Version,
|
||||
Tag: ctx.Git.CurrentTag,
|
||||
Binary: ctx.Config.Build.Binary,
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
t, err := template.New(data.Binary).Parse(ctx.Config.Archive.NameTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = t.Execute(&out, data)
|
||||
return out.String(), err
|
||||
}
|
||||
|
||||
func replace(replacements map[string]string, original string) string {
|
||||
result := replacements[original]
|
||||
if result == "" {
|
||||
return original
|
||||
}
|
||||
return result
|
||||
}
|
@ -5,7 +5,7 @@ import (
|
||||
"runtime"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
)
|
||||
|
||||
var runtimeTarget = buildTarget{runtime.GOOS, runtime.GOARCH, ""}
|
||||
@ -23,14 +23,14 @@ func (t buildTarget) PrettyString() string {
|
||||
return fmt.Sprintf("%v/%v%v", t.goos, t.goarch, t.goarm)
|
||||
}
|
||||
|
||||
func buildTargets(ctx *context.Context) (targets []buildTarget) {
|
||||
for _, target := range allBuildTargets(ctx) {
|
||||
func buildTargets(build config.Build) (targets []buildTarget) {
|
||||
for _, target := range allBuildTargets(build) {
|
||||
if !valid(target) {
|
||||
log.WithField("target", target.PrettyString()).
|
||||
Warn("skipped invalid build")
|
||||
continue
|
||||
}
|
||||
if ignored(ctx, target) {
|
||||
if ignored(build, target) {
|
||||
log.WithField("target", target.PrettyString()).
|
||||
Warn("skipped ignored build")
|
||||
continue
|
||||
@ -40,11 +40,11 @@ func buildTargets(ctx *context.Context) (targets []buildTarget) {
|
||||
return
|
||||
}
|
||||
|
||||
func allBuildTargets(ctx *context.Context) (targets []buildTarget) {
|
||||
for _, goos := range ctx.Config.Build.Goos {
|
||||
for _, goarch := range ctx.Config.Build.Goarch {
|
||||
func allBuildTargets(build config.Build) (targets []buildTarget) {
|
||||
for _, goos := range build.Goos {
|
||||
for _, goarch := range build.Goarch {
|
||||
if goarch == "arm" {
|
||||
for _, goarm := range ctx.Config.Build.Goarm {
|
||||
for _, goarm := range build.Goarm {
|
||||
targets = append(targets, buildTarget{goos, goarch, goarm})
|
||||
}
|
||||
continue
|
||||
@ -55,8 +55,8 @@ func allBuildTargets(ctx *context.Context) (targets []buildTarget) {
|
||||
return
|
||||
}
|
||||
|
||||
func ignored(ctx *context.Context, target buildTarget) bool {
|
||||
for _, ig := range ctx.Config.Build.Ignore {
|
||||
func ignored(build config.Build, target buildTarget) bool {
|
||||
for _, ig := range build.Ignore {
|
||||
var ignored = buildTarget{ig.Goos, ig.Goarch, ig.Goarm}
|
||||
if ignored == target {
|
||||
return true
|
||||
|
@ -5,40 +5,35 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAllBuildTargets(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Build: config.Build{
|
||||
Goos: []string{
|
||||
"linux",
|
||||
"darwin",
|
||||
"freebsd",
|
||||
},
|
||||
Goarch: []string{
|
||||
"386",
|
||||
"amd64",
|
||||
"arm",
|
||||
"arm64",
|
||||
},
|
||||
Goarm: []string{
|
||||
"6",
|
||||
"7",
|
||||
},
|
||||
Ignore: []config.IgnoredBuild{
|
||||
{
|
||||
Goos: "darwin",
|
||||
Goarch: "386",
|
||||
}, {
|
||||
Goos: "linux",
|
||||
Goarch: "arm",
|
||||
Goarm: "7",
|
||||
},
|
||||
},
|
||||
var build = config.Build{
|
||||
Goos: []string{
|
||||
"linux",
|
||||
"darwin",
|
||||
"freebsd",
|
||||
},
|
||||
Goarch: []string{
|
||||
"386",
|
||||
"amd64",
|
||||
"arm",
|
||||
"arm64",
|
||||
},
|
||||
Goarm: []string{
|
||||
"6",
|
||||
"7",
|
||||
},
|
||||
Ignore: []config.IgnoredBuild{
|
||||
{
|
||||
Goos: "darwin",
|
||||
Goarch: "386",
|
||||
}, {
|
||||
Goos: "linux",
|
||||
Goarch: "arm",
|
||||
Goarm: "7",
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -52,7 +47,7 @@ func TestAllBuildTargets(t *testing.T) {
|
||||
{"freebsd", "amd64", ""},
|
||||
{"freebsd", "arm", "6"},
|
||||
{"freebsd", "arm", "7"},
|
||||
}, buildTargets(ctx))
|
||||
}, buildTargets(build))
|
||||
}
|
||||
|
||||
func TestValidGoosGoarchCombos(t *testing.T) {
|
||||
|
@ -26,7 +26,7 @@ func (Pipe) Run(ctx *context.Context) (err error) {
|
||||
file, err := os.OpenFile(
|
||||
filepath.Join(
|
||||
ctx.Config.Dist,
|
||||
fmt.Sprintf("%v_checksums.txt", ctx.Config.Build.Binary),
|
||||
fmt.Sprintf("%v_checksums.txt", ctx.Config.ProjectName),
|
||||
),
|
||||
os.O_APPEND|os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
|
||||
0644,
|
||||
|
@ -24,10 +24,8 @@ func TestPipe(t *testing.T) {
|
||||
assert.NoError(ioutil.WriteFile(file, []byte("some string"), 0644))
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Dist: folder,
|
||||
Build: config.Build{
|
||||
Binary: binary,
|
||||
},
|
||||
Dist: folder,
|
||||
ProjectName: binary,
|
||||
},
|
||||
}
|
||||
ctx.AddArtifact(file)
|
||||
|
@ -4,7 +4,10 @@ package defaults
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
)
|
||||
|
||||
@ -31,14 +34,44 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
if err := setReleaseDefaults(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if ctx.Config.ProjectName == "" {
|
||||
ctx.Config.ProjectName = ctx.Config.Release.GitHub.Name
|
||||
}
|
||||
setBuildDefaults(ctx)
|
||||
if ctx.Config.Brew.Install == "" {
|
||||
ctx.Config.Brew.Install = fmt.Sprintf(
|
||||
`bin.install "%s"`,
|
||||
ctx.Config.Build.Binary,
|
||||
)
|
||||
var installs []string
|
||||
for _, build := range ctx.Config.Builds {
|
||||
if !isBrewBuild(build) {
|
||||
continue
|
||||
}
|
||||
installs = append(
|
||||
installs,
|
||||
fmt.Sprintf(`bin.install "%s"`, build.Binary),
|
||||
)
|
||||
}
|
||||
ctx.Config.Brew.Install = strings.Join(installs, "\n")
|
||||
}
|
||||
return setArchiveDefaults(ctx)
|
||||
err := setArchiveDefaults(ctx)
|
||||
log.WithField("config", ctx.Config).Debug("defaults set")
|
||||
return err
|
||||
}
|
||||
|
||||
func isBrewBuild(build config.Build) bool {
|
||||
for _, ignore := range build.Ignore {
|
||||
if ignore.Goos == "darwin" && ignore.Goarch == "amd64" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return contains(build.Goos, "darwin") && contains(build.Goarch, "amd64")
|
||||
}
|
||||
|
||||
func contains(ss []string, s string) bool {
|
||||
for _, zs := range ss {
|
||||
if zs == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func setReleaseDefaults(ctx *context.Context) error {
|
||||
@ -54,24 +87,36 @@ func setReleaseDefaults(ctx *context.Context) error {
|
||||
}
|
||||
|
||||
func setBuildDefaults(ctx *context.Context) {
|
||||
if ctx.Config.Build.Binary == "" {
|
||||
ctx.Config.Build.Binary = ctx.Config.Release.GitHub.Name
|
||||
for i, build := range ctx.Config.Builds {
|
||||
ctx.Config.Builds[i] = buildWithDefaults(ctx, build)
|
||||
}
|
||||
if ctx.Config.Build.Main == "" {
|
||||
ctx.Config.Build.Main = "."
|
||||
if len(ctx.Config.Builds) == 0 {
|
||||
ctx.Config.Builds = []config.Build{
|
||||
buildWithDefaults(ctx, ctx.Config.SingleBuild),
|
||||
}
|
||||
}
|
||||
if len(ctx.Config.Build.Goos) == 0 {
|
||||
ctx.Config.Build.Goos = []string{"linux", "darwin"}
|
||||
}
|
||||
|
||||
func buildWithDefaults(ctx *context.Context, build config.Build) config.Build {
|
||||
if build.Binary == "" {
|
||||
build.Binary = ctx.Config.Release.GitHub.Name
|
||||
}
|
||||
if len(ctx.Config.Build.Goarch) == 0 {
|
||||
ctx.Config.Build.Goarch = []string{"amd64", "386"}
|
||||
if build.Main == "" {
|
||||
build.Main = "."
|
||||
}
|
||||
if len(ctx.Config.Build.Goarm) == 0 {
|
||||
ctx.Config.Build.Goarm = []string{"6"}
|
||||
if len(build.Goos) == 0 {
|
||||
build.Goos = []string{"linux", "darwin"}
|
||||
}
|
||||
if ctx.Config.Build.Ldflags == "" {
|
||||
ctx.Config.Build.Ldflags = "-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}"
|
||||
if len(build.Goarch) == 0 {
|
||||
build.Goarch = []string{"amd64", "386"}
|
||||
}
|
||||
if len(build.Goarm) == 0 {
|
||||
build.Goarm = []string{"6"}
|
||||
}
|
||||
if build.Ldflags == "" {
|
||||
build.Ldflags = "-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}"
|
||||
}
|
||||
return build
|
||||
}
|
||||
|
||||
func setArchiveDefaults(ctx *context.Context) error {
|
||||
|
@ -15,33 +15,32 @@ func TestDescription(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFillBasicData(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var assert = assert.New(t)
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{},
|
||||
}
|
||||
|
||||
assert.NoError(Pipe{}.Run(ctx))
|
||||
|
||||
assert.Equal("goreleaser", ctx.Config.Release.GitHub.Owner)
|
||||
assert.Equal("goreleaser", ctx.Config.Release.GitHub.Name)
|
||||
assert.Equal("goreleaser", ctx.Config.Build.Binary)
|
||||
assert.Equal(".", ctx.Config.Build.Main)
|
||||
assert.NotEmpty(ctx.Config.Builds)
|
||||
assert.Equal("goreleaser", ctx.Config.Builds[0].Binary)
|
||||
assert.Equal(".", ctx.Config.Builds[0].Main)
|
||||
assert.Contains(ctx.Config.Builds[0].Goos, "darwin")
|
||||
assert.Contains(ctx.Config.Builds[0].Goos, "linux")
|
||||
assert.Contains(ctx.Config.Builds[0].Goarch, "386")
|
||||
assert.Contains(ctx.Config.Builds[0].Goarch, "amd64")
|
||||
assert.Equal("tar.gz", ctx.Config.Archive.Format)
|
||||
assert.Contains(ctx.Config.Build.Goos, "darwin")
|
||||
assert.Contains(ctx.Config.Build.Goos, "linux")
|
||||
assert.Contains(ctx.Config.Build.Goarch, "386")
|
||||
assert.Contains(ctx.Config.Build.Goarch, "amd64")
|
||||
assert.Contains(ctx.Config.Brew.Install, "bin.install \"goreleaser\"")
|
||||
assert.NotEmpty(
|
||||
ctx.Config.Archive.NameTemplate,
|
||||
ctx.Config.Build.Ldflags,
|
||||
ctx.Config.Builds[0].Ldflags,
|
||||
ctx.Config.Archive.Files,
|
||||
)
|
||||
}
|
||||
|
||||
func TestFillPartial(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
var assert = assert.New(t)
|
||||
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
@ -56,10 +55,36 @@ func TestFillPartial(t *testing.T) {
|
||||
"glob/*",
|
||||
},
|
||||
},
|
||||
Builds: []config.Build{
|
||||
{Binary: "testreleaser"},
|
||||
{Goos: []string{"linux"}},
|
||||
{
|
||||
Binary: "another",
|
||||
Ignore: []config.IgnoredBuild{
|
||||
{Goos: "darwin", Goarch: "amd64"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.NoError(Pipe{}.Run(ctx))
|
||||
assert.Len(ctx.Config.Archive.Files, 1)
|
||||
assert.Equal(`bin.install "testreleaser"`, ctx.Config.Brew.Install)
|
||||
}
|
||||
|
||||
func TestFillSingleBuild(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
SingleBuild: config.Build{
|
||||
Main: "testreleaser",
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.NoError(Pipe{}.Run(ctx))
|
||||
assert.Len(ctx.Config.Builds, 1)
|
||||
assert.Equal(ctx.Config.Builds[0].Binary, "goreleaser")
|
||||
}
|
||||
|
||||
func TestNotAGitRepo(t *testing.T) {
|
||||
|
@ -3,19 +3,17 @@ package fpm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
var goarchToUnix = map[string]string{
|
||||
"386": "i386",
|
||||
"amd64": "x86_64",
|
||||
}
|
||||
|
||||
// ErrNoFPM is shown when fpm cannot be found in $PATH
|
||||
var ErrNoFPM = errors.New("fpm not present in $PATH")
|
||||
|
||||
@ -40,31 +38,38 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
|
||||
var g errgroup.Group
|
||||
for _, format := range ctx.Config.FPM.Formats {
|
||||
format := format
|
||||
for _, goarch := range ctx.Config.Build.Goarch {
|
||||
if ctx.Archives["linux"+goarch] == "" {
|
||||
for key, folder := range ctx.Folders {
|
||||
if !strings.Contains(key, "linux") {
|
||||
log.WithField("key", key).Debug("skipped non-linux builds for fpm")
|
||||
continue
|
||||
}
|
||||
archive := ctx.Archives["linux"+goarch]
|
||||
arch := goarchToUnix[goarch]
|
||||
folder := folder
|
||||
format := format
|
||||
arch := archFor(key)
|
||||
g.Go(func() error {
|
||||
return create(ctx, format, archive, arch)
|
||||
return create(ctx, format, folder, arch)
|
||||
})
|
||||
}
|
||||
}
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
func create(ctx *context.Context, format, archive, arch string) error {
|
||||
var path = filepath.Join(ctx.Config.Dist, archive)
|
||||
func archFor(key string) string {
|
||||
if strings.Contains(key, "386") {
|
||||
return "i386"
|
||||
}
|
||||
return "x86_64"
|
||||
}
|
||||
|
||||
func create(ctx *context.Context, format, folder, arch string) error {
|
||||
var path = filepath.Join(ctx.Config.Dist, folder)
|
||||
var file = path + "." + format
|
||||
var name = ctx.Config.Build.Binary
|
||||
log.WithField("file", file).Info("Creating")
|
||||
log.WithField("file", file).Info("creating fpm archive")
|
||||
|
||||
var options = []string{
|
||||
"--input-type", "dir",
|
||||
"--output-type", format,
|
||||
"--name", name,
|
||||
"--name", ctx.Config.ProjectName,
|
||||
"--version", ctx.Version,
|
||||
"--architecture", arch,
|
||||
"--chdir", path,
|
||||
@ -94,9 +99,21 @@ func create(ctx *context.Context, format, archive, arch string) error {
|
||||
options = append(options, "--conflicts", conflict)
|
||||
}
|
||||
|
||||
// This basically tells fpm to put the binary in the /usr/local/bin
|
||||
// binary=/usr/local/bin/binary
|
||||
options = append(options, name+"="+filepath.Join("/usr/local/bin", name))
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, file := range files {
|
||||
// XXX: skip non executable files here?
|
||||
// This basically tells fpm to put the binary in the /usr/local/bin
|
||||
// binary=/usr/local/bin/binary
|
||||
log.WithField("file", file.Name()).Debug("passed binary to fpm")
|
||||
options = append(options, fmt.Sprintf(
|
||||
"%s=%s",
|
||||
file.Name(),
|
||||
filepath.Join("/usr/local/bin", file.Name()),
|
||||
))
|
||||
}
|
||||
|
||||
if out, err := exec.Command("fpm", options...).CombinedOutput(); err != nil {
|
||||
return errors.New(string(out))
|
||||
|
@ -33,18 +33,14 @@ func TestRunPipe(t *testing.T) {
|
||||
_, err = os.Create(filepath.Join(dist, "mybin", "mybin"))
|
||||
assert.NoError(err)
|
||||
var ctx = &context.Context{
|
||||
Archives: map[string]string{
|
||||
"linuxamd64": "mybin",
|
||||
Folders: map[string]string{
|
||||
"linuxamd64": "mybin",
|
||||
"linux386": "mybin",
|
||||
"darwinamd64": "anotherbin",
|
||||
},
|
||||
Config: config.Project{
|
||||
Dist: dist,
|
||||
Build: config.Build{
|
||||
Goarch: []string{
|
||||
"amd64",
|
||||
"i386",
|
||||
},
|
||||
Binary: "mybin",
|
||||
},
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
FPM: config.FPM{
|
||||
Formats: []string{"deb"},
|
||||
Dependencies: []string{"make"},
|
||||
@ -85,18 +81,11 @@ func TestCreateFileDoesntExist(t *testing.T) {
|
||||
assert.NoError(os.Mkdir(dist, 0755))
|
||||
assert.NoError(os.Mkdir(filepath.Join(dist, "mybin"), 0755))
|
||||
var ctx = &context.Context{
|
||||
Archives: map[string]string{
|
||||
Folders: map[string]string{
|
||||
"linuxamd64": "mybin",
|
||||
},
|
||||
Config: config.Project{
|
||||
Dist: dist,
|
||||
Build: config.Build{
|
||||
Goarch: []string{
|
||||
"amd64",
|
||||
"i386",
|
||||
},
|
||||
Binary: "mybin",
|
||||
},
|
||||
FPM: config.FPM{
|
||||
Formats: []string{"deb"},
|
||||
},
|
||||
@ -104,3 +93,12 @@ func TestCreateFileDoesntExist(t *testing.T) {
|
||||
}
|
||||
assert.Error(Pipe{}.Run(ctx))
|
||||
}
|
||||
|
||||
func TestCreatePathDoesntExist(t *testing.T) {
|
||||
var assert = assert.New(t)
|
||||
var ctx = &context.Context{}
|
||||
assert.Contains(
|
||||
create(ctx, "tar.gz", "/nope/noooo", "windowsarm64").Error(),
|
||||
"no such file",
|
||||
)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user