Skip to content

Commit

Permalink
feat: Add --release flag and handle extra tags via Dockerfile label
Browse files Browse the repository at this point in the history
  • Loading branch information
julienvey committed Feb 15, 2022
1 parent d85c0e4 commit 03f5a1b
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 41 deletions.
16 changes: 7 additions & 9 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ type buildOpts struct {
DryRun bool `mapstructure:"dry_run"`
ForceRebuild bool `mapstructure:"force_rebuild"`
LocalOnly bool `mapstructure:"local_only"`
TagReferential bool `mapstructure:"tag_referential"`
RetagLatest bool `mapstructure:"retag_latest"`
Release bool `mapstructure:"release"`
Backend string `mapstructure:"backend"`
Goss gossConfig `mapstructure:"goss"`
Kaniko kanikoConfig `mapstructure:"kaniko"`
Expand Down Expand Up @@ -132,8 +131,9 @@ func init() {
buildCmd.Flags().Bool("no-graph", false, "Disable generation of graph during the build process.")
buildCmd.Flags().Bool("no-tests", false, "Disable execution of tests during the build process.")
buildCmd.Flags().Bool("no-junit", false, "Disable generation of junit reports when running tests")
buildCmd.Flags().Bool("retag-latest", false, "Should images be retagged with the 'latest' tag for this build")
buildCmd.Flags().Bool("tag-referential", false, "Tag the referential image at the end of the build process.")
buildCmd.Flags().Bool("release", false, "This flag will cause all images to be "+
"retagged with the tags defined by the 'dib.extra-tags' Dockerfile's label, the referential "+
"image will also be tagged ")
buildCmd.Flags().Bool("local-only", false, "Build docker images locally, do not push on remote registry")
buildCmd.Flags().StringP("backend", "b", backendDocker, fmt.Sprintf("Build Backend used to run image builds. Supported backends: %v", supportedBackends))
buildCmd.Flags().Int("rate-limit", 1, "Concurrent number of build that can run simultaneously")
Expand Down Expand Up @@ -226,14 +226,12 @@ func doBuild(opts buildOpts) error {
return err
}

if opts.RetagLatest {
logrus.Info("--retag-latest is set to true, latest tag will now use current image versions")
if err := dib.RetagLatest(DAG, tagger, currentVersion); err != nil {
if opts.Release {
logrus.Info("--release is set to true, tags defined by dib.extra-tags will now use current image versions")
if err := dib.TagWithExtraTags(DAG, tagger, currentVersion); err != nil {
return err
}
}

if !opts.LocalOnly && opts.TagReferential {
// We retag the referential image to explicit this commit was build using dib
if err := tagger.Tag(fmt.Sprintf("%s:%s", path.Join(opts.RegistryURL, opts.ReferentialImage), "latest"),
fmt.Sprintf("%s:%s", path.Join(opts.RegistryURL, opts.ReferentialImage), currentVersion)); err != nil {
Expand Down
20 changes: 10 additions & 10 deletions dag/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import (

// Image holds the docker image information.
type Image struct {
Name string
ShortName string
Dockerfile *dockerfile.Dockerfile
NeedsRebuild bool
NeedsTests bool
NeedsRetag bool
RetagDone bool
RetagLatestDone bool
RebuildDone bool
RebuildFailed bool
Name string
ShortName string
Dockerfile *dockerfile.Dockerfile
NeedsRebuild bool
NeedsTests bool
NeedsRetag bool
RetagDone bool
TagWithExtraTagsDone bool
RebuildDone bool
RebuildFailed bool
}

// DockerRef returns the fully-qualified docker ref for a given version.
Expand Down
31 changes: 24 additions & 7 deletions dib/tag.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package dib

import (
"strings"

"github.com/radiofrance/dib/dag"
"github.com/radiofrance/dib/types"
"github.com/sirupsen/logrus"
Expand All @@ -25,18 +27,33 @@ func Retag(graph *dag.DAG, tagger types.ImageTagger, oldTag string, newTag strin
})
}

// RetagLatest iterates over the graph to retag each image with the latest tag.
func RetagLatest(graph *dag.DAG, tagger types.ImageTagger, tag string) error {
// TagWithExtraTags iterates over the graph to retag each image with the tags defined in dib.extra-tags LABEL.
func TagWithExtraTags(graph *dag.DAG, tagger types.ImageTagger, tag string) error {
return graph.WalkErr(func(node *dag.Node) error {
img := node.Image
if img.RetagLatestDone {
if img.TagWithExtraTagsDone {
return nil
}
logrus.Debugf("Retag latest tag for image %s with version %s", img.Name, tag)
if err := tagger.Tag(img.DockerRef(tag), img.DockerRef("latest")); err != nil {
return err
defer func() {
img.TagWithExtraTagsDone = true
}()

if img.Dockerfile == nil || img.Dockerfile.Labels == nil {
return nil
}

extraTags, hasLabel := img.Dockerfile.Labels["dib.extra-tags"]
if !hasLabel {
return nil
}
img.RetagLatestDone = true

for _, extraTag := range strings.Split(extraTags, ",") {
logrus.Debugf("Add tag %s to image %s:%s", extraTag, img.Name, tag)
if err := tagger.Tag(img.DockerRef(tag), img.DockerRef(extraTag)); err != nil {
return err
}
}

return nil
})
}
60 changes: 45 additions & 15 deletions dib/tag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package dib_test
import (
"testing"

"github.com/stretchr/testify/require"

"github.com/radiofrance/dib/dockerfile"

"github.com/radiofrance/dib/dag"
"github.com/radiofrance/dib/dib"
"github.com/radiofrance/dib/mock"
Expand Down Expand Up @@ -70,43 +74,69 @@ func Test_Retag_Retag(t *testing.T) {
assert.True(t, img.RetagDone)
}

func Test_RetagLatest_DoesNotRetagIfAlreadyDone(t *testing.T) {
func Test_TagWithExtraTags_DoesNotRetagIfAlreadyDone(t *testing.T) {
t.Parallel()

DAG := &dag.DAG{}
DAG.AddNode(dag.NewNode(&dag.Image{
Name: "registry.example.org/image",
ShortName: "image",
RetagLatestDone: true,
Name: "registry.example.org/image",
ShortName: "image",
TagWithExtraTagsDone: true,
}))

tagger := &mock.Tagger{}
err := dib.RetagLatest(DAG, tagger, "old")
err := dib.TagWithExtraTags(DAG, tagger, "old")

assert.NoError(t, err)
assert.Empty(t, tagger.RecordedCallsArgs)
}

func Test_RetagLatest_Retag(t *testing.T) {
func Test_TagWithExtraTags_NoLabels(t *testing.T) {
t.Parallel()

img := &dag.Image{
Name: "registry.example.org/image",
ShortName: "image",
RetagLatestDone: false,
Name: "registry.example.org/image",
ShortName: "image",
TagWithExtraTagsDone: false,
}
DAG := &dag.DAG{}
DAG.AddNode(dag.NewNode(img))

tagger := &mock.Tagger{}
err := dib.RetagLatest(DAG, tagger, "old")
err := dib.TagWithExtraTags(DAG, tagger, "old")

assert.NoError(t, err)
assert.Len(t, tagger.RecordedCallsArgs, 0)
assert.True(t, img.TagWithExtraTagsDone)
}

assert.Len(t, tagger.RecordedCallsArgs, 1)
args := tagger.RecordedCallsArgs[0]
assert.Equal(t, "registry.example.org/image:old", args.Src)
assert.Equal(t, "registry.example.org/image:latest", args.Dest)
func Test_TagWithExtraTags_WithLabels(t *testing.T) {
t.Parallel()

img := &dag.Image{
Name: "registry.example.org/image",
ShortName: "image",
TagWithExtraTagsDone: false,
Dockerfile: &dockerfile.Dockerfile{
Labels: map[string]string{
"dib.extra-tags": "latest1,latest2",
},
},
}
DAG := &dag.DAG{}
DAG.AddNode(dag.NewNode(img))

tagger := &mock.Tagger{}
err := dib.TagWithExtraTags(DAG, tagger, "old")

assert.NoError(t, err)

require.Len(t, tagger.RecordedCallsArgs, 2)

assert.Equal(t, "registry.example.org/image:old", tagger.RecordedCallsArgs[0].Src)
assert.Equal(t, "registry.example.org/image:latest1", tagger.RecordedCallsArgs[0].Dest)
assert.Equal(t, "registry.example.org/image:old", tagger.RecordedCallsArgs[1].Src)
assert.Equal(t, "registry.example.org/image:latest2", tagger.RecordedCallsArgs[1].Dest)

assert.True(t, img.RetagLatestDone)
assert.True(t, img.TagWithExtraTagsDone)
}

0 comments on commit 03f5a1b

Please sign in to comment.