Skip to content

Commit

Permalink
Add signing support in publish command
Browse files Browse the repository at this point in the history
Using both gpg and bouncycastle
  • Loading branch information
alexarchambault committed Feb 27, 2022
1 parent 4760971 commit b74b3bf
Show file tree
Hide file tree
Showing 25 changed files with 1,885 additions and 21 deletions.
34 changes: 25 additions & 9 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ trait Cli extends SbtModule with CliLaunchers with ScalaCliPublishModule with Fo
def repositories = super.repositories ++ customRepositories

def ivyDeps = super.ivyDeps() ++ Agg(
Deps.bouncycastle,
Deps.caseApp,
Deps.coursierLauncher,
Deps.coursierPublish,
Expand Down Expand Up @@ -394,15 +395,22 @@ trait CliIntegrationBase extends SbtModule with ScalaCliPublishModule with HasTe
super.scalacOptions() ++ Seq("-Xasync", "-Ywarn-unused", "-deprecation")
}

def sources = T.sources {
def modulesPath = T {
val name = mainArtifactName().stripPrefix(prefix)
val baseIntegrationPath = os.Path(millSourcePath.toString.stripSuffix(name))
val modulesPath = os.Path(
val p = os.Path(
baseIntegrationPath.toString.stripSuffix(baseIntegrationPath.baseName)
)
val mainPath = PathRef(modulesPath / "integration" / "src" / "main" / "scala")
PathRef(p)
}
def sources = T.sources {
val mainPath = PathRef(modulesPath().path / "integration" / "src" / "main" / "scala")
super.sources() ++ Seq(mainPath)
}
def resources = T.sources {
val mainPath = PathRef(modulesPath().path / "integration" / "src" / "main" / "resources")
super.resources() ++ Seq(mainPath)
}

def ivyDeps = super.ivyDeps() ++ Agg(
Deps.osLib
Expand All @@ -422,15 +430,23 @@ trait CliIntegrationBase extends SbtModule with ScalaCliPublishModule with HasTe
"SCALA_CLI_TMP" -> tmpDirBase().path.toString,
"CI" -> "1"
)
private def updateRef(name: String, ref: PathRef): PathRef = {
val rawPath = ref.path.toString.replace(
File.separator + name + File.separator,
File.separator
)
PathRef(os.Path(rawPath))
}
def sources = T.sources {
val name = mainArtifactName().stripPrefix(prefix)
super.sources().flatMap { ref =>
val rawPath = ref.path.toString.replace(
File.separator + name + File.separator,
File.separator
)
val base = PathRef(os.Path(rawPath))
Seq(base, ref)
Seq(updateRef(name, ref), ref)
}
}
def resources = T.sources {
val name = mainArtifactName().stripPrefix(prefix)
super.resources().flatMap { ref =>
Seq(updateRef(name, ref), ref)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import shapeless._
trait ConfigMonoid[T] {
def zero: T
def orElse(main: T, defaults: T): T

def sum(values: Seq[T]): T =
values.foldLeft(zero)(orElse(_, _))
}

object ConfigMonoid {
Expand All @@ -16,6 +19,9 @@ object ConfigMonoid {
def orElse(main: T, defaults: T) = orElseFn(main, defaults)
}

def sum[T](values: Seq[T])(implicit monoid: ConfigMonoid[T]): T =
monoid.sum(values)

trait HListConfigMonoid[T <: HList] {
def zero: T
def orElse(main: T, defaults: T): T
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ final case class PublishOptions(
scalaVersionSuffix: Option[String] = None,
scalaPlatformSuffix: Option[String] = None,
repository: Option[String] = None,
sourceJar: Option[Boolean] = None
sourceJar: Option[Boolean] = None,
gpgSignatureId: Option[String] = None,
gpgOptions: List[String] = Nil,
signer: Option[PublishOptions.Signer] = None,
secretKey: Option[os.Path] = None,
secretKeyPassword: Option[Secret[String]] = None
)

object PublishOptions {
Expand All @@ -26,6 +31,19 @@ object PublishOptions {
final case class Developer(id: String, name: String, url: String, mail: Option[String] = None)
final case class Vcs(url: String, connection: String, developerConnection: String)

sealed abstract class Signer extends Product with Serializable
object Signer {
case object Gpg extends Signer
case object BouncyCastle extends Signer
}

def parseSigner(input: Positioned[String]): Either[MalformedInputError, Signer] =
input.value match {
case "gpg" => Right(Signer.Gpg)
case "bc" | "bouncycastle" => Right(Signer.BouncyCastle)
case _ => Left(new MalformedInputError("signer", input.value, "gpg|bc", input.positions))
}

def parseLicense(input: Positioned[String]): Either[BuildException, Positioned[License]] =
input.value.split(":", 2) match {
case Array(name) =>
Expand Down
22 changes: 22 additions & 0 deletions modules/build/src/main/scala/scala/build/options/Secret.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package scala.build.options

final class Secret[+T](
value0: T
) {
def value: T = value0

override def equals(obj: Any): Boolean =
obj match {
case other: Secret[_] => value == other.value
case _ => false
}

// not leaking details about the secret here
override def hashCode(): Int = 0
override def toString: String = "****"
}

object Secret {
def apply[T](value: T): Secret[T] =
new Secret(value)
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ case object UsingPublishDirectiveHandler extends UsingDirectiveHandler {
cwd: ScopePath,
logger: Logger
): Either[BuildException, ProcessedUsingDirective] = either {
val singleValue = DirectiveUtil.singleStringValue(directive, path, cwd)
def singleValue = DirectiveUtil.singleStringValue(directive, path, cwd)
def severalValues = DirectiveUtil.stringValues(directive.values, path, cwd)

if (!directive.key.startsWith(prefix))
value(Left(new UnexpectedDirectiveError(directive)))
Expand Down Expand Up @@ -85,6 +86,10 @@ case object UsingPublishDirectiveHandler extends UsingDirectiveHandler {
PublishOptions(scalaPlatformSuffix = Some(value(singleValue).value))
case "repository" =>
PublishOptions(repository = Some(value(singleValue).value))
case "gpgKey" | "gpg-key" =>
PublishOptions(gpgSignatureId = Some(value(singleValue).value))
case "gpgOptions" | "gpg-options" | "gpgOption" | "gpg-option" =>
PublishOptions(gpgOptions = severalValues.map(_._1.value).toList)
case _ =>
value(Left(new UnexpectedDirectiveError(directive)))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package scala.cli.internal;

// from https://github.com/micronaut-projects/micronaut-oracle-cloud/pull/17
// see also https://github.com/oracle/graal/issues/2800#issuecomment-702480444

import com.oracle.svm.core.annotate.AutomaticFeature;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.hosted.RuntimeClassInitialization;

import java.security.Security;

@AutomaticFeature
public class BouncyCastleFeature implements Feature {

@Override
public void afterRegistration(AfterRegistrationAccess access) {
RuntimeClassInitialization.initializeAtBuildTime("org.bouncycastle");
Security.addProvider(new BouncyCastleProvider());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Args = --no-fallback \
--initialize-at-build-time=scala.collection.immutable.VM \
--initialize-at-build-time=com.google.common.jimfs.SystemJimfsFileSystemProvider \
--initialize-at-build-time=com.google.common.base.Preconditions \
--rerun-class-initialization-at-runtime=org.bouncycastle.jcajce.provider.drbg.DRBG$Default,org.bouncycastle.jcajce.provider.drbg.DRBG$NonceAndIV \
-H:IncludeResources=bootstrap.*.jar \
-H:IncludeResources=coursier/coursier.properties \
-H:IncludeResources=coursier/launcher/coursier.properties \
Expand Down
Loading

0 comments on commit b74b3bf

Please sign in to comment.