Skip to content

Commit

Permalink
Solves 345 : optional signing
Browse files Browse the repository at this point in the history
* Made gpgPassphrase optional for publishing
* Added a flag to remove signing of published artifacts altogether
  • Loading branch information
Baccata committed May 22, 2018
1 parent 7358b3c commit 43015ac
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 37 deletions.
76 changes: 45 additions & 31 deletions scalalib/src/mill/scalalib/PublishModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package scalalib

import ammonite.ops._
import mill.define.{ExternalModule, Task}
import mill.eval.{PathRef, Result}
import mill.eval.PathRef
import mill.scalalib.publish.{Artifact, SonatypePublisher}
import mill.util.Loose.Agg

/**
* Configuration necessary for publishing a Scala module to Maven Central or similar
*/
Expand All @@ -17,17 +17,18 @@ trait PublishModule extends JavaModule { outer =>
def pomSettings: T[PomSettings]
def publishVersion: T[String]

def publishSelfDependency = T{
Artifact(pomSettings().organization, artifactId(), publishVersion()),
def publishSelfDependency = T {
Artifact(pomSettings().organization, artifactId(), publishVersion())
}

def publishXmlDeps = T.task{
def publishXmlDeps = T.task {
val ivyPomDeps = ivyDeps().map(resolvePublishDependency().apply(_))
val modulePomDeps = Task.sequence(moduleDeps.map(_.publishSelfDependency))()
ivyPomDeps ++ modulePomDeps.map(Dependency(_, Scope.Compile))
}
def pom = T {
val pom = Pom(artifactMetadata(), publishXmlDeps(), artifactId(), pomSettings())
val pom =
Pom(artifactMetadata(), publishXmlDeps(), artifactId(), pomSettings())
val pomPath = T.ctx().dest / s"${artifactId()}-${publishVersion()}.pom"
write.over(pomPath, pom)
PathRef(pomPath)
Expand Down Expand Up @@ -57,9 +58,10 @@ trait PublishModule extends JavaModule { outer =>

def sonatypeUri: String = "https://oss.sonatype.org/service/local"

def sonatypeSnapshotUri: String = "https://oss.sonatype.org/content/repositories/snapshots"
def sonatypeSnapshotUri: String =
"https://oss.sonatype.org/content/repositories/snapshots"

def publishArtifacts = T{
def publishArtifacts = T {
val baseName = s"${artifactId()}-${publishVersion()}"
PublishModule.PublishData(
artifactMetadata(),
Expand All @@ -73,49 +75,61 @@ trait PublishModule extends JavaModule { outer =>
}

def publish(sonatypeCreds: String,
gpgPassphrase: String,
gpgPassphrase: String = "",
signed: Boolean = true,
release: Boolean): define.Command[Unit] = T.command {
val PublishModule.PublishData(artifactInfo, artifacts) = publishArtifacts()
new SonatypePublisher(
sonatypeUri,
sonatypeSnapshotUri,
sonatypeCreds,
gpgPassphrase,
Some(gpgPassphrase).filter(_.nonEmpty),
signed,
T.ctx().log
).publish(artifacts.map{case (a, b) => (a.path, b)}, artifactInfo, release)
).publish(artifacts.map { case (a, b) => (a.path, b) },
artifactInfo,
release)
}
}

object PublishModule extends ExternalModule{
object PublishModule extends ExternalModule {
case class PublishData(meta: Artifact, payload: Seq[(PathRef, String)])

object PublishData{
implicit def jsonify: upickle.default.ReadWriter[PublishData] = upickle.default.macroRW
object PublishData {
implicit def jsonify: upickle.default.ReadWriter[PublishData] =
upickle.default.macroRW
}

def publishAll(sonatypeCreds: String,
gpgPassphrase: String,
gpgPassphrase: String = "",
signed: Boolean = true,
publishArtifacts: mill.main.Tasks[PublishModule.PublishData],
release: Boolean = false,
sonatypeUri: String = "https://oss.sonatype.org/service/local",
sonatypeSnapshotUri: String = "https://oss.sonatype.org/content/repositories/snapshots") = T.command{

val x: Seq[(Seq[(Path, String)], Artifact)] = Task.sequence(publishArtifacts.value)().map{
case PublishModule.PublishData(a, s) => (s.map{case (p, f) => (p.path, f)}, a)
sonatypeSnapshotUri: String =
"https://oss.sonatype.org/content/repositories/snapshots") =
T.command {

val x: Seq[(Seq[(Path, String)], Artifact)] =
Task.sequence(publishArtifacts.value)().map {
case PublishModule.PublishData(a, s) =>
(s.map { case (p, f) => (p.path, f) }, a)
}
new SonatypePublisher(
sonatypeUri,
sonatypeSnapshotUri,
sonatypeCreds,
Some(gpgPassphrase).filter(_.nonEmpty),
signed,
T.ctx().log
).publishAll(
release,
x: _*
)
}
new SonatypePublisher(
sonatypeUri,
sonatypeSnapshotUri,
sonatypeCreds,
gpgPassphrase,
T.ctx().log
).publishAll(
release,
x:_*
)
}

implicit def millScoptTargetReads[T] = new mill.main.Tasks.Scopt[T]()

lazy val millDiscover: mill.define.Discover[this.type] = mill.define.Discover[this.type]
lazy val millDiscover: mill.define.Discover[this.type] =
mill.define.Discover[this.type]
}
18 changes: 12 additions & 6 deletions scalalib/src/mill/scalalib/publish/SonatypePublisher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import scalaj.http.HttpResponse
class SonatypePublisher(uri: String,
snapshotUri: String,
credentials: String,
gpgPassphrase: String,
gpgPassphrase: Option[String],
signed: Boolean,
log: Logger) {

private val api = new SonatypeHttpApi(uri, credentials)
Expand All @@ -29,11 +30,11 @@ class SonatypePublisher(uri: String,
).mkString("/")
val fileMapping = fileMapping0.map{ case (file, name) => (file, publishPath+"/"+name) }

val signedArtifacts = fileMapping ++ fileMapping.map {
val signedArtifacts = if (signed) fileMapping.map {
case (file, name) => poorMansSign(file, gpgPassphrase) -> s"$name.asc"
}
} else Seq()

artifact -> signedArtifacts.flatMap {
artifact -> (fileMapping ++ signedArtifacts).flatMap {
case (file, name) =>
val content = read.bytes(file)

Expand Down Expand Up @@ -135,10 +136,15 @@ class SonatypePublisher(uri: String,
}

// http://central.sonatype.org/pages/working-with-pgp-signatures.html#signing-a-file
private def poorMansSign(file: Path, passphrase: String): Path = {
private def poorMansSign(file: Path, maybePassphrase: Option[String]): Path = {
val fileName = file.toString
import ammonite.ops.ImplicitWd._
%("gpg", "--passphrase", passphrase, "--batch", "--yes", "-a", "-b", fileName)
maybePassphrase match {
case Some(passphrase) =>
%("gpg", "--passphrase", passphrase, "--batch", "--yes", "-a", "-b", fileName)
case None =>
%("gpg", "--batch", "--yes", "-a", "-b", fileName)
}
Path(fileName + ".asc")
}

Expand Down

0 comments on commit 43015ac

Please sign in to comment.