Skip to content

Commit

Permalink
Support SONATYPE_TOKEN env var for token auth
Browse files Browse the repository at this point in the history
  • Loading branch information
rtyley committed Jan 18, 2024
1 parent a8270ed commit 8a943d6
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 9 deletions.
16 changes: 7 additions & 9 deletions src/main/scala/xerial/sbt/Sonatype.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

package xerial.sbt

import sbt.Keys._
import sbt._
import sbt.Keys.*
import sbt.*
import sbt.librarymanagement.MavenRepository
import wvlet.log.{LogLevel, LogSupport}
import xerial.sbt.sonatype.SonatypeClient.StagingRepositoryProfile
import xerial.sbt.sonatype.SonatypeService._
import xerial.sbt.sonatype.{SonatypeClient, SonatypeException, SonatypeService}
import xerial.sbt.sonatype.SonatypeService.*
import xerial.sbt.sonatype.{EnvironmentCredentials, SonatypeClient, SonatypeException, SonatypeService}

import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext, Future}
Expand Down Expand Up @@ -77,15 +77,13 @@ object Sonatype extends AutoPlugin with LogSupport {
case _ => false
}
if (!alreadyContainsSonatypeCredentials) {
val env = sys.env.get(_)
(for {
username <- env("SONATYPE_USERNAME")
password <- env("SONATYPE_PASSWORD")
usernameAndPassword <- EnvironmentCredentials.getUsernameAndPassword()
} yield Credentials(
"Sonatype Nexus Repository Manager",
sonatypeCredentialHost.value,
username,
password
usernameAndPassword.username,
usernameAndPassword.password,
)).toSeq
} else Seq.empty
},
Expand Down
23 changes: 23 additions & 0 deletions src/main/scala/xerial/sbt/sonatype/EnvironmentCredentials.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package xerial.sbt.sonatype

final class UsernameAndPassword(val username: String, val password: String)

object UsernameAndPassword {
def fromToken(token: String): UsernameAndPassword = token.split(':') match {
case Array(user, pass) => new UsernameAndPassword(user, pass)
}
}

object EnvironmentCredentials {
val Username = "SONATYPE_USERNAME"
val Password = "SONATYPE_PASSWORD"
val Token = "SONATYPE_TOKEN"

def getUsernameAndPassword(envVars: Map[String, String] = sys.env): Option[UsernameAndPassword] =
envVars.get(Token).map(UsernameAndPassword.fromToken).orElse {
for {
u <- envVars.get(Username)
p <- envVars.get(Password)
} yield new UsernameAndPassword(u, p)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package xerial.sbt.sonatype

import wvlet.airspec.AirSpec

class EnvironmentCredentialsTest extends AirSpec {
test("Extract a username & password from a SONATYPE_TOKEN environment variable") {
val usernameAndPassword = EnvironmentCredentials.getUsernameAndPassword(Map(
"SONATYPE_TOKEN" -> "user:pass"
)).get

usernameAndPassword.username shouldBe "user"
usernameAndPassword.password shouldBe "pass"
}

test("Extract a legacy Sonatype Username & Password from environment variables") {
val usernameAndPassword = EnvironmentCredentials.getUsernameAndPassword(Map(
"SONATYPE_USERNAME" -> "user",
"SONATYPE_PASSWORD" -> "pass"
)).get

usernameAndPassword.username shouldBe "user"
usernameAndPassword.password shouldBe "pass"
}

test("Prefer a Sonatype token over a legacy Sonatype Username & Password") {
val usernameAndPassword = EnvironmentCredentials.getUsernameAndPassword(Map(
"SONATYPE_TOKEN" -> "newUser:newPass",
"SONATYPE_USERNAME" -> "oldUser",
"SONATYPE_PASSWORD" -> "oldPass"
)).get

usernameAndPassword.username shouldBe "newUser"
usernameAndPassword.password shouldBe "newPass"
}
}

0 comments on commit 8a943d6

Please sign in to comment.