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

PublishModule: add --gpgKeyName flag #530

Merged
merged 2 commits into from
Jan 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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