Skip to content

Commit

Permalink
Adds ability for use to define additional tags for images
Browse files Browse the repository at this point in the history
  • Loading branch information
fcaroline2020 committed Nov 14, 2024
1 parent 37e66ce commit 4b0b4ee
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 7 deletions.
9 changes: 9 additions & 0 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ func NewBuildCmd(flags *flags.GlobalFlags) *cobra.Command {
if err != nil {
return fmt.Errorf("cannot push to %s, please make sure you have push permissions to repository %s", cmd.Repository, cmd.Repository)
}

if cmd.Tag != nil {
err = image.ValidateTags(cmd.Tag)

if err != nil {
return fmt.Errorf("cannot build image, invalid tag defined %s", cmd.Tag)
}
}
}

// create a temporary workspace
Expand Down Expand Up @@ -112,6 +120,7 @@ func NewBuildCmd(flags *flags.GlobalFlags) *cobra.Command {
buildCmd.Flags().BoolVar(&cmd.SkipDelete, "skip-delete", false, "If true will not delete the workspace after building it")
buildCmd.Flags().StringVar(&cmd.Machine, "machine", "", "The machine to use for this workspace. The machine needs to exist beforehand or the command will fail. If the workspace already exists, this option has no effect")
buildCmd.Flags().StringVar(&cmd.Repository, "repository", "", "The repository to push to")
buildCmd.Flags().StringSliceVar(&cmd.Tag, "tag", []string{}, "Image Tag(s) in the form of a comma separated list --tag latest,arm64 or multiple flags --tag latest --tag arm64")
buildCmd.Flags().StringSliceVar(&cmd.Platform, "platform", []string{}, "Set target platform for build")
buildCmd.Flags().BoolVar(&cmd.SkipPush, "skip-push", false, "If true will not push the image to the repository, useful for testing")
buildCmd.Flags().Var(&cmd.GitCloneStrategy, "git-clone-strategy", "The git clone strategy DevPod uses to checkout git based workspaces. Can be full (default), blobless, treeless or shallow")
Expand Down
4 changes: 4 additions & 0 deletions pkg/devcontainer/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func (r *runner) build(
ImageName: overrideBuildImageName,
PrebuildHash: imageTag,
RegistryCache: options.RegistryCache,
Tags: options.Tag,
}, nil
}

Expand Down Expand Up @@ -135,6 +136,7 @@ func (r *runner) extendImage(
ImageMetadata: extendedBuildInfo.MetadataConfig,
ImageName: imageBase,
RegistryCache: options.RegistryCache,
Tags: options.Tag,
}, nil
}

Expand Down Expand Up @@ -322,6 +324,7 @@ func (r *runner) buildImage(
ImageName: prebuildImage,
PrebuildHash: prebuildHash,
RegistryCache: options.RegistryCache,
Tags: options.Tag,
}, nil
} else if err != nil {
r.Log.Debugf("Error trying to find prebuild image %s: %v", prebuildImage, err)
Expand Down Expand Up @@ -385,6 +388,7 @@ func dockerlessFallback(
User: buildInfo.User,
},
RegistryCache: options.RegistryCache,
Tags: options.Tag,
}, nil
}

Expand Down
1 change: 1 addition & 0 deletions pkg/devcontainer/config/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type BuildInfo struct {
ImageName string
PrebuildHash string
RegistryCache string
Tags []string

Dockerless *BuildInfoDockerless
}
Expand Down
27 changes: 24 additions & 3 deletions pkg/devcontainer/prebuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/loft-sh/devpod/pkg/devcontainer/config"
"github.com/loft-sh/devpod/pkg/driver"
Expand Down Expand Up @@ -87,10 +88,30 @@ func (r *runner) Build(ctx context.Context, options provider.BuildOptions) (stri
)
}

// Setup all image tags (prebuild and any user defined tags)
ImageRefs := []string{prebuildImage}
r.Log.Debug("Prebuilt Image=%s buildInfo.ImageName=%s", prebuildImage, buildInfo.ImageName)

imageRepoName := strings.Split(prebuildImage, ":")
if buildInfo.Tags != nil {
for _, tag := range buildInfo.Tags {
ImageRefs = append(ImageRefs, imageRepoName[0]+":"+tag)
}
}

// tag the image
for _, imageRef := range ImageRefs {
r.Log.Debug("Tagging Image=%s Tag=%s", prebuildImage, imageRef)
err = dockerDriver.TagDevContainer(ctx, prebuildImage, imageRef)
}

// push the image to the registry
err = dockerDriver.PushDevContainer(ctx, prebuildImage)
if err != nil {
return "", errors.Wrap(err, "push image")
for _, imageRef := range ImageRefs {
r.Log.Debug("Pushing Image=%s", imageRef)
err = dockerDriver.PushDevContainer(ctx, imageRef)
if err != nil {
return "", errors.Wrap(err, "push image")
}
}

return prebuildImage, nil
Expand Down
2 changes: 2 additions & 0 deletions pkg/driver/docker/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func (d *dockerDriver) BuildDevContainer(
ImageName: imageName,
PrebuildHash: prebuildHash,
RegistryCache: options.RegistryCache,
Tags: options.Tag,
}, nil
} else if err != nil {
d.Log.Debugf("Error trying to find local image %s: %v", imageName, err)
Expand Down Expand Up @@ -114,6 +115,7 @@ func (d *dockerDriver) BuildDevContainer(
ImageName: imageName,
PrebuildHash: prebuildHash,
RegistryCache: options.RegistryCache,
Tags: options.Tag,
}, nil
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/driver/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (d *dockerDriver) PushDevContainer(ctx context.Context, image string) error
}

func (d *dockerDriver) TagDevContainer(ctx context.Context, image, tag string) error {
// push image
// Tag image
writer := d.Log.Writer(logrus.InfoLevel, false)
defer writer.Close()

Expand All @@ -127,7 +127,7 @@ func (d *dockerDriver) TagDevContainer(ctx context.Context, image, tag string) e
d.Log.Debugf("Running docker command: %s %s", d.Docker.DockerCommand, strings.Join(args, " "))
err := d.Docker.Run(ctx, args, nil, writer, writer)
if err != nil {
return errors.Wrap(err, "push image")
return errors.Wrap(err, "tag image")
}

return nil
Expand Down
33 changes: 31 additions & 2 deletions pkg/image/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ package image
import (
"context"
"fmt"
"net/http"

"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/pkg/errors"
"net/http"
"regexp"
)

var (
dockerTagRegexp = regexp.MustCompile(`^[\w][\w.-]*$`)
DockerTagMaxSize = 128
)

func GetImage(ctx context.Context, image string) (v1.Image, error) {
Expand Down Expand Up @@ -58,3 +63,27 @@ func GetImageConfig(ctx context.Context, image string) (*v1.ConfigFile, v1.Image

return configFile, img, nil
}

func ValidateTags(tags []string) error {
for _, tag := range tags {
if !IsValidDockerTag(tag) {
return fmt.Errorf(`%q is not a valid docker tag
- a tag name must be valid ASCII and may contain lowercase and uppercase letters, digits, underscores, periods and dashes;
- a tag name may not start with a period or a dash and may contain a maximum of 128 characters.`, tag)
}
}
return nil
}

func IsValidDockerTag(tag string) bool {
if shouldNotBeSlugged(tag, dockerTagRegexp, DockerTagMaxSize) {
return true
}

return false
}

func shouldNotBeSlugged(data string, regexp *regexp.Regexp, maxSize int) bool {
return len(data) == 0 || regexp.Match([]byte(data)) && len(data) <= maxSize
}
1 change: 1 addition & 0 deletions pkg/provider/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ type CLIOptions struct {
Repository string `json:"repository,omitempty"`
SkipPush bool `json:"skipPush,omitempty"`
Platform []string `json:"platform,omitempty"`
Tag []string `json:"tag,omitempty"`

ForceBuild bool `json:"forceBuild,omitempty"`
ForceDockerless bool `json:"forceDockerless,omitempty"`
Expand Down

0 comments on commit 4b0b4ee

Please sign in to comment.