CI: move grafana-build into pkg/build (#105640)
* move grafana-build into pkg/build
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/containers"
|
||||
)
|
||||
|
||||
type BuildOpts struct {
|
||||
// Dockerfile is the path to the dockerfile with the '-f' command.
|
||||
// If it's not provided, then the docker command will default to 'Dockerfile' in `pwd`.
|
||||
Dockerfile string
|
||||
|
||||
// Tags are provided as the '-t' argument, and can include the registry domain as well as the repository.
|
||||
// Docker build supports building the same image with multiple tags.
|
||||
// You might want to also include a 'latest' version of the tag.
|
||||
Tags []string
|
||||
// BuildArgs are provided to the docker command as '--build-arg'
|
||||
BuildArgs []string
|
||||
// Set the target build stage to build as '--target'
|
||||
Target string
|
||||
|
||||
// Platform, if set to the non-default value, will use buildkit's emulation to build the docker image. This can be useful if building a docker image for a platform that doesn't match the host platform.
|
||||
Platform dagger.Platform
|
||||
}
|
||||
|
||||
func Builder(d *dagger.Client, socket *dagger.Socket, targz *dagger.File) *dagger.Container {
|
||||
extracted := containers.ExtractedArchive(d, targz)
|
||||
|
||||
// Instead of supplying the Platform argument here, we need to tell the host docker socket that it needs to build with the given platform.
|
||||
return d.Container().From("docker").
|
||||
WithUnixSocket("/var/run/docker.sock", socket).
|
||||
WithWorkdir("/src").
|
||||
WithMountedFile("/src/Dockerfile", extracted.File("Dockerfile")).
|
||||
WithMountedFile("/src/packaging/docker/run.sh", extracted.File("packaging/docker/run.sh")).
|
||||
WithMountedFile("/src/grafana.tar.gz", targz)
|
||||
}
|
||||
|
||||
func Build(d *dagger.Client, builder *dagger.Container, opts *BuildOpts) *dagger.Container {
|
||||
args := []string{"docker", "buildx", "build"}
|
||||
if p := opts.Platform; p != "" {
|
||||
args = append(args, fmt.Sprintf("--platform=%s", string(p)))
|
||||
}
|
||||
dockerfile := opts.Dockerfile
|
||||
if dockerfile == "" {
|
||||
dockerfile = "Dockerfile"
|
||||
}
|
||||
|
||||
args = append(args, ".", "-f", dockerfile)
|
||||
|
||||
for _, v := range opts.BuildArgs {
|
||||
args = append(args, fmt.Sprintf("--build-arg=%s", v))
|
||||
}
|
||||
|
||||
for _, v := range opts.Tags {
|
||||
args = append(args, "-t", v)
|
||||
}
|
||||
|
||||
if opts.Target != "" {
|
||||
args = append(args, "--target", opts.Target)
|
||||
}
|
||||
|
||||
return builder.WithExec(args)
|
||||
}
|
||||
|
||||
func Save(builder *dagger.Container, opts *BuildOpts) *dagger.File {
|
||||
return builder.WithExec([]string{"docker", "save", opts.Tags[0], "-o", "image.tar.gz"}).File("image.tar.gz")
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package docker
|
||||
|
||||
type DockerOpts struct {
|
||||
// Registry is the docker Registry for the image.
|
||||
// If using '--save', then this will have no effect.
|
||||
// Uses docker hub by default.
|
||||
// Example: us.gcr.io/12345
|
||||
Registry string
|
||||
|
||||
// AlpineBase is supplied as a build-arg when building the Grafana docker image.
|
||||
// When building alpine versions of Grafana it uses this image as its base.
|
||||
AlpineBase string
|
||||
|
||||
// UbuntuBase is supplied as a build-arg when building the Grafana docker image.
|
||||
// When building ubuntu versions of Grafana it uses this image as its base.
|
||||
UbuntuBase string
|
||||
|
||||
// Username is supplied to login to the docker registry when publishing images.
|
||||
Username string
|
||||
|
||||
// Password is supplied to login to the docker registry when publishing images.
|
||||
Password string
|
||||
|
||||
// Org overrides the organization when when publishing images.
|
||||
Org string
|
||||
|
||||
// Repository overrides the repository when when publishing images.
|
||||
Repository string
|
||||
|
||||
// Latest is supplied to also tag as latest when publishing images.
|
||||
Latest bool
|
||||
|
||||
// TagFormat and UbuntuTagFormat should be formatted using go template tags.
|
||||
TagFormat string
|
||||
UbuntuTagFormat string
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"dagger.io/dagger"
|
||||
)
|
||||
|
||||
func PublishPackageImage(ctx context.Context, d *dagger.Client, pkg *dagger.File, tag, username, password, registry string) (string, error) {
|
||||
return d.Container().From("docker").
|
||||
WithFile("grafana.img", pkg).
|
||||
WithSecretVariable("DOCKER_USERNAME", d.SetSecret("docker-username", username)).
|
||||
WithSecretVariable("DOCKER_PASSWORD", d.SetSecret("docker-password", password)).
|
||||
WithUnixSocket("/var/run/docker.sock", d.Host().UnixSocket("/var/run/docker.sock")).
|
||||
WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("docker login %s -u $DOCKER_USERNAME -p $DOCKER_PASSWORD", registry)}).
|
||||
WithExec([]string{"/bin/sh", "-c", "docker load -i grafana.img | awk -F 'Loaded image: ' '{print $2}' > /tmp/image_tag"}).
|
||||
WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("docker tag $(cat /tmp/image_tag) %s", tag)}).
|
||||
WithExec([]string{"docker", "push", tag}).
|
||||
Stdout(ctx)
|
||||
}
|
||||
|
||||
func PublishManifest(ctx context.Context, d *dagger.Client, manifest string, tags []string, username, password, registry string) (string, error) {
|
||||
return d.Container().From("docker").
|
||||
WithUnixSocket("/var/run/docker.sock", d.Host().UnixSocket("/var/run/docker.sock")).
|
||||
WithSecretVariable("DOCKER_USERNAME", d.SetSecret("docker-username", username)).
|
||||
WithSecretVariable("DOCKER_PASSWORD", d.SetSecret("docker-password", password)).
|
||||
WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("docker login %s -u $DOCKER_USERNAME -p $DOCKER_PASSWORD", registry)}).
|
||||
WithExec(append([]string{"docker", "manifest", "create", manifest}, tags...)).
|
||||
WithExec([]string{"docker", "manifest", "push", manifest}).
|
||||
Stdout(ctx)
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/backend"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/packages"
|
||||
)
|
||||
|
||||
type BaseImage int
|
||||
|
||||
const (
|
||||
BaseImageUbuntu BaseImage = iota
|
||||
BaseImageAlpine
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultTagFormat = "{{ .version }}-{{ .arch }}"
|
||||
DefaultUbuntuTagFormat = "{{ .version }}-ubuntu-{{ .arch }}"
|
||||
DefaultBoringTagFormat = "{{ .version }}-{{ .arch }}-boringcrypto"
|
||||
DefaultHGTagFormat = "{{ .version }}-{{ .arch }}"
|
||||
)
|
||||
|
||||
// Tags returns the name of the grafana docker image based on the tar package name.
|
||||
// To maintain backwards compatibility, we must keep this the same as it was before.
|
||||
func Tags(org, registry string, repos []string, format string, tarOpts packages.NameOpts) ([]string, error) {
|
||||
tags := make([]string, len(repos))
|
||||
|
||||
for i, repo := range repos {
|
||||
tag, err := ImageTag(tarOpts.Distro, format, registry, org, repo, tarOpts.Version, tarOpts.BuildID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tags[i] = tag
|
||||
}
|
||||
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func ImageTag(distro backend.Distribution, format, registry, org, repo, version, buildID string) (string, error) {
|
||||
version, err := ImageVersion(format, TemplateValues(distro, version, buildID))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/%s/%s:%s", registry, org, repo, version), nil
|
||||
}
|
||||
|
||||
func ImageVersion(format string, values map[string]string) (string, error) {
|
||||
tmpl, err := template.New("version").Parse(format)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := tmpl.Execute(buf, values); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func TemplateValues(distro backend.Distribution, version, buildID string) map[string]string {
|
||||
arch := backend.FullArch(distro)
|
||||
arch = strings.ReplaceAll(arch, "/", "")
|
||||
arch = strings.ReplaceAll(arch, "dynamic", "")
|
||||
ersion := strings.TrimPrefix(version, "v")
|
||||
|
||||
semverc := strings.Split(ersion, "-")
|
||||
return map[string]string{
|
||||
"arch": arch,
|
||||
"version": ersion,
|
||||
"version_base": semverc[0],
|
||||
"buildID": buildID,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/backend"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/containers"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/e2e"
|
||||
"github.com/grafana/grafana/pkg/build/daggerbuild/frontend"
|
||||
)
|
||||
|
||||
// Verify uses the given package (.docker.tar.gz) and grafana source code (src) to run the e2e smoke tests.
|
||||
// the returned directory is the e2e artifacts created by cypress (screenshots and videos).
|
||||
func Verify(
|
||||
ctx context.Context,
|
||||
d *dagger.Client,
|
||||
image *dagger.File,
|
||||
src *dagger.Directory,
|
||||
yarnCache *dagger.CacheVolume,
|
||||
distro backend.Distribution,
|
||||
) error {
|
||||
nodeVersion, err := frontend.NodeVersion(d, src).Stdout(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get node version from source code: %w", err)
|
||||
}
|
||||
|
||||
var (
|
||||
platform = backend.Platform(distro)
|
||||
)
|
||||
|
||||
// This grafana service runs in the background for the e2e tests
|
||||
service := d.Container(dagger.ContainerOpts{
|
||||
Platform: platform,
|
||||
}).
|
||||
WithMountedTemp("/var/lib/grafana/plugins").
|
||||
Import(image).
|
||||
WithExposedPort(3000)
|
||||
|
||||
// TODO: Add LICENSE to containers and implement validation
|
||||
container := e2e.ValidatePackage(d, service.AsService(), src, yarnCache, nodeVersion)
|
||||
_, err = containers.ExitError(ctx, container)
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user