Files
grafana/pkg/build/daggerbuild/pipelines/docker_publish.go
Kevin Minehart 13f4cf162e CI: move grafana-build into pkg/build (#105640)
* move grafana-build into pkg/build
2025-05-20 10:48:00 -05:00

142 lines
4.4 KiB
Go

package pipelines
import (
"context"
"fmt"
"log"
"strings"
"dagger.io/dagger"
"github.com/grafana/grafana/pkg/build/daggerbuild/containers"
"github.com/grafana/grafana/pkg/build/daggerbuild/docker"
"golang.org/x/sync/errgroup"
"golang.org/x/sync/semaphore"
)
func ImageManifest(tag string) string {
log.Println(tag)
log.Println(tag)
log.Println(tag)
log.Println(tag)
manifest := strings.ReplaceAll(tag, "-image-tags", "")
lastDash := strings.LastIndex(manifest, "-")
return manifest[:lastDash]
}
func LatestManifest(tag string) string {
suffix := ""
if strings.Contains(tag, "ubuntu") {
suffix = "-ubuntu"
}
manifest := strings.ReplaceAll(tag, "-image-tags", "")
manifestImage := strings.Split(manifest, ":")[0]
return strings.Join([]string{manifestImage, fmt.Sprintf("latest%s", suffix)}, ":")
}
// PublishDocker is a pipeline that uses a grafana.docker.tar.gz as input and publishes a Docker image to a container registry or repository.
// Grafana's Dockerfile should support supplying a tar.gz using a --build-arg.
func PublishDocker(ctx context.Context, d *dagger.Client, args PipelineArgs) error {
opts := args.DockerOpts
packages, err := containers.GetPackages(ctx, d, args.PackageInputOpts, args.GCPOpts)
if err != nil {
return err
}
var (
wg = &errgroup.Group{}
sm = semaphore.NewWeighted(args.ConcurrencyOpts.Parallel)
)
manifestTags := make(map[string][]string)
for i, name := range args.PackageInputOpts.Packages {
// For each package we retrieve the tags grafana-image-tags and grafana-oss-image-tags, or grafana-enterprise-image-tags
format := opts.TagFormat
if strings.Contains(name, "ubuntu") {
format = opts.UbuntuTagFormat
}
tarOpts := TarOptsFromFileName(name)
tags, err := docker.Tags(opts.Org, opts.Registry, []string{opts.Repository}, format, tarOpts.NameOpts())
if err != nil {
return err
}
log.Println(tags)
for _, tag := range tags {
// For each tag we publish an image and add the tag to the list of tags for a specific manifest
// Since each package has a maximum of 2 tags, this for loop will only run twice on a worst case scenario
manifest := ImageManifest(tag)
manifestTags[manifest] = append(manifestTags[manifest], tag)
if opts.Latest {
manifest := LatestManifest(tag)
manifestTags[manifest] = append(manifestTags[manifest], tag)
}
wg.Go(PublishPackageImageFunc(ctx, sm, d, packages[i], tag, opts))
}
}
if err := wg.Wait(); err != nil {
// Wait for all images to be published
return err
}
for manifest, tags := range manifestTags {
// Publish each manifest
wg.Go(PublishDockerManifestFunc(ctx, sm, d, manifest, tags, opts))
}
return wg.Wait()
}
func PublishPackageImageFunc(ctx context.Context, sm *semaphore.Weighted, d *dagger.Client, pkg *dagger.File, tag string, opts *docker.DockerOpts) func() error {
return func() error {
log.Printf("[%s] Attempting to publish image", tag)
log.Printf("[%s] Acquiring semaphore", tag)
if err := sm.Acquire(ctx, 1); err != nil {
return fmt.Errorf("failed to acquire semaphore: %w", err)
}
defer sm.Release(1)
log.Printf("[%s] Acquired semaphore", tag)
log.Printf("[%s] Publishing image", tag)
out, err := docker.PublishPackageImage(ctx, d, pkg, tag, opts.Username, opts.Password, opts.Registry)
if err != nil {
return fmt.Errorf("[%s] error: %w", tag, err)
}
log.Printf("[%s] Done publishing image", tag)
if _, err := fmt.Fprintln(Stdout, out); err != nil {
return fmt.Errorf("error writing to stdout: %w", err)
}
return nil
}
}
func PublishDockerManifestFunc(ctx context.Context, sm *semaphore.Weighted, d *dagger.Client, manifest string, tags []string, opts *docker.DockerOpts) func() error {
return func() error {
log.Printf("[%s] Attempting to publish manifest", manifest)
log.Printf("[%s] Acquiring semaphore", manifest)
if err := sm.Acquire(ctx, 1); err != nil {
return fmt.Errorf("failed to acquire semaphore: %w", err)
}
defer sm.Release(1)
log.Printf("[%s] Acquired semaphore", manifest)
log.Printf("[%s] Publishing manifest", manifest)
out, err := docker.PublishManifest(ctx, d, manifest, tags, opts.Username, opts.Password, opts.Registry)
if err != nil {
return fmt.Errorf("[%s] error: %w", manifest, err)
}
log.Printf("[%s] Done publishing manifest", manifest)
if _, err := fmt.Fprintln(Stdout, out); err != nil {
return fmt.Errorf("error writing to stdout: %w", err)
}
return nil
}
}