Skip to content

Commit

Permalink
Simplify latest version parsing and tagging
Browse files Browse the repository at this point in the history
  • Loading branch information
guicaulada committed Aug 28, 2023
1 parent be00cda commit 0b510aa
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 152 deletions.
12 changes: 12 additions & 0 deletions cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ var NPMFlags = []cli.Flag{
Usage: "Provides a token to use to authenticate with the package registry",
Required: true,
},
&cli.BoolFlag{
Name: "latest",
Usage: "Tags the published packages as latest",
},
&cli.BoolFlag{
Name: "next",
Usage: "Tags the published packages as next",
},
}

// PublishFlags are flags that are used in commands that create artifacts.
Expand Down Expand Up @@ -177,6 +185,10 @@ var DockerPublishFlags = []cli.Flag{
Usage: "Prefix the image name with the registry provided",
Value: "docker.io",
},
&cli.BoolFlag{
Name: "latest",
Usage: "Tags the published images as latest",
},
}

var FlagDistros = &cli.StringSliceFlag{
Expand Down
59 changes: 8 additions & 51 deletions containers/npm_publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"strings"

"dagger.io/dagger"
"github.com/grafana/grafana-build/executil"
)

// PublishNPM publishes a npm package to the given destination.
Expand All @@ -23,62 +22,20 @@ func PublishNPM(ctx context.Context, d *dagger.Client, pkg *dagger.File, opts *N
return "", err
}

isLatestStable, err := IsLatestGrafana(ctx, d, executil.Stable, version)
if err != nil {
return "", err
}

isLatestPreview, err := IsLatestGrafana(ctx, d, executil.Preview, version)
if err != nil {
return "", err
}

latestStable, err := GetLatestGrafanaVersion(ctx, d, executil.Stable)
if err != nil {
return "", err
}

latestPreview, err := GetLatestGrafanaVersion(ctx, d, executil.Preview)
if err != nil {
return "", err
}

isLaterThanPreview, err := IsLaterThan(ctx, d, version, latestPreview)
if err != nil {
return "", err
}

tag := "latest"
if channel := executil.GetVersionChannel(version); channel == executil.Test {
tag = "test"
}

if channel := executil.GetVersionChannel(version); channel == executil.Nightly {
tag = "canary"
}
major := strings.Split(version, ".")[0]
minor := strings.Split(version, ".")[1]
tag := fmt.Sprintf("latest-%s.%s", major, minor)

c := d.Container().From(NodeImage("lts")).
WithFile("/pkg.tgz", pkg).
// Workaround for now (maybe unnecessary?): set a NAME environment variable so that we don't accidentally cache
WithEnvVariable("NAME", name).
WithExec([]string{"npm", "set", fmt.Sprintf("//%s/:_authToken", opts.Registry), opts.Token})

// Get all published versions of this package
out, err := c.WithExec([]string{"npm", "view", name, "versions"}).Stdout(ctx)
if err != nil {
return "", err
}

if !strings.Contains(out, fmt.Sprintf("'%s'", version)) {
// Publish only if this version is not published already
c = c.WithExec([]string{"npm", "publish", "/pkg.tgz", fmt.Sprintf("--registry https://%s", opts.Registry), "--tag", tag})
}
WithExec([]string{"npm", "set", fmt.Sprintf("//%s/:_authToken", opts.Registry), opts.Token}).
WithExec([]string{"npm", "publish", "/pkg.tgz", fmt.Sprintf("--registry https://%s", opts.Registry), "--tag", tag})

if !isLatestStable {
c = c.WithExec([]string{"npm", "dist-tag", "add", fmt.Sprintf("%s@%s", name, latestStable), "latest"})
if opts.Latest {
c = c.WithExec([]string{"npm", "dist-tag", "add", fmt.Sprintf("%s@%s", name, version), "latest"})
}

if isLatestPreview || (isLatestStable && isLaterThanPreview) {
if opts.Next {
c = c.WithExec([]string{"npm", "dist-tag", "add", fmt.Sprintf("%s@%s", name, version), "next"})
}

Expand Down
4 changes: 4 additions & 0 deletions containers/opts_docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ type DockerOpts struct {

// Password is supplied to login to the docker registry when publishing images.
Password string

// Latest is supplied to also tag as latest when publishing images.
Latest bool
}

func DockerOptsFromFlags(c cliutil.CLIContext) *DockerOpts {
Expand All @@ -31,5 +34,6 @@ func DockerOptsFromFlags(c cliutil.CLIContext) *DockerOpts {
UbuntuBase: c.String("ubuntu-base"),
Username: c.String("username"),
Password: c.String("password"),
Latest: c.Bool("latest"),
}
}
8 changes: 8 additions & 0 deletions containers/opts_npm.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,19 @@ type NPMOpts struct {

// Token is supplied to login to the package registry when publishing packages.
Token string

// Latest is used to tag the package as latest after published.
Latest bool

// Next is used to tag the package as next after published.
Next bool
}

func NPMOptsFromFlags(c cliutil.CLIContext) *NPMOpts {
return &NPMOpts{
Registry: c.String("registry"),
Token: c.String("token"),
Latest: c.Bool("latest"),
Next: c.Bool("next"),
}
}
54 changes: 0 additions & 54 deletions containers/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"strings"

"dagger.io/dagger"
"github.com/grafana/grafana-build/executil"
)

// GetJSONValue gets the value of a JSON field from a JSON file in the 'src' directory.
Expand All @@ -23,56 +22,3 @@ func GetJSONValue(ctx context.Context, d *dagger.Client, src *dagger.Directory,

return c.Stderr(ctx)
}

// GetLatestGrafanaVersion gets the "version" field from https://grafana.com/api/grafana/versions/<channel>.
func GetLatestGrafanaVersion(ctx context.Context, d *dagger.Client, channel executil.VersionChannel) (string, error) {
c := d.Container().From("alpine").
WithExec([]string{"apk", "--update", "add", "jq", "curl"}).
WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("curl -s https://grafana.com/api/grafana/versions/%s | jq -r .version", channel)})

if stdout, err := c.Stdout(ctx); err == nil {
out := strings.TrimSpace(stdout)
if out == "" {
return out, fmt.Errorf("failed to retrieve grafana version from grafana.com")
}
return out, nil
}

return c.Stderr(ctx)
}

// IsLatestGrafana compares versions and returns true if the version provided is grater or equal the latest version of Grafana on the channel.
func IsLatestGrafana(ctx context.Context, d *dagger.Client, channel executil.VersionChannel, version string) (bool, error) {
if versionChannel := executil.GetVersionChannel(version); versionChannel != channel {
return false, nil
}

latestGrafana, err := GetLatestGrafanaVersion(ctx, d, channel)
if err != nil {
return false, err
}

return IsLaterThan(ctx, d, version, latestGrafana)
}

// GetLatestVersion compares versions and returns the latest version provided in the slice.
func GetLatestVersion(ctx context.Context, d *dagger.Client, versions []string) (string, error) {
c := d.Container().From("alpine").
WithExec([]string{"/bin/sh", "-c", fmt.Sprintf("echo -e '%s' | sort -V | tail -1", strings.Join(versions, "\\n"))})

stdout, err := c.Stdout(ctx)
if err != nil {
return "", err
}

return strings.TrimSpace(stdout), nil
}

// IsLaterThan compares versions and returns true if v1 is later than v2
func IsLaterThan(ctx context.Context, d *dagger.Client, v1 string, v2 string) (bool, error) {
latest, err := GetLatestVersion(ctx, d, []string{v1, v2})
if err != nil {
return false, err
}
return latest == v1, nil
}
26 changes: 0 additions & 26 deletions executil/version.go

This file was deleted.

23 changes: 4 additions & 19 deletions pipelines/docker_publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,25 @@ import (

"dagger.io/dagger"
"github.com/grafana/grafana-build/containers"
"github.com/grafana/grafana-build/executil"
"golang.org/x/sync/errgroup"
"golang.org/x/sync/semaphore"
)

func DockerChannelFromFileName(name string) string {
taropts := TarOptsFromFileName(name)
if taropts.Channel == "stable" {
return "latest"
}
return "main"
}

func ImageManifest(tag string) string {
manifest := strings.ReplaceAll(tag, "-image-tags", "")
lastDash := strings.LastIndex(manifest, "-")
return manifest[:lastDash]
}

func ChannelManifest(tag string, base BaseImage, channel string) string {
func LatestManifest(tag string, base BaseImage) string {
suffix := ""
if base == BaseImageUbuntu {
suffix = "-ubuntu"
}

manifest := strings.ReplaceAll(tag, "-image-tags", "")
manifestImage := strings.Split(manifest, ":")[0]
return strings.Join([]string{manifestImage, fmt.Sprintf("%s%s", channel, suffix)}, ":")
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.
Expand All @@ -61,21 +52,15 @@ func PublishDocker(ctx context.Context, d *dagger.Client, args PipelineArgs) err
base = BaseImageUbuntu
}

isLatest, err := containers.IsLatestGrafana(ctx, d, executil.Stable, tarOpts.Version)
if err != nil {
return err
}

tags := GrafanaImageTags(base, opts.Registry, tarOpts)
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 isLatest && tarOpts.Channel != "preview" {
channel := DockerChannelFromFileName(name)
manifest := ChannelManifest(tag, base, channel)
if opts.Latest {
manifest := LatestManifest(tag, base)
manifestTags[manifest] = append(manifestTags[manifest], tag)
}

Expand Down
2 changes: 0 additions & 2 deletions pipelines/package_names.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ type TarFileOpts struct {
Edition string
Distro executil.Distribution
Suffix string
Channel executil.VersionChannel
}

func WithoutExt(name string) string {
Expand Down Expand Up @@ -93,7 +92,6 @@ func TarOptsFromFileName(filename string) TarFileOpts {
BuildID: buildID,
Distro: executil.Distribution(strings.Join([]string{os, arch}, "/")),
Suffix: suffix,
Channel: executil.GetVersionChannel(version),
}
}

Expand Down

0 comments on commit 0b510aa

Please sign in to comment.