Skip to content

Commit

Permalink
Merge pull request #117 from olofwalker/return-image-id-from-docker-push
Browse files Browse the repository at this point in the history
Return image name and id from dockerPush and dockerBuildAndPush
  • Loading branch information
marcus-drake authored Aug 16, 2020
2 parents 40602a6 + 6718dd8 commit 5cb2f7d
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/main/scala/sbtdocker/DockerKeys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import sbt._

object DockerKeys {
val docker = taskKey[ImageId]("Build a Docker image.")
val dockerBuildAndPush = taskKey[ImageId]("Build a Docker image and pushes it to a registry.")
val dockerPush = taskKey[Unit]("Push a already built Docker image to a registry.")
val dockerBuildAndPush = taskKey[Map[ImageName, ImageDigest]]("Build a Docker image and pushes it to a registry.")
val dockerPush = taskKey[Map[ImageName, ImageDigest]]("Push a already built Docker image to a registry.")

@deprecated("Use imageNames instead.", "1.0.0")
val imageName = taskKey[ImageName]("Name of the built image.")
Expand Down
26 changes: 22 additions & 4 deletions src/main/scala/sbtdocker/DockerPush.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ object DockerPush {
* @param imageNames names of the images to push
* @param log logger
*/
def apply(dockerPath: String, imageNames: Seq[ImageName], log: Logger): Unit = {
imageNames.foreach { imageName =>
def apply(dockerPath: String, imageNames: Seq[ImageName], log: Logger): Map[ImageName, ImageDigest] = {
imageNames.map { imageName =>
apply(dockerPath, imageName, log)
}
}.toMap
}

/**
Expand All @@ -26,15 +26,18 @@ object DockerPush {
* @param imageName name of the image to push
* @param log logger
*/
def apply(dockerPath: String, imageName: ImageName, log: Logger): Unit = {
def apply(dockerPath: String, imageName: ImageName, log: Logger): (ImageName, ImageDigest) = {
log.info(s"Pushing docker image with name: '$imageName'")

var lines = Seq.empty[String]
val processLog = ProcessLogger(
{ line =>
log.info(line)
lines :+= line
},
{ line =>
log.info(line)
lines :+= line
}
)

Expand All @@ -44,5 +47,20 @@ object DockerPush {
val process = Process(command)
val exitValue = process ! processLog
if (exitValue != 0) sys.error("Failed to push")

val PushedImageDigestSha256 = ".* digest: sha256:([0-9a-f]+) .*".r

val imageDigest = lines.collect {
case PushedImageDigestSha256(digest) => ImageDigest("sha256", digest)
}.lastOption

imageDigest match {
case Some(digest) =>
imageName -> digest
case None =>
throw new DockerPushException("Could not parse Docker image digest")
}
}
}

class DockerPushException(message: String) extends RuntimeException(message)
3 changes: 1 addition & 2 deletions src/main/scala/sbtdocker/DockerSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ object DockerSettings {
DockerPush(dockerPath, imageNames, log)
},
dockerBuildAndPush := Def.taskDyn {
val id = docker.value
docker.value
Def.task {
dockerPush.value
id
}
}.value,
dockerfile in docker := {
Expand Down
15 changes: 12 additions & 3 deletions src/main/scala/sbtdocker/models.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ object BuildOptions {
* @param removeIntermediateContainers Remove intermediate containers after a build.
* @param pullBaseImage Always attempts to pull a newer version of the base image.
*/
case class BuildOptions(
final case class BuildOptions(
cache: Boolean = true,
removeIntermediateContainers: BuildOptions.Remove.Option = BuildOptions.Remove.OnSuccess,
pullBaseImage: BuildOptions.Pull.Option = BuildOptions.Pull.IfMissing
Expand All @@ -42,10 +42,19 @@ case class BuildOptions(
* Id of an Docker image.
* @param id Id as a hexadecimal digit string.
*/
case class ImageId(id: String) {
final case class ImageId(id: String) extends AnyVal {
override def toString = id
}

/**
* The image digest, the format of the digest is `algorithm:hex-string`
* @param algorithm The algorithm used to produce the digest.
* @param digest A digest of the image, as a string.
*/
final case class ImageDigest(algorithm: String, digest: String) {
override def toString = s"$algorithm:$digest"
}

object ImageName {

/**
Expand Down Expand Up @@ -88,7 +97,7 @@ object ImageName {
* @param namespace Namespace name.
* @param tag Tag, for example a version number.
*/
case class ImageName(
final case class ImageName(
registry: Option[String] = None,
namespace: Option[String] = None,
repository: String,
Expand Down

0 comments on commit 5cb2f7d

Please sign in to comment.