1
0
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:
Carlos Alexandro Becker 2018-02-26 18:49:58 -03:00 committed by GitHub
parent 2ea883e0c4
commit 76cfa61407
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 32 additions and 338 deletions

View File

@ -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

View File

@ -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/)

View File

@ -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"`

View File

@ -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{}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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)
}

View File

@ -1 +0,0 @@
this is a test file

View 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",
},