mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-01-16 03:52:12 +02:00
fix: wrong docker manifest on latest (#2130)
* fix: wrong docker manifest on latest Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com> * fix: do not fail on missing manifest Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com> * fix: simplify code a bit Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com> * test: existing manifest Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com> * fix: lint Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>
This commit is contained in:
parent
7378edc708
commit
251e4486ed
@ -19,9 +19,11 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var it = flag.Bool("it", false, "push images to docker hub")
|
||||
var registry = "localhost:5000/"
|
||||
var altRegistry = "localhost:5050/"
|
||||
var (
|
||||
it = flag.Bool("it", false, "push images to docker hub")
|
||||
registry = "localhost:5000/"
|
||||
altRegistry = "localhost:5050/"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
@ -65,19 +67,19 @@ func killAndRm(t *testing.T) {
|
||||
// TODO: this test is too big... split in smaller tests? Mainly the manifest ones...
|
||||
func TestRunPipe(t *testing.T) {
|
||||
type errChecker func(*testing.T, error)
|
||||
var shouldErr = func(msg string) errChecker {
|
||||
shouldErr := func(msg string) errChecker {
|
||||
return func(t *testing.T, err error) {
|
||||
t.Helper()
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), msg)
|
||||
}
|
||||
}
|
||||
var shouldNotErr = func(t *testing.T, err error) {
|
||||
shouldNotErr := func(t *testing.T, err error) {
|
||||
t.Helper()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
type imageLabelFinder func(*testing.T, int)
|
||||
var shouldFindImagesWithLabels = func(image string, filters ...string) func(*testing.T, int) {
|
||||
shouldFindImagesWithLabels := func(image string, filters ...string) func(*testing.T, int) {
|
||||
return func(t *testing.T, count int) {
|
||||
t.Helper()
|
||||
for _, filter := range filters {
|
||||
@ -90,13 +92,12 @@ func TestRunPipe(t *testing.T) {
|
||||
require.Equal(t, count, len(lines))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
var noLabels = func(t *testing.T, count int) {
|
||||
noLabels := func(t *testing.T, count int) {
|
||||
t.Helper()
|
||||
}
|
||||
|
||||
var table = map[string]struct {
|
||||
table := map[string]struct {
|
||||
dockers []config.Docker
|
||||
manifests []config.DockerManifest
|
||||
env map[string]string
|
||||
@ -105,7 +106,7 @@ func TestRunPipe(t *testing.T) {
|
||||
assertError errChecker
|
||||
pubAssertError errChecker
|
||||
manifestAssertError errChecker
|
||||
extraPrepare func(ctx *context.Context)
|
||||
extraPrepare func(t *testing.T, ctx *context.Context)
|
||||
}{
|
||||
"multiarch": {
|
||||
dockers: []config.Docker{
|
||||
@ -145,6 +146,55 @@ func TestRunPipe(t *testing.T) {
|
||||
manifestAssertError: shouldNotErr,
|
||||
assertImageLabels: noLabels,
|
||||
},
|
||||
"multiarch with previous existing manifest": {
|
||||
dockers: []config.Docker{
|
||||
{
|
||||
ImageTemplates: []string{registry + "goreleaser/test_multiarch:2test-amd64"},
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile.arch",
|
||||
BuildFlagTemplates: []string{"--build-arg", "ARCH=amd64"},
|
||||
},
|
||||
{
|
||||
ImageTemplates: []string{registry + "goreleaser/test_multiarch:2test-arm64v8"},
|
||||
Goos: "linux",
|
||||
Goarch: "arm64",
|
||||
Dockerfile: "testdata/Dockerfile.arch",
|
||||
BuildFlagTemplates: []string{"--build-arg", "ARCH=arm64v8"},
|
||||
},
|
||||
},
|
||||
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{
|
||||
registry + "goreleaser/test_multiarch:2test-amd64",
|
||||
registry + "goreleaser/test_multiarch:2test-arm64v8",
|
||||
},
|
||||
assertError: shouldNotErr,
|
||||
pubAssertError: shouldNotErr,
|
||||
manifestAssertError: shouldNotErr,
|
||||
assertImageLabels: noLabels,
|
||||
extraPrepare: func(t *testing.T, ctx *context.Context) {
|
||||
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),
|
||||
} {
|
||||
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{
|
||||
{
|
||||
@ -578,7 +628,7 @@ func TestRunPipe(t *testing.T) {
|
||||
},
|
||||
},
|
||||
assertImageLabels: noLabels,
|
||||
assertError: shouldErr("pull access denied for nope, repository does not exist"),
|
||||
assertError: shouldErr("pull access denied"),
|
||||
},
|
||||
"tag_template_error": {
|
||||
dockers: []config.Docker{
|
||||
@ -721,7 +771,7 @@ func TestRunPipe(t *testing.T) {
|
||||
},
|
||||
assertImageLabels: noLabels,
|
||||
assertError: shouldErr(`/wont-exist: no such file or directory`),
|
||||
extraPrepare: func(ctx *context.Context) {
|
||||
extraPrepare: func(t *testing.T, ctx *context.Context) {
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: "wont-exist",
|
||||
Path: "wont-exist",
|
||||
@ -796,10 +846,10 @@ func TestRunPipe(t *testing.T) {
|
||||
|
||||
for name, docker := range table {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
var folder = t.TempDir()
|
||||
var dist = filepath.Join(folder, "dist")
|
||||
require.NoError(t, os.Mkdir(dist, 0755))
|
||||
require.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
|
||||
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))
|
||||
_, err := os.Create(filepath.Join(dist, "mybin", "mybin"))
|
||||
require.NoError(t, err)
|
||||
_, err = os.Create(filepath.Join(dist, "mybin", "anotherbin"))
|
||||
@ -811,7 +861,7 @@ func TestRunPipe(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
var ctx = context.New(config.Project{
|
||||
ctx := context.New(config.Project{
|
||||
ProjectName: "mybin",
|
||||
Dist: dist,
|
||||
Dockers: docker.dockers,
|
||||
@ -846,7 +896,7 @@ func TestRunPipe(t *testing.T) {
|
||||
}
|
||||
}
|
||||
for _, arch := range []string{"amd64", "386", "arm64"} {
|
||||
var name = fmt.Sprintf("mybin_%s.apk", arch)
|
||||
name := fmt.Sprintf("mybin_%s.apk", arch)
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
Name: name,
|
||||
Path: filepath.Join(dist, name),
|
||||
@ -860,7 +910,7 @@ func TestRunPipe(t *testing.T) {
|
||||
}
|
||||
|
||||
if docker.extraPrepare != nil {
|
||||
docker.extraPrepare(ctx)
|
||||
docker.extraPrepare(t, ctx)
|
||||
}
|
||||
|
||||
// this might fail as the image doesnt exist yet, so lets ignore the error
|
||||
@ -885,7 +935,6 @@ func TestRunPipe(t *testing.T) {
|
||||
t.Log("removing docker image", img)
|
||||
require.NoError(t, exec.Command("docker", "rmi", img).Run(), "could not delete image %s", img)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -946,12 +995,12 @@ func TestNoDockerWithoutImageName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDockerNotInPath(t *testing.T) {
|
||||
var path = os.Getenv("PATH")
|
||||
path := os.Getenv("PATH")
|
||||
defer func() {
|
||||
require.NoError(t, os.Setenv("PATH", path))
|
||||
}()
|
||||
require.NoError(t, os.Setenv("PATH", ""))
|
||||
var ctx = &context.Context{
|
||||
ctx := &context.Context{
|
||||
Version: "1.0.0",
|
||||
Config: config.Project{
|
||||
Dockers: []config.Docker{
|
||||
@ -965,7 +1014,7 @@ func TestDockerNotInPath(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
ctx := &context.Context{
|
||||
Config: config.Project{
|
||||
Dockers: []config.Docker{
|
||||
{
|
||||
@ -978,14 +1027,14 @@ func TestDefault(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, Pipe{}.Default(ctx))
|
||||
require.Len(t, ctx.Config.Dockers, 1)
|
||||
var docker = ctx.Config.Dockers[0]
|
||||
docker := ctx.Config.Dockers[0]
|
||||
require.Equal(t, "linux", docker.Goos)
|
||||
require.Equal(t, "amd64", docker.Goarch)
|
||||
require.Equal(t, []string{"aa", "foo"}, docker.IDs)
|
||||
}
|
||||
|
||||
func TestDefaultDockerfile(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
ctx := &context.Context{
|
||||
Config: config.Project{
|
||||
Builds: []config.Build{
|
||||
{},
|
||||
@ -1003,7 +1052,7 @@ func TestDefaultDockerfile(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDraftRelease(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
ctx := &context.Context{
|
||||
Config: config.Project{
|
||||
Release: config.Release{
|
||||
Draft: true,
|
||||
@ -1015,7 +1064,7 @@ func TestDraftRelease(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDefaultNoDockers(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
ctx := &context.Context{
|
||||
Config: config.Project{
|
||||
Dockers: []config.Docker{},
|
||||
},
|
||||
@ -1025,7 +1074,7 @@ func TestDefaultNoDockers(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDefaultFilesDot(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
ctx := &context.Context{
|
||||
Config: config.Project{
|
||||
Dist: "/tmp/distt",
|
||||
Dockers: []config.Docker{
|
||||
@ -1039,7 +1088,7 @@ func TestDefaultFilesDot(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDefaultFilesDis(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
ctx := &context.Context{
|
||||
Config: config.Project{
|
||||
Dist: "/tmp/dist",
|
||||
Dockers: []config.Docker{
|
||||
@ -1053,7 +1102,7 @@ func TestDefaultFilesDis(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDefaultSet(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
ctx := &context.Context{
|
||||
Config: config.Project{
|
||||
Dockers: []config.Docker{
|
||||
{
|
||||
@ -1067,7 +1116,7 @@ func TestDefaultSet(t *testing.T) {
|
||||
}
|
||||
require.NoError(t, Pipe{}.Default(ctx))
|
||||
require.Len(t, ctx.Config.Dockers, 1)
|
||||
var docker = ctx.Config.Dockers[0]
|
||||
docker := ctx.Config.Dockers[0]
|
||||
require.Equal(t, "windows", docker.Goos)
|
||||
require.Equal(t, "i386", docker.Goarch)
|
||||
require.Equal(t, []string{"foo"}, docker.IDs)
|
||||
@ -1075,7 +1124,7 @@ func TestDefaultSet(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_processImageTemplates(t *testing.T) {
|
||||
var ctx = &context.Context{
|
||||
ctx := &context.Context{
|
||||
Config: config.Project{
|
||||
Builds: []config.Build{
|
||||
{
|
||||
@ -1136,29 +1185,29 @@ func TestLinkFile(t *testing.T) {
|
||||
})
|
||||
fmt.Println("src:", src.Name())
|
||||
fmt.Println("dst:", dst)
|
||||
require.NoError(t, ioutil.WriteFile(src.Name(), []byte("foo"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(src.Name(), []byte("foo"), 0o644))
|
||||
require.NoError(t, link(src.Name(), dst))
|
||||
require.Equal(t, inode(src.Name()), inode(dst))
|
||||
}
|
||||
|
||||
func TestLinkDirectory(t *testing.T) {
|
||||
var srcDir = t.TempDir()
|
||||
var dstDir = t.TempDir()
|
||||
srcDir := t.TempDir()
|
||||
dstDir := t.TempDir()
|
||||
const testFile = "test"
|
||||
require.NoError(t, ioutil.WriteFile(filepath.Join(srcDir, testFile), []byte("foo"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.Join(srcDir, testFile), []byte("foo"), 0o644))
|
||||
require.NoError(t, link(srcDir, dstDir))
|
||||
require.Equal(t, inode(filepath.Join(srcDir, testFile)), inode(filepath.Join(dstDir, testFile)))
|
||||
}
|
||||
|
||||
func TestLinkTwoLevelDirectory(t *testing.T) {
|
||||
var srcDir = t.TempDir()
|
||||
var dstDir = t.TempDir()
|
||||
var srcLevel2 = filepath.Join(srcDir, "level2")
|
||||
srcDir := t.TempDir()
|
||||
dstDir := t.TempDir()
|
||||
srcLevel2 := filepath.Join(srcDir, "level2")
|
||||
const testFile = "test"
|
||||
|
||||
require.NoError(t, os.Mkdir(srcLevel2, 0755))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.Join(srcDir, testFile), []byte("foo"), 0644))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.Join(srcLevel2, testFile), []byte("foo"), 0644))
|
||||
require.NoError(t, os.Mkdir(srcLevel2, 0o755))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.Join(srcDir, testFile), []byte("foo"), 0o644))
|
||||
require.NoError(t, ioutil.WriteFile(filepath.Join(srcLevel2, testFile), []byte("foo"), 0o644))
|
||||
|
||||
require.NoError(t, link(srcDir, dstDir))
|
||||
|
||||
|
@ -27,7 +27,7 @@ func (ManifestPipe) Publish(ctx *context.Context) error {
|
||||
if ctx.SkipPublish {
|
||||
return pipe.ErrSkipPublishEnabled
|
||||
}
|
||||
var g = semerrgroup.NewSkipAware(semerrgroup.New(1))
|
||||
g := semerrgroup.NewSkipAware(semerrgroup.New(1))
|
||||
for _, manifest := range ctx.Config.DockerManifests {
|
||||
manifest := manifest
|
||||
g.Go(func() error {
|
||||
@ -35,6 +35,9 @@ func (ManifestPipe) Publish(ctx *context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dockerManifestRm(ctx, name); err != nil {
|
||||
return err
|
||||
}
|
||||
images, err := manifestImages(ctx, manifest)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -65,7 +68,7 @@ func manifestName(ctx *context.Context, manifest config.DockerManifest) (string,
|
||||
}
|
||||
|
||||
func manifestImages(ctx *context.Context, manifest config.DockerManifest) ([]string, error) {
|
||||
var imgs = make([]string, 0, len(manifest.ImageTemplates))
|
||||
imgs := make([]string, 0, len(manifest.ImageTemplates))
|
||||
for _, img := range manifest.ImageTemplates {
|
||||
str, err := tmpl.New(ctx).Apply(img)
|
||||
if err != nil {
|
||||
@ -79,16 +82,31 @@ func manifestImages(ctx *context.Context, manifest config.DockerManifest) ([]str
|
||||
return imgs, nil
|
||||
}
|
||||
|
||||
func dockerManifestRm(ctx *context.Context, manifest string) error {
|
||||
log.WithField("manifest", manifest).Info("removing local docker manifest")
|
||||
/* #nosec */
|
||||
cmd := exec.CommandContext(ctx, "docker", "manifest", "rm", manifest)
|
||||
log.WithField("cmd", cmd.Args).Debug("running")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
if strings.HasPrefix(string(out), "No such manifest: ") {
|
||||
// ignore "no such manifest" error, is the state we want in the end...
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("failed to remove local docker manifest: %s: \n%s: %w", manifest, string(out), err)
|
||||
}
|
||||
log.Debugf("docker manifest rm output: \n%s", string(out))
|
||||
return nil
|
||||
}
|
||||
|
||||
func dockerManifestCreate(ctx *context.Context, manifest string, images, flags []string) error {
|
||||
log.WithField("manifest", manifest).WithField("images", images).Info("creating docker manifest")
|
||||
var args = []string{"manifest", "create", manifest}
|
||||
for _, img := range images {
|
||||
args = append(args, "--amend", img)
|
||||
}
|
||||
args := []string{"manifest", "create", manifest}
|
||||
args = append(args, images...)
|
||||
args = append(args, flags...)
|
||||
/* #nosec */
|
||||
var cmd = exec.CommandContext(ctx, "docker", args...)
|
||||
log.WithField("cmd", cmd.Args).WithField("cwd", cmd.Dir).Debug("running")
|
||||
cmd := exec.CommandContext(ctx, "docker", args...)
|
||||
log.WithField("cmd", cmd.Args).Debug("running")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create docker manifest: %s: \n%s: %w", manifest, string(out), err)
|
||||
@ -99,11 +117,11 @@ func dockerManifestCreate(ctx *context.Context, manifest string, images, flags [
|
||||
|
||||
func dockerManifestPush(ctx *context.Context, manifest string, flags []string) error {
|
||||
log.WithField("manifest", manifest).Info("pushing docker manifest")
|
||||
var args = []string{"manifest", "push", manifest}
|
||||
args := []string{"manifest", "push", manifest}
|
||||
args = append(args, flags...)
|
||||
/* #nosec */
|
||||
var cmd = exec.CommandContext(ctx, "docker", args...)
|
||||
log.WithField("cmd", cmd.Args).WithField("cwd", cmd.Dir).Debug("running")
|
||||
cmd := exec.CommandContext(ctx, "docker", args...)
|
||||
log.WithField("cmd", cmd.Args).Debug("running")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to push docker manifest: %s: \n%s: %w", manifest, string(out), err)
|
||||
|
2
internal/pipe/docker/testdata/Dockerfile.dummy
vendored
Normal file
2
internal/pipe/docker/testdata/Dockerfile.dummy
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
FROM alpine
|
||||
RUN echo "hi"
|
Loading…
Reference in New Issue
Block a user