Add configurable tag for use with auto_tag (#36)
Implements #30, allows setting a (single) tag to override the default of `latest` allows for the woodpecker-ci usecase of setting `next` as the tag for the default branch. Co-authored-by: Gapodo <gapodo@datenclown.at> Reviewed-on: https://codeberg.org/woodpecker-plugins/plugin-docker-buildx/pulls/36 Reviewed-by: 6543 <6543@obermui.de> Co-authored-by: gapodo <gapodo@geekvoid.net> Co-committed-by: gapodo <gapodo@geekvoid.net>
This commit is contained in:
parent
f10f7b4c7f
commit
fce3289743
@ -127,6 +127,13 @@ func settingsFlags(settings *plugin.Settings) []cli.Flag {
|
|||||||
Usage: "generates tag names automatically based on git branch and git tag",
|
Usage: "generates tag names automatically based on git branch and git tag",
|
||||||
Destination: &settings.Build.TagsAuto,
|
Destination: &settings.Build.TagsAuto,
|
||||||
},
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "tags.defaultName",
|
||||||
|
EnvVars: []string{"PLUGIN_DEFAULT_TAG"},
|
||||||
|
Usage: "allows setting an alternative to `latest` for the auto tag",
|
||||||
|
Destination: &settings.Build.TagsDefaultName,
|
||||||
|
Value: "latest",
|
||||||
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "tags.suffix",
|
Name: "tags.suffix",
|
||||||
EnvVars: []string{"PLUGIN_DEFAULT_SUFFIX", "PLUGIN_AUTO_TAG_SUFFIX"},
|
EnvVars: []string{"PLUGIN_DEFAULT_SUFFIX", "PLUGIN_AUTO_TAG_SUFFIX"},
|
||||||
|
1
docs.md
1
docs.md
@ -99,6 +99,7 @@ It will automatically generate buildkit configuration to use custom CA certifica
|
|||||||
| `context` | `.` | sets the path of the build context to use
|
| `context` | `.` | sets the path of the build context to use
|
||||||
| `default_tags`/`auto_tag` | `false` | generates tag names automatically based on git branch and git tag, tags supplied via `tags` are additionally added to the auto_tags without suffix
|
| `default_tags`/`auto_tag` | `false` | generates tag names automatically based on git branch and git tag, tags supplied via `tags` are additionally added to the auto_tags without suffix
|
||||||
| `default_suffix"`/`auto_tag_suffix`| *none* | generates tag names with the given suffix
|
| `default_suffix"`/`auto_tag_suffix`| *none* | generates tag names with the given suffix
|
||||||
|
| `default_tag` | `latest` | overrides the default tag name used when generating with `auto_tag` enabled
|
||||||
| `label`/`labels` | *none* | sets labels to use for the image in format `<name>=<value>`
|
| `label`/`labels` | *none* | sets labels to use for the image in format `<name>=<value>`
|
||||||
| `default_labels`/`auto_labels` | `true` | sets docker image labels based on git information
|
| `default_labels`/`auto_labels` | `true` | sets docker image labels based on git information
|
||||||
| `build_args` | *none* | sets custom build arguments for the build
|
| `build_args` | *none* | sets custom build arguments for the build
|
||||||
|
@ -49,6 +49,7 @@ type Build struct {
|
|||||||
Dockerfile string // Docker build Dockerfile
|
Dockerfile string // Docker build Dockerfile
|
||||||
Context string // Docker build context
|
Context string // Docker build context
|
||||||
TagsAuto bool // Docker build auto tag
|
TagsAuto bool // Docker build auto tag
|
||||||
|
TagsDefaultName string // Docker build auto tag name override
|
||||||
TagsSuffix string // Docker build tags with suffix
|
TagsSuffix string // Docker build tags with suffix
|
||||||
Tags cli.StringSlice // Docker build tags
|
Tags cli.StringSlice // Docker build tags
|
||||||
LabelsAuto bool // Docker build auto labels
|
LabelsAuto bool // Docker build auto labels
|
||||||
@ -110,6 +111,10 @@ func (p *Plugin) Validate() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !isSingleTag(p.settings.Build.TagsDefaultName) {
|
||||||
|
return fmt.Errorf("'%s' is not a valid, single tag", p.settings.Build.TagsDefaultName)
|
||||||
|
}
|
||||||
|
|
||||||
// beside the default login all other logins need to set a username and password
|
// beside the default login all other logins need to set a username and password
|
||||||
for _, l := range p.settings.Logins[1:] {
|
for _, l := range p.settings.Logins[1:] {
|
||||||
if l.anonymous() {
|
if l.anonymous() {
|
||||||
@ -126,6 +131,7 @@ func (p *Plugin) Validate() error {
|
|||||||
tag, err := DefaultTagSuffix(
|
tag, err := DefaultTagSuffix(
|
||||||
p.settings.Build.Ref,
|
p.settings.Build.Ref,
|
||||||
p.settings.Build.TagsSuffix,
|
p.settings.Build.TagsSuffix,
|
||||||
|
p.settings.Build.TagsDefaultName,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Printf("cannot build docker image for %s, invalid semantic version", p.settings.Build.Ref)
|
logrus.Printf("cannot build docker image for %s, invalid semantic version", p.settings.Build.Ref)
|
||||||
|
@ -15,6 +15,7 @@ var defaultSettings = Settings{
|
|||||||
Build: Build{
|
Build: Build{
|
||||||
Context: ".",
|
Context: ".",
|
||||||
Tags: *cli.NewStringSlice("latest"),
|
Tags: *cli.NewStringSlice("latest"),
|
||||||
|
TagsDefaultName: "latest",
|
||||||
LabelsAuto: true,
|
LabelsAuto: true,
|
||||||
Pull: true,
|
Pull: true,
|
||||||
},
|
},
|
||||||
|
@ -2,6 +2,7 @@ package plugin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/coreos/go-semver/semver"
|
"github.com/coreos/go-semver/semver"
|
||||||
@ -9,8 +10,8 @@ import (
|
|||||||
|
|
||||||
// DefaultTagSuffix returns a set of default suggested tags
|
// DefaultTagSuffix returns a set of default suggested tags
|
||||||
// based on the commit ref with an attached suffix.
|
// based on the commit ref with an attached suffix.
|
||||||
func DefaultTagSuffix(ref, suffix string) ([]string, error) {
|
func DefaultTagSuffix(ref, defaultTag, suffix string) ([]string, error) {
|
||||||
tags, err := DefaultTags(ref)
|
tags, err := DefaultTags(ref, defaultTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -18,7 +19,7 @@ func DefaultTagSuffix(ref, suffix string) ([]string, error) {
|
|||||||
return tags, nil
|
return tags, nil
|
||||||
}
|
}
|
||||||
for i, tag := range tags {
|
for i, tag := range tags {
|
||||||
if tag == "latest" {
|
if tag == defaultTag {
|
||||||
tags[i] = suffix
|
tags[i] = suffix
|
||||||
} else {
|
} else {
|
||||||
tags[i] = fmt.Sprintf("%s-%s", tag, suffix)
|
tags[i] = fmt.Sprintf("%s-%s", tag, suffix)
|
||||||
@ -39,14 +40,14 @@ func splitOff(input, delim string) string {
|
|||||||
|
|
||||||
// DefaultTags returns a set of default suggested tags based on
|
// DefaultTags returns a set of default suggested tags based on
|
||||||
// the commit ref.
|
// the commit ref.
|
||||||
func DefaultTags(ref string) ([]string, error) {
|
func DefaultTags(ref, defaultTag string) ([]string, error) {
|
||||||
if !strings.HasPrefix(ref, "refs/tags/") {
|
if !strings.HasPrefix(ref, "refs/tags/") {
|
||||||
return []string{"latest"}, nil
|
return []string{defaultTag}, nil
|
||||||
}
|
}
|
||||||
v := stripTagPrefix(ref)
|
v := stripTagPrefix(ref)
|
||||||
version, err := semver.NewVersion(v)
|
version, err := semver.NewVersion(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []string{"latest"}, err
|
return []string{defaultTag}, err
|
||||||
}
|
}
|
||||||
if version.PreRelease != "" || version.Metadata != "" {
|
if version.PreRelease != "" || version.Metadata != "" {
|
||||||
return []string{
|
return []string{
|
||||||
@ -91,3 +92,8 @@ func stripTagPrefix(ref string) string {
|
|||||||
ref = strings.TrimPrefix(ref, "v")
|
ref = strings.TrimPrefix(ref, "v")
|
||||||
return ref
|
return ref
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isSingleTag(tag string) bool {
|
||||||
|
// currently only filtering for seperators, this could be improoved...
|
||||||
|
return !regexp.MustCompile(`[,\s]+`).MatchString(tag) && len(tag) > 0 && len(tag) <= 128
|
||||||
|
}
|
||||||
|
@ -25,19 +25,20 @@ func Test_stripTagPrefix(t *testing.T) {
|
|||||||
|
|
||||||
func TestDefaultTags(t *testing.T) {
|
func TestDefaultTags(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
DefaultTag string
|
||||||
Before string
|
Before string
|
||||||
After []string
|
After []string
|
||||||
}{
|
}{
|
||||||
{"", []string{"latest"}},
|
{"latest", "", []string{"latest"}},
|
||||||
{"refs/heads/master", []string{"latest"}},
|
{"latest", "refs/heads/master", []string{"latest"}},
|
||||||
{"refs/tags/0.9.0", []string{"0.9", "0.9.0"}},
|
{"latest", "refs/tags/0.9.0", []string{"0.9", "0.9.0"}},
|
||||||
{"refs/tags/1.0.0", []string{"1", "1.0", "1.0.0"}},
|
{"latest", "refs/tags/1.0.0", []string{"1", "1.0", "1.0.0"}},
|
||||||
{"refs/tags/v1.0.0", []string{"1", "1.0", "1.0.0"}},
|
{"latest", "refs/tags/v1.0.0", []string{"1", "1.0", "1.0.0"}},
|
||||||
{"refs/tags/v1.0.0-alpha.1", []string{"1.0.0-alpha.1"}},
|
{"latest", "refs/tags/v1.0.0-alpha.1", []string{"1.0.0-alpha.1"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
tags, err := DefaultTags(test.Before)
|
tags, err := DefaultTags(test.Before, test.DefaultTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
continue
|
continue
|
||||||
@ -50,13 +51,22 @@ func TestDefaultTags(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaultTagsError(t *testing.T) {
|
func TestDefaultTagsError(t *testing.T) {
|
||||||
tests := []string{
|
tests := []struct {
|
||||||
"refs/tags/x1.0.0",
|
DefaultTag string
|
||||||
"refs/tags/20190203",
|
Before string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
DefaultTag: "latest",
|
||||||
|
Before: "refs/tags/x1.0.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DefaultTag: "latest",
|
||||||
|
Before: "refs/tags/20190203",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
_, err := DefaultTags(test)
|
_, err := DefaultTags(test.Before, test.DefaultTag)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expect tag error for %s", test)
|
t.Errorf("Expect tag error for %s", test)
|
||||||
}
|
}
|
||||||
@ -65,15 +75,25 @@ func TestDefaultTagsError(t *testing.T) {
|
|||||||
|
|
||||||
func TestDefaultTagSuffix(t *testing.T) {
|
func TestDefaultTagSuffix(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
Name string
|
||||||
Before string
|
Before string
|
||||||
Suffix string
|
Suffix string
|
||||||
After []string
|
After []string
|
||||||
|
DefaultTag string
|
||||||
}{
|
}{
|
||||||
// without suffix
|
|
||||||
{
|
{
|
||||||
|
Name: "Default tag without suffix",
|
||||||
|
DefaultTag: "latest",
|
||||||
After: []string{"latest"},
|
After: []string{"latest"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Name: "Overridden default tag without suffix",
|
||||||
|
DefaultTag: "next",
|
||||||
|
After: []string{"next"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Generate version",
|
||||||
|
DefaultTag: "latest",
|
||||||
Before: "refs/tags/v1.0.0",
|
Before: "refs/tags/v1.0.0",
|
||||||
After: []string{
|
After: []string{
|
||||||
"1",
|
"1",
|
||||||
@ -81,12 +101,31 @@ func TestDefaultTagSuffix(t *testing.T) {
|
|||||||
"1.0.0",
|
"1.0.0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// with suffix
|
|
||||||
{
|
{
|
||||||
|
Name: "Generate version with overridden default tag",
|
||||||
|
DefaultTag: "next",
|
||||||
|
Before: "refs/tags/v1.0.0",
|
||||||
|
After: []string{
|
||||||
|
"1",
|
||||||
|
"1.0",
|
||||||
|
"1.0.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Default tag with suffix (linux-amd64)",
|
||||||
|
DefaultTag: "latest",
|
||||||
Suffix: "linux-amd64",
|
Suffix: "linux-amd64",
|
||||||
After: []string{"linux-amd64"},
|
After: []string{"linux-amd64"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Name: "Overridden default tag with suffix (linux-amd64)",
|
||||||
|
DefaultTag: "next",
|
||||||
|
Suffix: "linux-amd64",
|
||||||
|
After: []string{"linux-amd64"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Generate version with suffix (linux-amd64)",
|
||||||
|
DefaultTag: "latest",
|
||||||
Before: "refs/tags/v1.0.0",
|
Before: "refs/tags/v1.0.0",
|
||||||
Suffix: "linux-amd64",
|
Suffix: "linux-amd64",
|
||||||
After: []string{
|
After: []string{
|
||||||
@ -96,10 +135,31 @@ func TestDefaultTagSuffix(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Name: "Generate version with suffix (linux-amd64) and overridden default tag (next)",
|
||||||
|
DefaultTag: "next",
|
||||||
|
Before: "refs/tags/v1.0.0",
|
||||||
|
Suffix: "linux-amd64",
|
||||||
|
After: []string{
|
||||||
|
"1-linux-amd64",
|
||||||
|
"1.0-linux-amd64",
|
||||||
|
"1.0.0-linux-amd64",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Default tag with suffix (nanoserver)",
|
||||||
|
DefaultTag: "latest",
|
||||||
Suffix: "nanoserver",
|
Suffix: "nanoserver",
|
||||||
After: []string{"nanoserver"},
|
After: []string{"nanoserver"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Name: "Overridden default tag with suffix (nanoserver)",
|
||||||
|
DefaultTag: "next",
|
||||||
|
Suffix: "nanoserver",
|
||||||
|
After: []string{"nanoserver"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Generate version with suffix (nanoserver)",
|
||||||
|
DefaultTag: "latest",
|
||||||
Before: "refs/tags/v1.9.2",
|
Before: "refs/tags/v1.9.2",
|
||||||
Suffix: "nanoserver",
|
Suffix: "nanoserver",
|
||||||
After: []string{
|
After: []string{
|
||||||
@ -109,6 +169,30 @@ func TestDefaultTagSuffix(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Name: "Generate version with suffix (nanoserver) and overridden default tag (next)",
|
||||||
|
DefaultTag: "latest",
|
||||||
|
Before: "refs/tags/v1.9.2",
|
||||||
|
Suffix: "nanoserver",
|
||||||
|
After: []string{
|
||||||
|
"1-nanoserver",
|
||||||
|
"1.9-nanoserver",
|
||||||
|
"1.9.2-nanoserver",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Generate version with suffix (zero-padded version)",
|
||||||
|
DefaultTag: "latest",
|
||||||
|
Before: "refs/tags/v18.06.0",
|
||||||
|
Suffix: "nanoserver",
|
||||||
|
After: []string{
|
||||||
|
"18-nanoserver",
|
||||||
|
"18.06-nanoserver",
|
||||||
|
"18.06.0-nanoserver",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Generate version with suffix (zero-padded version) with overridden default tag (next)",
|
||||||
|
DefaultTag: "next",
|
||||||
Before: "refs/tags/v18.06.0",
|
Before: "refs/tags/v18.06.0",
|
||||||
Suffix: "nanoserver",
|
Suffix: "nanoserver",
|
||||||
After: []string{
|
After: []string{
|
||||||
@ -120,14 +204,14 @@ func TestDefaultTagSuffix(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
tag, err := DefaultTagSuffix(test.Before, test.Suffix)
|
tag, err := DefaultTagSuffix(test.Before, test.DefaultTag, test.Suffix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
got, want := tag, test.After
|
got, want := tag, test.After
|
||||||
if !reflect.DeepEqual(got, want) {
|
if !reflect.DeepEqual(got, want) {
|
||||||
t.Errorf("Got tag %v, want %v", got, want)
|
t.Errorf("%q. Got tag %v, want %v", test.Name, got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,3 +279,26 @@ func TestUseDefaultTag(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_isSingleTag(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Tag string
|
||||||
|
IsValid bool
|
||||||
|
}{
|
||||||
|
{"latest", true},
|
||||||
|
{" latest", false},
|
||||||
|
{"LaTest__Hi", true},
|
||||||
|
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ__.-0123456789", true},
|
||||||
|
{"_wierd.but-ok1", true},
|
||||||
|
{"latest ", false},
|
||||||
|
{"latest,next", false},
|
||||||
|
// more tests to be added, once the validation is more powerful
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
valid := isSingleTag(test.Tag)
|
||||||
|
if valid != test.IsValid {
|
||||||
|
t.Errorf("Tag verification '%s' tag %v, want %v", test.Tag, valid, test.IsValid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user