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

Merge pull request #301 from goreleaser/298

WIP: fixing fpm on multiple naked binaries releases
This commit is contained in:
Carlos Alexandro Becker 2017-07-15 12:45:59 -03:00 committed by GitHub
commit 307d1a346b
10 changed files with 129 additions and 153 deletions

View File

@ -21,13 +21,18 @@ type GitInfo struct {
Commit string
}
// Binary with pretty name and path
type Binary struct {
Name, Path string
}
// Context carries along some data through the pipes
type Context struct {
ctx.Context
Config config.Project
Token string
Git GitInfo
Folders map[string]string
Binaries map[string]map[string][]Binary
Artifacts []string
ReleaseNotes string
Version string
@ -38,7 +43,7 @@ type Context struct {
}
var artifactsLock sync.Mutex
var foldersLock sync.Mutex
var binariesLock sync.Mutex
// AddArtifact adds a file to upload list
func (ctx *Context) AddArtifact(file string) {
@ -49,12 +54,28 @@ func (ctx *Context) AddArtifact(file string) {
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")
// AddBinary adds a built binary to the current context
func (ctx *Context) AddBinary(platform, folder, name, path string) {
binariesLock.Lock()
defer binariesLock.Unlock()
if ctx.Binaries == nil {
ctx.Binaries = map[string]map[string][]Binary{}
}
if ctx.Binaries[platform] == nil {
ctx.Binaries[platform] = map[string][]Binary{}
}
ctx.Binaries[platform][folder] = append(
ctx.Binaries[platform][folder],
Binary{
Name: name,
Path: path,
},
)
log.WithField("platform", platform).
WithField("folder", folder).
WithField("name", name).
WithField("path", path).
Info("new binary")
}
// New context
@ -62,6 +83,5 @@ func New(config config.Project) *Context {
return &Context{
Context: ctx.Background(),
Config: config,
Folders: map[string]string{},
}
}

View File

@ -32,13 +32,13 @@ func TestMultipleArtifactAdds(t *testing.T) {
assert.Contains(ctx.Artifacts, "a", "b", "c", "d")
}
func TestMultipleFolderAdds(t *testing.T) {
func TestMultipleBinaryAdds(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",
"a": "folder/a",
"b": "folder/b",
"c": "folder/c",
"d": "folder/d",
}
var ctx = New(config.Project{
Dist: "dist",
@ -48,10 +48,11 @@ func TestMultipleFolderAdds(t *testing.T) {
f := f
k := k
g.Go(func() error {
ctx.AddFolder(k, f)
ctx.AddBinary("linuxamd64", k, k, f)
return nil
})
}
assert.NoError(g.Wait())
assert.Len(ctx.Folders, len(list))
assert.Len(ctx.Binaries["linuxamd64"], len(list))
assert.Len(ctx.Binaries, 1)
}

View File

@ -4,7 +4,6 @@
package archive
import (
"io/ioutil"
"os"
"path/filepath"
@ -27,65 +26,56 @@ func (Pipe) Description() string {
// Run the pipe
func (Pipe) Run(ctx *context.Context) error {
var g errgroup.Group
for platform, folder := range ctx.Folders {
folder := folder
for platform, binaries := range ctx.Binaries {
platform := platform
binaries := binaries
g.Go(func() error {
if ctx.Config.Archive.Format == "binary" {
return skip(ctx, platform, folder)
return skip(ctx, platform, binaries)
}
return create(ctx, platform, folder)
return create(ctx, platform, binaries)
})
}
return g.Wait()
}
func create(ctx *context.Context, platform, name string) error {
var folder = filepath.Join(ctx.Config.Dist, name)
var format = archiveformat.For(ctx, platform)
file, err := os.Create(folder + "." + format)
if err != nil {
return err
}
log.WithField("archive", file.Name()).Info("creating")
defer func() { _ = file.Close() }()
var archive = archive.New(file)
defer func() { _ = archive.Close() }()
func create(ctx *context.Context, platform string, groups map[string][]context.Binary) error {
for folder, binaries := range groups {
var format = archiveformat.For(ctx, platform)
file, err := os.Create(filepath.Join(ctx.Config.Dist, folder+"."+format))
if err != nil {
return err
}
defer func() { _ = file.Close() }()
log.WithField("archive", file.Name()).Info("creating")
var archive = archive.New(file)
defer func() { _ = archive.Close() }()
files, err := findFiles(ctx)
if err != nil {
return err
}
for _, f := range files {
if err = archive.Add(f, f); err != nil {
files, err := findFiles(ctx)
if err != nil {
return err
}
}
var basepath = filepath.Join(ctx.Config.Dist, name)
binaries, err := ioutil.ReadDir(basepath)
if err != nil {
return err
}
for _, binary := range binaries {
var path = filepath.Join(basepath, binary.Name())
if err := archive.Add(binary.Name(), path); err != nil {
return err
for _, f := range files {
if err = archive.Add(f, f); err != nil {
return err
}
}
for _, binary := range binaries {
if err := archive.Add(binary.Name, binary.Path); err != nil {
return err
}
}
ctx.AddArtifact(file.Name())
}
ctx.AddArtifact(file.Name())
return nil
}
func skip(ctx *context.Context, platform, name string) error {
var path = filepath.Join(ctx.Config.Dist, name)
binaries, err := ioutil.ReadDir(path)
if err != nil {
return err
}
log.WithField("platform", platform).Debugf("found %v binaries", len(binaries))
for _, binary := range binaries {
log.WithField("binary", binary.Name()).Info("skip archiving")
ctx.AddArtifact(filepath.Join(path+"/", binary.Name()))
func skip(ctx *context.Context, platform string, groups map[string][]context.Binary) error {
for _, binaries := range groups {
for _, binary := range binaries {
log.WithField("binary", binary.Name).Info("skip archiving")
ctx.AddArtifact(binary.Path)
}
}
return nil
}

View File

@ -36,10 +36,6 @@ func TestRunPipe(t *testing.T) {
_, err = os.Create(filepath.Join(folder, "README.md"))
assert.NoError(err)
var ctx = &context.Context{
Folders: map[string]string{
"darwinamd64": "mybin_darwin_amd64",
"windowsamd64": "mybin_windows_amd64",
},
Config: config.Project{
Dist: dist,
Archive: config.Archive{
@ -55,6 +51,8 @@ func TestRunPipe(t *testing.T) {
},
},
}
ctx.AddBinary("darwinamd64", "mybin_darwin_amd64", "mybin", filepath.Join(dist, "mybin_darwin_amd64", "mybin"))
ctx.AddBinary("windowsamd64", "mybin_windows_amd64", "mybin.exe", filepath.Join(dist, "mybin_windows_amd64", "mybin.exe"))
for _, format := range []string{"tar.gz", "zip"} {
t.Run("Archive format "+format, func(t *testing.T) {
ctx.Config.Archive.Format = format
@ -84,10 +82,6 @@ func TestRunPipeBinary(t *testing.T) {
_, err = os.Create(filepath.Join(folder, "README.md"))
assert.NoError(err)
var ctx = &context.Context{
Folders: map[string]string{
"darwinamd64": "mybin_darwin",
"windowsamd64": "mybin_win",
},
Config: config.Project{
Dist: dist,
Builds: []config.Build{
@ -98,6 +92,8 @@ func TestRunPipeBinary(t *testing.T) {
},
},
}
ctx.AddBinary("darwinamd64", "mybin_darwin", "mybin", filepath.Join(dist, "mybin_darwin", "mybin"))
ctx.AddBinary("windowsamd64", "mybin_win", "mybin.exe", filepath.Join(dist, "mybin_win", "mybin.exe"))
assert.NoError(Pipe{}.Run(ctx))
assert.Contains(ctx.Artifacts, "mybin_darwin/mybin")
assert.Contains(ctx.Artifacts, "mybin_win/mybin.exe")
@ -107,9 +103,6 @@ func TestRunPipeBinary(t *testing.T) {
func TestRunPipeDistRemoved(t *testing.T) {
var assert = assert.New(t)
var ctx = &context.Context{
Folders: map[string]string{
"darwinamd64": "whatever",
},
Config: config.Project{
Dist: "/path/nope",
Archive: config.Archive{
@ -117,15 +110,13 @@ func TestRunPipeDistRemoved(t *testing.T) {
},
},
}
ctx.AddBinary("windowsamd64", "nope", "no", "blah")
assert.Error(Pipe{}.Run(ctx))
}
func TestRunPipeInvalidGlob(t *testing.T) {
var assert = assert.New(t)
var ctx = &context.Context{
Folders: map[string]string{
"windowsamd64": "whatever",
},
Config: config.Project{
Dist: "/tmp",
Archive: config.Archive{
@ -135,6 +126,7 @@ func TestRunPipeInvalidGlob(t *testing.T) {
},
},
}
ctx.AddBinary("windowsamd64", "whatever", "foo", "bar")
assert.Error(Pipe{}.Run(ctx))
}
@ -151,9 +143,6 @@ func TestRunPipeGlobFailsToAdd(t *testing.T) {
assert.NoError(os.MkdirAll(filepath.Join(folder, "folder", "another"), 0755))
var ctx = &context.Context{
Folders: map[string]string{
"windows386": "mybin",
},
Config: config.Project{
Dist: folder,
Archive: config.Archive{
@ -163,5 +152,6 @@ func TestRunPipeGlobFailsToAdd(t *testing.T) {
},
},
}
ctx.AddBinary("windows386", "mybin", "mybin", "dist/mybin")
assert.Error(Pipe{}.Run(ctx))
}

View File

@ -111,19 +111,28 @@ func doRun(ctx *context.Context, client client.Client) error {
log.Info("skipped because archive format is binary")
return nil
}
var group = ctx.Binaries["darwinamd64"]
if group == nil {
return ErrNoDarwin64Build
}
var folder string
for f := range group {
folder = f
break
}
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")
content, err := buildFormula(ctx, client)
content, err := buildFormula(ctx, client, folder)
if err != nil {
return err
}
return client.CreateFile(ctx, content, path)
}
func buildFormula(ctx *context.Context, client client.Client) (bytes.Buffer, error) {
data, err := dataFor(ctx, client)
func buildFormula(ctx *context.Context, client client.Client, folder string) (bytes.Buffer, error) {
data, err := dataFor(ctx, client, folder)
if err != nil {
return bytes.Buffer{}, err
}
@ -140,11 +149,7 @@ func doBuildFormula(data templateData) (bytes.Buffer, error) {
return out, err
}
func dataFor(ctx *context.Context, client client.Client) (result templateData, err error) {
var folder = ctx.Folders[platform]
if folder == "" {
return result, ErrNoDarwin64Build
}
func dataFor(ctx *context.Context, client client.Client, folder string) (result templateData, err error) {
var file = folder + "." + archiveformat.For(ctx, platform)
sum, err := checksum.SHA256(filepath.Join(ctx.Config.Dist, file))
if err != nil {

View File

@ -101,16 +101,15 @@ func TestRunPipe(t *testing.T) {
},
},
},
Folders: map[string]string{
"darwinamd64": "bin",
},
Publish: true,
}
var path = filepath.Join(folder, "bin.tar.gz")
ctx.AddBinary("darwinamd64", "bin", "bin", path)
client := &DummyClient{}
assert.Error(doRun(ctx, client))
assert.False(client.CreatedFile)
_, err = os.Create(filepath.Join(folder, "bin.tar.gz"))
_, err = os.Create(path)
assert.NoError(err)
assert.NoError(doRun(ctx, client))
assert.True(client.CreatedFile)
@ -120,7 +119,8 @@ func TestRunPipeFormatOverride(t *testing.T) {
assert := assert.New(t)
folder, err := ioutil.TempDir("", "goreleasertest")
assert.NoError(err)
_, err = os.Create(filepath.Join(folder, "bin.zip"))
var path = filepath.Join(folder, "bin.zip")
_, err = os.Create(path)
assert.NoError(err)
var ctx = &context.Context{
Config: config.Project{
@ -141,11 +141,9 @@ func TestRunPipeFormatOverride(t *testing.T) {
},
},
},
Folders: map[string]string{
"darwinamd64": "bin",
},
Publish: true,
}
ctx.AddBinary("darwinamd64", "bin", "bin", path)
client := &DummyClient{}
assert.NoError(doRun(ctx, client))
assert.True(client.CreatedFile)
@ -199,10 +197,8 @@ func TestRunPipeBinaryRelease(t *testing.T) {
},
},
},
Folders: map[string]string{
"darwinamd64": "bin",
},
}
ctx.AddBinary("darwinamd64", "foo", "bar", "baz")
client := &DummyClient{}
assert.NoError(doRun(ctx, client))
assert.False(client.CreatedFile)

View File

@ -74,8 +74,8 @@ func doBuild(ctx *context.Context, build config.Build, target buildtarget.Target
if err != nil {
return err
}
ctx.AddFolder(target.String(), folder)
var binaryName = build.Binary + ext.For(target)
var prettyName = binaryName
if ctx.Config.Archive.Format == "binary" {
binaryName, err = name.ForBuild(ctx, build, target)
if err != nil {
@ -84,6 +84,7 @@ func doBuild(ctx *context.Context, build config.Build, target buildtarget.Target
binaryName = binaryName + ext.For(target)
}
var binary = filepath.Join(ctx.Config.Dist, folder, binaryName)
ctx.AddBinary(target.String(), folder, prettyName, binary)
log.WithField("binary", binary).Info("building")
cmd := []string{"go", "build"}
if build.Flags != "" {

View File

@ -39,8 +39,7 @@ func TestBuild(t *testing.T) {
},
}
var ctx = &context.Context{
Config: config,
Folders: map[string]string{},
Config: config,
}
assert.NoError(doBuild(ctx, ctx.Config.Builds[0], buildtarget.Runtime))
}
@ -73,8 +72,7 @@ func TestRunFullPipe(t *testing.T) {
},
}
var ctx = &context.Context{
Config: config,
Folders: map[string]string{},
Config: config,
}
assert.NoError(Pipe{}.Run(ctx))
assert.True(exists(binary), binary)
@ -107,8 +105,7 @@ func TestRunPipeFormatBinary(t *testing.T) {
},
}
var ctx = &context.Context{
Config: config,
Folders: map[string]string{},
Config: config,
}
assert.NoError(Pipe{}.Run(ctx))
assert.True(exists(binary))
@ -140,8 +137,7 @@ func TestRunPipeArmBuilds(t *testing.T) {
},
}
var ctx = &context.Context{
Config: config,
Folders: map[string]string{},
Config: config,
}
assert.NoError(Pipe{}.Run(ctx))
assert.True(exists(binary), binary)
@ -163,8 +159,7 @@ func TestBuildFailed(t *testing.T) {
},
}
var ctx = &context.Context{
Config: config,
Folders: map[string]string{},
Config: config,
}
assert.Error(Pipe{}.Run(ctx))
}
@ -185,8 +180,7 @@ func TestRunPipeWithInvalidOS(t *testing.T) {
},
}
var ctx = &context.Context{
Config: config,
Folders: map[string]string{},
Config: config,
}
assert.NoError(Pipe{}.Run(ctx))
}
@ -222,7 +216,6 @@ func TestRunInvalidNametemplate(t *testing.T) {
func TestRunInvalidLdflags(t *testing.T) {
var assert = assert.New(t)
var ctx = &context.Context{
Folders: map[string]string{},
Config: config.Project{
Builds: []config.Build{
{
@ -258,8 +251,7 @@ func TestRunPipeFailingHooks(t *testing.T) {
},
}
var ctx = &context.Context{
Config: config,
Folders: map[string]string{},
Config: config,
}
t.Run("pre-hook", func(t *testing.T) {
ctx.Config.Builds[0].Hooks.Pre = "exit 1"

View File

@ -4,7 +4,6 @@ package fpm
import (
"errors"
"fmt"
"io/ioutil"
"os/exec"
"path/filepath"
"strings"
@ -31,10 +30,6 @@ func (Pipe) Run(ctx *context.Context) error {
log.Info("no output formats configured, skipping")
return nil
}
if ctx.Config.Archive.Format == "binary" {
log.Info("skipped because archive format is binary")
return nil
}
_, err := exec.LookPath("fpm")
if err != nil {
return ErrNoFPM
@ -42,17 +37,18 @@ func (Pipe) Run(ctx *context.Context) error {
var g errgroup.Group
for _, format := range ctx.Config.FPM.Formats {
for key, folder := range ctx.Folders {
if !strings.Contains(key, "linux") {
log.WithField("key", key).Debug("skipped non-linux builds for fpm")
for platform, groups := range ctx.Binaries {
if !strings.Contains(platform, "linux") {
log.WithField("platform", platform).Debug("skipped non-linux builds for fpm")
continue
}
folder := folder
format := format
arch := archFor(key)
g.Go(func() error {
return create(ctx, format, folder, arch)
})
arch := archFor(platform)
for folder, binaries := range groups {
g.Go(func() error {
return create(ctx, format, folder, arch, binaries)
})
}
}
}
return g.Wait()
@ -65,7 +61,7 @@ func archFor(key string) string {
return "x86_64"
}
func create(ctx *context.Context, format, folder, arch string) error {
func create(ctx *context.Context, format, folder, arch string, binaries []context.Binary) error {
var path = filepath.Join(ctx.Config.Dist, folder)
var file = path + "." + format
log.WithField("file", file).Info("creating fpm archive")
@ -76,7 +72,7 @@ func create(ctx *context.Context, format, folder, arch string) error {
"--name", ctx.Config.ProjectName,
"--version", ctx.Version,
"--architecture", arch,
"--chdir", path,
// "--chdir", path,
"--package", file,
"--force",
}
@ -103,19 +99,16 @@ func create(ctx *context.Context, format, folder, arch string) error {
options = append(options, "--conflicts", conflict)
}
files, err := ioutil.ReadDir(path)
if err != nil {
return err
}
for _, file := range files {
// XXX: skip non executable files here?
for _, binary := range binaries {
// 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")
log.WithField("path", binary.Path).
WithField("name", binary.Name).
Info("passed binary to fpm")
options = append(options, fmt.Sprintf(
"%s=%s",
file.Name(),
filepath.Join("/usr/local/bin", file.Name()),
binary.Path,
filepath.Join("/usr/local/bin", binary.Name),
))
}

View File

@ -45,14 +45,10 @@ 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"))
var binPath = filepath.Join(dist, "mybin", "mybin")
_, err = os.Create(binPath)
assert.NoError(err)
var ctx = &context.Context{
Folders: map[string]string{
"linuxamd64": "mybin",
"linux386": "mybin",
"darwinamd64": "anotherbin",
},
Config: config.Project{
ProjectName: "mybin",
Dist: dist,
@ -68,6 +64,9 @@ func TestRunPipe(t *testing.T) {
},
},
}
for _, plat := range []string{"linuxamd64", "linux386", "darwinamd64"} {
ctx.AddBinary(plat, "mybin", "mybin", binPath)
}
assert.NoError(Pipe{}.Run(ctx))
}
@ -96,9 +95,6 @@ func TestCreateFileDoesntExist(t *testing.T) {
assert.NoError(os.Mkdir(dist, 0755))
assert.NoError(os.Mkdir(filepath.Join(dist, "mybin"), 0755))
var ctx = &context.Context{
Folders: map[string]string{
"linuxamd64": "mybin",
},
Config: config.Project{
Dist: dist,
FPM: config.FPM{
@ -106,14 +102,6 @@ func TestCreateFileDoesntExist(t *testing.T) {
},
},
}
ctx.AddBinary("linuxamd64", "mybin", "mybin", filepath.Join(dist, "mybin", "mybin"))
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",
)
}