Skip to content
Open
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
93 changes: 93 additions & 0 deletions libs/javalib/src/mill/javalib/MavenPublish.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package mill.javalib

import com.lumidion.sonatype.central.client.core.SonatypeCredentials
import mill.api.daemon.Logger
import mill.javalib.PublishModule.PublishData
import mill.javalib.internal.MavenWorkerSupport as InternalMavenWorkerSupport

private[mill] trait MavenPublish {

def mavenPublishDatas(
publishDatas: Seq[PublishData],
bundleName: Option[String],
credentials: SonatypeCredentials,
releaseUri: String,
snapshotUri: String,
taskDest: os.Path,
log: Logger,
env: Map[String, String],
worker: InternalMavenWorkerSupport.Api
): Unit = {
val dryRun = env.get("MILL_TESTS_PUBLISH_DRY_RUN").contains("1")

val (snapshots, releases) = publishDatas.partition(_.meta.isSnapshot)

bundleName.filter(_ => snapshots.nonEmpty).foreach { bundleName =>
throw new IllegalArgumentException(
s"Publishing SNAPSHOT versions when bundle name ($bundleName) is specified is not supported.\n\n" +
s"SNAPSHOT versions: ${pprint.apply(snapshots)}"
)
}

releases.map(_ -> false).appendedAll(snapshots.map(_ -> true)).foreach { (data, isSnapshot) =>
mavenPublishData(
dryRun = dryRun,
publishData = data,
isSnapshot = isSnapshot,
credentials = credentials,
releaseUri = releaseUri,
snapshotUri = snapshotUri,
taskDest = taskDest,
log = log,
worker = worker
)
}
}

def mavenPublishData(
dryRun: Boolean,
publishData: PublishData,
isSnapshot: Boolean,
credentials: SonatypeCredentials,
releaseUri: String,
snapshotUri: String,
taskDest: os.Path,
log: Logger,
worker: InternalMavenWorkerSupport.Api
): Unit = {
val uri = if (isSnapshot) snapshotUri else releaseUri
val artifacts = MavenWorkerSupport.RemoteM2Publisher.asM2ArtifactsFromPublishDatas(
publishData.meta,
publishData.payloadAsMap
)

if (isSnapshot) {
log.info(
s"Detected a 'SNAPSHOT' version for ${publishData.meta}, publishing to Maven Repository at '$uri'"
)
}

/** Maven uses this as a workspace for file manipulation. */
val mavenWorkspace = taskDest / "maven"

if (dryRun) {
val publishTo = taskDest / "repository"
val result = worker.publishToLocal(
publishTo = publishTo,
workspace = mavenWorkspace,
artifacts
)
log.info(s"Dry-run publishing to '$publishTo' finished with result: $result")
} else {
val result = worker.publishToRemote(
uri = uri,
workspace = mavenWorkspace,
username = credentials.username,
password = credentials.password,
artifacts
)
log.info(s"Publishing to '$uri' finished with result: $result")
}
}

}
75 changes: 75 additions & 0 deletions libs/javalib/src/mill/javalib/MavenPublishModule.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package mill.javalib

import com.lihaoyi.unroll
import mill.*
import mill.api.*
import mill.javalib.PublishModule.PublishData
import mill.util.Tasks

trait MavenPublishModule extends PublishModule, MavenWorkerSupport, SonatypeCredentialsModule,
MavenPublish {

def mavenReleaseUri: T[String]

def mavenSnapshotUri: T[String]

def publishMaven(
username: String = "",
password: String = "",
@unroll sources: Boolean = true,
@unroll docs: Boolean = true
): Task.Command[Unit] = Task.Command {
val artifact = artifactMetadata()
val credentials = getSonatypeCredentials(username, password)()
val publishData = publishArtifactsPayload(sources = sources, docs = docs)()

mavenPublishDatas(
Seq(PublishData(artifact, publishData)),
bundleName = None,
credentials,
releaseUri = mavenReleaseUri(),
snapshotUri = mavenSnapshotUri(),
taskDest = Task.dest,
log = Task.log,
env = Task.env,
worker = mavenWorker()
)
}

}

object MavenPublishModule extends ExternalModule, DefaultTaskModule, MavenWorkerSupport,
SonatypeCredentialsModule, MavenPublish {

def defaultTask(): String = "publishAll"

def publishAll(
publishArtifacts: mill.util.Tasks[PublishModule.PublishData] =
Tasks.resolveMainDefault("__:PublishModule.publishArtifacts"),
username: String = "",
password: String = "",
bundleName: String = "",
releaseUri: String,
snapshotUri: String
): Command[Unit] = Task.Command {
val artifacts = Task.sequence(publishArtifacts.value)()

val finalBundleName = if (bundleName.isEmpty) None else Some(bundleName)
val credentials = getSonatypeCredentials(username, password)()

mavenPublishDatas(
artifacts,
finalBundleName,
credentials,
releaseUri = releaseUri,
snapshotUri = snapshotUri,
taskDest = Task.dest,
log = Task.log,
env = Task.env,
worker = mavenWorker()
)
}

lazy val millDiscover: Discover = Discover[this.type]

}
107 changes: 28 additions & 79 deletions libs/javalib/src/mill/javalib/SonatypeCentralPublishModule.scala
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
package mill.javalib

import com.lihaoyi.unroll
import com.lumidion.sonatype.central.client.core.{PublishingType, SonatypeCredentials}
import com.lumidion.sonatype.central.client.core.PublishingType
import com.lumidion.sonatype.central.client.core.SonatypeCredentials
import mill.*
import javalib.*
import mill.api.{ExternalModule, Task}
import mill.util.Tasks
import mill.api.BuildCtx
import mill.api.DefaultTaskModule
import mill.api.ExternalModule
import mill.api.Result
import mill.javalib.SonatypeCentralPublishModule.{
defaultAwaitTimeout,
defaultConnectTimeout,
defaultCredentials,
defaultReadTimeout,
getPublishingTypeFromReleaseFlag,
getSonatypeCredentials
}
import mill.javalib.publish.Artifact
import mill.javalib.publish.SonatypeHelpers.{PASSWORD_ENV_VARIABLE_NAME, USERNAME_ENV_VARIABLE_NAME}
import mill.api.BuildCtx
import mill.api.Task
import mill.api.daemon.Logger
import mill.javalib.PublishModule.PublishData
import mill.javalib.SonatypeCentralPublishModule.defaultAwaitTimeout
import mill.javalib.SonatypeCentralPublishModule.defaultConnectTimeout
import mill.javalib.SonatypeCentralPublishModule.defaultCredentials
import mill.javalib.SonatypeCentralPublishModule.defaultReadTimeout
import mill.javalib.SonatypeCentralPublishModule.getPublishingTypeFromReleaseFlag
import mill.javalib.internal.PublishModule.GpgArgs
import mill.javalib.publish.Artifact
import mill.util.Tasks

trait SonatypeCentralPublishModule extends PublishModule, MavenWorkerSupport {
import javalib.*

trait SonatypeCentralPublishModule extends PublishModule, MavenWorkerSupport,
SonatypeCredentialsModule {

@deprecated("Use `sonatypeCentralGpgArgsForKey` instead.", "Mill 1.0.1")
def sonatypeCentralGpgArgs: T[String] =
Expand Down Expand Up @@ -97,8 +97,8 @@ trait SonatypeCentralPublishModule extends PublishModule, MavenWorkerSupport {
/**
* External module to publish artifacts to `central.sonatype.org`
*/
object SonatypeCentralPublishModule extends ExternalModule with DefaultTaskModule
with MavenWorkerSupport {
object SonatypeCentralPublishModule extends ExternalModule, DefaultTaskModule, MavenWorkerSupport,
SonatypeCredentialsModule, MavenPublish {
private final val sonatypeCentralGpgArgsSentinelValue = "<user did not override this method>"

def self = this
Expand Down Expand Up @@ -169,37 +169,17 @@ object SonatypeCentralPublishModule extends ExternalModule with DefaultTaskModul
val dryRun = env.get("MILL_TESTS_PUBLISH_DRY_RUN").contains("1")

def publishSnapshot(publishData: PublishData): Unit = {
val uri = sonatypeCentralSnapshotUri
val artifacts = MavenWorkerSupport.RemoteM2Publisher.asM2ArtifactsFromPublishDatas(
publishData.meta,
publishData.payloadAsMap
)

log.info(
s"Detected a 'SNAPSHOT' version for ${publishData.meta}, publishing to Sonatype Central Snapshots at '$uri'"
mavenPublishData(
dryRun = dryRun,
publishData = publishData,
isSnapshot = true,
credentials = credentials,
releaseUri = sonatypeCentralSnapshotUri,
snapshotUri = sonatypeCentralSnapshotUri,
taskDest = taskDest,
log = log,
worker = worker
)

/** Maven uses this as a workspace for file manipulation. */
val mavenWorkspace = taskDest / "maven"

if (dryRun) {
val publishTo = taskDest / "repository"
val result = worker.publishToLocal(
publishTo = publishTo,
workspace = mavenWorkspace,
artifacts
)
log.info(s"Dry-run publishing to '$publishTo' finished with result: $result")
} else {
val result = worker.publishToRemote(
uri = uri,
workspace = mavenWorkspace,
username = credentials.username,
password = credentials.password,
artifacts
)
log.info(s"Publishing to '$uri' finished with result: $result")
}
}

def publishReleases(artifacts: Seq[PublishData], gpgArgs: GpgArgs): Unit = {
Expand Down Expand Up @@ -258,36 +238,5 @@ object SonatypeCentralPublishModule extends ExternalModule with DefaultTaskModul
}
}

private def getSonatypeCredential(
credentialParameterValue: String,
credentialName: String,
envVariableName: String
): Task[String] = Task.Anon {
if (credentialParameterValue.nonEmpty) {
Result.Success(credentialParameterValue)
} else {
(for {
credential <- Task.env.get(envVariableName)
} yield {
Result.Success(credential)
}).getOrElse(
Result.Failure(
s"No $credentialName set. Consider using the $envVariableName environment variable or passing `$credentialName` argument"
)
)
}
}

private def getSonatypeCredentials(
usernameParameterValue: String,
passwordParameterValue: String
): Task[SonatypeCredentials] = Task.Anon {
val username =
getSonatypeCredential(usernameParameterValue, "username", USERNAME_ENV_VARIABLE_NAME)()
val password =
getSonatypeCredential(passwordParameterValue, "password", PASSWORD_ENV_VARIABLE_NAME)()
Result.Success(SonatypeCredentials(username, password))
}

lazy val millDiscover: mill.api.Discover = mill.api.Discover[this.type]
}
39 changes: 39 additions & 0 deletions libs/javalib/src/mill/javalib/SonatypeCredentialsModule.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package mill.javalib

import com.lumidion.sonatype.central.client.core.SonatypeCredentials
import mill.api.*
import mill.javalib.publish.SonatypeHelpers.PASSWORD_ENV_VARIABLE_NAME
import mill.javalib.publish.SonatypeHelpers.USERNAME_ENV_VARIABLE_NAME

private[mill] trait SonatypeCredentialsModule extends Module {
def getSonatypeCredential(
credentialParameterValue: String,
credentialName: String,
envVariableName: String
): Task[String] = Task.Anon {
if (credentialParameterValue.nonEmpty) {
Result.Success(credentialParameterValue)
} else {
(for {
credential <- Task.env.get(envVariableName)
} yield {
Result.Success(credential)
}).getOrElse(
Result.Failure(
s"No $credentialName set. Consider using the $envVariableName environment variable or passing `$credentialName` argument"
)
)
}
}

def getSonatypeCredentials(
usernameParameterValue: String,
passwordParameterValue: String
): Task[SonatypeCredentials] = Task.Anon {
val username =
getSonatypeCredential(usernameParameterValue, "username", USERNAME_ENV_VARIABLE_NAME)()
val password =
getSonatypeCredential(passwordParameterValue, "password", PASSWORD_ENV_VARIABLE_NAME)()
Result.Success(SonatypeCredentials(username, password))
}
}
2 changes: 2 additions & 0 deletions libs/scalalib/src/mill/scalalib/aliases.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package mill.scalalib

object Dependency extends mill.api.ExternalModule.Alias(mill.javalib.Dependency)
object MavenPublishModule
extends mill.api.ExternalModule.Alias(mill.javalib.MavenPublishModule)
object SonatypeCentralPublishModule
extends mill.api.ExternalModule.Alias(mill.javalib.SonatypeCentralPublishModule)
2 changes: 2 additions & 0 deletions libs/scalalib/src/mill/scalalib/exports.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export mill.javalib.RunModule

export mill.javalib.SonatypeCentralPublisher

type MavenPublishModule = mill.javalib.MavenPublishModule

type SonatypeCentralPublishModule = mill.javalib.SonatypeCentralPublishModule

export mill.javalib.TestModule
Expand Down
Loading