mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-17 20:47:50 +02:00
feat: support multiple tag_templates for docker
This commit is contained in:
parent
2bc9d6751b
commit
92231bc930
@ -198,15 +198,16 @@ type Checksum struct {
|
||||
|
||||
// Docker image config
|
||||
type Docker struct {
|
||||
Binary string `yaml:",omitempty"`
|
||||
Goos string `yaml:",omitempty"`
|
||||
Goarch string `yaml:",omitempty"`
|
||||
Goarm string `yaml:",omitempty"`
|
||||
Image string `yaml:",omitempty"`
|
||||
Dockerfile string `yaml:",omitempty"`
|
||||
Latest bool `yaml:",omitempty"`
|
||||
TagTemplate string `yaml:"tag_template,omitempty"`
|
||||
Files []string `yaml:"extra_files,omitempty"`
|
||||
Binary string `yaml:",omitempty"`
|
||||
Goos string `yaml:",omitempty"`
|
||||
Goarch string `yaml:",omitempty"`
|
||||
Goarm string `yaml:",omitempty"`
|
||||
Image string `yaml:",omitempty"`
|
||||
Dockerfile string `yaml:",omitempty"`
|
||||
Latest bool `yaml:",omitempty"`
|
||||
OldTagTemplate string `yaml:"tag_template,omitempty"`
|
||||
TagTemplates []string `yaml:"tag_templates,omitempty"`
|
||||
Files []string `yaml:"extra_files,omitempty"`
|
||||
|
||||
// Capture all undefined fields and should be empty after loading
|
||||
XXX map[string]interface{} `yaml:",inline"`
|
||||
|
@ -34,8 +34,12 @@ func (Pipe) String() string {
|
||||
func (Pipe) Default(ctx *context.Context) error {
|
||||
for i := range ctx.Config.Dockers {
|
||||
var docker = &ctx.Config.Dockers[i]
|
||||
if docker.TagTemplate == "" {
|
||||
docker.TagTemplate = "{{ .Version }}"
|
||||
if docker.OldTagTemplate != "" {
|
||||
// TODO: deprecate docker.tag_template in favor of docker.tag_templates
|
||||
docker.TagTemplates = append(docker.TagTemplates, docker.OldTagTemplate)
|
||||
}
|
||||
if len(docker.TagTemplates) == 0 {
|
||||
docker.TagTemplates = append(docker.TagTemplates, "{{ .Version }}")
|
||||
}
|
||||
if docker.Goos == "" {
|
||||
docker.Goos = "linux"
|
||||
@ -43,6 +47,10 @@ func (Pipe) Default(ctx *context.Context) error {
|
||||
if docker.Goarch == "" {
|
||||
docker.Goarch = "amd64"
|
||||
}
|
||||
if docker.Latest {
|
||||
// TODO: deprecate docker.Latest in favor of multiple tags?
|
||||
docker.TagTemplates = append(docker.TagTemplates, "latest")
|
||||
}
|
||||
}
|
||||
// only set defaults if there is exacly 1 docker setup in the config file.
|
||||
if len(ctx.Config.Dockers) != 1 {
|
||||
@ -105,11 +113,9 @@ func doRun(ctx *context.Context) error {
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
func tagName(ctx *context.Context, docker config.Docker) (string, error) {
|
||||
func tagName(ctx *context.Context, tagTemplate string) (string, error) {
|
||||
var out bytes.Buffer
|
||||
t, err := template.New("tag").
|
||||
Option("missingkey=error").
|
||||
Parse(docker.TagTemplate)
|
||||
t, err := template.New("tag").Option("missingkey=error").Parse(tagTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -128,13 +134,14 @@ func tagName(ctx *context.Context, docker config.Docker) (string, error) {
|
||||
func process(ctx *context.Context, docker config.Docker, artifact artifact.Artifact) error {
|
||||
var root = filepath.Dir(artifact.Path)
|
||||
var dockerfile = filepath.Join(root, filepath.Base(docker.Dockerfile))
|
||||
tag, err := tagName(ctx, docker)
|
||||
if err != nil {
|
||||
return err
|
||||
var images []string
|
||||
for _, tagTemplate := range docker.TagTemplates {
|
||||
tag, err := tagName(ctx, tagTemplate)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to execute tag template '%s'", tagTemplate)
|
||||
}
|
||||
images = append(images, fmt.Sprintf("%s:%s", docker.Image, tag))
|
||||
}
|
||||
var image = fmt.Sprintf("%s:%s", docker.Image, tag)
|
||||
var latest = fmt.Sprintf("%s:latest", docker.Image)
|
||||
|
||||
if err := os.Link(docker.Dockerfile, dockerfile); err != nil {
|
||||
return errors.Wrap(err, "failed to link dockerfile")
|
||||
}
|
||||
@ -143,16 +150,15 @@ func process(ctx *context.Context, docker config.Docker, artifact artifact.Artif
|
||||
return errors.Wrapf(err, "failed to link extra file '%s'", file)
|
||||
}
|
||||
}
|
||||
if err := dockerBuild(ctx, root, dockerfile, image); err != nil {
|
||||
if err := dockerBuild(ctx, root, dockerfile, images[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
if docker.Latest {
|
||||
if err := dockerTag(ctx, image, latest); err != nil {
|
||||
for _, img := range images[1:] {
|
||||
if err := dockerTag(ctx, images[0], img); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return publish(ctx, docker, image, latest)
|
||||
return publish(ctx, docker, images)
|
||||
}
|
||||
|
||||
// walks the src, recreating dirs and hard-linking files
|
||||
@ -178,21 +184,17 @@ func link(src, dest string) error {
|
||||
})
|
||||
}
|
||||
|
||||
func publish(ctx *context.Context, docker config.Docker, image, latest string) error {
|
||||
func publish(ctx *context.Context, docker config.Docker, images []string) error {
|
||||
if !ctx.Publish {
|
||||
log.Warn("skipping push because --skip-publish is set")
|
||||
return nil
|
||||
}
|
||||
if err := dockerPush(ctx, docker, image); err != nil {
|
||||
return err
|
||||
for _, image := range images {
|
||||
if err := dockerPush(ctx, docker, image); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !docker.Latest {
|
||||
return nil
|
||||
}
|
||||
if err := dockerTag(ctx, image, latest); err != nil {
|
||||
return err
|
||||
}
|
||||
return dockerPush(ctx, docker, latest)
|
||||
return nil
|
||||
}
|
||||
|
||||
func dockerBuild(ctx *context.Context, root, dockerfile, image string) error {
|
||||
|
@ -58,13 +58,15 @@ func TestRunPipe(t *testing.T) {
|
||||
"valid": {
|
||||
publish: true,
|
||||
docker: config.Docker{
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Binary: "mybin",
|
||||
Latest: true,
|
||||
TagTemplate: "{{.Tag}}-{{.Env.FOO}}",
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Binary: "mybin",
|
||||
TagTemplates: []string{
|
||||
"{{.Tag}}-{{.Env.FOO}}",
|
||||
"latest",
|
||||
},
|
||||
Files: []string{
|
||||
"testdata/extra_file.txt",
|
||||
},
|
||||
@ -78,13 +80,14 @@ func TestRunPipe(t *testing.T) {
|
||||
"valid_no_latest": {
|
||||
publish: true,
|
||||
docker: config.Docker{
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Binary: "mybin",
|
||||
Latest: false,
|
||||
TagTemplate: "{{.Version}}",
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Binary: "mybin",
|
||||
TagTemplates: []string{
|
||||
"{{.Version}}",
|
||||
},
|
||||
Files: []string{
|
||||
"testdata/extra_file.txt",
|
||||
},
|
||||
@ -97,13 +100,15 @@ func TestRunPipe(t *testing.T) {
|
||||
"valid_dont_publish": {
|
||||
publish: false,
|
||||
docker: config.Docker{
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Binary: "mybin",
|
||||
Latest: true,
|
||||
TagTemplate: "{{.Tag}}-{{.Env.FOO}}",
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Binary: "mybin",
|
||||
TagTemplates: []string{
|
||||
"{{.Tag}}-{{.Env.FOO}}",
|
||||
"latest",
|
||||
},
|
||||
Files: []string{
|
||||
"testdata/extra_file.txt",
|
||||
},
|
||||
@ -117,51 +122,58 @@ func TestRunPipe(t *testing.T) {
|
||||
"bad_dockerfile": {
|
||||
publish: true,
|
||||
docker: config.Docker{
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile.bad",
|
||||
Binary: "mybin",
|
||||
TagTemplate: "{{.Version}}",
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile.bad",
|
||||
Binary: "mybin",
|
||||
TagTemplates: []string{
|
||||
"{{.Version}}",
|
||||
},
|
||||
},
|
||||
err: "pull access denied for nope, repository does not exist",
|
||||
},
|
||||
"template_error": {
|
||||
publish: true,
|
||||
docker: config.Docker{
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Binary: "mybin",
|
||||
Latest: true,
|
||||
TagTemplate: "{{.Tag}",
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Binary: "mybin",
|
||||
TagTemplates: []string{
|
||||
"{{.Tag}",
|
||||
},
|
||||
},
|
||||
err: `template: tag:1: unexpected "}" in operand`,
|
||||
},
|
||||
"missing_env_on_template": {
|
||||
publish: true,
|
||||
docker: config.Docker{
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Binary: "mybin",
|
||||
Latest: true,
|
||||
TagTemplate: "{{.Env.NOPE}}",
|
||||
Image: registry + "goreleaser/test_run_pipe",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
Binary: "mybin",
|
||||
TagTemplates: []string{
|
||||
"{{.Env.NOPE}}",
|
||||
},
|
||||
},
|
||||
err: `template: tag:1:6: executing "tag" at <.Env.NOPE>: map has no entry for key "NOPE"`,
|
||||
},
|
||||
"no_permissions": {
|
||||
publish: true,
|
||||
docker: config.Docker{
|
||||
Image: "docker.io/nope",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Binary: "mybin",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
TagTemplate: "{{.Tag}}",
|
||||
Latest: true,
|
||||
Image: "docker.io/nope",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Binary: "mybin",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
TagTemplates: []string{
|
||||
"{{.Tag}}",
|
||||
"latest",
|
||||
},
|
||||
Latest: true,
|
||||
},
|
||||
expect: []string{
|
||||
"docker.io/nope:latest",
|
||||
@ -172,12 +184,14 @@ func TestRunPipe(t *testing.T) {
|
||||
"dockerfile_doesnt_exist": {
|
||||
publish: true,
|
||||
docker: config.Docker{
|
||||
Image: "whatever",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Binary: "mybin",
|
||||
Dockerfile: "testdata/Dockerfilezzz",
|
||||
TagTemplate: "{{.Tag}}",
|
||||
Image: "whatever",
|
||||
Goos: "linux",
|
||||
Goarch: "amd64",
|
||||
Binary: "mybin",
|
||||
Dockerfile: "testdata/Dockerfilezzz",
|
||||
TagTemplates: []string{
|
||||
"{{.Tag}}",
|
||||
},
|
||||
},
|
||||
err: `failed to link dockerfile`,
|
||||
},
|
||||
@ -191,8 +205,10 @@ func TestRunPipe(t *testing.T) {
|
||||
Files: []string{
|
||||
"testdata/nope.txt",
|
||||
},
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
TagTemplate: "{{.Tag}}",
|
||||
Dockerfile: "testdata/Dockerfile",
|
||||
TagTemplates: []string{
|
||||
"{{.Tag}}",
|
||||
},
|
||||
},
|
||||
err: `failed to link extra file 'testdata/nope.txt'`,
|
||||
},
|
||||
@ -339,7 +355,9 @@ func TestDefault(t *testing.T) {
|
||||
assert.Equal(t, "amd64", docker.Goarch)
|
||||
assert.Equal(t, ctx.Config.Builds[0].Binary, docker.Binary)
|
||||
assert.Equal(t, "Dockerfile", docker.Dockerfile)
|
||||
assert.Equal(t, "{{ .Version }}", docker.TagTemplate)
|
||||
assert.Empty(t, docker.OldTagTemplate)
|
||||
assert.Equal(t, []string{"{{ .Version }}", "latest"}, docker.TagTemplates)
|
||||
|
||||
}
|
||||
|
||||
func TestDefaultNoDockers(t *testing.T) {
|
||||
@ -371,7 +389,8 @@ func TestDefaultSet(t *testing.T) {
|
||||
assert.Equal(t, "windows", docker.Goos)
|
||||
assert.Equal(t, "i386", docker.Goarch)
|
||||
assert.Equal(t, "bar", docker.Binary)
|
||||
assert.Equal(t, "{{ .Version }}", docker.TagTemplate)
|
||||
assert.Empty(t, docker.OldTagTemplate)
|
||||
assert.Equal(t, []string{"{{ .Version }}"}, docker.TagTemplates)
|
||||
assert.Equal(t, "Dockerfile.foo", docker.Dockerfile)
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user