You've already forked goreleaser
mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-09-16 09:26:52 +02:00
refactor(docker): preparing for multiple backends (#2319)
* refactor(docker): preparing for multiple backends Signed-off-by: Carlos A Becker <caarlos0@gmail.com> * fix: remove pro test Signed-off-by: Carlos A Becker <caarlos0@gmail.com> * fix: merge issues Signed-off-by: Carlos A Becker <caarlos0@gmail.com> * fix: merge issues Signed-off-by: Carlos A Becker <caarlos0@gmail.com> * fix: merge issues Signed-off-by: Carlos A Becker <caarlos0@gmail.com>
This commit is contained in:
committed by
GitHub
parent
80037a9136
commit
91848616e3
@@ -3,15 +3,33 @@ package docker
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"sync"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/goreleaser/pkg/config"
|
||||
)
|
||||
|
||||
var (
|
||||
manifesters = map[string]manifester{}
|
||||
imagers = map[string]imager{}
|
||||
lock sync.Mutex
|
||||
)
|
||||
|
||||
func registerManifester(use string, impl manifester) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
manifesters[use] = impl
|
||||
}
|
||||
|
||||
func registerImager(use string, impl imager) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
imagers[use] = impl
|
||||
}
|
||||
|
||||
// imager is something that can build and push docker images.
|
||||
type imager interface {
|
||||
Build(ctx context.Context, root string, images, flags []string) error
|
||||
Push(ctx context.Context, image string) error
|
||||
Push(ctx context.Context, image string, flags []string) error
|
||||
}
|
||||
|
||||
// manifester is something that can create and push docker manifests.
|
||||
@@ -20,18 +38,8 @@ type manifester interface {
|
||||
Push(ctx context.Context, manifest string, flags []string) error
|
||||
}
|
||||
|
||||
func newManifester(manifest config.DockerManifest) manifester {
|
||||
return dockerManifester{}
|
||||
}
|
||||
|
||||
func newImager(docker config.Docker) imager {
|
||||
return dockerImager{
|
||||
buildx: docker.Use == useBuildx,
|
||||
}
|
||||
}
|
||||
|
||||
// nolint: unparam
|
||||
func runCommand(ctx context.Context, dir, binary string, args ...string) error {
|
||||
func runCommand(ctx context.Context, dir, binary string, args ...string) ([]byte, error) {
|
||||
/* #nosec */
|
||||
cmd := exec.CommandContext(ctx, binary, args...)
|
||||
cmd.Dir = dir
|
||||
@@ -39,5 +47,5 @@ func runCommand(ctx context.Context, dir, binary string, args ...string) error {
|
||||
log.Debug("running")
|
||||
out, err := cmd.CombinedOutput()
|
||||
log.Debug(string(out))
|
||||
return err
|
||||
return out, err
|
||||
}
|
||||
|
@@ -5,16 +5,25 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerManifester(useDocker, dockerManifester{})
|
||||
|
||||
registerImager(useDocker, dockerImager{})
|
||||
registerImager(useBuildx, dockerImager{
|
||||
buildx: true,
|
||||
})
|
||||
}
|
||||
|
||||
type dockerManifester struct{}
|
||||
|
||||
func (m dockerManifester) Create(ctx context.Context, manifest string, images, flags []string) error {
|
||||
_ = runCommand(ctx, ".", "docker", "manifest", "rm", manifest)
|
||||
_, _ = runCommand(ctx, ".", "docker", "manifest", "rm", manifest)
|
||||
|
||||
args := []string{"manifest", "create", manifest}
|
||||
args = append(args, images...)
|
||||
args = append(args, flags...)
|
||||
|
||||
if err := runCommand(ctx, ".", "docker", args...); err != nil {
|
||||
if _, err := runCommand(ctx, ".", "docker", args...); err != nil {
|
||||
return fmt.Errorf("failed to create %s: %w", manifest, err)
|
||||
}
|
||||
return nil
|
||||
@@ -23,7 +32,7 @@ func (m dockerManifester) Create(ctx context.Context, manifest string, images, f
|
||||
func (m dockerManifester) Push(ctx context.Context, manifest string, flags []string) error {
|
||||
args := []string{"manifest", "push", manifest}
|
||||
args = append(args, flags...)
|
||||
if err := runCommand(ctx, ".", "docker", args...); err != nil {
|
||||
if _, err := runCommand(ctx, ".", "docker", args...); err != nil {
|
||||
return fmt.Errorf("failed to push %s: %w", manifest, err)
|
||||
}
|
||||
return nil
|
||||
@@ -33,15 +42,15 @@ type dockerImager struct {
|
||||
buildx bool
|
||||
}
|
||||
|
||||
func (i dockerImager) Push(ctx context.Context, image string) error {
|
||||
if err := runCommand(ctx, ".", "docker", "push", image); err != nil {
|
||||
func (i dockerImager) Push(ctx context.Context, image string, flags []string) error {
|
||||
if _, err := runCommand(ctx, ".", "docker", "push", image); err != nil {
|
||||
return fmt.Errorf("failed to push %s: %w", image, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i dockerImager) Build(ctx context.Context, root string, images, flags []string) error {
|
||||
if err := runCommand(ctx, root, "docker", i.buildCommand(images, flags)...); err != nil {
|
||||
if _, err := runCommand(ctx, root, "docker", i.buildCommand(images, flags)...); err != nil {
|
||||
return fmt.Errorf("failed to build %s: %w", images[0], err)
|
||||
}
|
||||
return nil
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
@@ -25,8 +26,6 @@ const (
|
||||
useDocker = "docker"
|
||||
)
|
||||
|
||||
var validDockerUses = []string{useBuildx, useDocker}
|
||||
|
||||
// Pipe for docker.
|
||||
type Pipe struct{}
|
||||
|
||||
@@ -64,8 +63,8 @@ func (Pipe) Default(ctx *context.Context) error {
|
||||
if docker.Use == "" {
|
||||
docker.Use = useDocker
|
||||
}
|
||||
if !isValidUse(docker.Use) {
|
||||
return fmt.Errorf("docker: invalid use: %s, valid options are %v", docker.Use, validDockerUses)
|
||||
if err := validateImager(docker.Use); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, f := range docker.Files {
|
||||
if f == "." || strings.HasPrefix(f, ctx.Config.Dist) {
|
||||
@@ -76,13 +75,18 @@ func (Pipe) Default(ctx *context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func isValidUse(use string) bool {
|
||||
for _, s := range validDockerUses {
|
||||
func validateImager(use string) error {
|
||||
valid := make([]string, 0, len(imagers))
|
||||
for k := range imagers {
|
||||
valid = append(valid, k)
|
||||
}
|
||||
for _, s := range valid {
|
||||
if s == use {
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return false
|
||||
sort.Strings(valid)
|
||||
return fmt.Errorf("docker: invalid use: %s, valid options are %v", use, valid)
|
||||
}
|
||||
|
||||
// Run the pipe.
|
||||
@@ -167,7 +171,7 @@ func process(ctx *context.Context, docker config.Docker, artifacts []*artifact.A
|
||||
return err
|
||||
}
|
||||
|
||||
if err := newImager(docker).Build(ctx, tmp, images, buildFlags); err != nil {
|
||||
if err := imagers[docker.Use].Build(ctx, tmp, images, buildFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -257,7 +261,7 @@ func link(src, dest string) error {
|
||||
func dockerPush(ctx *context.Context, image *artifact.Artifact) error {
|
||||
log.WithField("image", image.Name).Info("pushing docker image")
|
||||
docker := image.Extra[dockerConfigExtra].(config.Docker)
|
||||
if err := newImager(docker).Push(ctx, image.Name); err != nil {
|
||||
if err := imagers[docker.Use].Push(ctx, image.Name, docker.PushFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
|
@@ -11,6 +11,7 @@ import (
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/goreleaser/goreleaser/internal/artifact"
|
||||
"github.com/goreleaser/goreleaser/internal/pipe"
|
||||
"github.com/goreleaser/goreleaser/internal/testlib"
|
||||
@@ -21,6 +22,7 @@ import (
|
||||
|
||||
var (
|
||||
it = flag.Bool("it", false, "push images to docker hub")
|
||||
debug = flag.Bool("debug", false, "enable debug logs")
|
||||
registry = "localhost:5000/"
|
||||
altRegistry = "localhost:5050/"
|
||||
)
|
||||
@@ -30,6 +32,9 @@ func TestMain(m *testing.M) {
|
||||
if *it {
|
||||
registry = "docker.io/"
|
||||
}
|
||||
if *debug {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -38,17 +43,15 @@ func start(t *testing.T) {
|
||||
if *it {
|
||||
return
|
||||
}
|
||||
if out, err := exec.Command(
|
||||
"docker", "run", "-d", "-p", "5000:5000", "--name", "registry", "registry:2",
|
||||
).CombinedOutput(); err != nil {
|
||||
t.Log("failed to start docker registry", string(out), err)
|
||||
t.FailNow()
|
||||
}
|
||||
if out, err := exec.Command(
|
||||
"docker", "run", "-d", "-p", "5050:5000", "--name", "alt_registry", "registry:2",
|
||||
).CombinedOutput(); err != nil {
|
||||
t.Log("failed to start alternate docker registry", string(out), err)
|
||||
t.FailNow()
|
||||
t.Log("starting registries")
|
||||
for _, line := range []string{
|
||||
"run -d -p 5000:5000 --name registry registry:2",
|
||||
"run -d -p 5050:5000 --name alt_registry registry:2",
|
||||
} {
|
||||
if out, err := exec.Command("docker", strings.Fields(line)...).CombinedOutput(); err != nil {
|
||||
t.Log("failed to start docker registry", string(out), err)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,11 +60,10 @@ func killAndRm(t *testing.T) {
|
||||
if *it {
|
||||
return
|
||||
}
|
||||
t.Log("killing registry")
|
||||
_ = exec.Command("docker", "kill", "registry").Run()
|
||||
_ = exec.Command("docker", "rm", "registry").Run()
|
||||
_ = exec.Command("docker", "kill", "alt_registry").Run()
|
||||
_ = exec.Command("docker", "rm", "alt_registry").Run()
|
||||
t.Log("killing registries")
|
||||
for _, registry := range []string{"registry", "alt_registry"} {
|
||||
_ = exec.Command("docker", "rm", "--force", registry).Run()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this test is too big... split in smaller tests? Mainly the manifest ones...
|
||||
@@ -78,22 +80,24 @@ func TestRunPipe(t *testing.T) {
|
||||
t.Helper()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
type imageLabelFinder func(*testing.T, int)
|
||||
shouldFindImagesWithLabels := func(image string, filters ...string) func(*testing.T, int) {
|
||||
return func(t *testing.T, count int) {
|
||||
type imageLabelFinder func(*testing.T, string)
|
||||
shouldFindImagesWithLabels := func(image string, filters ...string) func(*testing.T, string) {
|
||||
return func(t *testing.T, use string) {
|
||||
t.Helper()
|
||||
for _, filter := range filters {
|
||||
output, err := exec.Command(
|
||||
"docker", "images", "-q", "*/"+image,
|
||||
"--filter", filter,
|
||||
).CombinedOutput()
|
||||
require.NoError(t, err)
|
||||
lines := strings.Split(strings.TrimSpace(string(output)), "\n")
|
||||
require.Equal(t, count, len(lines))
|
||||
cmd := exec.Command("docker", "images", "-q", "--filter", "reference=*/"+image, "--filter", filter)
|
||||
t.Log("running", cmd)
|
||||
output, err := cmd.CombinedOutput()
|
||||
require.NoError(t, err, string(output))
|
||||
uniqueIDs := map[string]string{}
|
||||
for _, id := range strings.Split(strings.TrimSpace(string(output)), "\n") {
|
||||
uniqueIDs[id] = id
|
||||
}
|
||||
require.Equal(t, 1, len(uniqueIDs))
|
||||
}
|
||||
}
|
||||
}
|
||||
noLabels := func(t *testing.T, count int) {
|
||||
noLabels := func(t *testing.T, _ string) {
|
||||
t.Helper()
|
||||
}
|
||||
|
||||
@@ -127,14 +131,11 @@ func TestRunPipe(t *testing.T) {
|
||||
},
|
||||
manifests: []config.DockerManifest{
|
||||
{
|
||||
// XXX: fails if :latest https://github.com/docker/distribution/issues/3100
|
||||
NameTemplate: registry + "goreleaser/test_multiarch:test",
|
||||
ImageTemplates: []string{
|
||||
registry + "goreleaser/test_multiarch:test-amd64",
|
||||
registry + "goreleaser/test_multiarch:test-arm64v8",
|
||||
},
|
||||
CreateFlags: []string{"--insecure"},
|
||||
PushFlags: []string{"--insecure"},
|
||||
},
|
||||
},
|
||||
expect: []string{
|
||||
@@ -161,9 +162,7 @@ func TestRunPipe(t *testing.T) {
|
||||
ImageTemplates: []string{
|
||||
registry + "goreleaser/test_manifestskip:test-amd64",
|
||||
},
|
||||
CreateFlags: []string{"--insecure"},
|
||||
PushFlags: []string{"--insecure"},
|
||||
SkipPush: "auto",
|
||||
SkipPush: "auto",
|
||||
},
|
||||
},
|
||||
expect: []string{
|
||||
@@ -189,9 +188,7 @@ func TestRunPipe(t *testing.T) {
|
||||
ImageTemplates: []string{
|
||||
registry + "goreleaser/test_manifestskip-prerelease:test-amd64",
|
||||
},
|
||||
CreateFlags: []string{"--insecure"},
|
||||
PushFlags: []string{"--insecure"},
|
||||
SkipPush: "auto",
|
||||
SkipPush: "auto",
|
||||
},
|
||||
},
|
||||
expect: []string{
|
||||
@@ -221,9 +218,7 @@ func TestRunPipe(t *testing.T) {
|
||||
ImageTemplates: []string{
|
||||
registry + "goreleaser/test_manifestskip-true:test-amd64",
|
||||
},
|
||||
CreateFlags: []string{"--insecure"},
|
||||
PushFlags: []string{"--insecure"},
|
||||
SkipPush: "true",
|
||||
SkipPush: "true",
|
||||
},
|
||||
},
|
||||
expect: []string{
|
||||
@@ -253,14 +248,11 @@ func TestRunPipe(t *testing.T) {
|
||||
},
|
||||
manifests: []config.DockerManifest{
|
||||
{
|
||||
// XXX: fails if :latest https://github.com/docker/distribution/issues/3100
|
||||
NameTemplate: registry + "goreleaser/test_multiarch:2test",
|
||||
ImageTemplates: []string{
|
||||
registry + "goreleaser/test_multiarch:2test-amd64",
|
||||
registry + "goreleaser/test_multiarch:2test-arm64v8",
|
||||
},
|
||||
CreateFlags: []string{"--insecure"},
|
||||
PushFlags: []string{"--insecure"},
|
||||
},
|
||||
},
|
||||
expect: []string{
|
||||
@@ -273,56 +265,19 @@ func TestRunPipe(t *testing.T) {
|
||||
assertImageLabels: noLabels,
|
||||
extraPrepare: func(t *testing.T, ctx *context.Context) {
|
||||
t.Helper()
|
||||
_ = exec.Command(fmt.Sprintf("docker manifest rm %sgoreleaser/test_multiarch:2test ", registry)).Run()
|
||||
for _, cmd := range []string{
|
||||
fmt.Sprintf("docker build -t %sgoreleaser/dummy:v1 --platform linux/amd64 -f testdata/Dockerfile.dummy .", registry),
|
||||
fmt.Sprintf("docker push %sgoreleaser/dummy:v1", registry),
|
||||
fmt.Sprintf("docker manifest create %sgoreleaser/test_multiarch:2test --amend %sgoreleaser/dummy:v1 --insecure", registry, registry),
|
||||
} {
|
||||
t.Log("running", cmd)
|
||||
parts := strings.Fields(cmd)
|
||||
out, err := exec.CommandContext(ctx, parts[0], parts[1:]...).CombinedOutput()
|
||||
require.NoError(t, err, cmd+": "+string(out))
|
||||
}
|
||||
},
|
||||
},
|
||||
"multiarch with buildx": {
|
||||
dockers: []config.Docker{
|
||||
{
|
||||
ImageTemplates: []string{registry + "goreleaser/test_multiarch_buildx:amd64"},
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Buildx: true,
|
||||
BuildFlagTemplates: []string{"--platform=linux/amd64"},
|
||||
},
|
||||
{
|
||||
ImageTemplates: []string{registry + "goreleaser/test_multiarch_buildx:arm64v8"},
|
||||
Goos: "linux",
|
||||
Goarch: "arm64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Buildx: true,
|
||||
BuildFlagTemplates: []string{"--platform=linux/arm64"},
|
||||
},
|
||||
},
|
||||
manifests: []config.DockerManifest{
|
||||
{
|
||||
NameTemplate: registry + "goreleaser/test_multiarch_buildx:test",
|
||||
ImageTemplates: []string{
|
||||
registry + "goreleaser/test_multiarch_buildx:amd64",
|
||||
registry + "goreleaser/test_multiarch_buildx:arm64v8",
|
||||
},
|
||||
CreateFlags: []string{"--insecure"},
|
||||
PushFlags: []string{"--insecure"},
|
||||
},
|
||||
},
|
||||
expect: []string{
|
||||
registry + "goreleaser/test_multiarch_buildx:amd64",
|
||||
registry + "goreleaser/test_multiarch_buildx:arm64v8",
|
||||
},
|
||||
assertError: shouldNotErr,
|
||||
pubAssertError: shouldNotErr,
|
||||
manifestAssertError: shouldNotErr,
|
||||
assertImageLabels: noLabels,
|
||||
},
|
||||
"multiarch image not found": {
|
||||
dockers: []config.Docker{
|
||||
{
|
||||
@@ -337,8 +292,6 @@ func TestRunPipe(t *testing.T) {
|
||||
{
|
||||
NameTemplate: registry + "goreleaser/test_multiarch_fail:test",
|
||||
ImageTemplates: []string{registry + "goreleaser/test_multiarch_fail:latest-amd64"},
|
||||
CreateFlags: []string{"--insecure"},
|
||||
PushFlags: []string{"--insecure"},
|
||||
},
|
||||
},
|
||||
expect: []string{registry + "goreleaser/test_multiarch_fail:latest-arm64v8"},
|
||||
@@ -977,101 +930,118 @@ func TestRunPipe(t *testing.T) {
|
||||
defer killAndRm(t)
|
||||
|
||||
for name, docker := range table {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
folder := t.TempDir()
|
||||
dist := filepath.Join(folder, "dist")
|
||||
require.NoError(t, os.Mkdir(dist, 0o755))
|
||||
require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
|
||||
f, err := os.Create(filepath.Join(dist, "mybin", "mybin"))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
f, err = os.Create(filepath.Join(dist, "mybin", "anotherbin"))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
f, err = os.Create(filepath.Join(dist, "mynfpm.apk"))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
for _, arch := range []string{"amd64", "386", "arm64"} {
|
||||
f, err = os.Create(filepath.Join(dist, fmt.Sprintf("mybin_%s.apk", arch)))
|
||||
for imager := range imagers {
|
||||
t.Run(name+" on "+imager, func(t *testing.T) {
|
||||
folder := t.TempDir()
|
||||
dist := filepath.Join(folder, "dist")
|
||||
require.NoError(t, os.Mkdir(dist, 0o755))
|
||||
require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0o755))
|
||||
f, err := os.Create(filepath.Join(dist, "mybin", "mybin"))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
f, err = os.Create(filepath.Join(dist, "mybin", "anotherbin"))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
f, err = os.Create(filepath.Join(dist, "mynfpm.apk"))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
}
|
||||
|
||||
ctx := context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Dockers: docker.dockers,
|
||||
DockerManifests: docker.manifests,
|
||||
})
|
||||
ctx.Parallelism = 1
|
||||
ctx.Env = docker.env
|
||||
ctx.Version = "1.0.0"
|
||||
ctx.Git = context.GitInfo{
|
||||
CurrentTag: "v1.0.0",
|
||||
Commit: "a1b2c3d4",
|
||||
}
|
||||
ctx.Semver = context.Semver{
|
||||
Major: 1,
|
||||
Minor: 0,
|
||||
Patch: 0,
|
||||
}
|
||||
for _, os := range []string{"linux", "darwin"} {
|
||||
for _, arch := range []string{"amd64", "386", "arm64"} {
|
||||
for _, bin := range []string{"mybin", "anotherbin"} {
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: bin,
|
||||
Path: filepath.Join(dist, "mybin", bin),
|
||||
Goarch: arch,
|
||||
Goos: os,
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]interface{}{
|
||||
"ID": bin,
|
||||
},
|
||||
})
|
||||
f, err = os.Create(filepath.Join(dist, fmt.Sprintf("mybin_%s.apk", arch)))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, f.Close())
|
||||
}
|
||||
|
||||
ctx := context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Dockers: docker.dockers,
|
||||
DockerManifests: docker.manifests,
|
||||
})
|
||||
ctx.Parallelism = 1
|
||||
ctx.Env = docker.env
|
||||
ctx.Version = "1.0.0"
|
||||
ctx.Git = context.GitInfo{
|
||||
CurrentTag: "v1.0.0",
|
||||
Commit: "a1b2c3d4",
|
||||
}
|
||||
ctx.Semver = context.Semver{
|
||||
Major: 1,
|
||||
Minor: 0,
|
||||
Patch: 0,
|
||||
}
|
||||
for _, os := range []string{"linux", "darwin"} {
|
||||
for _, arch := range []string{"amd64", "386", "arm64"} {
|
||||
for _, bin := range []string{"mybin", "anotherbin"} {
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: bin,
|
||||
Path: filepath.Join(dist, "mybin", bin),
|
||||
Goarch: arch,
|
||||
Goos: os,
|
||||
Type: artifact.Binary,
|
||||
Extra: map[string]interface{}{
|
||||
"ID": bin,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, arch := range []string{"amd64", "386", "arm64"} {
|
||||
name := fmt.Sprintf("mybin_%s.apk", arch)
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: name,
|
||||
Path: filepath.Join(dist, name),
|
||||
Goarch: arch,
|
||||
Goos: "linux",
|
||||
Type: artifact.LinuxPackage,
|
||||
Extra: map[string]interface{}{
|
||||
"ID": "mybin",
|
||||
},
|
||||
})
|
||||
}
|
||||
for _, arch := range []string{"amd64", "386", "arm64"} {
|
||||
name := fmt.Sprintf("mybin_%s.apk", arch)
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: name,
|
||||
Path: filepath.Join(dist, name),
|
||||
Goarch: arch,
|
||||
Goos: "linux",
|
||||
Type: artifact.LinuxPackage,
|
||||
Extra: map[string]interface{}{
|
||||
"ID": "mybin",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if docker.extraPrepare != nil {
|
||||
docker.extraPrepare(t, ctx)
|
||||
}
|
||||
if docker.extraPrepare != nil {
|
||||
docker.extraPrepare(t, ctx)
|
||||
}
|
||||
|
||||
// this might fail as the image doesnt exist yet, so lets ignore the error
|
||||
for _, img := range docker.expect {
|
||||
_ = exec.Command("docker", "rmi", img).Run()
|
||||
}
|
||||
rmi := func(img string) error {
|
||||
return exec.Command("docker", "rmi", "--force", img).Run()
|
||||
}
|
||||
|
||||
err = Pipe{}.Run(ctx)
|
||||
docker.assertError(t, err)
|
||||
if err == nil {
|
||||
docker.pubAssertError(t, Pipe{}.Publish(ctx))
|
||||
docker.manifestAssertError(t, ManifestPipe{}.Publish(ctx))
|
||||
}
|
||||
// this might fail as the image doesnt exist yet, so lets ignore the error
|
||||
for _, img := range docker.expect {
|
||||
_ = rmi(img)
|
||||
}
|
||||
|
||||
for _, d := range docker.dockers {
|
||||
docker.assertImageLabels(t, len(d.ImageTemplates))
|
||||
}
|
||||
for i := range ctx.Config.Dockers {
|
||||
docker := &ctx.Config.Dockers[i]
|
||||
docker.Use = imager
|
||||
docker.PushFlags = []string{}
|
||||
}
|
||||
for i := range ctx.Config.DockerManifests {
|
||||
manifest := &ctx.Config.DockerManifests[i]
|
||||
manifest.Use = useDocker
|
||||
manifest.PushFlags = []string{"--insecure"}
|
||||
manifest.CreateFlags = []string{"--insecure"}
|
||||
}
|
||||
err = Pipe{}.Run(ctx)
|
||||
docker.assertError(t, err)
|
||||
if err == nil {
|
||||
docker.pubAssertError(t, Pipe{}.Publish(ctx))
|
||||
docker.manifestAssertError(t, ManifestPipe{}.Publish(ctx))
|
||||
}
|
||||
|
||||
// this might should not fail as the image should have been created when
|
||||
// the step ran
|
||||
for _, img := range docker.expect {
|
||||
t.Log("removing docker image", img)
|
||||
require.NoError(t, exec.Command("docker", "rmi", img).Run(), "could not delete image %s", img)
|
||||
}
|
||||
})
|
||||
for _, d := range docker.dockers {
|
||||
docker.assertImageLabels(t, d.Use)
|
||||
}
|
||||
|
||||
// this might should not fail as the image should have been created when
|
||||
// the step ran
|
||||
for _, img := range docker.expect {
|
||||
t.Log("removing docker image", img)
|
||||
require.NoError(t, rmi(img), "could not delete image %s", img)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1146,6 +1116,12 @@ func TestDefault(t *testing.T) {
|
||||
Use: useBuildx,
|
||||
},
|
||||
},
|
||||
DockerManifests: []config.DockerManifest{
|
||||
{},
|
||||
{
|
||||
Use: useDocker,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
require.NoError(t, Pipe{}.Default(ctx))
|
||||
@@ -1157,6 +1133,11 @@ func TestDefault(t *testing.T) {
|
||||
require.Equal(t, useDocker, docker.Use)
|
||||
docker = ctx.Config.Dockers[1]
|
||||
require.Equal(t, useBuildx, docker.Use)
|
||||
|
||||
require.NoError(t, ManifestPipe{}.Default(ctx))
|
||||
require.Len(t, ctx.Config.DockerManifests, 2)
|
||||
require.Equal(t, useDocker, ctx.Config.DockerManifests[0].Use)
|
||||
require.Equal(t, useDocker, ctx.Config.DockerManifests[1].Use)
|
||||
}
|
||||
|
||||
func TestDefaultInvalidUse(t *testing.T) {
|
||||
@@ -1167,9 +1148,20 @@ func TestDefaultInvalidUse(t *testing.T) {
|
||||
Use: "something",
|
||||
},
|
||||
},
|
||||
DockerManifests: []config.DockerManifest{
|
||||
{
|
||||
Use: "something",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
require.EqualError(t, Pipe{}.Default(ctx), `docker: invalid use: something, valid options are [buildx docker]`)
|
||||
err := Pipe{}.Default(ctx)
|
||||
require.Error(t, err)
|
||||
require.True(t, strings.HasPrefix(err.Error(), `docker: invalid use: something, valid options are`))
|
||||
|
||||
err = ManifestPipe{}.Default(ctx)
|
||||
require.Error(t, err)
|
||||
require.True(t, strings.HasPrefix(err.Error(), `docker manifest: invalid use: something, valid options are`))
|
||||
}
|
||||
|
||||
func TestDefaultDockerfile(t *testing.T) {
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
@@ -20,6 +22,20 @@ func (ManifestPipe) String() string {
|
||||
return "docker manifests"
|
||||
}
|
||||
|
||||
// Default sets the pipe defaults.
|
||||
func (ManifestPipe) Default(ctx *context.Context) error {
|
||||
for i := range ctx.Config.DockerManifests {
|
||||
manifest := &ctx.Config.DockerManifests[i]
|
||||
if manifest.Use == "" {
|
||||
manifest.Use = useDocker
|
||||
}
|
||||
if err := validateManifester(manifest.Use); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Publish the docker manifests.
|
||||
func (ManifestPipe) Publish(ctx *context.Context) error {
|
||||
if ctx.SkipPublish {
|
||||
@@ -47,7 +63,7 @@ func (ManifestPipe) Publish(ctx *context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
manifester := newManifester(manifest)
|
||||
manifester := manifesters[manifest.Use]
|
||||
|
||||
log.WithField("manifest", name).WithField("images", images).Info("creating docker manifest")
|
||||
if err := manifester.Create(ctx, name, images, manifest.CreateFlags); err != nil {
|
||||
@@ -66,6 +82,20 @@ func (ManifestPipe) Publish(ctx *context.Context) error {
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
func validateManifester(use string) error {
|
||||
valid := make([]string, 0, len(manifesters))
|
||||
for k := range manifesters {
|
||||
valid = append(valid, k)
|
||||
}
|
||||
for _, s := range valid {
|
||||
if s == use {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
sort.Strings(valid)
|
||||
return fmt.Errorf("docker manifest: invalid use: %s, valid options are %v", use, valid)
|
||||
}
|
||||
|
||||
func manifestName(ctx *context.Context, manifest config.DockerManifest) (string, error) {
|
||||
name, err := tmpl.New(ctx).Apply(manifest.NameTemplate)
|
||||
if err != nil {
|
||||
|
@@ -1,3 +1,3 @@
|
||||
ARG ARCH
|
||||
FROM ${ARCH}/alpine
|
||||
FROM docker.io/${ARCH}/alpine
|
||||
ADD mybin /
|
||||
|
@@ -513,6 +513,7 @@ type Docker struct {
|
||||
SkipPush string `yaml:"skip_push,omitempty"`
|
||||
Files []string `yaml:"extra_files,omitempty"`
|
||||
BuildFlagTemplates []string `yaml:"build_flag_templates,omitempty"`
|
||||
PushFlags []string `yaml:"push_flags,omitempty"`
|
||||
Buildx bool `yaml:"use_buildx,omitempty"` // deprecated: use Use instead
|
||||
Use string `yaml:"use,omitempty"`
|
||||
}
|
||||
@@ -524,6 +525,7 @@ type DockerManifest struct {
|
||||
ImageTemplates []string `yaml:"image_templates,omitempty"`
|
||||
CreateFlags []string `yaml:"create_flags,omitempty"`
|
||||
PushFlags []string `yaml:"push_flags,omitempty"`
|
||||
Use string `yaml:"use,omitempty"`
|
||||
}
|
||||
|
||||
// Filters config.
|
||||
|
Reference in New Issue
Block a user