mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-01-26 04:22:05 +02:00
refactor: remove fpm in favor of nfpm (#567)
* refactor: remove fpm * refactor: remove fpm * refactor: .travis.yml * chore: more cleanup * chore: fix deploy
This commit is contained in:
parent
2ea883e0c4
commit
76cfa61407
13
.travis.yml
13
.travis.yml
@ -4,13 +4,17 @@ language: go
|
||||
go: '1.10'
|
||||
services:
|
||||
- docker
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- rpm
|
||||
- snapd
|
||||
- liblz4-dev
|
||||
env:
|
||||
- PATH=/snap/bin:$PATH
|
||||
install:
|
||||
- make setup
|
||||
- gem install fpm
|
||||
- npm install -g prettier
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install --yes snapd rpm liblz4-dev
|
||||
- export PATH=/snap/bin:$PATH
|
||||
- sudo snap install snapcraft --classic
|
||||
script:
|
||||
- make ci
|
||||
@ -27,6 +31,7 @@ deploy:
|
||||
local_dir: ./dist/goreleaser.github.io
|
||||
target_branch: master
|
||||
on:
|
||||
tags: true
|
||||
master: true
|
||||
- provider: script
|
||||
skip_cleanup: true
|
||||
|
@ -11,8 +11,7 @@ Prerequisites:
|
||||
|
||||
* `make`
|
||||
* [Go 1.8+](https://golang.org/doc/install)
|
||||
* [fpm](https://fpm.readthedocs.io/en/latest/installing.html)
|
||||
* rpm / rpmbuild
|
||||
* `rpmbuild` (`apt get install rpm`/`brew install rpm`)
|
||||
* [snapcraft](https://snapcraft.io/)
|
||||
* [Docker](https://www.docker.com/)
|
||||
|
||||
|
@ -116,8 +116,8 @@ type Release struct {
|
||||
NameTemplate string `yaml:"name_template,omitempty"`
|
||||
}
|
||||
|
||||
// FPM config
|
||||
type FPM struct {
|
||||
// NFPM config
|
||||
type NFPM struct {
|
||||
NameTemplate string `yaml:"name_template,omitempty"`
|
||||
Replacements map[string]string `yaml:",omitempty"`
|
||||
|
||||
@ -220,8 +220,8 @@ type Project struct {
|
||||
Scoop Scoop `yaml:",omitempty"`
|
||||
Builds []Build `yaml:",omitempty"`
|
||||
Archive Archive `yaml:",omitempty"`
|
||||
FPM FPM `yaml:",omitempty"`
|
||||
NFPM FPM `yaml:",omitempty"`
|
||||
FPM NFPM `yaml:",omitempty"` // deprecated
|
||||
NFPM NFPM `yaml:",omitempty"`
|
||||
Snapcraft Snapcraft `yaml:",omitempty"`
|
||||
Snapshot Snapshot `yaml:",omitempty"`
|
||||
Checksum Checksum `yaml:",omitempty"`
|
||||
|
@ -25,14 +25,14 @@ func TestEmptyRepoNameAndOwner(t *testing.T) {
|
||||
|
||||
func TestLoadReader(t *testing.T) {
|
||||
var conf = `
|
||||
fpm:
|
||||
nfpm:
|
||||
homepage: http://goreleaser.github.io
|
||||
`
|
||||
buf := strings.NewReader(conf)
|
||||
prop, err := LoadReader(buf)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "http://goreleaser.github.io", prop.FPM.Homepage, "yaml did not load correctly")
|
||||
assert.Equal(t, "http://goreleaser.github.io", prop.NFPM.Homepage, "yaml did not load correctly")
|
||||
}
|
||||
|
||||
type errorReader struct{}
|
||||
|
@ -18,7 +18,7 @@ const (
|
||||
UploadableBinary
|
||||
// Binary is a binary (output of a gobuild)
|
||||
Binary
|
||||
// LinuxPackage is a linux package generated by fpm or snapcraft
|
||||
// LinuxPackage is a linux package generated by nfpm or snapcraft
|
||||
LinuxPackage
|
||||
// DockerImage is a docker image
|
||||
DockerImage
|
||||
|
2
main.go
2
main.go
@ -28,7 +28,6 @@ import (
|
||||
"github.com/goreleaser/goreleaser/pipeline/docker"
|
||||
"github.com/goreleaser/goreleaser/pipeline/effectiveconfig"
|
||||
"github.com/goreleaser/goreleaser/pipeline/env"
|
||||
"github.com/goreleaser/goreleaser/pipeline/fpm"
|
||||
"github.com/goreleaser/goreleaser/pipeline/git"
|
||||
"github.com/goreleaser/goreleaser/pipeline/nfpm"
|
||||
"github.com/goreleaser/goreleaser/pipeline/release"
|
||||
@ -55,7 +54,6 @@ var (
|
||||
env.Pipe{}, // load and validate environment variables
|
||||
build.Pipe{}, // build
|
||||
archive.Pipe{}, // archive in tar.gz, zip or binary (which does no archiving at all)
|
||||
fpm.Pipe{}, // archive via fpm (deb, rpm) using fpm
|
||||
nfpm.Pipe{}, // archive via fpm (deb, rpm) using "native" go impl
|
||||
snapcraft.Pipe{}, // archive via snapcraft (snap)
|
||||
checksums.Pipe{}, // checksums of the files
|
||||
|
@ -2,32 +2,8 @@
|
||||
package fpm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/deprecate"
|
||||
"github.com/goreleaser/goreleaser/internal/filenametemplate"
|
||||
"github.com/goreleaser/goreleaser/internal/linux"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
)
|
||||
|
||||
// ErrNoFPM is shown when fpm cannot be found in $PATH
|
||||
var ErrNoFPM = errors.New("fpm not present in $PATH")
|
||||
|
||||
const (
|
||||
defaultNameTemplate = "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||
// path to gnu-tar on macOS when installed with homebrew
|
||||
gnuTarPath = "/usr/local/opt/gnu-tar/libexec/gnubin"
|
||||
)
|
||||
|
||||
// Pipe for fpm packaging
|
||||
@ -39,167 +15,9 @@ func (Pipe) String() string {
|
||||
|
||||
// Default sets the pipe defaults
|
||||
func (Pipe) Default(ctx *context.Context) error {
|
||||
var fpm = &ctx.Config.FPM
|
||||
if fpm.Bindir == "" {
|
||||
fpm.Bindir = "/usr/local/bin"
|
||||
}
|
||||
if fpm.NameTemplate == "" {
|
||||
fpm.NameTemplate = defaultNameTemplate
|
||||
}
|
||||
if len(fpm.Formats) > 0 {
|
||||
if len(ctx.Config.FPM.Formats) > 0 && len(ctx.Config.NFPM.Formats) == 0 {
|
||||
deprecate.Notice("fpm")
|
||||
ctx.Config.NFPM = ctx.Config.FPM
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run the pipe
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
if len(ctx.Config.FPM.Formats) == 0 {
|
||||
return pipeline.Skip("no output formats configured")
|
||||
}
|
||||
_, err := exec.LookPath("fpm")
|
||||
if err != nil {
|
||||
return ErrNoFPM
|
||||
}
|
||||
return doRun(ctx)
|
||||
}
|
||||
|
||||
func doRun(ctx *context.Context) error {
|
||||
var g errgroup.Group
|
||||
sem := make(chan bool, ctx.Parallelism)
|
||||
for _, format := range ctx.Config.FPM.Formats {
|
||||
for platform, artifacts := range ctx.Artifacts.Filter(
|
||||
artifact.And(
|
||||
artifact.ByType(artifact.Binary),
|
||||
artifact.ByGoos("linux"),
|
||||
),
|
||||
).GroupByPlatform() {
|
||||
sem <- true
|
||||
format := format
|
||||
arch := linux.Arch(platform)
|
||||
artifacts := artifacts
|
||||
g.Go(func() error {
|
||||
defer func() {
|
||||
<-sem
|
||||
}()
|
||||
return create(ctx, format, arch, artifacts)
|
||||
})
|
||||
}
|
||||
}
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
func create(ctx *context.Context, format, arch string, binaries []artifact.Artifact) error {
|
||||
name, err := filenametemplate.Apply(
|
||||
ctx.Config.FPM.NameTemplate,
|
||||
filenametemplate.NewFields(ctx, ctx.Config.FPM.Replacements, binaries...),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var path = filepath.Join(ctx.Config.Dist, name)
|
||||
var file = path + "." + format
|
||||
var log = log.WithField("format", format).WithField("arch", arch)
|
||||
dir, err := ioutil.TempDir("", "fpm")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.WithField("file", file).WithField("workdir", dir).Info("creating fpm archive")
|
||||
var options = basicOptions(ctx, dir, format, arch, file)
|
||||
|
||||
for _, binary := range binaries {
|
||||
// This basically tells fpm to put the binary in the bindir, e.g. /usr/local/bin
|
||||
// binary=/usr/local/bin/binary
|
||||
log.WithField("path", binary.Path).
|
||||
WithField("name", binary.Name).
|
||||
Debug("added binary to fpm package")
|
||||
options = append(options, fmt.Sprintf(
|
||||
"%s=%s",
|
||||
binary.Path,
|
||||
filepath.Join(ctx.Config.FPM.Bindir, binary.Name),
|
||||
))
|
||||
}
|
||||
|
||||
for src, dest := range ctx.Config.FPM.Files {
|
||||
log.WithField("src", src).
|
||||
WithField("dest", dest).
|
||||
Debug("added an extra file to the fpm package")
|
||||
options = append(options, fmt.Sprintf(
|
||||
"%s=%s",
|
||||
src,
|
||||
dest,
|
||||
))
|
||||
}
|
||||
|
||||
log.WithField("args", options).Debug("creating fpm package")
|
||||
if out, err := cmd(ctx, options).CombinedOutput(); err != nil {
|
||||
return errors.Wrap(err, string(out))
|
||||
}
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.LinuxPackage,
|
||||
Name: name + "." + format,
|
||||
Path: file,
|
||||
Goos: binaries[0].Goos,
|
||||
Goarch: binaries[0].Goarch,
|
||||
Goarm: binaries[0].Goarm,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func cmd(ctx *context.Context, options []string) *exec.Cmd {
|
||||
/* #nosec */
|
||||
var cmd = exec.CommandContext(ctx, "fpm", options...)
|
||||
cmd.Env = []string{fmt.Sprintf("PATH=%s:%s", gnuTarPath, os.Getenv("PATH"))}
|
||||
for _, env := range os.Environ() {
|
||||
if strings.HasPrefix(env, "PATH=") {
|
||||
continue
|
||||
}
|
||||
cmd.Env = append(cmd.Env, env)
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func basicOptions(ctx *context.Context, workdir, format, arch, file string) []string {
|
||||
var options = []string{
|
||||
"--input-type", "dir",
|
||||
"--output-type", format,
|
||||
"--name", ctx.Config.ProjectName,
|
||||
"--version", ctx.Version,
|
||||
"--architecture", arch,
|
||||
"--package", file,
|
||||
"--force",
|
||||
"--workdir", workdir,
|
||||
}
|
||||
|
||||
if ctx.Debug {
|
||||
options = append(options, "--debug")
|
||||
}
|
||||
|
||||
if ctx.Config.FPM.Vendor != "" {
|
||||
options = append(options, "--vendor", ctx.Config.FPM.Vendor)
|
||||
}
|
||||
if ctx.Config.FPM.Homepage != "" {
|
||||
options = append(options, "--url", ctx.Config.FPM.Homepage)
|
||||
}
|
||||
if ctx.Config.FPM.Maintainer != "" {
|
||||
options = append(options, "--maintainer", ctx.Config.FPM.Maintainer)
|
||||
}
|
||||
if ctx.Config.FPM.Description != "" {
|
||||
options = append(options, "--description", ctx.Config.FPM.Description)
|
||||
}
|
||||
if ctx.Config.FPM.License != "" {
|
||||
options = append(options, "--license", ctx.Config.FPM.License)
|
||||
}
|
||||
for _, dep := range ctx.Config.FPM.Dependencies {
|
||||
options = append(options, "--depends", dep)
|
||||
}
|
||||
for _, conflict := range ctx.Config.FPM.Conflicts {
|
||||
options = append(options, "--conflicts", conflict)
|
||||
}
|
||||
|
||||
// FPM requires --rpm-os=linux if your rpm target is linux
|
||||
if format == "rpm" {
|
||||
options = append(options, "--rpm-os", "linux")
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
@ -1,16 +1,10 @@
|
||||
package fpm
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/testlib"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -18,145 +12,26 @@ func TestDescription(t *testing.T) {
|
||||
assert.NotEmpty(t, Pipe{}.String())
|
||||
}
|
||||
|
||||
func TestRunPipeNoFormats(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Config: config.Project{},
|
||||
Parallelism: runtime.NumCPU(),
|
||||
}
|
||||
testlib.AssertSkipped(t, Pipe{}.Run(ctx))
|
||||
}
|
||||
|
||||
func TestRunPipe(t *testing.T) {
|
||||
folder, err := ioutil.TempDir("", "archivetest")
|
||||
assert.NoError(t, err)
|
||||
var dist = filepath.Join(folder, "dist")
|
||||
assert.NoError(t, os.Mkdir(dist, 0755))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
|
||||
var binPath = filepath.Join(dist, "mybin", "mybin")
|
||||
_, err = os.Create(binPath)
|
||||
assert.NoError(t, err)
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
FPM: config.FPM{
|
||||
NameTemplate: defaultNameTemplate,
|
||||
Formats: []string{"deb", "rpm"},
|
||||
Dependencies: []string{"make"},
|
||||
Conflicts: []string{"git"},
|
||||
Description: "Some description",
|
||||
License: "MIT",
|
||||
Maintainer: "me@me",
|
||||
Vendor: "asdf",
|
||||
Homepage: "https://goreleaser.github.io",
|
||||
},
|
||||
})
|
||||
ctx.Version = "1.0.0"
|
||||
for _, goos := range []string{"linux", "darwin"} {
|
||||
for _, goarch := range []string{"amd64", "386"} {
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: binPath,
|
||||
Goarch: goarch,
|
||||
Goos: goos,
|
||||
Type: artifact.Binary,
|
||||
})
|
||||
}
|
||||
}
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
}
|
||||
|
||||
func TestNoFPMInPath(t *testing.T) {
|
||||
var path = os.Getenv("PATH")
|
||||
defer func() {
|
||||
assert.NoError(t, os.Setenv("PATH", path))
|
||||
}()
|
||||
assert.NoError(t, os.Setenv("PATH", ""))
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Parallelism: runtime.NumCPU(),
|
||||
Config: config.Project{
|
||||
FPM: config.FPM{
|
||||
Formats: []string{"deb", "rpm"},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.EqualError(t, Pipe{}.Run(ctx), ErrNoFPM.Error())
|
||||
}
|
||||
|
||||
func TestInvalidNameTemplate(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Parallelism: runtime.NumCPU(),
|
||||
Artifacts: artifact.New(),
|
||||
Config: config.Project{
|
||||
FPM: config.FPM{
|
||||
NameTemplate: "{{.Foo}",
|
||||
Formats: []string{"deb"},
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Type: artifact.Binary,
|
||||
})
|
||||
assert.Contains(t, Pipe{}.Run(ctx).Error(), `template: {{.Foo}:1: unexpected "}" in operand`)
|
||||
}
|
||||
|
||||
func TestCreateFileDoesntExist(t *testing.T) {
|
||||
folder, err := ioutil.TempDir("", "archivetest")
|
||||
assert.NoError(t, err)
|
||||
var dist = filepath.Join(folder, "dist")
|
||||
assert.NoError(t, os.Mkdir(dist, 0755))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
|
||||
var ctx = context.New(config.Project{
|
||||
Dist: dist,
|
||||
FPM: config.FPM{
|
||||
Formats: []string{"deb", "rpm"},
|
||||
Files: map[string]string{
|
||||
"testdata/testfile.txt": "/var/lib/test/testfile.txt",
|
||||
},
|
||||
},
|
||||
})
|
||||
ctx.Version = "1.0.0"
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: filepath.Join(dist, "mybin", "mybin"),
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Type: artifact.Binary,
|
||||
})
|
||||
assert.Contains(t, Pipe{}.Run(ctx).Error(), `dist/mybin/mybin', does it exist?`)
|
||||
}
|
||||
|
||||
func TestCmd(t *testing.T) {
|
||||
cmd := cmd(context.New(config.Project{}), []string{"--help"})
|
||||
assert.NotEmpty(t, cmd.Env)
|
||||
assert.Contains(t, cmd.Env[0], gnuTarPath)
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
FPM: config.FPM{},
|
||||
FPM: config.NFPM{
|
||||
Formats: []string{"deb"},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.Equal(t, "/usr/local/bin", ctx.Config.FPM.Bindir)
|
||||
assert.Equal(t, defaultNameTemplate, ctx.Config.FPM.NameTemplate)
|
||||
assert.Equal(t, ctx.Config.FPM, ctx.Config.NFPM)
|
||||
}
|
||||
|
||||
func TestDefaultSet(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
FPM: config.FPM{
|
||||
Bindir: "/bin",
|
||||
NameTemplate: "foo",
|
||||
NFPM: config.NFPM{
|
||||
Formats: []string{"deb"},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
assert.Equal(t, "/bin", ctx.Config.FPM.Bindir)
|
||||
assert.Equal(t, "foo", ctx.Config.FPM.NameTemplate)
|
||||
assert.Equal(t, config.NFPM{}, ctx.Config.FPM)
|
||||
}
|
||||
|
1
pipeline/fpm/testdata/testfile.txt
vendored
1
pipeline/fpm/testdata/testfile.txt
vendored
@ -1 +0,0 @@
|
||||
this is a test file
|
@ -31,7 +31,7 @@ func TestRunPipeNoFormats(t *testing.T) {
|
||||
|
||||
func TestRunPipeInvalidFormat(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
NFPM: config.FPM{
|
||||
NFPM: config.NFPM{
|
||||
Bindir: "/usr/bin",
|
||||
NameTemplate: defaultNameTemplate,
|
||||
Formats: []string{"nope"},
|
||||
@ -64,7 +64,7 @@ func TestRunPipe(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
NFPM: config.FPM{
|
||||
NFPM: config.NFPM{
|
||||
Bindir: "/usr/bin",
|
||||
NameTemplate: defaultNameTemplate,
|
||||
Formats: []string{"deb", "rpm"},
|
||||
@ -106,7 +106,7 @@ func TestInvalidNameTemplate(t *testing.T) {
|
||||
Parallelism: runtime.NumCPU(),
|
||||
Artifacts: artifact.New(),
|
||||
Config: config.Project{
|
||||
NFPM: config.FPM{
|
||||
NFPM: config.NFPM{
|
||||
NameTemplate: "{{.Foo}",
|
||||
Formats: []string{"deb"},
|
||||
},
|
||||
@ -129,7 +129,7 @@ func TestCreateFileDoesntExist(t *testing.T) {
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
|
||||
var ctx = context.New(config.Project{
|
||||
Dist: dist,
|
||||
NFPM: config.FPM{
|
||||
NFPM: config.NFPM{
|
||||
Formats: []string{"deb", "rpm"},
|
||||
Files: map[string]string{
|
||||
"testdata/testfile.txt": "/var/lib/test/testfile.txt",
|
||||
@ -150,7 +150,7 @@ func TestCreateFileDoesntExist(t *testing.T) {
|
||||
func TestDefault(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
NFPM: config.FPM{},
|
||||
NFPM: config.NFPM{},
|
||||
},
|
||||
}
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
@ -161,7 +161,7 @@ func TestDefault(t *testing.T) {
|
||||
func TestDefaultSet(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
NFPM: config.FPM{
|
||||
NFPM: config.NFPM{
|
||||
Bindir: "/bin",
|
||||
NameTemplate: "foo",
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user