Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publish Arbitrary Docker Tags #979

Closed
apeschel opened this issue May 16, 2017 · 5 comments
Closed

Publish Arbitrary Docker Tags #979

apeschel opened this issue May 16, 2017 · 5 comments

Comments

@apeschel
Copy link
Contributor

apeschel commented May 16, 2017

Expected behaviour

docker:publishLocal and docker:publish should be configurable to accept any arbitrary tags.

Ideally, the ability to set a sequence of tags would ease the difficulty of publishing of docker image aliases.

EG:

In build.sbt:

version := v1.0.0-develop.20170516,
dockerRepository := "initech",
packageName := "halting-problem",
dockerImageTags := Seq("latest", "develop")

Should create the following images:

initech/halting-problem:v1.0.0-develop.20170516
initech/halting-problem:latest
initech/halting-problem:develop

Actual behaviour

Only the project version and the literal string latest are available for use as image tags.

Here's the best workaround I've found at the moment:

dockerBuildOptions ++= {
  val alias = DockerAlias(
    dockerRepository.value,
    None,
    (packageName in Docker).value,
    Some("develop")
  )
  Seq("-t", alias.versioned)
}
@muuki88
Copy link
Contributor

muuki88 commented May 17, 2017

Thanks @apeschel for your well written feature request.

Is this a common issue we should integrate into sbt-native-packager? I'm asking because we need to maintain every setting we add. And as you already mentioned there is a way to define this behavior very easily. You can shorten this even more

dockerBuildOptions ++= {
  val alias = dockerAlias.value
  List("tag1", "tag2", "tag3").flatMap(tag => List("-t", alias.copy(tag = Some(tag)).versioned))
}

This is so simple to generalize it into a setting IMHO.

@muuki88 muuki88 closed this as completed May 17, 2017
@apeschel
Copy link
Contributor Author

@muuki88 Thanks for the quick response! I appreciate your shortened alternative.

I think your argument makes sense since there doesn't seem to be much demand for this -- I'm the only person requesting the setting at the moment.

@apeschel
Copy link
Contributor Author

@muuki88 As a side note, the workaround described here only publishes the image locally, but doesn't publish to the remote docker repository. I'm currently trying to figure out how to add this functionality as well.

@apeschel
Copy link
Contributor Author

apeschel commented May 17, 2017

@muuki88 Here's the full workaround that I developed, it's much more complex than the original workaround.

import com.typesafe.sbt.packager.docker.DockerPlugin

// Add image alias for the latest develop and master image.
// It's not currently possible to easily add arbitrary tags.
// https://github.com/sbt/sbt-native-packager/issues/979
dockerBuildOptions ++= {
  val branch = getGitBranch
  if (Seq("master", "develop").contains(branch)) {
    val alias = dockerAlias.value
    val branch_alias = alias.copy(tag = Some(branch))
    List("-t", branch_alias.versioned)
  } else {
    Seq()
  }
},
inConfig(Docker)(
  Seq(
    // Modifying an existing task
    // http://www.scala-sbt.org/0.13/docs/Tasks.html
    // intTask := intTask.value + 1
    publish := {
      publish.value
      val branch = getGitBranch
      if (Seq("master", "develop").contains(branch)) {
        val alias = dockerAlias.value
        val branch_alias = alias.copy(tag = Some(branch))
        val log = streams.value.log
        DockerPlugin.publishDocker(dockerExecCommand.value, branch_alias.versioned, log)
      }
    }
  )
)

@muuki88
Copy link
Contributor

muuki88 commented May 18, 2017

Thanks @apeschel for sharing. This is totally fine doing this, we have the DockerPlugin.publishDocker explicitly opened and the dockerBuildOptions to add arbitrary stuff you may need.

Some recommendations for the code

  1. Use filter instead of if and flatMap on sequences to append stuff
dockerBuildOptions ++= List("master", "develop")
   .filter(_.contains(getGitBranch))
   .flatMap(branch => List("-t", dockerAlias.value.copy(tag = Some(branch)).versioned)
  1. Put this into an AutoPlugin in your build and share logic as you would in an application
package com.example

import sbt._
import sbt.Keys._

// the sbt-git plugin
import com.typesafe.sbt.SbtGit.GitKeys

object DockerBranchPublishingPlugin extends AutoPlugin {
   override val requires = DockerPlugin // must be imported

   // create your own settings and task that enhance your build
   object autoImport {
       val dockerBranchesAsTags = SettingKey[Seq[String]]("dockerBranchesAsTags", "if you publish from one of these branches they will also be published as docker tags")
   }

   import autoImport._

   override def projectSettings(): Seq[Setting[_]] = Seq(
      dockerBranchesAsTags := Seq("master", "develop"),
      dockerBuildOptions ++= dockerBranchesAsTags.value
         // using sbt-git here
         .filter(_.contains(gitBranch.value))
         .flatMap(branch => List("-t", dockerAlias.value.copy(tag = Some(branch)).versioned),
      publish in Docker := {
         (publish in Docker).value
          dockerBranchesAsTags.value
            .filter(_.contains(gitBranch.value))
            .foreach { branch =>
                val alias = dockerAlias.value.copy(tag = Some(branch))
                DockerPlugin.publishDocker(dockerExecCommand.value, alias.versioned, streams.value.log)
            }
      }
   )

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants