<commit_before>package docker

import (
	"fmt"
	"os/exec"
	"strings"

	"github.com/apex/log"
	"github.com/goreleaser/goreleaser/internal/pipe"
	"github.com/goreleaser/goreleaser/internal/semerrgroup"
	"github.com/goreleaser/goreleaser/internal/tmpl"
	"github.com/goreleaser/goreleaser/pkg/config"
	"github.com/goreleaser/goreleaser/pkg/context"
)

// ManifestPipe is beta implementation of for the docker manifest feature,
// allowing to publish multi-arch docker images.
type ManifestPipe struct{}

func (ManifestPipe) String() string {
	return "docker manifests"
}

// Publish the docker manifests.
func (ManifestPipe) Publish(ctx *context.Context) error {
	if ctx.SkipPublish {
		return pipe.ErrSkipPublishEnabled
	}
	var g = semerrgroup.NewSkipAware(semerrgroup.New(ctx.Parallelism))
	for _, manifest := range ctx.Config.DockerManifests {
		manifest := manifest
		g.Go(func() error {
			name, err := manifestName(ctx, manifest)
			if err != nil {
				return err
			}
			images, err := manifestImages(ctx, manifest)
			if err != nil {
				return err
			}
			if err := dockerManifestCreate(ctx, name, images, manifest.CreateFlags); err != nil {
				return err
			}
			return dockerManifestPush(ctx, name, manifest.PushFlags)
		})
	}
	return g.Wait()
}

func manifestName(ctx *context.Context, manifest config.DockerManifest) (string, error) {
	name, err := tmpl.New(ctx).Apply(manifest.NameTemplate)
	if err != nil {
		return name, err
	}
	if strings.TrimSpace(name) == "" {
		return name, pipe.Skip("manifest name is empty")
	}
	return name, nil
}

func manifestImages(ctx *context.Context, manifest config.DockerManifest) ([]string, error) {
	var imgs []string
	for _, img := range manifest.ImageTemplates {
		str, err := tmpl.New(ctx).Apply(img)
		if err != nil {
			return []string{}, err
		}
		imgs = append(imgs, str)
	}
	if strings.TrimSpace(strings.Join(manifest.ImageTemplates, "")) == "" {
		return imgs, pipe.Skip("manifest has no images")
	}
	return imgs, nil
}

func dockerManifestCreate(ctx *context.Context, manifest string, images, flags []string) error {
	log.WithField("manifest", manifest).Info("creating docker manifest")
	var args = []string{"manifest", "create", manifest}
	for _, img := range images {
		args = append(args, "--amend", img)
	}
	args = append(args, flags...)
	/* #nosec */
	var cmd = exec.CommandContext(ctx, "docker", args...)<commit_msg>chore: lint issues<commit_after>package docker

import (
	"fmt"
	"os/exec"
	"strings"

	"github.com/apex/log"
	"github.com/goreleaser/goreleaser/internal/pipe"
	"github.com/goreleaser/goreleaser/internal/semerrgroup"
	"github.com/goreleaser/goreleaser/internal/tmpl"
	"github.com/goreleaser/goreleaser/pkg/config"
	"github.com/goreleaser/goreleaser/pkg/context"
)

// ManifestPipe is beta implementation of for the docker manifest feature,
// allowing to publish multi-arch docker images.
type ManifestPipe struct{}

func (ManifestPipe) String() string {
	return "docker manifests"
}

// Publish the docker manifests.
func (ManifestPipe) Publish(ctx *context.Context) error {
	if ctx.SkipPublish {
		return pipe.ErrSkipPublishEnabled
	}
	var g = semerrgroup.NewSkipAware(semerrgroup.New(ctx.Parallelism))
	for _, manifest := range ctx.Config.DockerManifests {
		manifest := manifest
		g.Go(func() error {
			name, err := manifestName(ctx, manifest)
			if err != nil {
				return err
			}
			images, err := manifestImages(ctx, manifest)
			if err != nil {
				return err
			}
			if err := dockerManifestCreate(ctx, name, images, manifest.CreateFlags); err != nil {
				return err
			}
			return dockerManifestPush(ctx, name, manifest.PushFlags)
		})
	}
	return g.Wait()
}

func manifestName(ctx *context.Context, manifest config.DockerManifest) (string, error) {
	name, err := tmpl.New(ctx).Apply(manifest.NameTemplate)
	if err != nil {
		return name, err
	}
	if strings.TrimSpace(name) == "" {
		return name, pipe.Skip("manifest name is empty")
	}
	return name, nil
}

func manifestImages(ctx *context.Context, manifest config.DockerManifest) ([]string, error) {
	var imgs = make([]string, 0, len(manifest.ImageTemplates))
	for _, img := range manifest.ImageTemplates {
		str, err := tmpl.New(ctx).Apply(img)
		if err != nil {
			return []string{}, err
		}
		imgs = append(imgs, str)
	}
	if strings.TrimSpace(strings.Join(manifest.ImageTemplates, "")) == "" {
		return imgs, pipe.Skip("manifest has no images")
	}
	return imgs, nil
}

func dockerManifestCreate(ctx *context.Context, manifest string, images, flags []string) error {
	log.WithField("manifest", manifest).Info("creating docker manifest")
	var args = []string{"manifest", "create", manifest}
	for _, img := range images {
		args = append(args, "--amend", img)
	}
	args = append(args, flags...)
	/* #nosec */
	var cmd = exec.CommandContext(ctx, "docker", args...)
{'fraction_non_alphanumeric': 0.13759367194004996, 'fraction_numerical': 0.00020815986677768527, 'mean_word_length': 4.286028602860286, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2992388', 'n_tokens_mistral': 1731, 'n_tokens_neox': 1624, 'n_words': 393}