Skip to content

Commit

Permalink
PublishModule: add --gpgKeyName flag (#530)
Browse files Browse the repository at this point in the history
* PublishModule: adds gpgKeyName flag

* 1 - Intro to Mill.md: usage sample of publish updates for gpgKeyName
  • Loading branch information
lxohi authored and lihaoyi committed Jan 22, 2019
1 parent b3efd5a commit eed2be0
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 16 deletions.
6 changes: 4 additions & 2 deletions docs/pages/1 - Intro to Mill.md
Original file line number Diff line number Diff line change
Expand Up @@ -740,13 +740,15 @@ your sonatype credentials (e.g. `lihaoyi:foobarbaz`) and GPG password as inputs:
```bash
$ mill foo.publish
Missing arguments: (--sonatypeCreds: String, --gpgPassphrase: String, --release: Boolean)
Missing arguments: (--sonatypeCreds: String, --release: Boolean)
Arguments provided did not match expected signature:
publish
--sonatypeCreds String (format: "username:password")
--gpgPassphrase String
--gpgPassphrase String (default null)
--gpgKeyName String (default null)
--signed Boolean (default true)
--release Boolean
```
Expand Down
4 changes: 4 additions & 0 deletions scalalib/src/PublishModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ trait PublishModule extends JavaModule { outer =>

def publish(sonatypeCreds: String,
gpgPassphrase: String = null,
gpgKeyName: String = null,
signed: Boolean = true,
release: Boolean): define.Command[Unit] = T.command {
val PublishModule.PublishData(artifactInfo, artifacts) = publishArtifacts()
Expand All @@ -81,6 +82,7 @@ trait PublishModule extends JavaModule { outer =>
sonatypeSnapshotUri,
sonatypeCreds,
Option(gpgPassphrase),
Option(gpgKeyName),
signed,
T.ctx().log
).publish(artifacts.map{case (a, b) => (a.path, b)}, artifactInfo, release)
Expand All @@ -96,6 +98,7 @@ object PublishModule extends ExternalModule {

def publishAll(sonatypeCreds: String,
gpgPassphrase: String = null,
gpgKeyName: String = null,
publishArtifacts: mill.main.Tasks[PublishModule.PublishData],
release: Boolean = false,
sonatypeUri: String = "https://oss.sonatype.org/service/local",
Expand All @@ -110,6 +113,7 @@ object PublishModule extends ExternalModule {
sonatypeSnapshotUri,
sonatypeCreds,
Option(gpgPassphrase),
Option(gpgKeyName),
signed,
T.ctx().log
).publishAll(
Expand Down
30 changes: 16 additions & 14 deletions scalalib/src/publish/SonatypePublisher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import java.math.BigInteger
import java.security.MessageDigest

import mill.api.Logger

import os.Shellable
import scalaj.http.HttpResponse

class SonatypePublisher(uri: String,
snapshotUri: String,
credentials: String,
gpgPassphrase: Option[String],
gpgKeyName: Option[String],
signed: Boolean,
log: Logger) {

Expand All @@ -19,6 +20,7 @@ class SonatypePublisher(uri: String,
def publish(fileMapping: Seq[(os.Path, String)], artifact: Artifact, release: Boolean): Unit = {
publishAll(release, fileMapping -> artifact)
}

def publishAll(release: Boolean, artifacts: (Seq[(os.Path, String)], Artifact)*): Unit = {

val mappings = for ((fileMapping0, artifact) <- artifacts) yield {
Expand All @@ -27,10 +29,10 @@ class SonatypePublisher(uri: String,
artifact.id,
artifact.version
).mkString("/")
val fileMapping = fileMapping0.map{ case (file, name) => (file, publishPath+"/"+name) }
val fileMapping = fileMapping0.map { case (file, name) => (file, publishPath + "/" + name) }

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

artifact -> (fileMapping ++ signedArtifacts).flatMap {
Expand All @@ -46,11 +48,11 @@ class SonatypePublisher(uri: String,
}

val (snapshots, releases) = mappings.partition(_._1.isSnapshot)
if(snapshots.nonEmpty) {
if (snapshots.nonEmpty) {
publishSnapshot(snapshots.flatMap(_._2), snapshots.map(_._1))
}
val releaseGroups = releases.groupBy(_._1.group)
for((group, groupReleases) <- releaseGroups){
for ((group, groupReleases) <- releaseGroups) {
publishRelease(release, groupReleases.flatMap(_._2), group, releases.map(_._1))
}
}
Expand Down Expand Up @@ -122,6 +124,7 @@ class SonatypePublisher(uri: String,
attempts: Int = 20): Unit = {
def isRightStatus =
api.getStagingRepoState(stagingRepoId).equalsIgnoreCase(status)

var attemptsLeft = attempts

while (attemptsLeft > 0 && !isRightStatus) {
Expand All @@ -135,16 +138,15 @@ class SonatypePublisher(uri: String,
}

// http://central.sonatype.org/pages/working-with-pgp-signatures.html#signing-a-file
private def poorMansSign(file: os.Path, maybePassphrase: Option[String]): os.Path = {
private def poorMansSign(file: os.Path, maybePassphrase: Option[String], maybeKeyName: Option[String]): os.Path = {
val fileName = file.toString
maybePassphrase match {
case Some(passphrase) =>
os.proc("gpg", "--passphrase", passphrase, "--batch", "--yes", "-a", "-b", fileName)
.call(stdin = os.Inherit, stdout = os.Inherit, stderr = os.Inherit)
case None =>
os.proc("gpg", "--batch", "--yes", "-a", "-b", fileName)
.call(stdin = os.Inherit, stdout = os.Inherit, stderr = os.Inherit)
}
val optionFlag = (flag: String, ov: Option[String]) => ov.map(flag :: _ :: Nil).getOrElse(Nil)
val command = "gpg" ::
optionFlag("--passphrase", maybePassphrase) ++ optionFlag("-u", maybeKeyName) ++
Seq("--batch", "--yes", "-a", "-b", fileName)

os.proc(command.map(v => v: Shellable))
.call(stdin = os.Inherit, stdout = os.Inherit, stderr = os.Inherit)
os.Path(fileName + ".asc")
}

Expand Down

0 comments on commit eed2be0

Please sign in to comment.