mirror of https://github.com/sbt/sbt.git
Merge pull request #8130 from eed3si9n/wip/querystring
[1.x] fix: Fix Sonatype publishing
This commit is contained in:
commit
8a7d84aa08
|
|
@ -11,6 +11,7 @@ package internal
|
||||||
package sona
|
package sona
|
||||||
|
|
||||||
import gigahorse.*, support.apachehttp.Gigahorse
|
import gigahorse.*, support.apachehttp.Gigahorse
|
||||||
|
import java.net.URLEncoder
|
||||||
import java.util.Base64
|
import java.util.Base64
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
@ -30,7 +31,7 @@ class Sona(client: SonaClient) extends AutoCloseable {
|
||||||
log: Logger,
|
log: Logger,
|
||||||
): Unit = {
|
): Unit = {
|
||||||
val deploymentId = client.uploadBundle(bundleZipPath, deploymentName, pt, log)
|
val deploymentId = client.uploadBundle(bundleZipPath, deploymentName, pt, log)
|
||||||
client.waitForDeploy(deploymentId, pt, log)
|
client.waitForDeploy(deploymentId, deploymentName, pt, 1, log)
|
||||||
}
|
}
|
||||||
def close(): Unit = client.close()
|
def close(): Unit = client.close()
|
||||||
}
|
}
|
||||||
|
|
@ -49,16 +50,17 @@ class SonaClient(reqTransform: Request => Request) extends AutoCloseable {
|
||||||
log: Logger,
|
log: Logger,
|
||||||
): String = {
|
): String = {
|
||||||
val res = retryF(maxAttempt = 2) { (attempt: Int) =>
|
val res = retryF(maxAttempt = 2) { (attempt: Int) =>
|
||||||
log.info(s"uploading bundle to Sonatype Central (attempt: $attempt)")
|
log.info(s"uploading bundle to the Central Portal (attempt: $attempt)")
|
||||||
|
// addQuery string doesn't work for post
|
||||||
|
val q = queryString(
|
||||||
|
"name" -> deploymentName,
|
||||||
|
"publishingType" -> (publishingType match {
|
||||||
|
case PublishingType.Automatic => "AUTOMATIC"
|
||||||
|
case PublishingType.UserManaged => "USER_MANAGED"
|
||||||
|
})
|
||||||
|
)
|
||||||
val req = Gigahorse
|
val req = Gigahorse
|
||||||
.url(s"${baseUrl}/publisher/upload")
|
.url(s"${baseUrl}/publisher/upload?$q")
|
||||||
.addQueryString(
|
|
||||||
"name" -> deploymentName,
|
|
||||||
"publishingType" -> (publishingType match {
|
|
||||||
case PublishingType.Automatic => "AUTOMATIC"
|
|
||||||
case PublishingType.UserManaged => "USER_MANAGED"
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.post(
|
.post(
|
||||||
MultipartFormBody(
|
MultipartFormBody(
|
||||||
FormPart("bundle", bundleZipPath.toFile())
|
FormPart("bundle", bundleZipPath.toFile())
|
||||||
|
|
@ -70,23 +72,39 @@ class SonaClient(reqTransform: Request => Request) extends AutoCloseable {
|
||||||
awaitWithMessage(res, "uploading...", log)
|
awaitWithMessage(res, "uploading...", log)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def queryString(kv: (String, String)*): String =
|
||||||
|
kv.map {
|
||||||
|
case (k, v) =>
|
||||||
|
val encodedV = URLEncoder.encode(v, "UTF-8")
|
||||||
|
s"$k=$encodedV"
|
||||||
|
}
|
||||||
|
.mkString("&")
|
||||||
|
|
||||||
def waitForDeploy(
|
def waitForDeploy(
|
||||||
deploymentId: String,
|
deploymentId: String,
|
||||||
|
deploymentName: String,
|
||||||
publishingType: PublishingType,
|
publishingType: PublishingType,
|
||||||
|
attempt: Int,
|
||||||
log: Logger,
|
log: Logger,
|
||||||
): Unit = {
|
): Unit = {
|
||||||
val status = deploymentStatus(deploymentId)
|
val status = deploymentStatus(deploymentId)
|
||||||
log.info(s"deployment $deploymentId ${status.deploymentState}")
|
log.info(s"deployment $deploymentName ${status.deploymentState} ${attempt}/n")
|
||||||
|
val sleepSec =
|
||||||
|
if (attempt <= 3) List(5, 5, 10, 15)(attempt)
|
||||||
|
else 30
|
||||||
status.deploymentState match {
|
status.deploymentState match {
|
||||||
case DeploymentState.FAILED => sys.error(s"deployment $deploymentId failed")
|
case DeploymentState.FAILED => sys.error(s"deployment $deploymentId failed")
|
||||||
case DeploymentState.PENDING | DeploymentState.PUBLISHING | DeploymentState.VALIDATING =>
|
case DeploymentState.PENDING | DeploymentState.PUBLISHING | DeploymentState.VALIDATING =>
|
||||||
Thread.sleep(5000)
|
Thread.sleep(sleepSec * 1000L)
|
||||||
waitForDeploy(deploymentId, publishingType, log)
|
waitForDeploy(deploymentId, deploymentName, publishingType, attempt + 1, log)
|
||||||
case DeploymentState.PUBLISHED if publishingType == PublishingType.Automatic => ()
|
case DeploymentState.PUBLISHED if publishingType == PublishingType.Automatic => ()
|
||||||
case DeploymentState.VALIDATED if publishingType == PublishingType.UserManaged => ()
|
case DeploymentState.VALIDATED if publishingType == PublishingType.UserManaged => ()
|
||||||
|
case DeploymentState.VALIDATED =>
|
||||||
|
Thread.sleep(sleepSec * 1000L)
|
||||||
|
waitForDeploy(deploymentId, deploymentName, publishingType, attempt + 1, log)
|
||||||
case _ =>
|
case _ =>
|
||||||
Thread.sleep(5000)
|
Thread.sleep(sleepSec * 1000L)
|
||||||
waitForDeploy(deploymentId, publishingType, log)
|
waitForDeploy(deploymentId, deploymentName, publishingType, attempt + 1, log)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ package sbt
|
||||||
|
|
||||||
import java.io.{ File, PrintWriter }
|
import java.io.{ File, PrintWriter }
|
||||||
import java.nio.file.{ Path => NioPath }
|
import java.nio.file.{ Path => NioPath }
|
||||||
import java.util.Optional
|
import java.util.{ Optional, UUID }
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import lmcoursier.CoursierDependencyResolution
|
import lmcoursier.CoursierDependencyResolution
|
||||||
import lmcoursier.definitions.{ Configuration => CConfiguration }
|
import lmcoursier.definitions.{ Configuration => CConfiguration }
|
||||||
|
|
@ -3102,6 +3102,12 @@ object Classpaths {
|
||||||
if (!alreadyContainsCentralCredentials) SysProp.sonatypeCredentalsEnv.toSeq
|
if (!alreadyContainsCentralCredentials) SysProp.sonatypeCredentalsEnv.toSeq
|
||||||
else Nil
|
else Nil
|
||||||
},
|
},
|
||||||
|
sonaDeploymentName := {
|
||||||
|
val o = organization.value
|
||||||
|
val v = version.value
|
||||||
|
val uuid = UUID.randomUUID().toString().take(8)
|
||||||
|
s"$o:$v:$uuid"
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@nowarn("cat=deprecation")
|
@nowarn("cat=deprecation")
|
||||||
|
|
|
||||||
|
|
@ -570,6 +570,7 @@ object Keys {
|
||||||
val stagingDirectory = settingKey[File]("Local staging directory for Sonatype publishing").withRank(CSetting)
|
val stagingDirectory = settingKey[File]("Local staging directory for Sonatype publishing").withRank(CSetting)
|
||||||
val sonaBundle = taskKey[File]("Local bundle for Sonatype publishing").withRank(DTask)
|
val sonaBundle = taskKey[File]("Local bundle for Sonatype publishing").withRank(DTask)
|
||||||
val localStaging = settingKey[Option[Resolver]]("Local staging resolver for Sonatype publishing").withRank(CSetting)
|
val localStaging = settingKey[Option[Resolver]]("Local staging resolver for Sonatype publishing").withRank(CSetting)
|
||||||
|
val sonaDeploymentName = settingKey[String]("The name used for deployment").withRank(DSetting)
|
||||||
|
|
||||||
val classifiersModule = taskKey[GetClassifiersModule]("classifiers-module").withRank(CTask)
|
val classifiersModule = taskKey[GetClassifiersModule]("classifiers-module").withRank(CTask)
|
||||||
val compatibilityWarningOptions = settingKey[CompatibilityWarningOptions]("Configures warnings around Maven incompatibility.").withRank(CSetting)
|
val compatibilityWarningOptions = settingKey[CompatibilityWarningOptions]("Configures warnings around Maven incompatibility.").withRank(CSetting)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ package internal
|
||||||
package librarymanagement
|
package librarymanagement
|
||||||
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.util.UUID
|
|
||||||
import sbt.internal.util.MessageOnlyException
|
import sbt.internal.util.MessageOnlyException
|
||||||
import sbt.io.IO
|
import sbt.io.IO
|
||||||
import sbt.io.Path.contentOf
|
import sbt.io.Path.contentOf
|
||||||
|
|
@ -40,12 +39,12 @@ object Publishing {
|
||||||
private def sonatypeReleaseAction(pt: PublishingType)(s0: State): State = {
|
private def sonatypeReleaseAction(pt: PublishingType)(s0: State): State = {
|
||||||
val extracted = Project.extract(s0)
|
val extracted = Project.extract(s0)
|
||||||
val log = extracted.get(Keys.sLog)
|
val log = extracted.get(Keys.sLog)
|
||||||
|
val dn = extracted.get(Keys.sonaDeploymentName)
|
||||||
val (s1, bundle) = extracted.runTask(Keys.sonaBundle, s0)
|
val (s1, bundle) = extracted.runTask(Keys.sonaBundle, s0)
|
||||||
val (s2, creds) = extracted.runTask(Keys.credentials, s1)
|
val (s2, creds) = extracted.runTask(Keys.credentials, s1)
|
||||||
val client = fromCreds(creds)
|
val client = fromCreds(creds)
|
||||||
try {
|
try {
|
||||||
val uuid = UUID.randomUUID().toString().take(8)
|
client.uploadBundle(bundle.toPath(), dn, pt, log)
|
||||||
client.uploadBundle(bundle.toPath(), uuid, pt, log)
|
|
||||||
s2
|
s2
|
||||||
} finally {
|
} finally {
|
||||||
client.close()
|
client.close()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue