diff --git a/plugin/publish/docker.go b/plugin/publish/docker.go index e868afba..5af0cb27 100644 --- a/plugin/publish/docker.go +++ b/plugin/publish/docker.go @@ -30,10 +30,9 @@ type Docker struct { Email string `yaml:"email"` // Keep the build on the Docker host after pushing? - KeepBuild bool `yaml:"keep_build"` - // Do we want to override "latest" automatically with this build? - PushLatest bool `yaml:"push_latest"` - CustomTag string `yaml:"custom_tag"` + KeepBuild bool `yaml:"keep_build"` + Tag string `yaml:"tag"` + Tags []string `yaml:"tags"` Condition *condition.Condition `yaml:"when,omitempty"` } @@ -67,36 +66,42 @@ func (d *Docker) Write(f *buildfile.Buildfile) { } // Run the command commands to build and deploy the image. - // Are we setting a custom tag, or do we use the git hash? - imageTag := "" - if len(d.CustomTag) > 0 { - imageTag = d.CustomTag - } else { - imageTag = "$(git rev-parse --short HEAD)" + + // Add the single tag if one exists + if len(d.Tag) > 0 { + d.Tags = append(d.Tags, d.Tag) } + + // If no tags are specified, use the commit hash + if len(d.Tags) == 0 { + d.Tags = append(d.Tags, "$(git rev-parse --short HEAD)") + } + + // There is always at least 1 tag + buildImageTag := d.Tags[0] + + // Export docker host once f.WriteCmd("export DOCKER_HOST=" + d.DockerHost) - f.WriteCmd(fmt.Sprintf("docker build -t %s:%s %s", d.ImageName, imageTag, dockerPath)) + + // Build the image + f.WriteCmd(fmt.Sprintf("docker build -t %s:%s %s", d.ImageName, buildImageTag, dockerPath)) // Login? if d.RegistryLogin == true { f.WriteCmdSilent(fmt.Sprintf("docker login -u %s -p %s -e %s %s", d.Username, d.Password, d.Email, d.RegistryLoginUrl)) } - // Push the tagged image only - Do not push all image tags - f.WriteCmd(fmt.Sprintf("docker push %s:%s", d.ImageName, imageTag)) - // Are we overriding the "latest" tag? - if d.PushLatest { - f.WriteCmd(fmt.Sprintf("docker tag %s:%s %s:latest", - d.ImageName, imageTag, d.ImageName)) - f.WriteCmd(fmt.Sprintf("docker push %s:latest", d.ImageName)) + // Tag and push all tags + for _, tag := range d.Tags { + f.WriteCmd(fmt.Sprintf("docker tag %s:%s %s:%s", d.ImageName, buildImageTag, d.ImageName, tag)) + f.WriteCmd(fmt.Sprintf("docker push %s:%s", d.ImageName, tag)) } - // Delete the image from the docker server we built on. + // Remove tags after pushing unless keepBuild is set if !d.KeepBuild { - f.WriteCmd(fmt.Sprintf("docker rmi %s:%s", d.ImageName, imageTag)) - if d.PushLatest { - f.WriteCmd(fmt.Sprintf("docker rmi %s:latest", d.ImageName)) + for _, tag := range d.Tags { + f.WriteCmd(fmt.Sprintf("docker rmi %s:%s", d.ImageName, tag)) } } } diff --git a/plugin/publish/docker_test.go b/plugin/publish/docker_test.go index 46c1497e..5263461b 100644 --- a/plugin/publish/docker_test.go +++ b/plugin/publish/docker_test.go @@ -32,6 +32,7 @@ publish: docker_version: 1.3.0 image_name: registry/image ` + func TestDockerHost(t *testing.T) { response, err := setUpWithDrone(dockerHostYaml) t.Log(privateRegistryNoAuthYaml) @@ -59,6 +60,7 @@ publish: registry_login: false image_name: registry/image ` + func TestPrivateRegistryNoAuth(t *testing.T) { response, err := setUpWithDrone(privateRegistryNoAuthYaml) t.Log(privateRegistryNoAuthYaml) @@ -101,36 +103,6 @@ func TestPrivateRegistryAuth(t *testing.T) { } } -// Override "latest" Test -var overrideLatestTagYaml = ` -publish: - docker: - docker_host: tcp://server:1000 - docker_version: 1.0 - username: username - password: password - email: email@example.com - image_name: username/image - push_latest: true -` - -func TestOverrideLatestTag(t *testing.T) { - response, err := setUpWithDrone(overrideLatestTagYaml) - t.Log(overrideLatestTagYaml) - if err != nil { - t.Fatalf("Can't unmarshal script: %s\n\n", err.Error()) - } - if !strings.Contains(response, "docker build -t username/image:$(git rev-parse --short HEAD) .") { - t.Fatalf("Response: " + response + " doesn't contain the git-ref tagged image\n\n") - } - if !strings.Contains(response, "docker tag username/image:$(git rev-parse --short HEAD) username/image:latest") { - t.Fatalf("Response: " + response + " doesn't contain 'latest' tag command\n\n") - } - if !strings.Contains(response, "docker push username/image:latest") { - t.Fatalf("Response: " + response + " doesn't contain push command\n\n") - } -} - // Keep builds Test var keepBuildsYaml = ` publish: @@ -161,14 +133,14 @@ publish: docker: docker_host: tcp://server:1000 docker_version: 1.0 - custom_tag: release-0.1 + tag: release-0.1 username: username password: password email: email@example.com image_name: username/image ` -func TestCustomTag(t *testing.T) { +func TestSingleTag(t *testing.T) { response, err := setUpWithDrone(customTagYaml) t.Log(customTagYaml) if err != nil { @@ -183,6 +155,9 @@ func TestCustomTag(t *testing.T) { if !strings.Contains(response, "docker push username/image:release-0.1") { t.Fatalf("Response: " + response + " doesn't push the custom tagged image\n\n") } + if !strings.Contains(response, "docker rmi username/image:release-0.1") { + t.Fatalf("Response: " + response + " doesn't remove custom tagged image\n\n") + } } var missingFieldsYaml = ` @@ -191,6 +166,98 @@ publish: dockerfile: file ` +var multipleTagsYaml = ` +publish: + docker: + docker_host: tcp://server:1000 + docker_version: 1.0 + tags: [release-0.2, release-latest] + username: username + password: password + email: email@example.com + image_name: username/image +` + +func TestTagsNoSingle(t *testing.T) { + response, err := setUpWithDrone(multipleTagsYaml) + t.Log(multipleTagsYaml) + if err != nil { + t.Fatalf("Can't unmarshal script: %s\n", err.Error()) + } + if strings.Contains(response, "$(git rev-parse --short HEAD)") { + t.Fatalf("Response: " + response + " is tagging images from git-refs when it should using custom tag\n\n") + } + if !strings.Contains(response, "docker build -t username/image:release-0.2") { + t.Fatalf("Response: " + response + " isn't tagging images using our first custom tag\n\n") + } + if !strings.Contains(response, "docker tag username/image:release-0.2 username/image:release-latest") { + t.Fatalf("Response: " + response + " isn't tagging images using our second custom tag\n\n") + } + if !strings.Contains(response, "docker push username/image:release-0.2") { + t.Fatalf("Response: " + response + " doesn't push the custom tagged image\n\n") + } + if !strings.Contains(response, "docker rmi username/image:release-0.2") { + t.Fatalf("Response: " + response + " doesn't remove custom tagged image\n\n") + } + if !strings.Contains(response, "docker push username/image:release-latest") { + t.Fatalf("Response: " + response + " doesn't push the second custom tagged image\n\n") + } + if !strings.Contains(response, "docker rmi username/image:release-latest") { + t.Fatalf("Response: " + response + " doesn't remove second custom tagged image\n\n") + } +} + +var bothTagsYaml = ` +publish: + docker: + docker_host: tcp://server:1000 + docker_version: 1.0 + tag: release-0.2 + tags: [release-0.3, release-latest] + username: username + password: password + email: email@example.com + image_name: username/image +` + +func TestTagsWithSingle(t *testing.T) { + response, err := setUpWithDrone(bothTagsYaml) + t.Log(bothTagsYaml) + if err != nil { + t.Fatalf("Can't unmarshal script: %s\n", err.Error()) + } + if strings.Contains(response, "$(git rev-parse --short HEAD)") { + t.Fatalf("Response: " + response + " is tagging images from git-refs when it should using custom tag\n\n") + } + if !strings.Contains(response, "docker build -t username/image:release-0.3") { + t.Fatalf("Response: " + response + " isn't tagging images using our first custom tag\n\n") + } + if !strings.Contains(response, "docker tag username/image:release-0.3 username/image:release-0.2") { + t.Fatalf("Response: " + response + " isn't tagging images using our second custom tag\n\n") + } + if !strings.Contains(response, "docker tag username/image:release-0.3 username/image:release-latest") { + t.Fatalf("Response: " + response + " isn't tagging images using our third custom tag\n\n") + } + if !strings.Contains(response, "docker push username/image:release-0.2") { + t.Fatalf("Response: " + response + " doesn't push the custom tagged image\n\n") + } + if !strings.Contains(response, "docker rmi username/image:release-0.2") { + t.Fatalf("Response: " + response + " doesn't remove custom tagged image\n\n") + } + if !strings.Contains(response, "docker push username/image:release-0.3") { + t.Fatalf("Response: " + response + " doesn't push the custom tagged image\n\n") + } + if !strings.Contains(response, "docker rmi username/image:release-0.3") { + t.Fatalf("Response: " + response + " doesn't remove custom tagged image\n\n") + } + if !strings.Contains(response, "docker push username/image:release-latest") { + t.Fatalf("Response: " + response + " doesn't push the second custom tagged image\n\n") + } + if !strings.Contains(response, "docker rmi username/image:release-latest") { + t.Fatalf("Response: " + response + " doesn't remove second custom tagged image\n\n") + } +} + func TestMissingFields(t *testing.T) { response, err := setUpWithDrone(missingFieldsYaml) t.Log(missingFieldsYaml) @@ -212,7 +279,6 @@ publish: password: password email: email image_name: user/image - push_latest: true registry_login: true ` @@ -223,9 +289,6 @@ func TestValidYaml(t *testing.T) { t.Fatalf("Can't unmarshal script: %s\n\n", err.Error()) } - if !strings.Contains(response, "docker tag user/image:$(git rev-parse --short HEAD) user/image:latest") { - t.Fatalf("Response: " + response + " doesn't contain tag command for latest\n\n") - } if !strings.Contains(response, "docker build -t user/image:$(git rev-parse --short HEAD) - <") { t.Fatalf("Response: " + response + "doesn't contain build command for commit hash\n\n") }