mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-19 20:57:53 +02:00
commit
aaab7e1732
4
Makefile
4
Makefile
@ -4,6 +4,7 @@ TEST_OPTIONS?=
|
||||
|
||||
# Install all the build and lint dependencies
|
||||
setup:
|
||||
go get -u golang.org/x/tools/cmd/stringer
|
||||
go get -u github.com/alecthomas/gometalinter
|
||||
go get -u github.com/golang/dep/cmd/dep
|
||||
go get -u github.com/pierrre/gotestcover
|
||||
@ -36,11 +37,12 @@ lint:
|
||||
.PHONY: lint
|
||||
|
||||
# Run all the tests and code checks
|
||||
ci: test lint
|
||||
ci: build test lint
|
||||
.PHONY: ci
|
||||
|
||||
# Build a beta version of goreleaser
|
||||
build:
|
||||
go generate ./...
|
||||
go build
|
||||
.PHONY: build
|
||||
|
||||
|
@ -7,8 +7,6 @@ import (
|
||||
"hash"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/apex/log"
|
||||
)
|
||||
|
||||
// SHA256 sum of the given file
|
||||
@ -21,11 +19,7 @@ func calculate(hash hash.Hash, path string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer func() {
|
||||
if err := file.Close(); err != nil {
|
||||
log.WithError(err).Errorf("failed to close %s", path)
|
||||
}
|
||||
}()
|
||||
defer file.Close() // nolint: errcheck
|
||||
|
||||
return doCalculate(hash, file)
|
||||
}
|
||||
|
@ -9,12 +9,10 @@ package context
|
||||
import (
|
||||
ctx "context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
)
|
||||
|
||||
// GitInfo includes tags and diffs used in some point
|
||||
@ -23,11 +21,6 @@ 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
|
||||
@ -35,10 +28,7 @@ type Context struct {
|
||||
Env map[string]string
|
||||
Token string
|
||||
Git GitInfo
|
||||
Binaries map[string]map[string][]Binary
|
||||
Artifacts []string
|
||||
Checksums []string
|
||||
Dockers []string
|
||||
Artifacts artifact.Artifacts
|
||||
ReleaseNotes string
|
||||
Version string
|
||||
Validate bool
|
||||
@ -49,63 +39,6 @@ type Context struct {
|
||||
Parallelism int
|
||||
}
|
||||
|
||||
var (
|
||||
artifactsLock sync.Mutex
|
||||
checksumsLock sync.Mutex
|
||||
dockersLock sync.Mutex
|
||||
binariesLock sync.Mutex
|
||||
)
|
||||
|
||||
// AddArtifact adds a file to upload list
|
||||
func (ctx *Context) AddArtifact(file string) {
|
||||
artifactsLock.Lock()
|
||||
defer artifactsLock.Unlock()
|
||||
file = strings.TrimPrefix(file, ctx.Config.Dist+string(filepath.Separator))
|
||||
ctx.Artifacts = append(ctx.Artifacts, file)
|
||||
log.WithField("artifact", file).Info("new release artifact")
|
||||
}
|
||||
|
||||
// AddChecksum adds a checksum file.
|
||||
func (ctx *Context) AddChecksum(file string) {
|
||||
checksumsLock.Lock()
|
||||
defer checksumsLock.Unlock()
|
||||
file = strings.TrimPrefix(file, ctx.Config.Dist+string(filepath.Separator))
|
||||
ctx.Checksums = append(ctx.Checksums, file)
|
||||
log.WithField("checksum", file).Info("new checksum file")
|
||||
}
|
||||
|
||||
// AddDocker adds a docker image to the docker images list
|
||||
func (ctx *Context) AddDocker(image string) {
|
||||
dockersLock.Lock()
|
||||
defer dockersLock.Unlock()
|
||||
ctx.Dockers = append(ctx.Dockers, image)
|
||||
log.WithField("image", image).Info("new docker image")
|
||||
}
|
||||
|
||||
// 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).
|
||||
Debug("new binary")
|
||||
}
|
||||
|
||||
// New context
|
||||
func New(config config.Project) *Context {
|
||||
return &Context{
|
||||
@ -113,6 +46,7 @@ func New(config config.Project) *Context {
|
||||
Config: config,
|
||||
Env: splitEnv(os.Environ()),
|
||||
Parallelism: 4,
|
||||
Artifacts: artifact.New(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,81 +4,11 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"github.com/tj/assert"
|
||||
)
|
||||
|
||||
func TestMultipleAdds(t *testing.T) {
|
||||
var artifacts = []string{
|
||||
"dist/a",
|
||||
"dist/b",
|
||||
"dist/c",
|
||||
"dist/d",
|
||||
}
|
||||
var checksums = []string{
|
||||
"dist/a.sha256",
|
||||
}
|
||||
var dockerfiles = []string{
|
||||
"a/b:1.0.0",
|
||||
"c/d:2.0.0",
|
||||
"e/f:3.0.0",
|
||||
}
|
||||
var ctx = New(config.Project{
|
||||
Dist: "dist",
|
||||
})
|
||||
var g errgroup.Group
|
||||
for _, f := range artifacts {
|
||||
f := f
|
||||
g.Go(func() error {
|
||||
ctx.AddArtifact(f)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
assert.NoError(t, g.Wait())
|
||||
for _, c := range checksums {
|
||||
c := c
|
||||
g.Go(func() error {
|
||||
ctx.AddChecksum(c)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
assert.NoError(t, g.Wait())
|
||||
for _, d := range dockerfiles {
|
||||
d := d
|
||||
g.Go(func() error {
|
||||
ctx.AddDocker(d)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
assert.NoError(t, g.Wait())
|
||||
assert.Len(t, ctx.Artifacts, len(artifacts))
|
||||
assert.Contains(t, ctx.Artifacts, "a", "b", "c", "d")
|
||||
assert.Len(t, ctx.Checksums, len(checksums))
|
||||
assert.Contains(t, ctx.Checksums, "a.sha256")
|
||||
assert.Len(t, ctx.Dockers, len(dockerfiles))
|
||||
assert.Contains(t, ctx.Dockers, "a/b:1.0.0", "c/d:2.0.0", "e/f:3.0.0")
|
||||
}
|
||||
|
||||
func TestMultipleBinaryAdds(t *testing.T) {
|
||||
var list = map[string]string{
|
||||
"a": "folder/a",
|
||||
"b": "folder/b",
|
||||
"c": "folder/c",
|
||||
"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.AddBinary("linuxamd64", k, k, f)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
assert.NoError(t, g.Wait())
|
||||
assert.Len(t, ctx.Binaries["linuxamd64"], len(list))
|
||||
assert.Len(t, ctx.Binaries, 1)
|
||||
func TestNew(t *testing.T) {
|
||||
var ctx = New(config.Project{})
|
||||
assert.NotEmpty(t, ctx.Env)
|
||||
assert.Equal(t, 4, ctx.Parallelism)
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/apex/log/handlers/cli"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
@ -27,7 +29,6 @@ import (
|
||||
"github.com/goreleaser/goreleaser/pipeline/release"
|
||||
"github.com/goreleaser/goreleaser/pipeline/sign"
|
||||
"github.com/goreleaser/goreleaser/pipeline/snapcraft"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -1,5 +1,6 @@
|
||||
// Package archiveformat provides functions to get the format of given package
|
||||
// based on the config
|
||||
// TODO: this can be moved inside the archive pipe package
|
||||
package archiveformat
|
||||
|
||||
import (
|
||||
|
1
internal/artifact/.gitignore
vendored
Normal file
1
internal/artifact/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
type_string.go
|
151
internal/artifact/artifact.go
Normal file
151
internal/artifact/artifact.go
Normal file
@ -0,0 +1,151 @@
|
||||
// Package artifact provides the core artifact storage for goreleaser
|
||||
package artifact
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/apex/log"
|
||||
)
|
||||
|
||||
// Type defines the type of an artifact
|
||||
//go:generate stringer -type=Type
|
||||
type Type int
|
||||
|
||||
const (
|
||||
// UploadableArchive a tar.gz/zip archive to be uploaded
|
||||
UploadableArchive Type = iota
|
||||
// UploadableBinary is a binary file to be uploaded
|
||||
UploadableBinary
|
||||
// Binary is a binary (output of a gobuild)
|
||||
Binary
|
||||
// LinuxPackage is a linux package generated by fpm or snapcraft
|
||||
LinuxPackage
|
||||
// DockerImage is a docker image
|
||||
DockerImage
|
||||
// Checksum is a checksums file
|
||||
Checksum
|
||||
// Signature is a signature file
|
||||
Signature
|
||||
)
|
||||
|
||||
// Artifact represents an artifact and its relevant info
|
||||
type Artifact struct {
|
||||
Name string
|
||||
Path string
|
||||
Goos string
|
||||
Goarch string
|
||||
Goarm string
|
||||
Type Type
|
||||
Extra map[string]string
|
||||
}
|
||||
|
||||
// Artifacts is a list of artifacts
|
||||
type Artifacts struct {
|
||||
items []Artifact
|
||||
lock *sync.Mutex
|
||||
}
|
||||
|
||||
// New return a new list of artifacts
|
||||
func New() Artifacts {
|
||||
return Artifacts{
|
||||
items: []Artifact{},
|
||||
lock: &sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
// List return the actual list of artifacts
|
||||
func (artifacts Artifacts) List() []Artifact {
|
||||
return artifacts.items
|
||||
}
|
||||
|
||||
// GroupByPlatform groups the artifacts by their platform
|
||||
func (artifacts Artifacts) GroupByPlatform() map[string][]Artifact {
|
||||
var result = map[string][]Artifact{}
|
||||
for _, a := range artifacts.items {
|
||||
plat := a.Goos + a.Goarch + a.Goarm
|
||||
result[plat] = append(result[plat], a)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Add safely adds a new artifact to an artifact list
|
||||
func (artifacts *Artifacts) Add(a Artifact) {
|
||||
artifacts.lock.Lock()
|
||||
defer artifacts.lock.Unlock()
|
||||
log.WithFields(log.Fields{
|
||||
"name": a.Name,
|
||||
"path": a.Path,
|
||||
"type": a.Type,
|
||||
}).Info("added new artifact")
|
||||
artifacts.items = append(artifacts.items, a)
|
||||
}
|
||||
|
||||
// Filter defines an artifact filter which can be used within the Filter
|
||||
// function
|
||||
type Filter func(a Artifact) bool
|
||||
|
||||
// ByGoos is a predefined filter that filters by the given goos
|
||||
func ByGoos(s string) Filter {
|
||||
return func(a Artifact) bool {
|
||||
return a.Goos == s
|
||||
}
|
||||
}
|
||||
|
||||
// ByGoarch is a predefined filter that filters by the given goarch
|
||||
func ByGoarch(s string) Filter {
|
||||
return func(a Artifact) bool {
|
||||
return a.Goarch == s
|
||||
}
|
||||
}
|
||||
|
||||
// ByGoarm is a predefined filter that filters by the given goarm
|
||||
func ByGoarm(s string) Filter {
|
||||
return func(a Artifact) bool {
|
||||
return a.Goarm == s
|
||||
}
|
||||
}
|
||||
|
||||
// ByType is a predefined filter that filters by the given type
|
||||
func ByType(t Type) Filter {
|
||||
return func(a Artifact) bool {
|
||||
return a.Type == t
|
||||
}
|
||||
}
|
||||
|
||||
// Or performs an OR between all given filters
|
||||
func Or(filters ...Filter) Filter {
|
||||
return func(a Artifact) bool {
|
||||
for _, f := range filters {
|
||||
if f(a) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// And performs an AND between all given filters
|
||||
func And(filters ...Filter) Filter {
|
||||
return func(a Artifact) bool {
|
||||
for _, f := range filters {
|
||||
if !f(a) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Filter filters the artifact list, returning a new instance.
|
||||
// There are some pre-defined filters but anything of the Type Filter
|
||||
// is accepted.
|
||||
// You can compose filters by using the And and Or filters.
|
||||
func (artifacts *Artifacts) Filter(filter Filter) Artifacts {
|
||||
var result = New()
|
||||
for _, a := range artifacts.items {
|
||||
if filter(a) {
|
||||
result.items = append(result.items, a)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
137
internal/artifact/artifact_test.go
Normal file
137
internal/artifact/artifact_test.go
Normal file
@ -0,0 +1,137 @@
|
||||
package artifact
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// ensure Type implements the stringer interface...
|
||||
var _ fmt.Stringer = Type(0)
|
||||
|
||||
func TestAdd(t *testing.T) {
|
||||
var g errgroup.Group
|
||||
var artifacts = New()
|
||||
for _, a := range []Artifact{
|
||||
{
|
||||
Name: "foo",
|
||||
Type: UploadableArchive,
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
Type: Binary,
|
||||
},
|
||||
{
|
||||
Name: "foobar",
|
||||
Type: DockerImage,
|
||||
},
|
||||
{
|
||||
Name: "check",
|
||||
Type: Checksum,
|
||||
},
|
||||
} {
|
||||
a := a
|
||||
g.Go(func() error {
|
||||
artifacts.Add(a)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
assert.NoError(t, g.Wait())
|
||||
assert.Len(t, artifacts.List(), 4)
|
||||
}
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
var data = []Artifact{
|
||||
{
|
||||
Name: "foo",
|
||||
Goos: "linux",
|
||||
Goarch: "arm",
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
Goarch: "amd64",
|
||||
},
|
||||
{
|
||||
Name: "foobar",
|
||||
Goarm: "6",
|
||||
},
|
||||
{
|
||||
Name: "check",
|
||||
Type: Checksum,
|
||||
},
|
||||
{
|
||||
Name: "checkzumm",
|
||||
Type: Checksum,
|
||||
},
|
||||
}
|
||||
var artifacts = New()
|
||||
for _, a := range data {
|
||||
artifacts.Add(a)
|
||||
}
|
||||
|
||||
assert.Len(t, artifacts.Filter(ByGoos("linux")).items, 1)
|
||||
assert.Len(t, artifacts.Filter(ByGoos("darwin")).items, 0)
|
||||
|
||||
assert.Len(t, artifacts.Filter(ByGoarch("amd64")).items, 1)
|
||||
assert.Len(t, artifacts.Filter(ByGoarch("386")).items, 0)
|
||||
|
||||
assert.Len(t, artifacts.Filter(ByGoarm("6")).items, 1)
|
||||
assert.Len(t, artifacts.Filter(ByGoarm("7")).items, 0)
|
||||
|
||||
assert.Len(t, artifacts.Filter(ByType(Checksum)).items, 2)
|
||||
assert.Len(t, artifacts.Filter(ByType(Binary)).items, 0)
|
||||
|
||||
assert.Len(t, artifacts.Filter(
|
||||
And(
|
||||
ByType(Checksum),
|
||||
func(a Artifact) bool {
|
||||
return a.Name == "checkzumm"
|
||||
},
|
||||
),
|
||||
).List(), 1)
|
||||
|
||||
assert.Len(t, artifacts.Filter(
|
||||
Or(
|
||||
ByType(Checksum),
|
||||
And(
|
||||
ByGoos("linux"),
|
||||
ByGoarm("arm"),
|
||||
),
|
||||
),
|
||||
).List(), 2)
|
||||
}
|
||||
|
||||
func TestGroupByPlatform(t *testing.T) {
|
||||
var data = []Artifact{
|
||||
{
|
||||
Name: "foo",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
},
|
||||
{
|
||||
Name: "foobar",
|
||||
Goos: "linux",
|
||||
Goarch: "arm",
|
||||
Goarm: "6",
|
||||
},
|
||||
{
|
||||
Name: "check",
|
||||
Type: Checksum,
|
||||
},
|
||||
}
|
||||
var artifacts = New()
|
||||
for _, a := range data {
|
||||
artifacts.Add(a)
|
||||
}
|
||||
|
||||
var groups = artifacts.GroupByPlatform()
|
||||
assert.Len(t, groups["linuxamd64"], 2)
|
||||
assert.Len(t, groups["linuxarm6"], 1)
|
||||
}
|
@ -28,6 +28,7 @@ func (t Target) Env() []string {
|
||||
}
|
||||
|
||||
func (t Target) String() string {
|
||||
// TODO: maybe replace this as suggested to OS_ArchArm?
|
||||
return fmt.Sprintf("%v%v%v", t.OS, t.Arch, t.Arm)
|
||||
}
|
||||
|
||||
|
3
internal/buildtarget/doc.go
Normal file
3
internal/buildtarget/doc.go
Normal file
@ -0,0 +1,3 @@
|
||||
// Package buildtarget provides the utilities targeting build matrixes.
|
||||
// TODO: probably this package should be removed and used only inside the build package
|
||||
package buildtarget
|
@ -3,9 +3,9 @@ package ext
|
||||
import "github.com/goreleaser/goreleaser/internal/buildtarget"
|
||||
|
||||
// For returns the binary extension for the given platform
|
||||
func For(target buildtarget.Target) (ext string) {
|
||||
func For(target buildtarget.Target) string {
|
||||
if target.OS == "windows" {
|
||||
ext = ".exe"
|
||||
return ".exe"
|
||||
}
|
||||
return
|
||||
return ""
|
||||
}
|
||||
|
@ -1,16 +1,18 @@
|
||||
package build
|
||||
package nametemplate
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"text/template"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/buildtarget"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
)
|
||||
|
||||
func nameFor(ctx *context.Context, target buildtarget.Target, name string) (string, error) {
|
||||
// Apply applies the name template to the given artifact and name
|
||||
// TODO: this should be refactored alongside with other name template related todos
|
||||
func Apply(ctx *context.Context, a artifact.Artifact, name string) (string, error) {
|
||||
var out bytes.Buffer
|
||||
t, err := template.New(name).Parse(ctx.Config.Archive.NameTemplate)
|
||||
t, err := template.New("archive_name").Parse(ctx.Config.Archive.NameTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -18,12 +20,11 @@ func nameFor(ctx *context.Context, target buildtarget.Target, name string) (stri
|
||||
Os, Arch, Arm, Version, Tag, Binary, ProjectName string
|
||||
Env map[string]string
|
||||
}{
|
||||
Os: replace(ctx.Config.Archive.Replacements, target.OS),
|
||||
Arch: replace(ctx.Config.Archive.Replacements, target.Arch),
|
||||
Arm: replace(ctx.Config.Archive.Replacements, target.Arm),
|
||||
Os: replace(ctx.Config.Archive.Replacements, a.Goos),
|
||||
Arch: replace(ctx.Config.Archive.Replacements, a.Goarch),
|
||||
Arm: replace(ctx.Config.Archive.Replacements, a.Goarm),
|
||||
Version: ctx.Version,
|
||||
Tag: ctx.Git.CurrentTag,
|
||||
Binary: name, // TODO: deprecated: remove this sometime
|
||||
ProjectName: name,
|
||||
Env: ctx.Env,
|
||||
}
|
@ -7,13 +7,17 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/mattn/go-zglob"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/goreleaser/archive"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/archiveformat"
|
||||
"github.com/mattn/go-zglob"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/nametemplate"
|
||||
)
|
||||
|
||||
// Pipe for archive
|
||||
@ -26,14 +30,14 @@ func (Pipe) String() string {
|
||||
// Run the pipe
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
var g errgroup.Group
|
||||
for platform, binaries := range ctx.Binaries {
|
||||
platform := platform
|
||||
binaries := binaries
|
||||
var filtered = ctx.Artifacts.Filter(artifact.ByType(artifact.Binary))
|
||||
for _, artifacts := range filtered.GroupByPlatform() {
|
||||
artifacts := artifacts
|
||||
g.Go(func() error {
|
||||
if ctx.Config.Archive.Format == "binary" {
|
||||
return skip(ctx, platform, binaries)
|
||||
return skip(ctx, artifacts)
|
||||
}
|
||||
return create(ctx, platform, binaries)
|
||||
return create(ctx, artifacts)
|
||||
})
|
||||
}
|
||||
return g.Wait()
|
||||
@ -62,26 +66,21 @@ func (Pipe) Default(ctx *context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func create(ctx *context.Context, platform string, groups map[string][]context.Binary) error {
|
||||
for folder, binaries := range groups {
|
||||
var format = archiveformat.For(ctx, platform)
|
||||
func create(ctx *context.Context, artifacts []artifact.Artifact) error {
|
||||
var format = archiveformat.For(ctx, artifacts[0].Goos)
|
||||
folder, err := nametemplate.Apply(ctx, artifacts[0], ctx.Config.ProjectName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
archivePath := filepath.Join(ctx.Config.Dist, folder+"."+format)
|
||||
archiveFile, err := os.Create(archivePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create directory %s: %s", archivePath, err.Error())
|
||||
}
|
||||
defer func() {
|
||||
if e := archiveFile.Close(); e != nil {
|
||||
log.WithField("archive", archivePath).Errorf("failed to close file: %v", e)
|
||||
}
|
||||
}()
|
||||
defer archiveFile.Close() // nolint: errcheck
|
||||
log.WithField("archive", archivePath).Info("creating")
|
||||
var a = archive.New(archiveFile)
|
||||
defer func() {
|
||||
if e := a.Close(); e != nil {
|
||||
log.WithField("archive", archivePath).Errorf("failed to close archive: %v", e)
|
||||
}
|
||||
}()
|
||||
defer a.Close() // nolint: errcheck
|
||||
|
||||
files, err := findFiles(ctx)
|
||||
if err != nil {
|
||||
@ -92,22 +91,33 @@ func create(ctx *context.Context, platform string, groups map[string][]context.B
|
||||
return fmt.Errorf("failed to add %s to the archive: %s", f, err.Error())
|
||||
}
|
||||
}
|
||||
for _, binary := range binaries {
|
||||
for _, binary := range artifacts {
|
||||
if err := a.Add(wrap(ctx, binary.Name, folder), binary.Path); err != nil {
|
||||
return fmt.Errorf("failed to add %s -> %s to the archive: %s", binary.Path, binary.Name, err.Error())
|
||||
}
|
||||
}
|
||||
ctx.AddArtifact(archivePath)
|
||||
}
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.UploadableArchive,
|
||||
Name: folder + "." + format,
|
||||
Path: archivePath,
|
||||
Goos: artifacts[0].Goos,
|
||||
Goarch: artifacts[0].Goarch,
|
||||
Goarm: artifacts[0].Goarm,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
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)
|
||||
func skip(ctx *context.Context, artifacts []artifact.Artifact) error {
|
||||
for _, a := range artifacts {
|
||||
log.WithField("binary", a.Name).Info("skip archiving")
|
||||
// TODO: this should not happen here, maybe add another extra field for the extension and/or name without extension?
|
||||
name, err := nametemplate.Apply(ctx, a, strings.TrimSuffix(a.Name, ".exe"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Type = artifact.UploadableBinary
|
||||
a.Name = name + a.Extra["Ext"]
|
||||
ctx.Artifacts.Add(a)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -8,10 +8,12 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
func TestDescription(t *testing.T) {
|
||||
@ -23,18 +25,19 @@ func TestRunPipe(t *testing.T) {
|
||||
defer back()
|
||||
var dist = filepath.Join(folder, "dist")
|
||||
assert.NoError(t, os.Mkdir(dist, 0755))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin_darwin_amd64"), 0755))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin_windows_amd64"), 0755))
|
||||
_, err := os.Create(filepath.Join(dist, "mybin_darwin_amd64", "mybin"))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0755))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "windowsamd64"), 0755))
|
||||
_, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
|
||||
assert.NoError(t, err)
|
||||
_, err = os.Create(filepath.Join(dist, "mybin_windows_amd64", "mybin.exe"))
|
||||
_, err = os.Create(filepath.Join(dist, "windowsamd64", "mybin.exe"))
|
||||
assert.NoError(t, err)
|
||||
_, err = os.Create(filepath.Join(folder, "README.md"))
|
||||
assert.NoError(t, err)
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
var ctx = context.New(
|
||||
config.Project{
|
||||
Dist: dist,
|
||||
Archive: config.Archive{
|
||||
NameTemplate: "whatever",
|
||||
Files: []string{
|
||||
"README.*",
|
||||
},
|
||||
@ -46,9 +49,27 @@ 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"))
|
||||
)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Name: "mybin",
|
||||
Path: filepath.Join(dist, "darwinamd64", "mybin"),
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]string{
|
||||
"Binary": "mybin",
|
||||
},
|
||||
})
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Goos: "windows",
|
||||
Goarch: "amd64",
|
||||
Name: "mybin.exe",
|
||||
Path: filepath.Join(dist, "windowsamd64", "mybin.exe"),
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]string{
|
||||
"Binary": "mybin",
|
||||
},
|
||||
})
|
||||
for _, format := range []string{"tar.gz", "zip"} {
|
||||
t.Run("Archive format "+format, func(t *testing.T) {
|
||||
ctx.Config.Archive.Format = format
|
||||
@ -57,7 +78,7 @@ func TestRunPipe(t *testing.T) {
|
||||
}
|
||||
|
||||
// Check archive contents
|
||||
f, err := os.Open(filepath.Join(dist, "mybin_darwin_amd64.tar.gz"))
|
||||
f, err := os.Open(filepath.Join(dist, "whatever.tar.gz"))
|
||||
assert.NoError(t, err)
|
||||
defer func() { assert.NoError(t, f.Close()) }()
|
||||
gr, err := gzip.NewReader(f)
|
||||
@ -79,16 +100,16 @@ func TestRunPipeBinary(t *testing.T) {
|
||||
defer back()
|
||||
var dist = filepath.Join(folder, "dist")
|
||||
assert.NoError(t, os.Mkdir(dist, 0755))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin_darwin"), 0755))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin_win"), 0755))
|
||||
_, err := os.Create(filepath.Join(dist, "mybin_darwin", "mybin"))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0755))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "windowsamd64"), 0755))
|
||||
_, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
|
||||
assert.NoError(t, err)
|
||||
_, err = os.Create(filepath.Join(dist, "mybin_win", "mybin.exe"))
|
||||
_, err = os.Create(filepath.Join(dist, "windowsamd64", "mybin.exe"))
|
||||
assert.NoError(t, err)
|
||||
_, err = os.Create(filepath.Join(folder, "README.md"))
|
||||
assert.NoError(t, err)
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
var ctx = context.New(
|
||||
config.Project{
|
||||
Dist: dist,
|
||||
Builds: []config.Build{
|
||||
{Binary: "mybin"},
|
||||
@ -97,60 +118,88 @@ func TestRunPipeBinary(t *testing.T) {
|
||||
Format: "binary",
|
||||
},
|
||||
},
|
||||
}
|
||||
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"))
|
||||
)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Name: "mybin",
|
||||
Path: filepath.Join(dist, "darwinamd64", "mybin"),
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]string{
|
||||
"Binary": "mybin",
|
||||
},
|
||||
})
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Goos: "windows",
|
||||
Goarch: "amd64",
|
||||
Name: "mybin.exe",
|
||||
Path: filepath.Join(dist, "windowsamd64", "mybin.exe"),
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]string{
|
||||
"Binary": "mybin",
|
||||
},
|
||||
})
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
assert.Contains(t, ctx.Artifacts, "mybin_darwin/mybin")
|
||||
assert.Contains(t, ctx.Artifacts, "mybin_win/mybin.exe")
|
||||
assert.Len(t, ctx.Artifacts, 2)
|
||||
var binaries = ctx.Artifacts.Filter(artifact.ByType(artifact.UploadableBinary))
|
||||
assert.Len(t, binaries.Filter(artifact.ByGoos("darwin")).List(), 1)
|
||||
assert.Len(t, binaries.Filter(artifact.ByGoos("windows")).List(), 1)
|
||||
assert.Len(t, binaries.List(), 2)
|
||||
}
|
||||
|
||||
func TestRunPipeDistRemoved(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
var ctx = context.New(
|
||||
config.Project{
|
||||
Dist: "/path/nope",
|
||||
Archive: config.Archive{
|
||||
NameTemplate: "nope",
|
||||
Format: "zip",
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx.AddBinary("windowsamd64", "nope", "no", "blah")
|
||||
assert.Error(t, Pipe{}.Run(ctx))
|
||||
)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Goos: "windows",
|
||||
Goarch: "amd64",
|
||||
Name: "mybin.exe",
|
||||
Path: filepath.Join("/path/to/nope", "windowsamd64", "mybin.exe"),
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]string{
|
||||
"Binary": "mybin",
|
||||
},
|
||||
})
|
||||
assert.EqualError(t, Pipe{}.Run(ctx), `failed to create directory /path/nope/nope.zip: open /path/nope/nope.zip: no such file or directory`)
|
||||
}
|
||||
|
||||
func TestRunPipeInvalidGlob(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Dist: "/tmp",
|
||||
folder, back := testlib.Mktmp(t)
|
||||
defer back()
|
||||
var dist = filepath.Join(folder, "dist")
|
||||
assert.NoError(t, os.Mkdir(dist, 0755))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0755))
|
||||
_, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
|
||||
assert.NoError(t, err)
|
||||
var ctx = context.New(
|
||||
config.Project{
|
||||
Dist: dist,
|
||||
Archive: config.Archive{
|
||||
NameTemplate: "foo",
|
||||
Format: "zip",
|
||||
Files: []string{
|
||||
"[x-]",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx.AddBinary("windowsamd64", "whatever", "foo", "bar")
|
||||
assert.Error(t, Pipe{}.Run(ctx))
|
||||
}
|
||||
|
||||
func TestRunPipeGlobFailsToAdd(t *testing.T) {
|
||||
folder, back := testlib.Mktmp(t)
|
||||
defer back()
|
||||
assert.NoError(t, os.MkdirAll(filepath.Join(folder, "folder", "another"), 0755))
|
||||
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Dist: folder,
|
||||
Archive: config.Archive{
|
||||
Files: []string{
|
||||
"folder",
|
||||
)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Name: "mybin",
|
||||
Path: filepath.Join("dist", "darwinamd64", "mybin"),
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]string{
|
||||
"Binary": "mybin",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx.AddBinary("windows386", "mybin", "mybin", "dist/mybin")
|
||||
assert.Error(t, Pipe{}.Run(ctx))
|
||||
})
|
||||
assert.EqualError(t, Pipe{}.Run(ctx), `failed to find files to archive: globbing failed for pattern [x-]: file does not exist`)
|
||||
}
|
||||
|
||||
func TestRunPipeWrap(t *testing.T) {
|
||||
@ -158,15 +207,16 @@ func TestRunPipeWrap(t *testing.T) {
|
||||
defer back()
|
||||
var dist = filepath.Join(folder, "dist")
|
||||
assert.NoError(t, os.Mkdir(dist, 0755))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin_darwin_amd64"), 0755))
|
||||
_, err := os.Create(filepath.Join(dist, "mybin_darwin_amd64", "mybin"))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "darwinamd64"), 0755))
|
||||
_, err := os.Create(filepath.Join(dist, "darwinamd64", "mybin"))
|
||||
assert.NoError(t, err)
|
||||
_, err = os.Create(filepath.Join(folder, "README.md"))
|
||||
assert.NoError(t, err)
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
var ctx = context.New(
|
||||
config.Project{
|
||||
Dist: dist,
|
||||
Archive: config.Archive{
|
||||
NameTemplate: "foo",
|
||||
WrapInDirectory: true,
|
||||
Format: "tar.gz",
|
||||
Files: []string{
|
||||
@ -174,12 +224,21 @@ func TestRunPipeWrap(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx.AddBinary("darwinamd64", "mybin_darwin_amd64", "mybin", filepath.Join(dist, "mybin_darwin_amd64", "mybin"))
|
||||
)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Name: "mybin",
|
||||
Path: filepath.Join("dist", "darwinamd64", "mybin"),
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]string{
|
||||
"Binary": "mybin",
|
||||
},
|
||||
})
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
|
||||
// Check archive contents
|
||||
f, err := os.Open(filepath.Join(dist, "mybin_darwin_amd64.tar.gz"))
|
||||
f, err := os.Open(filepath.Join(dist, "foo.tar.gz"))
|
||||
assert.NoError(t, err)
|
||||
defer func() { assert.NoError(t, f.Close()) }()
|
||||
gr, err := gzip.NewReader(f)
|
||||
@ -192,7 +251,7 @@ func TestRunPipeWrap(t *testing.T) {
|
||||
break
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, filepath.Join("mybin_darwin_amd64", n), h.Name)
|
||||
assert.Equal(t, filepath.Join("foo", n), h.Name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,17 +11,16 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/buildtarget"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
)
|
||||
|
||||
// artifactoryResponse reflects the response after an upload request
|
||||
@ -69,7 +68,7 @@ func (Pipe) Default(ctx *context.Context) error {
|
||||
// Check if a mode was set
|
||||
for i := range ctx.Config.Artifactories {
|
||||
if ctx.Config.Artifactories[i].Mode == "" {
|
||||
ctx.Config.Artifactories[i].Mode = "archive"
|
||||
ctx.Config.Artifactories[i].Mode = modeArchive
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,15 +120,10 @@ func doRun(ctx *context.Context) error {
|
||||
var err error
|
||||
switch v := strings.ToLower(instance.Mode); v {
|
||||
case modeArchive:
|
||||
err = runPipeForModeArchive(ctx, instance)
|
||||
err = runPipeByFilter(ctx, instance, artifact.ByType(artifact.UploadableArchive))
|
||||
|
||||
case modeBinary:
|
||||
// Loop over all builds, because we want to publish every build to Artifactory
|
||||
for _, build := range ctx.Config.Builds {
|
||||
if err = runPipeForModeBinary(ctx, instance, build); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = runPipeByFilter(ctx, instance, artifact.ByType(artifact.UploadableBinary))
|
||||
|
||||
default:
|
||||
err = fmt.Errorf("artifactory: mode \"%s\" not supported", v)
|
||||
@ -147,50 +141,29 @@ func doRun(ctx *context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// runPipeForModeArchive uploads all ctx.Artifacts to instance
|
||||
func runPipeForModeArchive(ctx *context.Context, instance config.Artifactory) error {
|
||||
func runPipeByFilter(ctx *context.Context, instance config.Artifactory, filter artifact.Filter) error {
|
||||
sem := make(chan bool, ctx.Parallelism)
|
||||
var g errgroup.Group
|
||||
|
||||
// Get all artifacts and upload them
|
||||
for _, artifact := range ctx.Artifacts {
|
||||
for _, artifact := range ctx.Artifacts.Filter(filter).List() {
|
||||
sem <- true
|
||||
artifact := artifact
|
||||
g.Go(func() error {
|
||||
defer func() {
|
||||
<-sem
|
||||
}()
|
||||
|
||||
return uploadArchive(ctx, instance, artifact)
|
||||
return uploadAsset(ctx, instance, artifact)
|
||||
})
|
||||
}
|
||||
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
// uploadArchive will upload artifact in mode archive
|
||||
func uploadArchive(ctx *context.Context, instance config.Artifactory, artifact string) error {
|
||||
var path = filepath.Join(ctx.Config.Dist, artifact)
|
||||
return uploadAssetAndLog(ctx, instance, path, nil)
|
||||
}
|
||||
|
||||
// uploadBinary will upload the current build and the current target in mode binary
|
||||
func uploadBinary(ctx *context.Context, instance config.Artifactory, build config.Build, target buildtarget.Target) error {
|
||||
binary, err := getBinaryForUploadPerBuild(ctx, target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return uploadAssetAndLog(ctx, instance, binary.Path, &target)
|
||||
}
|
||||
|
||||
// uploadAssetAndLog uploads file to target and logs all actions
|
||||
func uploadAssetAndLog(ctx *context.Context, instance config.Artifactory, path string, target *buildtarget.Target) error {
|
||||
// uploadAsset uploads file to target and logs all actions
|
||||
func uploadAsset(ctx *context.Context, instance config.Artifactory, artifact artifact.Artifact) error {
|
||||
envName := fmt.Sprintf("ARTIFACTORY_%s_SECRET", strings.ToUpper(instance.Name))
|
||||
secret := ctx.Env[envName]
|
||||
|
||||
// Generate the target url
|
||||
targetURL, err := resolveTargetTemplate(ctx, instance, target)
|
||||
targetURL, err := resolveTargetTemplate(ctx, instance, artifact)
|
||||
if err != nil {
|
||||
msg := "artifactory: error while building the target url"
|
||||
log.WithField("instance", instance.Name).WithError(err).Error(msg)
|
||||
@ -198,20 +171,19 @@ func uploadAssetAndLog(ctx *context.Context, instance config.Artifactory, path s
|
||||
}
|
||||
|
||||
// Handle the artifact
|
||||
file, err := os.Open(path)
|
||||
file, err := os.Open(artifact.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close() // nolint: errcheck
|
||||
_, name := filepath.Split(path)
|
||||
|
||||
// The target url needs to contain the artifact name
|
||||
if !strings.HasSuffix(targetURL, "/") {
|
||||
targetURL += "/"
|
||||
}
|
||||
targetURL += name
|
||||
targetURL += artifact.Name
|
||||
|
||||
artifact, _, err := uploadAssetToArtifactory(ctx, targetURL, instance.Username, secret, file)
|
||||
uploaded, _, err := uploadAssetToArtifactory(ctx, targetURL, instance.Username, secret, file)
|
||||
if err != nil {
|
||||
msg := "artifactory: upload failed"
|
||||
log.WithError(err).WithFields(log.Fields{
|
||||
@ -224,54 +196,12 @@ func uploadAssetAndLog(ctx *context.Context, instance config.Artifactory, path s
|
||||
log.WithFields(log.Fields{
|
||||
"instance": instance.Name,
|
||||
"mode": instance.Mode,
|
||||
"uri": artifact.DownloadURI,
|
||||
"uri": uploaded.DownloadURI,
|
||||
}).Info("uploaded successful")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// runPipeForModeBinary uploads all configured builds to instance
|
||||
func runPipeForModeBinary(ctx *context.Context, instance config.Artifactory, build config.Build) error {
|
||||
sem := make(chan bool, ctx.Parallelism)
|
||||
var g errgroup.Group
|
||||
|
||||
// Lets generate the build matrix, because we want
|
||||
// to publish every target to Artifactory
|
||||
for _, target := range buildtarget.All(build) {
|
||||
sem <- true
|
||||
target := target
|
||||
build := build
|
||||
g.Go(func() error {
|
||||
defer func() {
|
||||
<-sem
|
||||
}()
|
||||
|
||||
return uploadBinary(ctx, instance, build, target)
|
||||
})
|
||||
}
|
||||
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
// getBinaryForUploadPerBuild determines the correct binary for the upload
|
||||
func getBinaryForUploadPerBuild(ctx *context.Context, target buildtarget.Target) (*context.Binary, error) {
|
||||
var group = ctx.Binaries[target.String()]
|
||||
if group == nil {
|
||||
return nil, fmt.Errorf("binary for build target %s not found", target.String())
|
||||
}
|
||||
|
||||
var binary context.Binary
|
||||
for _, binaries := range group {
|
||||
for _, b := range binaries {
|
||||
binary = b
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return &binary, nil
|
||||
}
|
||||
|
||||
// targetData is used as a template struct for
|
||||
// Artifactory.Target
|
||||
type targetData struct {
|
||||
@ -287,18 +217,17 @@ type targetData struct {
|
||||
|
||||
// resolveTargetTemplate returns the resolved target template with replaced variables
|
||||
// Those variables can be replaced by the given context, goos, goarch, goarm and more
|
||||
func resolveTargetTemplate(ctx *context.Context, artifactory config.Artifactory, target *buildtarget.Target) (string, error) {
|
||||
func resolveTargetTemplate(ctx *context.Context, artifactory config.Artifactory, artifact artifact.Artifact) (string, error) {
|
||||
data := targetData{
|
||||
Version: ctx.Version,
|
||||
Tag: ctx.Git.CurrentTag,
|
||||
ProjectName: ctx.Config.ProjectName,
|
||||
}
|
||||
|
||||
// Only supported in mode binary
|
||||
if target != nil {
|
||||
data.Os = replace(ctx.Config.Archive.Replacements, target.OS)
|
||||
data.Arch = replace(ctx.Config.Archive.Replacements, target.Arch)
|
||||
data.Arm = replace(ctx.Config.Archive.Replacements, target.Arm)
|
||||
if artifactory.Mode == modeBinary {
|
||||
data.Os = replace(ctx.Config.Archive.Replacements, artifact.Goos)
|
||||
data.Arch = replace(ctx.Config.Archive.Replacements, artifact.Goarch)
|
||||
data.Arm = replace(ctx.Config.Archive.Replacements, artifact.Goarm)
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
@ -404,10 +333,6 @@ type Error struct {
|
||||
Message string `json:"message"` // Message describing the error.
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("%v (%v)", e.Message, e.Status)
|
||||
}
|
||||
|
||||
// checkResponse checks the API response for errors, and returns them if
|
||||
// present. A response is considered an error if it has a status code outside
|
||||
// the 200 range.
|
||||
|
@ -11,8 +11,8 @@ import (
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -167,24 +167,9 @@ func TestRunPipe_ModeBinary(t *testing.T) {
|
||||
}`)
|
||||
})
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Publish: true,
|
||||
Parallelism: 4,
|
||||
Env: map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION-US_SECRET": "deployuser-secret",
|
||||
"ARTIFACTORY_PRODUCTION-EU_SECRET": "productionuser-apikey",
|
||||
},
|
||||
Config: config.Project{
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Env: []string{"CGO_ENABLED=0"},
|
||||
Goos: []string{"linux", "darwin"},
|
||||
Goarch: []string{"amd64"},
|
||||
},
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production-us",
|
||||
@ -199,10 +184,20 @@ func TestRunPipe_ModeBinary(t *testing.T) {
|
||||
Username: "productionuser",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION-US_SECRET": "deployuser-secret",
|
||||
"ARTIFACTORY_PRODUCTION-EU_SECRET": "productionuser-apikey",
|
||||
}
|
||||
for _, plat := range []string{"linuxamd64", "linux386", "darwinamd64"} {
|
||||
ctx.AddBinary(plat, "mybin", "mybin", binPath)
|
||||
ctx.Publish = true
|
||||
for _, goos := range []string{"linux", "darwin"} {
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: binPath,
|
||||
Goarch: "amd64",
|
||||
Goos: goos,
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
}
|
||||
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
@ -219,14 +214,7 @@ func TestRunPipe_ModeArchive(t *testing.T) {
|
||||
debfile, err := os.Create(filepath.Join(folder, "bin.deb"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Publish: true,
|
||||
Parallelism: 4,
|
||||
Env: map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "goreleaser",
|
||||
Dist: folder,
|
||||
Artifactories: []config.Artifactory{
|
||||
@ -237,11 +225,22 @@ func TestRunPipe_ModeArchive(t *testing.T) {
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
|
||||
ctx.AddArtifact(tarfile.Name())
|
||||
ctx.AddArtifact(debfile.Name())
|
||||
ctx.Publish = true
|
||||
ctx.Version = "1.0.0"
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.UploadableArchive,
|
||||
Name: "bin.tar.gz",
|
||||
Path: tarfile.Name(),
|
||||
})
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.LinuxPackage,
|
||||
Name: "bin.deb",
|
||||
Path: debfile.Name(),
|
||||
})
|
||||
|
||||
// Dummy artifactories
|
||||
mux.HandleFunc("/example-repo-local/goreleaser/1.0.0/bin.tar.gz", func(w http.ResponseWriter, r *http.Request) {
|
||||
@ -298,29 +297,47 @@ func TestRunPipe_ModeArchive(t *testing.T) {
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
}
|
||||
|
||||
func TestRunPipe_ArtifactoryDown(t *testing.T) {
|
||||
folder, err := ioutil.TempDir("", "goreleasertest")
|
||||
assert.NoError(t, err)
|
||||
tarfile, err := os.Create(filepath.Join(folder, "bin.tar.gz"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "goreleaser",
|
||||
Dist: folder,
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "archive",
|
||||
Target: "http://localhost:1234/example-repo-local/{{ .ProjectName }}/{{ .Version }}/",
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
})
|
||||
ctx.Version = "2.0.0"
|
||||
ctx.Env = map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Publish = true
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.UploadableArchive,
|
||||
Name: "bin.tar.gz",
|
||||
Path: tarfile.Name(),
|
||||
})
|
||||
|
||||
assert.EqualError(t, Pipe{}.Run(ctx), `artifactory: upload failed: Put http://localhost:1234/example-repo-local/goreleaser/2.0.0/bin.tar.gz: dial tcp 127.0.0.1:1234: getsockopt: connection refused`)
|
||||
}
|
||||
|
||||
func TestRunPipe_TargetTemplateError(t *testing.T) {
|
||||
folder, err := ioutil.TempDir("", "archivetest")
|
||||
assert.NoError(t, err)
|
||||
var dist = filepath.Join(folder, "dist")
|
||||
var binPath = filepath.Join(dist, "mybin", "mybin")
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Publish: true,
|
||||
Parallelism: 4,
|
||||
Env: map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Env: []string{"CGO_ENABLED=0"},
|
||||
Goos: []string{"darwin"},
|
||||
Goarch: []string{"amd64"},
|
||||
},
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
@ -330,11 +347,20 @@ func TestRunPipe_TargetTemplateError(t *testing.T) {
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
ctx.Publish = true
|
||||
ctx.Env = map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.AddBinary("darwinamd64", "mybin", "mybin", binPath)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: binPath,
|
||||
Goarch: "amd64",
|
||||
Goos: "darwin",
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.Error(t, Pipe{}.Run(ctx))
|
||||
assert.EqualError(t, Pipe{}.Run(ctx), `artifactory: error while building the target url: template: mybin:1: unexpected "/" in operand`)
|
||||
}
|
||||
|
||||
func TestRunPipe_BadCredentials(t *testing.T) {
|
||||
@ -367,23 +393,9 @@ func TestRunPipe_BadCredentials(t *testing.T) {
|
||||
}`)
|
||||
})
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Publish: true,
|
||||
Parallelism: 4,
|
||||
Env: map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Env: []string{"CGO_ENABLED=0"},
|
||||
Goos: []string{"darwin"},
|
||||
Goarch: []string{"amd64"},
|
||||
},
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
@ -392,15 +404,22 @@ func TestRunPipe_BadCredentials(t *testing.T) {
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, plat := range []string{"darwinamd64"} {
|
||||
ctx.AddBinary(plat, "mybin", "mybin", binPath)
|
||||
})
|
||||
ctx.Publish = true
|
||||
ctx.Env = map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: binPath,
|
||||
Goarch: "amd64",
|
||||
Goos: "darwin",
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
err = Pipe{}.Run(ctx)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, len(err.Error()) > 0)
|
||||
assert.Contains(t, err.Error(), "Bad credentials")
|
||||
}
|
||||
|
||||
func TestRunPipe_UnparsableErrorResponse(t *testing.T) {
|
||||
@ -432,23 +451,9 @@ func TestRunPipe_UnparsableErrorResponse(t *testing.T) {
|
||||
}`)
|
||||
})
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Publish: true,
|
||||
Parallelism: 4,
|
||||
Env: map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Env: []string{"CGO_ENABLED=0"},
|
||||
Goos: []string{"darwin"},
|
||||
Goarch: []string{"amd64"},
|
||||
},
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
@ -457,13 +462,20 @@ func TestRunPipe_UnparsableErrorResponse(t *testing.T) {
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, plat := range []string{"darwinamd64"} {
|
||||
ctx.AddBinary(plat, "mybin", "mybin", binPath)
|
||||
})
|
||||
ctx.Publish = true
|
||||
ctx.Env = map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: binPath,
|
||||
Goarch: "amd64",
|
||||
Goos: "darwin",
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.Error(t, Pipe{}.Run(ctx))
|
||||
assert.EqualError(t, Pipe{}.Run(ctx), `artifactory: upload failed: invalid character '.' looking for beginning of value`)
|
||||
}
|
||||
|
||||
func TestRunPipe_UnparsableResponse(t *testing.T) {
|
||||
@ -494,23 +506,9 @@ func TestRunPipe_UnparsableResponse(t *testing.T) {
|
||||
}`)
|
||||
})
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Publish: true,
|
||||
Parallelism: 4,
|
||||
Env: map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Env: []string{"CGO_ENABLED=0"},
|
||||
Goos: []string{"darwin"},
|
||||
Goarch: []string{"amd64"},
|
||||
},
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
@ -519,67 +517,26 @@ func TestRunPipe_UnparsableResponse(t *testing.T) {
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
ctx.Publish = true
|
||||
ctx.Env = map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.AddBinary("darwinamd64", "mybin", "mybin", binPath)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: binPath,
|
||||
Goarch: "amd64",
|
||||
Goos: "darwin",
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.Error(t, Pipe{}.Run(ctx))
|
||||
assert.EqualError(t, Pipe{}.Run(ctx), `artifactory: upload failed: invalid character 'i' looking for beginning of value`)
|
||||
}
|
||||
|
||||
func TestRunPipe_WithoutBinaryTarget(t *testing.T) {
|
||||
folder, err := ioutil.TempDir("", "archivetest")
|
||||
assert.NoError(t, err)
|
||||
var dist = filepath.Join(folder, "dist")
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Publish: true,
|
||||
Parallelism: 4,
|
||||
Env: map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Env: []string{"CGO_ENABLED=0"},
|
||||
Goos: []string{"darwin"},
|
||||
Goarch: []string{"amd64"},
|
||||
},
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
Mode: "binary",
|
||||
Target: fmt.Sprintf("%s/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}", server.URL),
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
assert.Error(t, Pipe{}.Run(ctx))
|
||||
}
|
||||
|
||||
func TestRunPipe_NoFile(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Publish: true,
|
||||
Parallelism: 4,
|
||||
Env: map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
func TestRunPipe_FileNotFound(t *testing.T) {
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: "archivetest/dist",
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Env: []string{"CGO_ENABLED=0"},
|
||||
Goos: []string{"darwin"},
|
||||
Goarch: []string{"amd64"},
|
||||
},
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
@ -588,11 +545,20 @@ func TestRunPipe_NoFile(t *testing.T) {
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
ctx.Publish = true
|
||||
ctx.Env = map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.AddBinary("darwinamd64", "mybin", "mybin", "archivetest/dist/mybin/mybin")
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: "archivetest/dist/mybin/mybin",
|
||||
Goarch: "amd64",
|
||||
Goos: "darwin",
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.Error(t, Pipe{}.Run(ctx))
|
||||
assert.EqualError(t, Pipe{}.Run(ctx), `open archivetest/dist/mybin/mybin: no such file or directory`)
|
||||
}
|
||||
|
||||
func TestRunPipe_UnparsableTarget(t *testing.T) {
|
||||
@ -606,23 +572,9 @@ func TestRunPipe_UnparsableTarget(t *testing.T) {
|
||||
err = ioutil.WriteFile(binPath, d1, 0666)
|
||||
assert.NoError(t, err)
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Publish: true,
|
||||
Parallelism: 4,
|
||||
Env: map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Env: []string{"CGO_ENABLED=0"},
|
||||
Goos: []string{"darwin"},
|
||||
Goarch: []string{"amd64"},
|
||||
},
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
@ -631,22 +583,24 @@ func TestRunPipe_UnparsableTarget(t *testing.T) {
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, plat := range []string{"darwinamd64"} {
|
||||
ctx.AddBinary(plat, "mybin", "mybin", binPath)
|
||||
})
|
||||
ctx.Publish = true
|
||||
ctx.Env = map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: binPath,
|
||||
Goarch: "amd64",
|
||||
Goos: "darwin",
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.Error(t, Pipe{}.Run(ctx))
|
||||
assert.EqualError(t, Pipe{}.Run(ctx), `artifactory: upload failed: parse ://artifacts.company.com/example-repo-local/mybin/darwin/amd64/mybin: missing protocol scheme`)
|
||||
}
|
||||
|
||||
func TestRunPipe_SkipWhenPublishFalse(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Publish: false,
|
||||
Env: map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
var ctx = context.New(config.Project{
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
@ -655,10 +609,14 @@ func TestRunPipe_SkipWhenPublishFalse(t *testing.T) {
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
|
||||
assert.True(t, pipeline.IsSkip(Pipe{}.Run(ctx)))
|
||||
err := Pipe{}.Run(ctx)
|
||||
assert.True(t, pipeline.IsSkip(err))
|
||||
assert.Equal(t, err.Error(), "--skip-publish is set")
|
||||
}
|
||||
|
||||
func TestRunPipe_DirUpload(t *testing.T) {
|
||||
@ -669,23 +627,9 @@ func TestRunPipe_DirUpload(t *testing.T) {
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
|
||||
var binPath = filepath.Join(dist, "mybin")
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Publish: true,
|
||||
Parallelism: 4,
|
||||
Env: map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
},
|
||||
Config: config.Project{
|
||||
var ctx = context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Env: []string{"CGO_ENABLED=0"},
|
||||
Goos: []string{"darwin"},
|
||||
Goarch: []string{"amd64"},
|
||||
},
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
@ -694,13 +638,20 @@ func TestRunPipe_DirUpload(t *testing.T) {
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, plat := range []string{"darwinamd64"} {
|
||||
ctx.AddBinary(plat, "mybin", "mybin", binPath)
|
||||
})
|
||||
ctx.Env = map[string]string{
|
||||
"ARTIFACTORY_PRODUCTION_SECRET": "deployuser-secret",
|
||||
}
|
||||
ctx.Publish = true
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: filepath.Dir(binPath),
|
||||
Goarch: "amd64",
|
||||
Goos: "darwin",
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
|
||||
assert.Error(t, Pipe{}.Run(ctx))
|
||||
assert.EqualError(t, Pipe{}.Run(ctx), `artifactory: upload failed: the asset to upload can't be a directory`)
|
||||
}
|
||||
|
||||
func TestDescription(t *testing.T) {
|
||||
|
@ -1,5 +1,3 @@
|
||||
// Package brew implements the Pipe, providing formula generation and
|
||||
// uploading it to a configured repo.
|
||||
package brew
|
||||
|
||||
import (
|
||||
@ -11,19 +9,20 @@ import (
|
||||
"text/template"
|
||||
|
||||
"github.com/apex/log"
|
||||
|
||||
"github.com/goreleaser/goreleaser/checksum"
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/archiveformat"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/client"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
)
|
||||
|
||||
// ErrNoDarwin64Build when there is no build for darwin_amd64 (goos doesn't
|
||||
// contain darwin and/or goarch doesn't contain amd64)
|
||||
var ErrNoDarwin64Build = errors.New("brew tap requires a darwin amd64 build")
|
||||
// ErrNoDarwin64Build when there is no build for darwin_amd64
|
||||
var ErrNoDarwin64Build = errors.New("brew tap requires one darwin amd64 build")
|
||||
|
||||
const platform = "darwinamd64"
|
||||
// ErrTooManyDarwin64Builds when there are too many builds for darwin_amd64
|
||||
var ErrTooManyDarwin64Builds = errors.New("brew tap requires at most one darwin amd64 build")
|
||||
|
||||
// Pipe for brew deployment
|
||||
type Pipe struct{}
|
||||
@ -98,28 +97,33 @@ func doRun(ctx *context.Context, client client.Client) error {
|
||||
return pipeline.Skip("archive format is binary")
|
||||
}
|
||||
|
||||
var group = ctx.Binaries["darwinamd64"]
|
||||
if group == nil {
|
||||
var archives = ctx.Artifacts.Filter(
|
||||
artifact.And(
|
||||
artifact.ByGoos("darwin"),
|
||||
artifact.ByGoarch("amd64"),
|
||||
artifact.ByGoarm(""),
|
||||
artifact.ByType(artifact.UploadableArchive),
|
||||
),
|
||||
).List()
|
||||
if len(archives) == 0 {
|
||||
return ErrNoDarwin64Build
|
||||
}
|
||||
var folder string
|
||||
for f := range group {
|
||||
folder = f
|
||||
break
|
||||
if len(archives) > 1 {
|
||||
return ErrTooManyDarwin64Builds
|
||||
}
|
||||
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, folder)
|
||||
content, err := buildFormula(ctx, client, archives[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return client.CreateFile(ctx, content, path)
|
||||
}
|
||||
|
||||
func buildFormula(ctx *context.Context, client client.Client, folder string) (bytes.Buffer, error) {
|
||||
data, err := dataFor(ctx, client, folder)
|
||||
func buildFormula(ctx *context.Context, client client.Client, artifact artifact.Artifact) (bytes.Buffer, error) {
|
||||
data, err := dataFor(ctx, client, artifact)
|
||||
if err != nil {
|
||||
return bytes.Buffer{}, err
|
||||
}
|
||||
@ -135,9 +139,8 @@ func doBuildFormula(data templateData) (out bytes.Buffer, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
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))
|
||||
func dataFor(ctx *context.Context, client client.Client, artifact artifact.Artifact) (result templateData, err error) {
|
||||
sum, err := checksum.SHA256(artifact.Path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -154,7 +157,7 @@ func dataFor(ctx *context.Context, client client.Client, folder string) (result
|
||||
Tag: ctx.Git.CurrentTag,
|
||||
Version: ctx.Version,
|
||||
Caveats: ctx.Config.Brew.Caveats,
|
||||
File: file,
|
||||
File: artifact.Name,
|
||||
SHA256: sum,
|
||||
Dependencies: ctx.Config.Brew.Dependencies,
|
||||
Conflicts: ctx.Config.Brew.Conflicts,
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"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"
|
||||
)
|
||||
@ -94,6 +95,7 @@ func TestRunPipe(t *testing.T) {
|
||||
CurrentTag: "v1.0.1",
|
||||
},
|
||||
Version: "1.0.1",
|
||||
Artifacts: artifact.New(),
|
||||
Config: config.Project{
|
||||
Dist: folder,
|
||||
ProjectName: "run-pipe",
|
||||
@ -124,55 +126,42 @@ func TestRunPipe(t *testing.T) {
|
||||
Publish: true,
|
||||
}
|
||||
var path = filepath.Join(folder, "bin.tar.gz")
|
||||
ctx.AddBinary("darwinamd64", "bin", "bin", path)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "bin.tar.gz",
|
||||
Path: path,
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Type: artifact.UploadableArchive,
|
||||
})
|
||||
client := &DummyClient{}
|
||||
assert.Error(t, doRun(ctx, client))
|
||||
assert.False(t, client.CreatedFile)
|
||||
|
||||
_, err = os.Create(path)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, doRun(ctx, client))
|
||||
assert.True(t, client.CreatedFile)
|
||||
|
||||
t.Run("default git url", func(tt *testing.T) {
|
||||
assert.NoError(tt, doRun(ctx, client))
|
||||
assert.True(tt, client.CreatedFile)
|
||||
|
||||
bts, err := ioutil.ReadFile("testdata/run_pipe.rb")
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(tt, err)
|
||||
// TODO: make writing this file toggleable somehow?
|
||||
// ioutil.WriteFile("testdata/run_pipe.rb", []byte(client.Content), 0644)
|
||||
assert.Equal(tt, string(bts), client.Content)
|
||||
})
|
||||
|
||||
assert.Equal(t, string(bts), client.Content)
|
||||
}
|
||||
t.Run("github enterprise url", func(tt *testing.T) {
|
||||
ctx.Config.GitHubURLs.Download = "http://github.example.org"
|
||||
assert.NoError(tt, doRun(ctx, client))
|
||||
assert.True(tt, client.CreatedFile)
|
||||
|
||||
func TestRunPipeFormatOverride(t *testing.T) {
|
||||
folder, err := ioutil.TempDir("", "goreleasertest")
|
||||
assert.NoError(t, err)
|
||||
var path = filepath.Join(folder, "bin.zip")
|
||||
_, err = os.Create(path)
|
||||
assert.NoError(t, err)
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
Dist: folder,
|
||||
Archive: config.Archive{
|
||||
Format: "tar.gz",
|
||||
FormatOverrides: []config.FormatOverride{
|
||||
{
|
||||
Format: "zip",
|
||||
Goos: "darwin",
|
||||
},
|
||||
},
|
||||
},
|
||||
Brew: config.Homebrew{
|
||||
GitHub: config.Repo{
|
||||
Owner: "test",
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
Publish: true,
|
||||
}
|
||||
ctx.AddBinary("darwinamd64", "bin", "bin", path)
|
||||
client := &DummyClient{}
|
||||
assert.NoError(t, doRun(ctx, client))
|
||||
assert.True(t, client.CreatedFile)
|
||||
assert.Contains(t, client.Content, "bin.zip")
|
||||
bts, err := ioutil.ReadFile("testdata/run_pipe_enterprise.rb")
|
||||
assert.NoError(tt, err)
|
||||
// TODO: make writing this file toggleable somehow?
|
||||
// ioutil.WriteFile("testdata/run_pipe_enterprise.rb", []byte(client.Content), 0644)
|
||||
assert.Equal(tt, string(bts), client.Content)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRunPipeNoDarwin64Build(t *testing.T) {
|
||||
@ -195,6 +184,40 @@ func TestRunPipeNoDarwin64Build(t *testing.T) {
|
||||
assert.False(t, client.CreatedFile)
|
||||
}
|
||||
|
||||
func TestRunPipeMultipleDarwin64Build(t *testing.T) {
|
||||
var ctx = context.New(
|
||||
config.Project{
|
||||
Archive: config.Archive{
|
||||
Format: "tar.gz",
|
||||
},
|
||||
Brew: config.Homebrew{
|
||||
GitHub: config.Repo{
|
||||
Owner: "test",
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
ctx.Publish = true
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "bin1",
|
||||
Path: "doesnt mather",
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Type: artifact.UploadableArchive,
|
||||
})
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "bin2",
|
||||
Path: "doesnt mather",
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Type: artifact.UploadableArchive,
|
||||
})
|
||||
client := &DummyClient{}
|
||||
assert.Equal(t, ErrTooManyDarwin64Builds, doRun(ctx, client))
|
||||
assert.False(t, client.CreatedFile)
|
||||
}
|
||||
|
||||
func TestRunPipeBrewNotSetup(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{},
|
||||
@ -206,9 +229,8 @@ func TestRunPipeBrewNotSetup(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRunPipeBinaryRelease(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Publish: true,
|
||||
Config: config.Project{
|
||||
var ctx = context.New(
|
||||
config.Project{
|
||||
Archive: config.Archive{
|
||||
Format: "binary",
|
||||
},
|
||||
@ -219,8 +241,15 @@ func TestRunPipeBinaryRelease(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx.AddBinary("darwinamd64", "foo", "bar", "baz")
|
||||
)
|
||||
ctx.Publish = true
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "bin",
|
||||
Path: "doesnt mather",
|
||||
Goos: "darwin",
|
||||
Goarch: "amd64",
|
||||
Type: artifact.Binary,
|
||||
})
|
||||
client := &DummyClient{}
|
||||
testlib.AssertSkipped(t, doRun(ctx, client))
|
||||
assert.False(t, client.CreatedFile)
|
||||
|
3
pipeline/brew/doc.go
Normal file
3
pipeline/brew/doc.go
Normal file
@ -0,0 +1,3 @@
|
||||
// Package brew implements the Pipe, providing formula generation and
|
||||
// uploading it to a configured repo.
|
||||
package brew
|
33
pipeline/brew/testdata/run_pipe_enterprise.rb
vendored
Normal file
33
pipeline/brew/testdata/run_pipe_enterprise.rb
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
class RunPipe < Formula
|
||||
desc "A run pipe test formula"
|
||||
homepage "https://github.com/goreleaser"
|
||||
url "http://github.example.org/test/test/releases/download/v1.0.1/bin.tar.gz"
|
||||
version "1.0.1"
|
||||
sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
|
||||
depends_on "zsh"
|
||||
depends_on "bash"
|
||||
|
||||
conflicts_with "gtk+"
|
||||
conflicts_with "qt"
|
||||
|
||||
def install
|
||||
bin.install "foo"
|
||||
end
|
||||
|
||||
def caveats
|
||||
"don't do this"
|
||||
end
|
||||
|
||||
plist_options :startup => false
|
||||
|
||||
def plist; <<-EOS.undent
|
||||
<xml>whatever</xml>
|
||||
EOS
|
||||
end
|
||||
|
||||
test do
|
||||
system "true"
|
||||
system "#{bin}/foo -h"
|
||||
end
|
||||
end
|
@ -7,12 +7,14 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/buildtarget"
|
||||
"github.com/goreleaser/goreleaser/internal/ext"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/buildtarget"
|
||||
"github.com/goreleaser/goreleaser/internal/ext"
|
||||
)
|
||||
|
||||
// Pipe for build
|
||||
@ -104,22 +106,21 @@ func runHook(env []string, hook string) error {
|
||||
}
|
||||
|
||||
func doBuild(ctx *context.Context, build config.Build, target buildtarget.Target) error {
|
||||
var binaryName = build.Binary + ext.For(target)
|
||||
var prettyName = binaryName
|
||||
if ctx.Config.Archive.Format == "binary" {
|
||||
var err error
|
||||
binaryName, err = nameFor(ctx, target, build.Binary)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
binaryName = binaryName + ext.For(target)
|
||||
}
|
||||
folder, err := nameFor(ctx, target, ctx.Config.ProjectName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var binary = filepath.Join(ctx.Config.Dist, folder, binaryName)
|
||||
ctx.AddBinary(target.String(), folder, prettyName, binary)
|
||||
var ext = ext.For(target)
|
||||
var binaryName = build.Binary + ext
|
||||
var binary = filepath.Join(ctx.Config.Dist, target.String(), binaryName)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.Binary,
|
||||
Path: binary,
|
||||
Name: binaryName,
|
||||
Goos: target.OS,
|
||||
Goarch: target.Arch,
|
||||
Goarm: target.Arm,
|
||||
Extra: map[string]string{
|
||||
"Binary": build.Binary,
|
||||
"Ext": ext,
|
||||
},
|
||||
})
|
||||
log.WithField("binary", binary).Info("building")
|
||||
cmd := []string{"go", "build"}
|
||||
if build.Flags != "" {
|
||||
|
@ -46,7 +46,7 @@ func TestRunFullPipe(t *testing.T) {
|
||||
folder, back := testlib.Mktmp(t)
|
||||
defer back()
|
||||
writeGoodMain(t, folder)
|
||||
var binary = filepath.Join(folder, "testing")
|
||||
var binary = filepath.Join(folder, buildtarget.Runtime.String(), "testing")
|
||||
var pre = filepath.Join(folder, "pre")
|
||||
var post = filepath.Join(folder, "post")
|
||||
var config = config.Project{
|
||||
@ -80,41 +80,11 @@ func TestRunFullPipe(t *testing.T) {
|
||||
assert.True(t, exists(post), post)
|
||||
}
|
||||
|
||||
func TestRunPipeFormatBinary(t *testing.T) {
|
||||
folder, back := testlib.Mktmp(t)
|
||||
defer back()
|
||||
writeGoodMain(t, folder)
|
||||
var binary = filepath.Join(folder, "binary-testing-bar")
|
||||
var config = config.Project{
|
||||
ProjectName: "testing",
|
||||
Dist: folder,
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Binary: "testing",
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
},
|
||||
},
|
||||
},
|
||||
Archive: config.Archive{
|
||||
Format: "binary",
|
||||
NameTemplate: "binary-{{.Binary}}-{{.Env.Foo}}",
|
||||
},
|
||||
}
|
||||
ctx := context.New(config)
|
||||
ctx.Env = map[string]string{"Foo": "bar"}
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
assert.True(t, exists(binary))
|
||||
}
|
||||
|
||||
func TestRunPipeArmBuilds(t *testing.T) {
|
||||
folder, back := testlib.Mktmp(t)
|
||||
defer back()
|
||||
writeGoodMain(t, folder)
|
||||
var binary = filepath.Join(folder, "armtesting")
|
||||
var binary = filepath.Join(folder, "linuxarm6", "armtesting")
|
||||
var config = config.Project{
|
||||
Builds: []config.Build{
|
||||
{
|
||||
@ -178,40 +148,6 @@ func TestRunPipeWithInvalidOS(t *testing.T) {
|
||||
assert.NoError(t, Pipe{}.Run(context.New(config)))
|
||||
}
|
||||
|
||||
func TestRunInvalidNametemplate(t *testing.T) {
|
||||
folder, back := testlib.Mktmp(t)
|
||||
defer back()
|
||||
writeGoodMain(t, folder)
|
||||
for format, msg := range map[string]string{
|
||||
"binary": `template: bar:1: unexpected "}" in operand`,
|
||||
"tar.gz": `template: foo:1: unexpected "}" in operand`,
|
||||
"zip": `template: foo:1: unexpected "}" in operand`,
|
||||
} {
|
||||
t.Run(format, func(t *testing.T) {
|
||||
var config = config.Project{
|
||||
ProjectName: "foo",
|
||||
Builds: []config.Build{
|
||||
{
|
||||
Binary: "bar",
|
||||
Flags: "-v",
|
||||
Goos: []string{
|
||||
runtime.GOOS,
|
||||
},
|
||||
Goarch: []string{
|
||||
runtime.GOARCH,
|
||||
},
|
||||
},
|
||||
},
|
||||
Archive: config.Archive{
|
||||
Format: format,
|
||||
NameTemplate: "{{.Binary}",
|
||||
},
|
||||
}
|
||||
assert.EqualError(t, Pipe{}.Run(context.New(config)), msg)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunInvalidLdflags(t *testing.T) {
|
||||
folder, back := testlib.Mktmp(t)
|
||||
defer back()
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/testlib"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
// Package checksums provides a Pipe that creates .checksums files for
|
||||
// each artifact.
|
||||
package checksums
|
||||
|
||||
import (
|
||||
@ -8,9 +6,11 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/apex/log"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/goreleaser/goreleaser/checksum"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
)
|
||||
|
||||
// Pipe for checksums
|
||||
@ -20,6 +20,14 @@ func (Pipe) String() string {
|
||||
return "calculating checksums"
|
||||
}
|
||||
|
||||
// Default sets the pipe defaults
|
||||
func (Pipe) Default(ctx *context.Context) error {
|
||||
if ctx.Config.Checksum.NameTemplate == "" {
|
||||
ctx.Config.Checksum.NameTemplate = "{{ .ProjectName }}_{{ .Version }}_checksums.txt"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run the pipe
|
||||
func (Pipe) Run(ctx *context.Context) (err error) {
|
||||
filename, err := filenameFor(ctx)
|
||||
@ -34,38 +42,36 @@ func (Pipe) Run(ctx *context.Context) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := file.Close(); err != nil {
|
||||
log.WithError(err).Errorf("failed to close %s", file.Name())
|
||||
}
|
||||
ctx.AddArtifact(file.Name())
|
||||
ctx.AddChecksum(file.Name())
|
||||
}()
|
||||
defer file.Close() // nolint: errcheck
|
||||
|
||||
// TODO: parallelism should be considered here as well.
|
||||
var g errgroup.Group
|
||||
for _, artifact := range ctx.Artifacts {
|
||||
for _, artifact := range ctx.Artifacts.Filter(
|
||||
artifact.Or(
|
||||
artifact.ByType(artifact.UploadableArchive),
|
||||
artifact.ByType(artifact.UploadableBinary),
|
||||
artifact.ByType(artifact.LinuxPackage),
|
||||
),
|
||||
).List() {
|
||||
artifact := artifact
|
||||
g.Go(func() error {
|
||||
return checksums(ctx, file, artifact)
|
||||
})
|
||||
}
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.Checksum,
|
||||
Path: file.Name(),
|
||||
Name: filename,
|
||||
})
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
// Default sets the pipe defaults
|
||||
func (Pipe) Default(ctx *context.Context) error {
|
||||
if ctx.Config.Checksum.NameTemplate == "" {
|
||||
ctx.Config.Checksum.NameTemplate = "{{ .ProjectName }}_{{ .Version }}_checksums.txt"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checksums(ctx *context.Context, file *os.File, name string) error {
|
||||
log.WithField("file", name).Info("checksumming")
|
||||
var artifact = filepath.Join(ctx.Config.Dist, name)
|
||||
sha, err := checksum.SHA256(artifact)
|
||||
func checksums(ctx *context.Context, file *os.File, artifact artifact.Artifact) error {
|
||||
log.WithField("file", artifact.Name).Info("checksumming")
|
||||
sha, err := checksum.SHA256(artifact.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = file.WriteString(fmt.Sprintf("%v %v\n", sha, name))
|
||||
_, err = file.WriteString(fmt.Sprintf("%v %v\n", sha, artifact.Name))
|
||||
return err
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -21,18 +22,26 @@ func TestPipe(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
var file = filepath.Join(folder, binary)
|
||||
assert.NoError(t, ioutil.WriteFile(file, []byte("some string"), 0644))
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
var ctx = context.New(
|
||||
config.Project{
|
||||
Dist: folder,
|
||||
ProjectName: binary,
|
||||
Checksum: config.Checksum{
|
||||
NameTemplate: "{{ .ProjectName }}_checksums.txt",
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx.AddArtifact(file)
|
||||
)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: binary,
|
||||
Path: file,
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
assert.Contains(t, ctx.Artifacts, checksums, binary)
|
||||
var artifacts []string
|
||||
for _, a := range ctx.Artifacts.List() {
|
||||
artifacts = append(artifacts, a.Name)
|
||||
}
|
||||
assert.Contains(t, artifacts, checksums, binary)
|
||||
bts, err := ioutil.ReadFile(filepath.Join(folder, checksums))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc binary\n", string(bts))
|
||||
@ -41,15 +50,19 @@ func TestPipe(t *testing.T) {
|
||||
func TestPipeFileNotExist(t *testing.T) {
|
||||
folder, err := ioutil.TempDir("", "goreleasertest")
|
||||
assert.NoError(t, err)
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
var ctx = context.New(
|
||||
config.Project{
|
||||
Dist: folder,
|
||||
Checksum: config.Checksum{
|
||||
NameTemplate: "checksums.txt",
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx.AddArtifact("nope")
|
||||
)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "nope",
|
||||
Path: "/nope",
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
err = Pipe{}.Run(ctx)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "/nope: no such file or directory")
|
||||
@ -58,16 +71,19 @@ func TestPipeFileNotExist(t *testing.T) {
|
||||
func TestPipeInvalidNameTemplate(t *testing.T) {
|
||||
folder, err := ioutil.TempDir("", "goreleasertest")
|
||||
assert.NoError(t, err)
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
var ctx = context.New(
|
||||
config.Project{
|
||||
Dist: folder,
|
||||
ProjectName: "name",
|
||||
Checksum: config.Checksum{
|
||||
NameTemplate: "{{ .Pro }_checksums.txt",
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx.AddArtifact("whatever")
|
||||
)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "whatever",
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
err = Pipe{}.Run(ctx)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, `template: checksums:1: unexpected "}" in operand`, err.Error())
|
||||
@ -78,15 +94,18 @@ func TestPipeCouldNotOpenChecksumsTxt(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
var file = filepath.Join(folder, "checksums.txt")
|
||||
assert.NoError(t, ioutil.WriteFile(file, []byte("some string"), 0000))
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
var ctx = context.New(
|
||||
config.Project{
|
||||
Dist: folder,
|
||||
Checksum: config.Checksum{
|
||||
NameTemplate: "checksums.txt",
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx.AddArtifact("nope")
|
||||
)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "whatever",
|
||||
Type: artifact.UploadableBinary,
|
||||
})
|
||||
err = Pipe{}.Run(ctx)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "/checksums.txt: permission denied")
|
||||
|
3
pipeline/checksums/doc.go
Normal file
3
pipeline/checksums/doc.go
Normal file
@ -0,0 +1,3 @@
|
||||
// Package checksums provides a Pipe that creates .checksums files for
|
||||
// each artifact.
|
||||
package checksums
|
3
pipeline/doc.go
Normal file
3
pipeline/doc.go
Normal file
@ -0,0 +1,3 @@
|
||||
// Package pipeline provides the generic piper and defaulter interfaces,
|
||||
// which should be implemented add new pipes to goreleaser..
|
||||
package pipeline
|
@ -10,10 +10,12 @@ import (
|
||||
"text/template"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ErrNoDocker is shown when docker cannot be found in $PATH
|
||||
@ -26,6 +28,33 @@ func (Pipe) String() string {
|
||||
return "creating Docker images"
|
||||
}
|
||||
|
||||
// Default sets the pipe defaults
|
||||
func (Pipe) Default(ctx *context.Context) error {
|
||||
for i := range ctx.Config.Dockers {
|
||||
var docker = &ctx.Config.Dockers[i]
|
||||
if docker.TagTemplate == "" {
|
||||
docker.TagTemplate = "{{ .Version }}"
|
||||
}
|
||||
if docker.Goos == "" {
|
||||
docker.Goos = "linux"
|
||||
}
|
||||
if docker.Goarch == "" {
|
||||
docker.Goarch = "amd64"
|
||||
}
|
||||
}
|
||||
// only set defaults if there is exacly 1 docker setup in the config file.
|
||||
if len(ctx.Config.Dockers) != 1 {
|
||||
return nil
|
||||
}
|
||||
if ctx.Config.Dockers[0].Binary == "" {
|
||||
ctx.Config.Dockers[0].Binary = ctx.Config.Builds[0].Binary
|
||||
}
|
||||
if ctx.Config.Dockers[0].Dockerfile == "" {
|
||||
ctx.Config.Dockers[0].Dockerfile = "Dockerfile"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run the pipe
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
if len(ctx.Config.Dockers) == 0 || ctx.Config.Dockers[0].Image == "" {
|
||||
@ -38,52 +67,31 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
return doRun(ctx)
|
||||
}
|
||||
|
||||
// Default sets the pipe defaults
|
||||
func (Pipe) Default(ctx *context.Context) error {
|
||||
for i := range ctx.Config.Dockers {
|
||||
if ctx.Config.Dockers[i].TagTemplate == "" {
|
||||
ctx.Config.Dockers[i].TagTemplate = "{{ .Version }}"
|
||||
}
|
||||
}
|
||||
// only set defaults if there is exacly 1 docker setup in the config file.
|
||||
if len(ctx.Config.Dockers) != 1 {
|
||||
return nil
|
||||
}
|
||||
if ctx.Config.Dockers[0].Goos == "" {
|
||||
ctx.Config.Dockers[0].Goos = "linux"
|
||||
}
|
||||
if ctx.Config.Dockers[0].Goarch == "" {
|
||||
ctx.Config.Dockers[0].Goarch = "amd64"
|
||||
}
|
||||
if ctx.Config.Dockers[0].Binary == "" {
|
||||
ctx.Config.Dockers[0].Binary = ctx.Config.Builds[0].Binary
|
||||
}
|
||||
if ctx.Config.Dockers[0].Dockerfile == "" {
|
||||
ctx.Config.Dockers[0].Dockerfile = "Dockerfile"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func doRun(ctx *context.Context) error {
|
||||
// TODO: could be done in parallel.
|
||||
for _, docker := range ctx.Config.Dockers {
|
||||
var imagePlatform = docker.Goos + docker.Goarch + docker.Goarm
|
||||
for platform, groups := range ctx.Binaries {
|
||||
if platform != imagePlatform {
|
||||
continue
|
||||
log.WithField("docker", docker).Debug("looking for binaries matching")
|
||||
var binaries = ctx.Artifacts.Filter(
|
||||
artifact.And(
|
||||
artifact.ByGoos(docker.Goos),
|
||||
artifact.ByGoarch(docker.Goarch),
|
||||
artifact.ByGoarm(docker.Goarm),
|
||||
artifact.ByType(artifact.Binary),
|
||||
func(a artifact.Artifact) bool {
|
||||
return a.Extra["Binary"] == docker.Binary
|
||||
},
|
||||
),
|
||||
).List()
|
||||
if len(binaries) == 0 {
|
||||
log.Warn("no binaries found")
|
||||
}
|
||||
for folder, binaries := range groups {
|
||||
for _, binary := range binaries {
|
||||
if binary.Name != docker.Binary {
|
||||
continue
|
||||
}
|
||||
var err = process(ctx, folder, docker, binary)
|
||||
var err = process(ctx, docker, binary)
|
||||
if err != nil && !pipeline.IsSkip(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -105,8 +113,8 @@ func tagName(ctx *context.Context, docker config.Docker) (string, error) {
|
||||
return out.String(), err
|
||||
}
|
||||
|
||||
func process(ctx *context.Context, folder string, docker config.Docker, binary context.Binary) error {
|
||||
var root = filepath.Join(ctx.Config.Dist, folder)
|
||||
func process(ctx *context.Context, docker config.Docker, artifact artifact.Artifact) error {
|
||||
var root = filepath.Dir(artifact.Path)
|
||||
var dockerfile = filepath.Join(root, filepath.Base(docker.Dockerfile))
|
||||
tag, err := tagName(ctx, docker)
|
||||
if err != nil {
|
||||
@ -143,17 +151,16 @@ func publish(ctx *context.Context, docker config.Docker, image, latest string) e
|
||||
if ctx.Config.Release.Draft {
|
||||
return pipeline.Skip("release is marked as draft")
|
||||
}
|
||||
if err := dockerPush(image); err != nil {
|
||||
if err := dockerPush(ctx, image); err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.AddDocker(image)
|
||||
if !docker.Latest {
|
||||
return nil
|
||||
}
|
||||
if err := dockerTag(image, latest); err != nil {
|
||||
return err
|
||||
}
|
||||
return dockerPush(latest)
|
||||
return dockerPush(ctx, latest)
|
||||
}
|
||||
|
||||
func dockerBuild(root, dockerfile, image string) error {
|
||||
@ -182,7 +189,7 @@ func dockerTag(image, tag string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func dockerPush(image string) error {
|
||||
func dockerPush(ctx *context.Context, image string) error {
|
||||
log.WithField("image", image).Info("pushing docker image")
|
||||
/* #nosec */
|
||||
var cmd = exec.Command("docker", "push", image)
|
||||
@ -192,5 +199,10 @@ func dockerPush(image string) error {
|
||||
return errors.Wrapf(err, "failed to push docker image: \n%s", string(out))
|
||||
}
|
||||
log.Debugf("docker push output: \n%s", string(out))
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.DockerImage,
|
||||
Name: image,
|
||||
// TODO: are the rest of the params relevant here?
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
@ -7,30 +7,19 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func killAndRm() {
|
||||
log.Info("killing registry")
|
||||
func killAndRm(t *testing.T) {
|
||||
t.Log("killing registry")
|
||||
_ = exec.Command("docker", "kill", "registry").Run()
|
||||
_ = exec.Command("docker", "rm", "registry").Run()
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
killAndRm()
|
||||
if err := exec.Command(
|
||||
"docker", "run", "-d", "-p", "5000:5000", "--name", "registry", "registry:2",
|
||||
).Run(); err != nil {
|
||||
log.WithError(err).Fatal("failed to start docker registry")
|
||||
}
|
||||
defer killAndRm()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestRunPipe(t *testing.T) {
|
||||
folder, err := ioutil.TempDir("", "archivetest")
|
||||
assert.NoError(t, err)
|
||||
@ -90,11 +79,21 @@ func TestRunPipe(t *testing.T) {
|
||||
_ = exec.Command("docker", "rmi", img).Run()
|
||||
}
|
||||
|
||||
killAndRm(t)
|
||||
if err := exec.Command(
|
||||
"docker", "run", "-d", "-p", "5000:5000", "--name", "registry", "registry:2",
|
||||
).Run(); err != nil {
|
||||
t.Log("failed to start docker registry", err)
|
||||
t.FailNow()
|
||||
}
|
||||
defer killAndRm(t)
|
||||
|
||||
for name, docker := range table {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Run(name, func(tt *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Publish: true,
|
||||
Artifacts: artifact.New(),
|
||||
Git: context.GitInfo{
|
||||
CurrentTag: "v1.0.0",
|
||||
},
|
||||
@ -107,13 +106,24 @@ func TestRunPipe(t *testing.T) {
|
||||
},
|
||||
Env: map[string]string{"FOO": "123"},
|
||||
}
|
||||
for _, plat := range []string{"linuxamd64", "linux386", "darwinamd64"} {
|
||||
ctx.AddBinary(plat, "mybin", "mybin", binPath)
|
||||
for _, os := range []string{"linux", "darwin"} {
|
||||
for _, arch := range []string{"amd64", "386"} {
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: binPath,
|
||||
Goarch: arch,
|
||||
Goos: os,
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]string{
|
||||
"Binary": "mybin",
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
if docker.err == "" {
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
assert.NoError(tt, Pipe{}.Run(ctx))
|
||||
} else {
|
||||
assert.EqualError(t, Pipe{}.Run(ctx), docker.err)
|
||||
assert.EqualError(tt, Pipe{}.Run(ctx), docker.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -6,14 +6,16 @@ import (
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/linux"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
"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/linux"
|
||||
"github.com/goreleaser/goreleaser/internal/nametemplate"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
)
|
||||
|
||||
// ErrNoFPM is shown when fpm cannot be found in $PATH
|
||||
@ -50,28 +52,33 @@ 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, groups := range ctx.Binaries {
|
||||
if !strings.Contains(platform, "linux") {
|
||||
log.WithField("platform", platform).Debug("skipped non-linux builds for fpm")
|
||||
continue
|
||||
}
|
||||
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)
|
||||
for folder, binaries := range groups {
|
||||
arch := linux.Arch(platform) // TODO: could probably pass artifact.Goarch here
|
||||
artifacts := artifacts
|
||||
g.Go(func() error {
|
||||
defer func() {
|
||||
<-sem
|
||||
}()
|
||||
return create(ctx, format, folder, arch, binaries)
|
||||
return create(ctx, format, arch, artifacts)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
func create(ctx *context.Context, format, folder, arch string, binaries []context.Binary) error {
|
||||
func create(ctx *context.Context, format, arch string, binaries []artifact.Artifact) error {
|
||||
// TODO: should add template support here probably... for now, let's use archive's template
|
||||
folder, err := nametemplate.Apply(ctx, binaries[0], ctx.Config.ProjectName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var path = filepath.Join(ctx.Config.Dist, folder)
|
||||
var file = path + "." + format
|
||||
var log = log.WithField("format", format).WithField("arch", arch)
|
||||
@ -111,7 +118,14 @@ func create(ctx *context.Context, format, folder, arch string, binaries []contex
|
||||
if out, err := exec.Command("fpm", options...).CombinedOutput(); err != nil {
|
||||
return errors.Wrap(err, string(out))
|
||||
}
|
||||
ctx.AddArtifact(file)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.LinuxPackage,
|
||||
Name: folder + "." + format,
|
||||
Path: file,
|
||||
Goos: binaries[0].Goos,
|
||||
Goarch: binaries[0].Goarch,
|
||||
Goarm: binaries[0].Goarm,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"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"
|
||||
)
|
||||
@ -39,9 +40,14 @@ func TestRunPipe(t *testing.T) {
|
||||
Version: "1.0.0",
|
||||
Parallelism: runtime.NumCPU(),
|
||||
Debug: true,
|
||||
Artifacts: artifact.New(),
|
||||
Config: config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
// TODO: remove this when fpm have its own name template
|
||||
Archive: config.Archive{
|
||||
NameTemplate: "foo",
|
||||
},
|
||||
FPM: config.FPM{
|
||||
Formats: []string{"deb", "rpm"},
|
||||
Dependencies: []string{"make"},
|
||||
@ -54,8 +60,16 @@ func TestRunPipe(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, plat := range []string{"linuxamd64", "linux386", "darwinamd64"} {
|
||||
ctx.AddBinary(plat, "mybin", "mybin", binPath)
|
||||
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))
|
||||
}
|
||||
@ -87,6 +101,7 @@ func TestCreateFileDoesntExist(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Parallelism: runtime.NumCPU(),
|
||||
Artifacts: artifact.New(),
|
||||
Config: config.Project{
|
||||
Dist: dist,
|
||||
FPM: config.FPM{
|
||||
@ -97,23 +112,16 @@ func TestCreateFileDoesntExist(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
ctx.AddBinary("linuxamd64", "mybin", "mybin", filepath.Join(dist, "mybin", "mybin"))
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: filepath.Join(dist, "mybin", "mybin"),
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Type: artifact.Binary,
|
||||
})
|
||||
assert.Error(t, Pipe{}.Run(ctx))
|
||||
}
|
||||
|
||||
func TestRunPipeWithExtraFiles(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
Parallelism: runtime.NumCPU(),
|
||||
Config: config.Project{
|
||||
FPM: config.FPM{
|
||||
Formats: []string{"deb", "rpm"},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
Config: config.Project{
|
||||
|
3
pipeline/git/doc.go
Normal file
3
pipeline/git/doc.go
Normal file
@ -0,0 +1,3 @@
|
||||
// Package git implements the Pipe interface getting and validating the
|
||||
// current git repository state
|
||||
package git
|
@ -1,5 +1,3 @@
|
||||
// Package git implements the Pipe interface getting and validating the
|
||||
// current git repository state
|
||||
package git
|
||||
|
||||
import (
|
||||
|
@ -1,4 +1,3 @@
|
||||
// Package pipeline provides a generic pipe interface.
|
||||
package pipeline
|
||||
|
||||
import (
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"text/template"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
)
|
||||
|
||||
const bodyTemplate = `{{ .ReleaseNotes }}
|
||||
@ -34,13 +35,17 @@ func describeBody(ctx *context.Context) (bytes.Buffer, error) {
|
||||
func describeBodyVersion(ctx *context.Context, version string) (bytes.Buffer, error) {
|
||||
var out bytes.Buffer
|
||||
var template = template.Must(template.New("release").Parse(bodyTemplate))
|
||||
var dockers []string
|
||||
for _, a := range ctx.Artifacts.Filter(artifact.ByType(artifact.DockerImage)).List() {
|
||||
dockers = append(dockers, a.Name)
|
||||
}
|
||||
err := template.Execute(&out, struct {
|
||||
ReleaseNotes, GoVersion string
|
||||
DockerImages []string
|
||||
}{
|
||||
ReleaseNotes: ctx.ReleaseNotes,
|
||||
GoVersion: version,
|
||||
DockerImages: ctx.Dockers,
|
||||
DockerImages: dockers,
|
||||
})
|
||||
return out, err
|
||||
}
|
||||
|
@ -5,19 +5,25 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDescribeBody(t *testing.T) {
|
||||
var changelog = "\nfeature1: description\nfeature2: other description"
|
||||
var ctx = &context.Context{
|
||||
ReleaseNotes: changelog,
|
||||
Dockers: []string{
|
||||
var ctx = context.New(config.Project{})
|
||||
ctx.ReleaseNotes = changelog
|
||||
for _, d := range []string{
|
||||
"goreleaser/goreleaser:0.40.0",
|
||||
"goreleaser/goreleaser:latest",
|
||||
"goreleaser/godownloader:v0.1.0",
|
||||
},
|
||||
} {
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: d,
|
||||
Type: artifact.DockerImage,
|
||||
})
|
||||
}
|
||||
out, err := describeBodyVersion(ctx, "go version go1.9 darwin/amd64")
|
||||
assert.NoError(t, err)
|
||||
|
3
pipeline/release/doc.go
Normal file
3
pipeline/release/doc.go
Normal file
@ -0,0 +1,3 @@
|
||||
// Package release implements Pipe and manages github releases and its
|
||||
// artifacts.
|
||||
package release
|
@ -1,16 +1,15 @@
|
||||
// Package release implements Pipe and manages github releases and its
|
||||
// artifacts.
|
||||
package release
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/apex/log"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/client"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// Pipe for github release
|
||||
@ -20,15 +19,6 @@ func (Pipe) String() string {
|
||||
return "releasing to GitHub"
|
||||
}
|
||||
|
||||
// Run the pipe
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
c, err := client.NewGitHub(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return doRun(ctx, c)
|
||||
}
|
||||
|
||||
// Default sets the pipe defaults
|
||||
func (Pipe) Default(ctx *context.Context) error {
|
||||
if ctx.Config.Release.NameTemplate == "" {
|
||||
@ -45,6 +35,15 @@ func (Pipe) Default(ctx *context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run the pipe
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
c, err := client.NewGitHub(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return doRun(ctx, c)
|
||||
}
|
||||
|
||||
func doRun(ctx *context.Context, c client.Client) error {
|
||||
if !ctx.Publish {
|
||||
return pipeline.Skip("--skip-publish is set")
|
||||
@ -62,7 +61,15 @@ func doRun(ctx *context.Context, c client.Client) error {
|
||||
}
|
||||
var g errgroup.Group
|
||||
sem := make(chan bool, ctx.Parallelism)
|
||||
for _, artifact := range ctx.Artifacts {
|
||||
for _, artifact := range ctx.Artifacts.Filter(
|
||||
artifact.Or(
|
||||
artifact.ByType(artifact.UploadableArchive),
|
||||
artifact.ByType(artifact.UploadableBinary),
|
||||
artifact.ByType(artifact.Checksum),
|
||||
artifact.ByType(artifact.Signature),
|
||||
artifact.ByType(artifact.LinuxPackage),
|
||||
),
|
||||
).List() {
|
||||
sem <- true
|
||||
artifact := artifact
|
||||
g.Go(func() error {
|
||||
@ -75,14 +82,12 @@ func doRun(ctx *context.Context, c client.Client) error {
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
func upload(ctx *context.Context, c client.Client, releaseID int, artifact string) error {
|
||||
var path = filepath.Join(ctx.Config.Dist, artifact)
|
||||
file, err := os.Open(path)
|
||||
func upload(ctx *context.Context, c client.Client, releaseID int, artifact artifact.Artifact) error {
|
||||
file, err := os.Open(artifact.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = file.Close() }()
|
||||
_, name := filepath.Split(path)
|
||||
log.WithField("file", file.Name()).WithField("name", name).Info("uploading to release")
|
||||
return c.Upload(ctx, releaseID, name, file)
|
||||
defer file.Close() // nolint: errcheck
|
||||
log.WithField("file", file.Name()).WithField("name", artifact.Name).Info("uploading to release")
|
||||
return c.Upload(ctx, releaseID, artifact.Name, file)
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"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"
|
||||
)
|
||||
@ -37,8 +38,16 @@ func TestRunPipe(t *testing.T) {
|
||||
var ctx = context.New(config)
|
||||
ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
|
||||
ctx.Publish = true
|
||||
ctx.AddArtifact(tarfile.Name())
|
||||
ctx.AddArtifact(debfile.Name())
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.UploadableArchive,
|
||||
Name: "bin.tar.gz",
|
||||
Path: tarfile.Name(),
|
||||
})
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.LinuxPackage,
|
||||
Name: "bin.deb",
|
||||
Path: debfile.Name(),
|
||||
})
|
||||
client := &DummyClient{}
|
||||
assert.NoError(t, doRun(ctx, client))
|
||||
assert.True(t, client.CreatedRelease)
|
||||
@ -79,7 +88,11 @@ func TestRunPipeWithFileThatDontExist(t *testing.T) {
|
||||
var ctx = context.New(config)
|
||||
ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
|
||||
ctx.Publish = true
|
||||
ctx.AddArtifact("this-file-wont-exist-hopefully")
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.UploadableArchive,
|
||||
Name: "bin.tar.gz",
|
||||
Path: "/nope/nope/nope",
|
||||
})
|
||||
client := &DummyClient{}
|
||||
assert.Error(t, doRun(ctx, client))
|
||||
assert.True(t, client.CreatedRelease)
|
||||
@ -102,7 +115,11 @@ func TestRunPipeUploadFailure(t *testing.T) {
|
||||
var ctx = context.New(config)
|
||||
ctx.Git = context.GitInfo{CurrentTag: "v1.0.0"}
|
||||
ctx.Publish = true
|
||||
ctx.AddArtifact(tarfile.Name())
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.UploadableArchive,
|
||||
Name: "bin.tar.gz",
|
||||
Path: tarfile.Name(),
|
||||
})
|
||||
client := &DummyClient{
|
||||
FailToUpload: true,
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/goreleaser/internal/testlib"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
)
|
||||
|
||||
@ -39,9 +40,15 @@ func (Pipe) Default(ctx *context.Context) error {
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
switch ctx.Config.Sign.Artifacts {
|
||||
case "checksum":
|
||||
return sign(ctx, ctx.Checksums)
|
||||
return sign(ctx, ctx.Artifacts.Filter(artifact.ByType(artifact.Checksum)).List())
|
||||
case "all":
|
||||
return sign(ctx, ctx.Artifacts)
|
||||
return sign(ctx, ctx.Artifacts.Filter(
|
||||
artifact.Or(
|
||||
artifact.ByType(artifact.UploadableArchive),
|
||||
artifact.ByType(artifact.UploadableBinary),
|
||||
artifact.ByType(artifact.Checksum),
|
||||
artifact.ByType(artifact.LinuxPackage),
|
||||
)).List())
|
||||
case "none":
|
||||
return pipeline.Skip("artifact signing disabled")
|
||||
default:
|
||||
@ -49,7 +56,7 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
func sign(ctx *context.Context, artifacts []string) error {
|
||||
func sign(ctx *context.Context, artifacts []artifact.Artifact) error {
|
||||
var sigs []string
|
||||
for _, a := range artifacts {
|
||||
sig, err := signone(ctx, a)
|
||||
@ -59,17 +66,20 @@ func sign(ctx *context.Context, artifacts []string) error {
|
||||
sigs = append(sigs, sig)
|
||||
}
|
||||
for _, sig := range sigs {
|
||||
ctx.AddArtifact(sig)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.Signature,
|
||||
Name: sig,
|
||||
Path: filepath.Join(ctx.Config.Dist, sig),
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func signone(ctx *context.Context, artifact string) (string, error) {
|
||||
func signone(ctx *context.Context, artifact artifact.Artifact) (string, error) {
|
||||
cfg := ctx.Config.Sign
|
||||
|
||||
artifact = filepath.Join(ctx.Config.Dist, artifact)
|
||||
env := map[string]string{
|
||||
"artifact": artifact,
|
||||
"artifact": artifact.Path,
|
||||
}
|
||||
env["signature"] = expand(cfg.Signature, env)
|
||||
|
||||
@ -87,7 +97,7 @@ func signone(ctx *context.Context, artifact string) (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("sign: %s failed with %q", cfg.Cmd, string(output))
|
||||
}
|
||||
return env["signature"], nil
|
||||
return filepath.Base(env["signature"]), nil
|
||||
}
|
||||
|
||||
func expand(s string, env map[string]string) string {
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -44,9 +44,7 @@ func TestSignInvalidArtifacts(t *testing.T) {
|
||||
|
||||
func TestSignArtifacts(t *testing.T) {
|
||||
// fix permission on keyring dir to suppress warning about insecure permissions
|
||||
if err := os.Chmod(keyring, 0700); err != nil {
|
||||
t.Fatal("Chmod: ", err)
|
||||
}
|
||||
assert.NoError(t, os.Chmod(keyring, 0700))
|
||||
|
||||
tests := []struct {
|
||||
desc string
|
||||
@ -55,24 +53,20 @@ func TestSignArtifacts(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
desc: "sign all artifacts",
|
||||
ctx: &context.Context{
|
||||
Config: config.Project{
|
||||
ctx: context.New(
|
||||
config.Project{
|
||||
Sign: config.Sign{Artifacts: "all"},
|
||||
},
|
||||
Artifacts: []string{"artifact1", "artifact2", "checksum"},
|
||||
Checksums: []string{"checksum"},
|
||||
},
|
||||
),
|
||||
signatures: []string{"artifact1.sig", "artifact2.sig", "checksum.sig"},
|
||||
},
|
||||
{
|
||||
desc: "sign only checksums",
|
||||
ctx: &context.Context{
|
||||
Config: config.Project{
|
||||
ctx: context.New(
|
||||
config.Project{
|
||||
Sign: config.Sign{Artifacts: "checksum"},
|
||||
},
|
||||
Artifacts: []string{"artifact1", "artifact2", "checksum"},
|
||||
Checksums: []string{"checksum"},
|
||||
},
|
||||
),
|
||||
signatures: []string{"checksum.sig"},
|
||||
},
|
||||
}
|
||||
@ -90,49 +84,50 @@ const user = "nopass"
|
||||
func testSign(t *testing.T, ctx *context.Context, signatures []string) {
|
||||
// create temp dir for file and signature
|
||||
tmpdir, err := ioutil.TempDir("", "goreleaser")
|
||||
if err != nil {
|
||||
t.Fatal("TempDir: ", err)
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
ctx.Config.Dist = tmpdir
|
||||
|
||||
// create some fake artifacts
|
||||
artifacts := ctx.Artifacts
|
||||
var artifacts = []string{"artifact1", "artifact2", "checksum"}
|
||||
for _, f := range artifacts {
|
||||
file := filepath.Join(tmpdir, f)
|
||||
if err2 := ioutil.WriteFile(file, []byte("foo"), 0644); err2 != nil {
|
||||
t.Fatal("WriteFile: ", err2)
|
||||
}
|
||||
assert.NoError(t, ioutil.WriteFile(file, []byte("foo"), 0644))
|
||||
}
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "artifact1",
|
||||
Path: filepath.Join(tmpdir, "artifact1"),
|
||||
Type: artifact.UploadableArchive,
|
||||
})
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "artifact2",
|
||||
Path: filepath.Join(tmpdir, "artifact2"),
|
||||
Type: artifact.UploadableArchive,
|
||||
})
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "checksum",
|
||||
Path: filepath.Join(tmpdir, "checksum"),
|
||||
Type: artifact.Checksum,
|
||||
})
|
||||
|
||||
// configure the pipeline
|
||||
// make sure we are using the test keyring
|
||||
err = Pipe{}.Default(ctx)
|
||||
if err != nil {
|
||||
t.Fatal("Default: ", err)
|
||||
}
|
||||
assert.NoError(t, Pipe{}.Default(ctx))
|
||||
ctx.Config.Sign.Args = append([]string{"--homedir", keyring}, ctx.Config.Sign.Args...)
|
||||
|
||||
// run the pipeline
|
||||
err = Pipe{}.Run(ctx)
|
||||
if err != nil {
|
||||
t.Fatal("Run: ", err)
|
||||
}
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
|
||||
// verify that only the artifacts and the signatures are in the dist dir
|
||||
files, err := ioutil.ReadDir(tmpdir)
|
||||
if err != nil {
|
||||
t.Fatal("ReadDir: ", err)
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
gotFiles := []string{}
|
||||
for _, f := range files {
|
||||
gotFiles = append(gotFiles, f.Name())
|
||||
}
|
||||
|
||||
wantFiles := append(artifacts, signatures...)
|
||||
sort.Strings(wantFiles)
|
||||
|
||||
assert.Equal(t, wantFiles, gotFiles)
|
||||
|
||||
// verify the signatures
|
||||
@ -140,8 +135,12 @@ func testSign(t *testing.T, ctx *context.Context, signatures []string) {
|
||||
verifySignature(t, ctx, sig)
|
||||
}
|
||||
|
||||
var signArtifacts []string
|
||||
for _, sig := range ctx.Artifacts.Filter(artifact.ByType(artifact.Signature)).List() {
|
||||
signArtifacts = append(signArtifacts, sig.Name)
|
||||
}
|
||||
// check signature is an artifact
|
||||
assert.Equal(t, ctx.Artifacts, append(artifacts, signatures...))
|
||||
assert.Equal(t, signArtifacts, signatures)
|
||||
}
|
||||
|
||||
func verifySignature(t *testing.T, ctx *context.Context, sig string) {
|
||||
@ -150,10 +149,7 @@ func verifySignature(t *testing.T, ctx *context.Context, sig string) {
|
||||
// verify signature was made with key for usesr 'nopass'
|
||||
cmd := exec.Command("gpg", "--homedir", keyring, "--verify", filepath.Join(ctx.Config.Dist, sig), filepath.Join(ctx.Config.Dist, artifact))
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Log(string(out))
|
||||
t.Fatal("verify: ", err)
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
|
||||
// check if the signature matches the user we expect to do this properly we
|
||||
// might need to have either separate keyrings or export the key from the
|
||||
|
@ -8,14 +8,16 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/linux"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
"golang.org/x/sync/errgroup"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/linux"
|
||||
"github.com/goreleaser/goreleaser/internal/nametemplate"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
)
|
||||
|
||||
// ErrNoSnapcraft is shown when snapcraft cannot be found in $PATH
|
||||
@ -70,29 +72,34 @@ func (Pipe) Run(ctx *context.Context) error {
|
||||
}
|
||||
|
||||
var g errgroup.Group
|
||||
for platform, groups := range ctx.Binaries {
|
||||
if !strings.Contains(platform, "linux") {
|
||||
log.WithField("platform", platform).Debug("skipped non-linux builds for snapcraft")
|
||||
continue
|
||||
}
|
||||
arch := linux.Arch(platform)
|
||||
for folder, binaries := range groups {
|
||||
for platform, binaries := range ctx.Artifacts.Filter(
|
||||
artifact.And(
|
||||
artifact.ByGoos("linux"),
|
||||
artifact.ByType(artifact.Binary),
|
||||
),
|
||||
).GroupByPlatform() {
|
||||
arch := linux.Arch(platform) // TODO: could use artifact.goarch here
|
||||
binaries := binaries
|
||||
g.Go(func() error {
|
||||
return create(ctx, folder, arch, binaries)
|
||||
return create(ctx, arch, binaries)
|
||||
})
|
||||
}
|
||||
}
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
func create(ctx *context.Context, folder, arch string, binaries []context.Binary) error {
|
||||
func create(ctx *context.Context, arch string, binaries []artifact.Artifact) error {
|
||||
var log = log.WithField("arch", arch)
|
||||
// TODO: should add template support here probably... for now, let's use archive's template
|
||||
folder, err := nametemplate.Apply(ctx, binaries[0], ctx.Config.ProjectName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// prime is the directory that then will be compressed to make the .snap package.
|
||||
var folderDir = filepath.Join(ctx.Config.Dist, folder)
|
||||
var primeDir = filepath.Join(folderDir, "prime")
|
||||
var metaDir = filepath.Join(primeDir, "meta")
|
||||
// #nosec
|
||||
if err := os.MkdirAll(metaDir, 0755); err != nil {
|
||||
if err = os.MkdirAll(metaDir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -128,7 +135,7 @@ func create(ctx *context.Context, folder, arch string, binaries []context.Binary
|
||||
metadata.Apps[binary.Name] = appMetadata
|
||||
|
||||
destBinaryPath := filepath.Join(primeDir, filepath.Base(binary.Path))
|
||||
if err := os.Link(binary.Path, destBinaryPath); err != nil {
|
||||
if err = os.Link(binary.Path, destBinaryPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -147,6 +154,13 @@ func create(ctx *context.Context, folder, arch string, binaries []context.Binary
|
||||
if out, err = cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to generate snap package: %s", string(out))
|
||||
}
|
||||
ctx.AddArtifact(snap)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Type: artifact.LinuxPackage,
|
||||
Name: folder + ".snap",
|
||||
Path: snap,
|
||||
Goos: binaries[0].Goos,
|
||||
Goarch: binaries[0].Goarch,
|
||||
Goarm: binaries[0].Goarm,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/goreleaser/goreleaser/config"
|
||||
"github.com/goreleaser/goreleaser/context"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/pipeline"
|
||||
"github.com/stretchr/testify/assert"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
@ -47,9 +48,14 @@ func TestRunPipe(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
var ctx = &context.Context{
|
||||
Version: "testversion",
|
||||
Artifacts: artifact.New(),
|
||||
Config: config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
// TODO: remove this when we start using our own name template
|
||||
Archive: config.Archive{
|
||||
NameTemplate: "foo_{{.Arch}}",
|
||||
},
|
||||
Snapcraft: config.Snapcraft{
|
||||
Summary: "test summary",
|
||||
Description: "test description",
|
||||
@ -68,9 +74,14 @@ func TestRunPipeWithName(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
var ctx = &context.Context{
|
||||
Version: "testversion",
|
||||
Artifacts: artifact.New(),
|
||||
Config: config.Project{
|
||||
ProjectName: "testprojectname",
|
||||
Dist: dist,
|
||||
// TODO: remove this when we start using our own name template
|
||||
Archive: config.Archive{
|
||||
NameTemplate: "foo_{{.Arch}}",
|
||||
},
|
||||
Snapcraft: config.Snapcraft{
|
||||
Name: "testsnapname",
|
||||
Summary: "test summary",
|
||||
@ -80,7 +91,7 @@ func TestRunPipeWithName(t *testing.T) {
|
||||
}
|
||||
addBinaries(t, ctx, "testprojectname", dist)
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "testprojectname_linuxamd64", "prime", "meta", "snap.yaml"))
|
||||
yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "foo_amd64", "prime", "meta", "snap.yaml"))
|
||||
assert.NoError(t, err)
|
||||
var metadata Metadata
|
||||
err = yaml.Unmarshal(yamlFile, &metadata)
|
||||
@ -96,9 +107,14 @@ func TestRunPipeWithPlugsAndDaemon(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
var ctx = &context.Context{
|
||||
Version: "testversion",
|
||||
Artifacts: artifact.New(),
|
||||
Config: config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
// TODO: remove this when we start using our own name template
|
||||
Archive: config.Archive{
|
||||
NameTemplate: "foo_{{.Arch}}",
|
||||
},
|
||||
Snapcraft: config.Snapcraft{
|
||||
Summary: "test summary",
|
||||
Description: "test description",
|
||||
@ -113,7 +129,7 @@ func TestRunPipeWithPlugsAndDaemon(t *testing.T) {
|
||||
}
|
||||
addBinaries(t, ctx, "mybin", dist)
|
||||
assert.NoError(t, Pipe{}.Run(ctx))
|
||||
yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "mybin_linuxamd64", "prime", "meta", "snap.yaml"))
|
||||
yamlFile, err := ioutil.ReadFile(filepath.Join(dist, "foo_amd64", "prime", "meta", "snap.yaml"))
|
||||
assert.NoError(t, err)
|
||||
var metadata Metadata
|
||||
err = yaml.Unmarshal(yamlFile, &metadata)
|
||||
@ -140,19 +156,20 @@ func TestNoSnapcraftInPath(t *testing.T) {
|
||||
}
|
||||
|
||||
func addBinaries(t *testing.T, ctx *context.Context, name, dist string) {
|
||||
for _, plat := range []string{
|
||||
"linuxamd64",
|
||||
"linux386",
|
||||
"darwinamd64",
|
||||
"linuxarm64",
|
||||
"linuxarm6",
|
||||
"linuxwtf",
|
||||
} {
|
||||
var folder = name + "_" + plat
|
||||
for _, goos := range []string{"linux", "darwin"} {
|
||||
for _, goarch := range []string{"amd64", "386"} {
|
||||
var folder = goos + goarch
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, folder), 0755))
|
||||
var binPath = filepath.Join(dist, folder, name)
|
||||
_, err := os.Create(binPath)
|
||||
assert.NoError(t, err)
|
||||
ctx.AddBinary(plat, folder, name, binPath)
|
||||
ctx.Artifacts.Add(artifact.Artifact{
|
||||
Name: "mybin",
|
||||
Path: binPath,
|
||||
Goarch: goarch,
|
||||
Goos: goos,
|
||||
Type: artifact.Binary,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user