From 922c92c78e5d1ff70dd451bb560abfc3490221c2 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Sun, 11 Sep 2022 06:56:10 +0000 Subject: [PATCH 01/30] It cross-compiles --- build.sbt | 100 ++++++++++++------ .../src/main/scala/SSLPlatform.scala | 0 .../src/main/scala}/message/Scram.scala | 31 +----- .../scala}/protocol/StartupPlatform.scala | 0 .../scala/net/message/ScramPlatform.scala | 40 +++++++ .../core/jvm/src/main/scala/SSLPlatform.scala | 18 ++-- .../net/message/PasswordMessagePlatform.scala | 72 +++++++++++++ .../scala/net/message/ScramPlatform.scala | 56 ++++++++++ .../src/main/scala/net/message/openssl.scala | 65 ++++++++++++ modules/core/shared/src/main/scala/SSL.scala | 23 ++-- .../core/shared/src/main/scala/Session.scala | 2 +- .../scala/ffstest/FFrameworkPlatform.scala | 12 +++ .../scala-2/codec/TemporalCodecTest.scala | 2 +- .../tests/shared/src/test/scala/SslTest.scala | 2 +- project/build.properties | 2 +- project/plugins.sbt | 2 + 16 files changed, 338 insertions(+), 89 deletions(-) rename modules/core/{js => js-native}/src/main/scala/SSLPlatform.scala (100%) rename modules/core/{js/src/main/scala/net => js-native/src/main/scala}/message/Scram.scala (76%) rename modules/core/{js/src/main/scala/net => js-native/src/main/scala}/protocol/StartupPlatform.scala (100%) create mode 100644 modules/core/js/src/main/scala/net/message/ScramPlatform.scala create mode 100644 modules/core/native/src/main/scala/net/message/PasswordMessagePlatform.scala create mode 100644 modules/core/native/src/main/scala/net/message/ScramPlatform.scala create mode 100644 modules/core/native/src/main/scala/net/message/openssl.scala create mode 100644 modules/tests/native/src/main/scala/ffstest/FFrameworkPlatform.scala diff --git a/build.sbt b/build.sbt index 0a14f6bd..54439195 100644 --- a/build.sbt +++ b/build.sbt @@ -30,7 +30,20 @@ lazy val setupCertAndDocker = Seq( ) ) -ThisBuild / githubWorkflowBuildPreamble ++= setupCertAndDocker +val isLinux = { + val osName = Option(System.getProperty("os.name")) + osName.exists(_.toLowerCase().contains("linux")) +} + +lazy val installNativeDeps = Seq( + WorkflowStep.Run( + List("brew install utf8proc s2n"), + name = Some("Install utf8proc and s2n"), + cond = Some("startsWith(matrix.project, 'rootNative')") + ) +) + +ThisBuild / githubWorkflowBuildPreamble ++= installNativeDeps ++ setupCertAndDocker ThisBuild / githubWorkflowBuild ~= { steps => WorkflowStep.Sbt( commands = List("headerCheckAll"), @@ -62,9 +75,11 @@ ThisBuild / githubWorkflowAddedJobs += ) ) +ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") + // This is used in a couple places -lazy val fs2Version = "3.2.14" -lazy val natchezVersion = "0.1.6" +lazy val fs2Version = "3.2.14-75-7902cbf" +lazy val natchezVersion = "0.1.6-SNAPSHOT" // We do `evictionCheck` in CI inThisBuild(Seq( @@ -115,9 +130,9 @@ lazy val commonSettings = Seq( Compile / unmanagedSourceDirectories ++= { val sourceDir = (Compile / sourceDirectory).value CrossVersion.partialVersion(scalaVersion.value) match { - case Some((3, _)) => Seq(sourceDir / "scala-2.13+", file(sourceDir.getPath.replaceFirst("jvm", "shared").replaceFirst("js", "shared")) / "scala-2.13+") + case Some((3, _)) => Seq(sourceDir / "scala-2.13+", file(sourceDir.getPath.replaceFirst("jvm", "shared").replaceFirst("js", "shared").replaceFirst("native", "shared")) / "scala-2.13+") case Some((2, 12)) => Seq() - case Some((2, _)) => Seq(sourceDir / "scala-2.13+", file(sourceDir.getPath.replaceFirst("jvm", "shared").replaceFirst("js", "shared")) / "scala-2.13+") + case Some((2, _)) => Seq(sourceDir / "scala-2.13+", file(sourceDir.getPath.replaceFirst("jvm", "shared").replaceFirst("js", "shared").replaceFirst("native", "shared")) / "scala-2.13+") case _ => Seq() } }, @@ -139,7 +154,7 @@ lazy val skunk = tlCrossRootProject .aggregate(core, tests, circe, refined, example) .settings(commonSettings) -lazy val core = crossProject(JVMPlatform, JSPlatform) +lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform) .crossType(CrossType.Full) .in(file("modules/core")) .enablePlugins(AutomateHeaderPlugin) @@ -149,30 +164,30 @@ lazy val core = crossProject(JVMPlatform, JSPlatform) description := "Tagless, non-blocking data access library for Postgres.", resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots", libraryDependencies ++= Seq( - "org.typelevel" %%% "cats-core" % "2.7.0", - "org.typelevel" %%% "cats-effect" % "3.3.5", + "org.typelevel" %%% "cats-core" % "2.8.0", + "org.typelevel" %%% "cats-effect" % "3.3.14-1-5d11fe9", "co.fs2" %%% "fs2-core" % fs2Version, "co.fs2" %%% "fs2-io" % fs2Version, - "org.scodec" %%% "scodec-bits" % "1.1.30", - "org.scodec" %%% "scodec-core" % (if (tlIsScala3.value) "2.0.0" else "1.11.9"), - "org.scodec" %%% "scodec-cats" % "1.1.0", - "org.tpolecat" %%% "natchez-core" % natchezVersion, - "org.tpolecat" %%% "sourcepos" % "1.0.1", - "org.scala-lang.modules" %%% "scala-collection-compat" % "2.6.0", + "org.scodec" %%% "scodec-bits" % "1.1.34", + "org.scodec" %%% "scodec-core" % (if (tlIsScala3.value) "2.2.0" else "1.11.10"), + "com.armanbilge" %%% "scodec-cats" % "1.2-7c1c2f7-SNAPSHOT", + "com.armanbilge" %%% "natchez-core" % natchezVersion, + "com.armanbilge" %%% "sourcepos" % "1.0.2-SNAPSHOT", + "org.scala-lang.modules" %%% "scala-collection-compat" % "2.8.1", ) ++ Seq( - "com.beachape" %%% "enumeratum" % "1.6.1", + "com.armanbilge" %%% "enumeratum" % "1.7.1-SNAPSHOT", ).filterNot(_ => tlIsScala3.value) ).jvmSettings( libraryDependencies += "com.ongres.scram" % "client" % "2.1", - ).jsSettings( + ).platformsSettings(JSPlatform, NativePlatform)( libraryDependencies ++= Seq( - "com.armanbilge" %%% "saslprep" % "0.1.0", - "io.github.cquiroz" %%% "scala-java-time" % "2.3.0", - "io.github.cquiroz" %%% "locales-minimal-en_us-db" % "1.3.0" + "com.armanbilge" %%% "saslprep" % "0.1.1", + "io.github.cquiroz" %%% "scala-java-time" % "2.4.0", + "io.github.cquiroz" %%% "locales-minimal-en_us-db" % "1.4.1" ), ) -lazy val refined = crossProject(JVMPlatform, JSPlatform) +lazy val refined = crossProject(JVMPlatform, JSPlatform, NativePlatform) .crossType(CrossType.Pure) .in(file("modules/refined")) .dependsOn(core) @@ -180,11 +195,11 @@ lazy val refined = crossProject(JVMPlatform, JSPlatform) .settings(commonSettings) .settings( libraryDependencies ++= Seq( - "eu.timepit" %%% "refined" % "0.9.28", + "eu.timepit" %%% "refined" % "0.10.1", ) ) -lazy val circe = crossProject(JVMPlatform, JSPlatform) +lazy val circe = crossProject(JVMPlatform, JSPlatform, NativePlatform) .crossType(CrossType.Pure) .in(file("modules/circe")) .dependsOn(core) @@ -193,12 +208,12 @@ lazy val circe = crossProject(JVMPlatform, JSPlatform) .settings( name := "skunk-circe", libraryDependencies ++= Seq( - "io.circe" %%% "circe-core" % "0.14.1", - "io.circe" %%% "circe-parser" % "0.14.1" + "com.armanbilge" %%% "circe-core" % "0.14.2-158-f15be0d", + "com.armanbilge" %%% "circe-parser" % "0.14.2-158-f15be0d" ) ) -lazy val tests = crossProject(JVMPlatform, JSPlatform) +lazy val tests = crossProject(JVMPlatform, JSPlatform, NativePlatform) .crossType(CrossType.Full) .in(file("modules/tests")) .dependsOn(core, circe) @@ -207,21 +222,36 @@ lazy val tests = crossProject(JVMPlatform, JSPlatform) .settings( scalacOptions -= "-Xfatal-warnings", libraryDependencies ++= Seq( - "org.scalameta" %%% "munit" % "0.7.29", - "org.scalameta" % "junit-interface" % "0.7.29", - "org.typelevel" %%% "scalacheck-effect-munit" % "1.0.3", - "org.typelevel" %%% "munit-cats-effect-3" % "1.0.7", - "org.typelevel" %%% "cats-free" % "2.7.0", - "org.typelevel" %%% "cats-laws" % "2.7.0", - "org.typelevel" %%% "discipline-munit" % "1.0.9", + "org.scalameta" %%% "munit" % "1.0.0-M6", + "org.scalameta" % "junit-interface" % "1.0.0-M6", + "org.typelevel" %%% "scalacheck-effect-munit" % "2.0-9366e44", + "org.typelevel" %%% "munit-cats-effect" % "2.0-5e03bfc", + "org.typelevel" %%% "cats-free" % "2.8.0", + "org.typelevel" %%% "cats-laws" % "2.8.0", + "org.typelevel" %%% "discipline-munit" % "2.0.0-M3", ) ++ Seq( - "io.chrisdavenport" %%% "cats-time" % "0.3.4", + "org.typelevel" %%% "cats-time" % "0.5.0-116-9b15b89-SNAPSHOT", ).filterNot(_ => scalaVersion.value.startsWith("3.")), testFrameworks += new TestFramework("munit.Framework") ) .jsSettings( Test / scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule)), ) + .nativeSettings( + libraryDependencies += "com.armanbilge" %%% "epollcat" % "0.0-3c7bdac", + nativeConfig ~= { c => + if (isLinux) { // brew-installed s2n + c.withLinkingOptions(c.linkingOptions :+ "-L/home/linuxbrew/.linuxbrew/lib") + } else c + }, + Test / envVars ++= { + val ldLibPath = + if (isLinux) + Map("LD_LIBRARY_PATH" -> "/home/linuxbrew/.linuxbrew/lib") + else Map.empty + Map("S2N_DONT_MLOCK" -> "1") ++ ldLibPath + } + ) lazy val example = project .in(file("modules/example")) @@ -230,8 +260,8 @@ lazy val example = project .settings(commonSettings) .settings( libraryDependencies ++= Seq( - "org.tpolecat" %%% "natchez-honeycomb" % natchezVersion, - "org.tpolecat" %%% "natchez-jaeger" % natchezVersion, + "org.tpolecat" %%% "natchez-honeycomb" % "0.1.6", + "org.tpolecat" %%% "natchez-jaeger" % "0.1.6", ) // ) ++ Seq( // "org.http4s" %%% "http4s-dsl" % "0.21.22", diff --git a/modules/core/js/src/main/scala/SSLPlatform.scala b/modules/core/js-native/src/main/scala/SSLPlatform.scala similarity index 100% rename from modules/core/js/src/main/scala/SSLPlatform.scala rename to modules/core/js-native/src/main/scala/SSLPlatform.scala diff --git a/modules/core/js/src/main/scala/net/message/Scram.scala b/modules/core/js-native/src/main/scala/message/Scram.scala similarity index 76% rename from modules/core/js/src/main/scala/net/message/Scram.scala rename to modules/core/js-native/src/main/scala/message/Scram.scala index e01678d2..68ac6c03 100644 --- a/modules/core/js/src/main/scala/net/message/Scram.scala +++ b/modules/core/js-native/src/main/scala/message/Scram.scala @@ -8,16 +8,13 @@ import com.armanbilge.SaslPrep import scodec.bits.ByteVector import scodec.codecs.utf8 -import scala.scalajs.js -import scala.scalajs.js.typedarray.Uint8Array - /** * Partial implementation of [RFC5802](https://tools.ietf.org/html/rfc5802), as needed by PostgreSQL. * * That is, only features used by PostgreSQL are implemented -- e.g., channel binding is not supported and * optional message fields omitted by PostgreSQL are not supported. */ -private[skunk] object Scram { +private[skunk] object Scram extends ScramPlatform { val SaslMechanism = "SCRAM-SHA-256" val NoChannelBinding = ByteVector.view("n,,".getBytes) @@ -26,11 +23,6 @@ private[skunk] object Scram { def bytesUtf8: ByteVector = ByteVector.view(value.getBytes(java.nio.charset.StandardCharsets.UTF_8)) } - def clientFirstBareWithRandomNonce: ByteVector = { - val nonce = ByteVector.view(crypto.randomBytes(32).asInstanceOf[Uint8Array]).toBase64 - clientFirstBareWithNonce(nonce) - } - def clientFirstBareWithNonce(nonce: String): ByteVector = s"n=,r=${nonce}".bytesUtf8 @@ -69,27 +61,6 @@ private[skunk] object Scram { } } - private val crypto = js.Dynamic.global.require("crypto") - - private def HMAC(key: ByteVector, str: ByteVector): ByteVector = { - val mac = crypto.createHmac("sha256", key.toUint8Array) - mac.update(str.toUint8Array) - ByteVector.view(mac.digest().asInstanceOf[Uint8Array]) - } - - private def H(input: ByteVector): ByteVector = { - val hash = crypto.createHash("sha256") - hash.update(input.toUint8Array) - ByteVector.view(hash.digest().asInstanceOf[Uint8Array]) - } - - private def Hi(str: String, salt: ByteVector, iterations: Int): ByteVector = { - // TODO It is unfortunate that we have to use a sync API here when an async is available - // To make the change here will require running an F[_]: Async up the hiearchy - val salted = crypto.pbkdf2Sync(str, salt.toUint8Array, iterations, 8 * 32, "sha256") - ByteVector.view(salted.asInstanceOf[Uint8Array]).take(32) - } - private def makeClientProofAndServerSignature(password: String, salt: ByteVector, iterations: Int, clientFirstMessageBare: ByteVector, serverFirstMessage: ByteVector, clientFinalMessageWithoutProof: ByteVector): (ClientProof, Verifier) = { val saltedPassword = Hi(SaslPrep.saslPrepStored(password), salt, iterations) val clientKey = HMAC(saltedPassword, "Client Key".bytesUtf8) diff --git a/modules/core/js/src/main/scala/net/protocol/StartupPlatform.scala b/modules/core/js-native/src/main/scala/protocol/StartupPlatform.scala similarity index 100% rename from modules/core/js/src/main/scala/net/protocol/StartupPlatform.scala rename to modules/core/js-native/src/main/scala/protocol/StartupPlatform.scala diff --git a/modules/core/js/src/main/scala/net/message/ScramPlatform.scala b/modules/core/js/src/main/scala/net/message/ScramPlatform.scala new file mode 100644 index 00000000..82c35517 --- /dev/null +++ b/modules/core/js/src/main/scala/net/message/ScramPlatform.scala @@ -0,0 +1,40 @@ +// Copyright (c) 2018-2021 by Rob Norris +// This software is licensed under the MIT License (MIT). +// For more information see LICENSE or https://opensource.org/licenses/MIT + +package skunk.net.message + +import scodec.bits.ByteVector + +import scala.scalajs.js +import scala.scalajs.js.typedarray.Uint8Array + +private[message] trait ScramPlatform { this: Scram.type => + + private val crypto = js.Dynamic.global.require("crypto") + + def clientFirstBareWithRandomNonce: ByteVector = { + val nonce = ByteVector.view(crypto.randomBytes(32).asInstanceOf[Uint8Array]).toBase64 + clientFirstBareWithNonce(nonce) + } + + private[message] def HMAC(key: ByteVector, str: ByteVector): ByteVector = { + val mac = crypto.createHmac("sha256", key.toUint8Array) + mac.update(str.toUint8Array) + ByteVector.view(mac.digest().asInstanceOf[Uint8Array]) + } + + private[message] def H(input: ByteVector): ByteVector = { + val hash = crypto.createHash("sha256") + hash.update(input.toUint8Array) + ByteVector.view(hash.digest().asInstanceOf[Uint8Array]) + } + + private[message] def Hi(str: String, salt: ByteVector, iterations: Int): ByteVector = { + // TODO It is unfortunate that we have to use a sync API here when an async is available + // To make the change here will require running an F[_]: Async up the hiearchy + val salted = crypto.pbkdf2Sync(str, salt.toUint8Array, iterations, 8 * 32, "sha256") + ByteVector.view(salted.asInstanceOf[Uint8Array]).take(32) + } + +} diff --git a/modules/core/jvm/src/main/scala/SSLPlatform.scala b/modules/core/jvm/src/main/scala/SSLPlatform.scala index efc77efa..3e64aa44 100644 --- a/modules/core/jvm/src/main/scala/SSLPlatform.scala +++ b/modules/core/jvm/src/main/scala/SSLPlatform.scala @@ -5,7 +5,7 @@ package skunk import cats._ -import cats.syntax.all._ +import cats.effect._ import java.nio.file.Path import java.security.KeyStore import javax.net.ssl.SSLContext @@ -17,8 +17,8 @@ private[skunk] trait SSLCompanionPlatform { this: SSL.type => /** Creates a `SSL` from an `SSLContext`. */ def fromSSLContext(ctx: SSLContext): SSL = new SSL { - def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): F[TLSContext[F]] = - Network[F].tlsContext.fromSSLContext(ctx).pure[F] + def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): Resource[F, TLSContext[F]] = + Resource.pure(Network[F].tlsContext.fromSSLContext(ctx)) } /** Creates a `SSL` from the specified key store file. */ @@ -28,8 +28,8 @@ private[skunk] trait SSLCompanionPlatform { this: SSL.type => keyPassword: Array[Char], ): SSL = new SSL { - def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): F[TLSContext[F]] = - Network[F].tlsContext.fromKeyStoreFile(file, storePassword, keyPassword) + def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): Resource[F, TLSContext[F]] = + Resource.eval(Network[F].tlsContext.fromKeyStoreFile(file, storePassword, keyPassword)) } /** Creates a `SSL` from the specified class path resource. */ @@ -39,8 +39,8 @@ private[skunk] trait SSLCompanionPlatform { this: SSL.type => keyPassword: Array[Char], ): SSL = new SSL { - def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): F[TLSContext[F]] = - Network[F].tlsContext.fromKeyStoreResource(resource, storePassword, keyPassword) + def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): Resource[F, TLSContext[F]] = + Resource.eval(Network[F].tlsContext.fromKeyStoreResource(resource, storePassword, keyPassword)) } /** Creates a `TLSContext` from the specified key store. */ @@ -49,8 +49,8 @@ private[skunk] trait SSLCompanionPlatform { this: SSL.type => keyPassword: Array[Char], ): SSL = new SSL { - def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): F[TLSContext[F]] = - Network[F].tlsContext.fromKeyStore(keyStore, keyPassword) + def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): Resource[F, TLSContext[F]] = + Resource.eval(Network[F].tlsContext.fromKeyStore(keyStore, keyPassword)) } } diff --git a/modules/core/native/src/main/scala/net/message/PasswordMessagePlatform.scala b/modules/core/native/src/main/scala/net/message/PasswordMessagePlatform.scala new file mode 100644 index 00000000..e5fca60b --- /dev/null +++ b/modules/core/native/src/main/scala/net/message/PasswordMessagePlatform.scala @@ -0,0 +1,72 @@ +// Copyright (c) 2018-2021 by Rob Norris +// This software is licensed under the MIT License (MIT). +// For more information see LICENSE or https://opensource.org/licenses/MIT + +package skunk.net.message + +import scodec.bits.ByteVector + +import scala.scalanative.unsafe._ +import scala.scalanative.unsigned._ + +import openssl._ + +private[message] trait PasswordMessagePlatform { + + // See https://www.postgresql.org/docs/9.6/protocol-flow.html#AEN113418 + // and https://github.com/pgjdbc/pgjdbc/blob/master/pgjdbc/src/main/java/org/postgresql/util/MD5Digest.java + def md5(user: String, password: String, salt: Array[Byte]): PasswordMessage = Zone { implicit z => + + // Hash with this thing + val ctx = EVP_MD_CTX_new() + if (ctx == null) + throw new RuntimeException("EVP_MD_CTX_new") + + val `type` = EVP_get_digestbyname(c"MD5") + if (`type` == null) + throw new RuntimeException("EVP_get_digestbyname") + + try { + + val md = stackalloc[Byte](EVP_MAX_MD_SIZE) + val size = stackalloc[CUnsignedInt]() + + // First round + if (EVP_DigestInit_ex(ctx, `type`, null) != 1) + throw new RuntimeException("EVP_DigestInit_ex") + if (EVP_DigestUpdate(ctx, toCString(password), password.length.toULong) != 1) + throw new RuntimeException("EVP_DigestUpdate") + if (EVP_DigestUpdate(ctx, toCString(user), user.length.toULong) != 1) + throw new RuntimeException("EVP_DigestUpdate") + if (EVP_DigestFinal_ex(ctx, md, size) != 1) + throw new RuntimeException("EVP_DigestFinal_ex") + var hex = BigInt(1, ByteVector.view(md, (!size).toLong).toArray).toString(16) + while (hex.length < 32) + hex = "0" + hex + + if (EVP_MD_CTX_reset(ctx) != 1) + throw new RuntimeException("EVP_MD_CTX_reset") + + // Second round + if (EVP_DigestInit_ex(ctx, `type`, null) != 1) + throw new RuntimeException("EVP_DigestInit_ex") + if (EVP_DigestUpdate(ctx, toCString(hex), 32.toULong) != 1) + throw new RuntimeException("EVP_DigestUpdate") + if (EVP_DigestUpdate(ctx, ByteVector.view(salt).toPtr, salt.length.toULong) != 1) + throw new RuntimeException("EVP_DigestUpdate") + if (EVP_DigestFinal_ex(ctx, md, size) != 1) + throw new RuntimeException("EVP_DigestFinal_ex") + hex = BigInt(1, ByteVector.view(md, (!size).toLong).toArray).toString(16) + while (hex.length < 32) + hex = "0" + hex + + // Done + new PasswordMessage("md5" + hex) {} + + } finally { + openssl.EVP_MD_CTX_free(ctx) + } + + } + +} diff --git a/modules/core/native/src/main/scala/net/message/ScramPlatform.scala b/modules/core/native/src/main/scala/net/message/ScramPlatform.scala new file mode 100644 index 00000000..1f9a37ce --- /dev/null +++ b/modules/core/native/src/main/scala/net/message/ScramPlatform.scala @@ -0,0 +1,56 @@ +// Copyright (c) 2018-2021 by Rob Norris +// This software is licensed under the MIT License (MIT). +// For more information see LICENSE or https://opensource.org/licenses/MIT + +package skunk.net.message + +import scodec.bits.ByteVector + +import scala.scalanative.unsafe._ +import scala.scalanative.unsigned._ + +import openssl._ + +private[message] trait ScramPlatform { this: Scram.type => + + def clientFirstBareWithRandomNonce: ByteVector = { + val buf = stackalloc[Byte](32) + if (RAND_bytes(buf, 32) != 1) + throw new RuntimeException("RAND_bytes") + val nonce = ByteVector.view(buf, 32).toBase64 + clientFirstBareWithNonce(nonce) + } + + private[message] def HMAC(key: ByteVector, str: ByteVector): ByteVector = Zone { implicit z => + val evpMd = EVP_get_digestbyname(c"SHA256") + if (evpMd == null) + throw new RuntimeException("EVP_get_digestbyname") + val md = stackalloc[Byte](EVP_MAX_MD_SIZE) + val mdLen = stackalloc[CUnsignedInt]() + if (openssl.HMAC(evpMd, key.toPtr, key.size.toInt, str.toPtr, str.size.toULong, md, mdLen) != 1) + throw new RuntimeException("HMAC") + ByteVector.fromPtr(md.asInstanceOf[Ptr[Byte]], (!mdLen).toLong) + } + + private[message] def H(input: ByteVector): ByteVector = Zone { implicit z => + val md = stackalloc[Byte](EVP_MAX_MD_SIZE) + val size = stackalloc[CUnsignedInt]() + val `type` = EVP_get_digestbyname(c"SHA256") + if (`type` == null) + throw new RuntimeException("EVP_get_digestbyname") + if (EVP_Digest(input.toPtr, input.size.toULong, md, size, `type`, null) != 1) + throw new RuntimeException("EVP_Digest") + ByteVector.fromPtr(md, (!size).toLong) + } + + private[message] def Hi(str: String, salt: ByteVector, iterations: Int): ByteVector = Zone { implicit z => + val digest = EVP_get_digestbyname(c"SHA256") + if (digest == null) + throw new RuntimeException("EVP_get_digestbyname") + val out = stackalloc[Byte](32) + if (PKCS5_PBKDF2_HMAC(toCString(str), str.length, salt.toPtr, salt.size.toInt, iterations, digest, 32, out) != 1) + throw new RuntimeException("PKCS5_PBKDF2_HMAC") + ByteVector.fromPtr(out, 32) + } + +} diff --git a/modules/core/native/src/main/scala/net/message/openssl.scala b/modules/core/native/src/main/scala/net/message/openssl.scala new file mode 100644 index 00000000..0f701559 --- /dev/null +++ b/modules/core/native/src/main/scala/net/message/openssl.scala @@ -0,0 +1,65 @@ +// Copyright (c) 2018-2021 by Rob Norris +// This software is licensed under the MIT License (MIT). +// For more information see LICENSE or https://opensource.org/licenses/MIT + +package skunk.net.message + +import scala.annotation.nowarn +import scala.scalanative.unsafe._ + +@link("crypto") +@extern +@nowarn +private[message] object openssl { + + final val EVP_MAX_MD_SIZE = 64 + + type EVP_MD + type EVP_MD_CTX + type ENGINE + + def EVP_get_digestbyname(name: Ptr[CChar]): Ptr[EVP_MD] = extern + + def EVP_MD_CTX_new(): Ptr[EVP_MD_CTX] = extern + def EVP_MD_CTX_reset(ctx: Ptr[EVP_MD_CTX]): CInt = extern + def EVP_MD_CTX_free(ctx: Ptr[EVP_MD_CTX]): Unit = extern + + def EVP_DigestInit_ex(ctx: Ptr[EVP_MD_CTX], `type`: Ptr[EVP_MD], impl: Ptr[ENGINE]): CInt = extern + def EVP_DigestUpdate(ctx: Ptr[EVP_MD_CTX], d: Ptr[Byte], cnt: CSize): CInt = extern + def EVP_DigestFinal_ex(ctx: Ptr[EVP_MD_CTX], md: Ptr[Byte], s: Ptr[CUnsignedInt]): CInt = extern + def EVP_Digest( + data: Ptr[Byte], + count: CSize, + md: Ptr[Byte], + size: Ptr[CUnsignedInt], + `type`: Ptr[EVP_MD], + impl: Ptr[ENGINE] + ): CInt = extern + + def HMAC( + evp_md: Ptr[EVP_MD], + key: Ptr[Byte], + key_len: Int, + d: Ptr[Byte], + n: CSize, + md: Ptr[Byte], + md_len: Ptr[CUnsignedInt] + ): Ptr[CUnsignedChar] = extern + + def PKCS5_PBKDF2_HMAC( + pass: Ptr[CChar], + passlen: CInt, + salt: Ptr[Byte], + saltlen: CInt, + iter: CInt, + digest: Ptr[EVP_MD], + keylen: CInt, + out: Ptr[Byte] + ): CInt = extern + + def RAND_bytes( + buf: Ptr[CChar], + num: CInt + ): CInt = extern + +} diff --git a/modules/core/shared/src/main/scala/SSL.scala b/modules/core/shared/src/main/scala/SSL.scala index 19efcfc0..0dd1926c 100644 --- a/modules/core/shared/src/main/scala/SSL.scala +++ b/modules/core/shared/src/main/scala/SSL.scala @@ -5,6 +5,7 @@ package skunk import cats._ +import cats.effect._ import cats.syntax.all._ import fs2.io.net.Network import fs2.io.net.tls.TLSContext @@ -16,25 +17,25 @@ abstract class SSL private[skunk] ( val fallbackOk: Boolean = false, ) { outer => - def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): F[TLSContext[F]] + def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): Resource[F, TLSContext[F]] def withTLSParameters(tlsParameters: TLSParameters): SSL = new SSL(tlsParameters, fallbackOk) { - def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): F[TLSContext[F]] = + def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): Resource[F, TLSContext[F]] = outer.tlsContext } def withFallback(fallbackOk: Boolean): SSL = new SSL(tlsParameters, fallbackOk) { - def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): F[TLSContext[F]] = + def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): Resource[F, TLSContext[F]] = outer.tlsContext } def toSSLNegotiationOptions[F[_]: Network](logger: Option[String => F[Unit]])( implicit ev: ApplicativeError[F, Throwable] - ): F[Option[SSLNegotiation.Options[F]]] = + ): Resource[F, Option[SSLNegotiation.Options[F]]] = this match { - case SSL.None => none.pure[F] + case SSL.None => Resource.pure(None) case _ => tlsContext.map(SSLNegotiation.Options(_, tlsParameters, fallbackOk, logger).some) } @@ -44,22 +45,22 @@ object SSL extends SSLCompanionPlatform { /** `SSL` which indicates that SSL is not to be used. */ object None extends SSL { - def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): F[TLSContext[F]] = - ev.raiseError(new Exception("SSL.None: cannot create a TLSContext.")) + def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): Resource[F, TLSContext[F]] = + Resource.eval(ev.raiseError(new Exception("SSL.None: cannot create a TLSContext."))) override def withFallback(fallbackOk: Boolean): SSL = this override def withTLSParameters(tlsParameters: TLSParameters): SSL = this } /** `SSL` which trusts all certificates. */ object Trusted extends SSL { - def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): F[TLSContext[F]] = - Network[F].tlsContext.insecure + def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): Resource[F, TLSContext[F]] = + Network[F].tlsContext.insecureResource } /** `SSL` from the system default `SSLContext`. */ object System extends SSL { - def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): F[TLSContext[F]] = - Network[F].tlsContext.system + def tlsContext[F[_]: Network](implicit ev: ApplicativeError[F, Throwable]): Resource[F, TLSContext[F]] = + Network[F].tlsContext.systemResource } } diff --git a/modules/core/shared/src/main/scala/Session.scala b/modules/core/shared/src/main/scala/Session.scala index 873c63f0..ac17fd4c 100644 --- a/modules/core/shared/src/main/scala/Session.scala +++ b/modules/core/shared/src/main/scala/Session.scala @@ -281,7 +281,7 @@ object Session { for { dc <- Resource.eval(Describe.Cache.empty[F](commandCache, queryCache)) - sslOp <- Resource.eval(ssl.toSSLNegotiationOptions(if (debug) logger.some else none)) + sslOp <- ssl.toSSLNegotiationOptions(if (debug) logger.some else none) pool <- Pool.of(session(Network[F], sslOp, dc), max)(Recyclers.full) } yield pool diff --git a/modules/tests/native/src/main/scala/ffstest/FFrameworkPlatform.scala b/modules/tests/native/src/main/scala/ffstest/FFrameworkPlatform.scala new file mode 100644 index 00000000..d1db0352 --- /dev/null +++ b/modules/tests/native/src/main/scala/ffstest/FFrameworkPlatform.scala @@ -0,0 +1,12 @@ +// Copyright (c) 2018-2021 by Rob Norris +// This software is licensed under the MIT License (MIT). +// For more information see LICENSE or https://opensource.org/licenses/MIT + +package ffstest + +import epollcat.unsafe.EpollRuntime +import munit.CatsEffectSuite + +trait FTestPlatform extends CatsEffectSuite { + override def munitIORuntime = EpollRuntime.global +} \ No newline at end of file diff --git a/modules/tests/shared/src/test/scala-2/codec/TemporalCodecTest.scala b/modules/tests/shared/src/test/scala-2/codec/TemporalCodecTest.scala index d4222fef..5ba93846 100644 --- a/modules/tests/shared/src/test/scala-2/codec/TemporalCodecTest.scala +++ b/modules/tests/shared/src/test/scala-2/codec/TemporalCodecTest.scala @@ -7,7 +7,7 @@ package codec import cats.Eq import cats.syntax.all._ -import io.chrisdavenport.cats.time.{ offsetdatetimeInstances => _, _ } +import org.typelevel.cats.time.{ offsetdatetimeInstances => _, _ } import java.time._ import skunk.codec.temporal._ import cats.effect.{IO, Resource} diff --git a/modules/tests/shared/src/test/scala/SslTest.scala b/modules/tests/shared/src/test/scala/SslTest.scala index 24723535..17c10aaa 100644 --- a/modules/tests/shared/src/test/scala/SslTest.scala +++ b/modules/tests/shared/src/test/scala/SslTest.scala @@ -79,7 +79,7 @@ class SslTest extends ffstest.FTest { test("SSL.None cannot produce an SSLContext") { for { - ex <- SSL.None.tlsContext[IO].assertFailsWith[Exception] + ex <- SSL.None.tlsContext[IO].use_.assertFailsWith[Exception] _ <- assertEqual("failure message", ex.getMessage, "SSL.None: cannot create a TLSContext.") } yield "ok" } diff --git a/project/build.properties b/project/build.properties index c8fcab54..22af2628 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.6.2 +sbt.version=1.7.1 diff --git a/project/plugins.sbt b/project/plugins.sbt index 37794b03..fe51429f 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -10,3 +10,5 @@ addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.9.3") addSbtPlugin("ch.epfl.scala" % "sbt-eviction-rules" % "1.0.0-RC1") addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.1.0") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.8.0") +addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.7") +addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.2.0") From d131ca69fbcf32f1c3822d9eae951216dc1fa81d Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Sun, 11 Sep 2022 07:23:51 +0000 Subject: [PATCH 02/30] fix HMAC use --- .../core/native/src/main/scala/net/message/ScramPlatform.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/native/src/main/scala/net/message/ScramPlatform.scala b/modules/core/native/src/main/scala/net/message/ScramPlatform.scala index 1f9a37ce..b19eb2f4 100644 --- a/modules/core/native/src/main/scala/net/message/ScramPlatform.scala +++ b/modules/core/native/src/main/scala/net/message/ScramPlatform.scala @@ -27,7 +27,7 @@ private[message] trait ScramPlatform { this: Scram.type => throw new RuntimeException("EVP_get_digestbyname") val md = stackalloc[Byte](EVP_MAX_MD_SIZE) val mdLen = stackalloc[CUnsignedInt]() - if (openssl.HMAC(evpMd, key.toPtr, key.size.toInt, str.toPtr, str.size.toULong, md, mdLen) != 1) + if (openssl.HMAC(evpMd, key.toPtr, key.size.toInt, str.toPtr, str.size.toULong, md, mdLen) == null) throw new RuntimeException("HMAC") ByteVector.fromPtr(md.asInstanceOf[Ptr[Byte]], (!mdLen).toLong) } From 56e68684e69c63c2da1a30d534363924c60fbc79 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Sun, 11 Sep 2022 20:53:37 +0000 Subject: [PATCH 03/30] official scodec-cats --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 54439195..c95281b4 100644 --- a/build.sbt +++ b/build.sbt @@ -170,7 +170,7 @@ lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform) "co.fs2" %%% "fs2-io" % fs2Version, "org.scodec" %%% "scodec-bits" % "1.1.34", "org.scodec" %%% "scodec-core" % (if (tlIsScala3.value) "2.2.0" else "1.11.10"), - "com.armanbilge" %%% "scodec-cats" % "1.2-7c1c2f7-SNAPSHOT", + "org.scodec" %%% "scodec-cats" % "1.2.0", "com.armanbilge" %%% "natchez-core" % natchezVersion, "com.armanbilge" %%% "sourcepos" % "1.0.2-SNAPSHOT", "org.scala-lang.modules" %%% "scala-collection-compat" % "2.8.1", From 6df34717227c353d6ea5e3e4fc983bfbdbc1fd4a Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Sun, 11 Sep 2022 20:59:33 +0000 Subject: [PATCH 04/30] temporal codec test cross-compiles now --- .../src/test/{scala-2 => scala}/codec/TemporalCodecTest.scala | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/tests/shared/src/test/{scala-2 => scala}/codec/TemporalCodecTest.scala (100%) diff --git a/modules/tests/shared/src/test/scala-2/codec/TemporalCodecTest.scala b/modules/tests/shared/src/test/scala/codec/TemporalCodecTest.scala similarity index 100% rename from modules/tests/shared/src/test/scala-2/codec/TemporalCodecTest.scala rename to modules/tests/shared/src/test/scala/codec/TemporalCodecTest.scala From 083acc27a0eb0a4a4482f808bccaf924bbffb7ca Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 12 Sep 2022 03:22:56 +0000 Subject: [PATCH 05/30] Bump fs2 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c95281b4..cfded3c1 100644 --- a/build.sbt +++ b/build.sbt @@ -78,7 +78,7 @@ ThisBuild / githubWorkflowAddedJobs += ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") // This is used in a couple places -lazy val fs2Version = "3.2.14-75-7902cbf" +lazy val fs2Version = "3.2.14-76-9e561b4-SNAPSHOT" lazy val natchezVersion = "0.1.6-SNAPSHOT" // We do `evictionCheck` in CI From 171e6e65cc20e8fde572cf97e51d013407c80999 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 12 Sep 2022 22:52:20 +0000 Subject: [PATCH 06/30] Version bumps --- build.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index cfded3c1..0828d095 100644 --- a/build.sbt +++ b/build.sbt @@ -165,7 +165,7 @@ lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform) resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots", libraryDependencies ++= Seq( "org.typelevel" %%% "cats-core" % "2.8.0", - "org.typelevel" %%% "cats-effect" % "3.3.14-1-5d11fe9", + "org.typelevel" %%% "cats-effect" % "3.3.14-2-0972521", "co.fs2" %%% "fs2-core" % fs2Version, "co.fs2" %%% "fs2-io" % fs2Version, "org.scodec" %%% "scodec-bits" % "1.1.34", @@ -238,7 +238,7 @@ lazy val tests = crossProject(JVMPlatform, JSPlatform, NativePlatform) Test / scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule)), ) .nativeSettings( - libraryDependencies += "com.armanbilge" %%% "epollcat" % "0.0-3c7bdac", + libraryDependencies += "com.armanbilge" %%% "epollcat" % "0.0-e7dd9a7", nativeConfig ~= { c => if (isLinux) { // brew-installed s2n c.withLinkingOptions(c.linkingOptions :+ "-L/home/linuxbrew/.linuxbrew/lib") From 9a9ccf591361068d9f9f54c61be45f19ae0d2ac4 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 12 Sep 2022 22:52:42 +0000 Subject: [PATCH 07/30] Regenerate workflow --- .github/workflows/ci.yml | 44 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39359f4d..5c8ee2ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: os: [ubuntu-latest] scala: [2.12.13, 2.13.8, 3.1.1] java: [temurin@8] - project: [rootJS, rootJVM] + project: [rootJS, rootJVM, rootNative] runs-on: ${{ matrix.os }} steps: - name: Checkout current branch (full) @@ -57,6 +57,10 @@ jobs: ~/Library/Caches/Coursier/v1 key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} + - name: Install utf8proc and s2n + if: startsWith(matrix.project, 'rootNative') + run: brew install utf8proc s2n + - name: Set up cert permissions run: | chmod 600 world/server.key @@ -75,6 +79,10 @@ jobs: if: matrix.project == 'rootJS' run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' Test/scalaJSLinkerResult + - name: nativeLink + if: matrix.project == 'rootNative' + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' Test/nativeLink + - name: Test run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' test @@ -92,11 +100,11 @@ jobs: - name: Make target directories if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') - run: mkdir -p modules/circe/.jvm/target target .js/target modules/docs/target modules/core/js/target modules/circe/.js/target modules/core/jvm/target modules/tests/js/target .jvm/target .native/target modules/refined/.js/target modules/refined/.jvm/target modules/tests/jvm/target modules/example/target project/target + run: mkdir -p modules/circe/.jvm/target target .js/target modules/core/native/target modules/docs/target modules/core/js/target modules/circe/.js/target modules/core/jvm/target modules/tests/js/target modules/refined/.native/target .jvm/target .native/target modules/refined/.js/target modules/refined/.jvm/target modules/circe/.native/target modules/tests/jvm/target modules/example/target modules/tests/native/target project/target - name: Compress target directories if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') - run: tar cf targets.tar modules/circe/.jvm/target target .js/target modules/docs/target modules/core/js/target modules/circe/.js/target modules/core/jvm/target modules/tests/js/target .jvm/target .native/target modules/refined/.js/target modules/refined/.jvm/target modules/tests/jvm/target modules/example/target project/target + run: tar cf targets.tar modules/circe/.jvm/target target .js/target modules/core/native/target modules/docs/target modules/core/js/target modules/circe/.js/target modules/core/jvm/target modules/tests/js/target modules/refined/.native/target .jvm/target .native/target modules/refined/.js/target modules/refined/.jvm/target modules/circe/.native/target modules/tests/jvm/target modules/example/target modules/tests/native/target project/target - name: Upload target directories if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') @@ -160,6 +168,16 @@ jobs: tar xf targets.tar rm targets.tar + - name: Download target directories (2.12.13, rootNative) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.13-rootNative + + - name: Inflate target directories (2.12.13, rootNative) + run: | + tar xf targets.tar + rm targets.tar + - name: Download target directories (2.13.8, rootJS) uses: actions/download-artifact@v2 with: @@ -180,6 +198,16 @@ jobs: tar xf targets.tar rm targets.tar + - name: Download target directories (2.13.8, rootNative) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.8-rootNative + + - name: Inflate target directories (2.13.8, rootNative) + run: | + tar xf targets.tar + rm targets.tar + - name: Download target directories (3.1.1, rootJS) uses: actions/download-artifact@v2 with: @@ -200,6 +228,16 @@ jobs: tar xf targets.tar rm targets.tar + - name: Download target directories (3.1.1, rootNative) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-3.1.1-rootNative + + - name: Inflate target directories (3.1.1, rootNative) + run: | + tar xf targets.tar + rm targets.tar + - name: Import signing key if: env.PGP_SECRET != '' && env.PGP_PASSPHRASE == '' run: echo $PGP_SECRET | base64 -di | gpg --import From 80b9ad4b240d81c45ffbdf97b4352e8871bee3d5 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 12 Sep 2022 23:00:22 +0000 Subject: [PATCH 08/30] cats-time on Scala 3 --- build.sbt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/build.sbt b/build.sbt index 0828d095..75495894 100644 --- a/build.sbt +++ b/build.sbt @@ -225,13 +225,12 @@ lazy val tests = crossProject(JVMPlatform, JSPlatform, NativePlatform) "org.scalameta" %%% "munit" % "1.0.0-M6", "org.scalameta" % "junit-interface" % "1.0.0-M6", "org.typelevel" %%% "scalacheck-effect-munit" % "2.0-9366e44", - "org.typelevel" %%% "munit-cats-effect" % "2.0-5e03bfc", + "org.typelevel" %%% "munit-cats-effect" % "2.0-5e03bfc", "org.typelevel" %%% "cats-free" % "2.8.0", "org.typelevel" %%% "cats-laws" % "2.8.0", "org.typelevel" %%% "discipline-munit" % "2.0.0-M3", - ) ++ Seq( - "org.typelevel" %%% "cats-time" % "0.5.0-116-9b15b89-SNAPSHOT", - ).filterNot(_ => scalaVersion.value.startsWith("3.")), + "org.typelevel" %%% "cats-time" % "0.5.0-116-9b15b89-SNAPSHOT", + ), testFrameworks += new TestFramework("munit.Framework") ) .jsSettings( From a0153d7e270458ad4bd9742a570de6c0a25047a1 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 12 Sep 2022 23:20:19 +0000 Subject: [PATCH 09/30] Fix natchez dep --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 75495894..589f4253 100644 --- a/build.sbt +++ b/build.sbt @@ -301,7 +301,7 @@ lazy val docs = project makeSite := makeSite.dependsOn(mdoc.toTask("")).value, mdocExtraArguments := Seq("--no-link-hygiene"), // paradox handles this libraryDependencies ++= Seq( - "org.tpolecat" %%% "natchez-jaeger" % natchezVersion, + "org.tpolecat" %%% "natchez-jaeger" % "0.1.6", ) ) From 8b416481cd89cad89b76847cd81512bcb0ed029b Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 12 Sep 2022 23:30:55 +0000 Subject: [PATCH 10/30] Bump base version --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 589f4253..aaa9da16 100644 --- a/build.sbt +++ b/build.sbt @@ -1,4 +1,4 @@ -ThisBuild / tlBaseVersion := "0.3" +ThisBuild / tlBaseVersion := "0.4" // Our Scala versions. lazy val `scala-2.12` = "2.12.13" From 83ddbdb99e86f6f625bbdc0115e3fade8aaf3373 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Tue, 13 Sep 2022 20:38:06 +0000 Subject: [PATCH 11/30] bumps --- build.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index aaa9da16..9e6c53f4 100644 --- a/build.sbt +++ b/build.sbt @@ -165,7 +165,7 @@ lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform) resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots", libraryDependencies ++= Seq( "org.typelevel" %%% "cats-core" % "2.8.0", - "org.typelevel" %%% "cats-effect" % "3.3.14-2-0972521", + "org.typelevel" %%% "cats-effect" % "3.3.14-5-4591364", "co.fs2" %%% "fs2-core" % fs2Version, "co.fs2" %%% "fs2-io" % fs2Version, "org.scodec" %%% "scodec-bits" % "1.1.34", @@ -237,7 +237,7 @@ lazy val tests = crossProject(JVMPlatform, JSPlatform, NativePlatform) Test / scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule)), ) .nativeSettings( - libraryDependencies += "com.armanbilge" %%% "epollcat" % "0.0-e7dd9a7", + libraryDependencies += "com.armanbilge" %%% "epollcat" % "0.0-ab1026e", nativeConfig ~= { c => if (isLinux) { // brew-installed s2n c.withLinkingOptions(c.linkingOptions :+ "-L/home/linuxbrew/.linuxbrew/lib") From faa392ba87d83698cd6ccf2cdd68e79d93286aef Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 31 Oct 2022 15:06:15 +0000 Subject: [PATCH 12/30] bumps --- build.sbt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index 16048e19..64eb84ec 100644 --- a/build.sbt +++ b/build.sbt @@ -84,8 +84,8 @@ ThisBuild / libraryDependencySchemes ++= Seq( ) // This is used in a couple places -lazy val fs2Version = "3.2.14-76-9e561b4-SNAPSHOT" -lazy val natchezVersion = "0.1.6-SNAPSHOT" +lazy val fs2Version = "3.3.0" +lazy val natchezVersion = "0.1.6-269-2b28bcd-SNAPSHOT" // Global Settings lazy val commonSettings = Seq( @@ -225,7 +225,7 @@ lazy val tests = crossProject(JVMPlatform, JSPlatform, NativePlatform) "org.typelevel" %%% "cats-free" % "2.8.0", "org.typelevel" %%% "cats-laws" % "2.8.0", "org.typelevel" %%% "discipline-munit" % "2.0.0-M3", - "org.typelevel" %%% "cats-time" % "0.5.0-116-9b15b89-SNAPSHOT", + "org.typelevel" %%% "cats-time" % "0.5.0-144-8b56ffa-SNAPSHOT", ), testFrameworks += new TestFramework("munit.Framework") ) From 3b2e8c92b2ec961482fe4c6c233cd11cf5191464 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 31 Oct 2022 15:17:33 +0000 Subject: [PATCH 13/30] Setup brew plugin --- .github/workflows/ci.yml | 6 +++--- build.sbt | 28 +++++++--------------------- project/plugins.sbt | 1 + 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f5a64280..48c46ae6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,9 +66,9 @@ jobs: ~/Library/Caches/Coursier/v1 key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - name: Install utf8proc and s2n - if: startsWith(matrix.project, 'rootNative') - run: brew install utf8proc s2n + - name: Install brew formulae (ubuntu) + if: (matrix.project == 'rootNative') && startsWith(matrix.os, 'ubuntu') + run: /home/linuxbrew/.linuxbrew/bin/brew install s2n utf8proc - name: Set up cert permissions run: | diff --git a/build.sbt b/build.sbt index 64eb84ec..b88623a0 100644 --- a/build.sbt +++ b/build.sbt @@ -20,6 +20,9 @@ ThisBuild / tlSonatypeUseLegacyHost := false ThisBuild / githubWorkflowJavaVersions := Seq(JavaSpec.temurin("11")) ThisBuild / tlJdkRelease := Some(8) +ThisBuild / githubWorkflowBuildPreamble ++= nativeBrewInstallWorkflowSteps.value +ThisBuild / nativeBrewInstallCond := Some("matrix.project == 'rootNative'") + lazy val setupCertAndDocker = Seq( WorkflowStep.Run( commands = List("chmod 600 world/server.key", "sudo chown 999 world/server.key"), @@ -36,15 +39,7 @@ val isLinux = { osName.exists(_.toLowerCase().contains("linux")) } -lazy val installNativeDeps = Seq( - WorkflowStep.Run( - List("brew install utf8proc s2n"), - name = Some("Install utf8proc and s2n"), - cond = Some("startsWith(matrix.project, 'rootNative')") - ) -) - -ThisBuild / githubWorkflowBuildPreamble ++= installNativeDeps ++ setupCertAndDocker +ThisBuild / githubWorkflowBuildPreamble ++= setupCertAndDocker ThisBuild / githubWorkflowBuild ~= { steps => WorkflowStep.Sbt( commands = List("headerCheckAll"), @@ -232,20 +227,11 @@ lazy val tests = crossProject(JVMPlatform, JSPlatform, NativePlatform) .jsSettings( Test / scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule)), ) + .nativeEnablePlugins(ScalaNativeBrewedConfigPlugin) .nativeSettings( libraryDependencies += "com.armanbilge" %%% "epollcat" % "0.0-ab1026e", - nativeConfig ~= { c => - if (isLinux) { // brew-installed s2n - c.withLinkingOptions(c.linkingOptions :+ "-L/home/linuxbrew/.linuxbrew/lib") - } else c - }, - Test / envVars ++= { - val ldLibPath = - if (isLinux) - Map("LD_LIBRARY_PATH" -> "/home/linuxbrew/.linuxbrew/lib") - else Map.empty - Map("S2N_DONT_MLOCK" -> "1") ++ ldLibPath - } + Test / nativeBrewFormulas ++= Set("s2n", "utf8proc"), + Test / envVars ++= Map("S2N_DONT_MLOCK" -> "1") ) lazy val example = project diff --git a/project/plugins.sbt b/project/plugins.sbt index 532085d8..320b3227 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -13,3 +13,4 @@ addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.2") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.10.1") addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.7") addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.2.0") +addSbtPlugin("com.armanbilge" % "sbt-scala-native-config-brew-github-actions" % "0.1.2") From 7de6c9b56b1e1861a85978bd5eb7bf820243ceb6 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 31 Oct 2022 15:21:13 +0000 Subject: [PATCH 14/30] Cleanup old/redundant settings --- build.sbt | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/build.sbt b/build.sbt index b88623a0..17d2dd44 100644 --- a/build.sbt +++ b/build.sbt @@ -107,9 +107,6 @@ lazy val commonSettings = Seq( "-sourcepath", (LocalRootProject / baseDirectory).value.getAbsolutePath, "-doc-source-url", "https://github.com/tpolecat/skunk/blob/v" + version.value + "€{FILE_PATH}.scala", ), - libraryDependencies ++= Seq( - compilerPlugin("org.typelevel" %% "kind-projector" % "0.13.2" cross CrossVersion.full), - ).filterNot(_ => tlIsScala3.value), // Coverage Exclusions coverageExcludedPackages := "ffstest.*;tests.*;example.*;natchez.http4s.*", @@ -117,27 +114,6 @@ lazy val commonSettings = Seq( // uncomment in case of emergency // scalacOptions ++= { if (scalaVersion.value.startsWith("3.")) Seq("-source:3.0-migration") else Nil }, - // Add some more source directories - Compile / unmanagedSourceDirectories ++= { - val sourceDir = (Compile / sourceDirectory).value - CrossVersion.partialVersion(scalaVersion.value) match { - case Some((3, _)) => Seq(sourceDir / "scala-2.13+", file(sourceDir.getPath.replaceFirst("jvm", "shared").replaceFirst("js", "shared").replaceFirst("native", "shared")) / "scala-2.13+") - case Some((2, 12)) => Seq() - case Some((2, _)) => Seq(sourceDir / "scala-2.13+", file(sourceDir.getPath.replaceFirst("jvm", "shared").replaceFirst("js", "shared").replaceFirst("native", "shared")) / "scala-2.13+") - case _ => Seq() - } - }, - - - // dottydoc really doesn't work at all right now - Compile / doc / sources := { - val old = (Compile / doc / sources).value - if (scalaVersion.value.startsWith("3.")) - Seq() - else - old - }, - ) lazy val skunk = tlCrossRootProject From b15e44afdf354285f51a8ced9eda23779e90e12b Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 31 Oct 2022 15:23:22 +0000 Subject: [PATCH 15/30] Bump Scala 3 --- .github/workflows/ci.yml | 20 ++++++++++---------- build.sbt | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 48c46ae6..0482d443 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.12.16, 2.13.8, 3.1.3] + scala: [2.12.16, 2.13.8, 3.2.0] java: [temurin@11] project: [rootJS, rootJVM, rootNative] runs-on: ${{ matrix.os }} @@ -230,32 +230,32 @@ jobs: tar xf targets.tar rm targets.tar - - name: Download target directories (3.1.3, rootJS) + - name: Download target directories (3.2.0, rootJS) uses: actions/download-artifact@v2 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-3.1.3-rootJS + name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootJS - - name: Inflate target directories (3.1.3, rootJS) + - name: Inflate target directories (3.2.0, rootJS) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (3.1.3, rootJVM) + - name: Download target directories (3.2.0, rootJVM) uses: actions/download-artifact@v2 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-3.1.3-rootJVM + name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootJVM - - name: Inflate target directories (3.1.3, rootJVM) + - name: Inflate target directories (3.2.0, rootJVM) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (3.1.3, rootNative) + - name: Download target directories (3.2.0, rootNative) uses: actions/download-artifact@v2 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-3.1.3-rootNative + name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootNative - - name: Inflate target directories (3.1.3, rootNative) + - name: Inflate target directories (3.2.0, rootNative) run: | tar xf targets.tar rm targets.tar diff --git a/build.sbt b/build.sbt index 17d2dd44..740df3a5 100644 --- a/build.sbt +++ b/build.sbt @@ -3,7 +3,7 @@ ThisBuild / tlBaseVersion := "0.4" // Our Scala versions. lazy val `scala-2.12` = "2.12.16" lazy val `scala-2.13` = "2.13.8" -lazy val `scala-3.0` = "3.1.3" +lazy val `scala-3.0` = "3.2.0" ThisBuild / scalaVersion := `scala-2.13` ThisBuild / crossScalaVersions := From 7eb53b4123caf99e9533b951180e122bbcb725ea Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 31 Oct 2022 15:28:15 +0000 Subject: [PATCH 16/30] Fix compile --- .../core/shared/src/main/scala-3/syntax/StringContextOps.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/shared/src/main/scala-3/syntax/StringContextOps.scala b/modules/core/shared/src/main/scala-3/syntax/StringContextOps.scala index f8e42136..baa91b6c 100644 --- a/modules/core/shared/src/main/scala-3/syntax/StringContextOps.scala +++ b/modules/core/shared/src/main/scala-3/syntax/StringContextOps.scala @@ -71,7 +71,7 @@ object StringContextOps { // The interpolated args are a list of size `parts.length - 1`. We also just know this. val args: List[Expr[Any]] = { - val Varargs(args) = argsExpr + val Varargs(args) = argsExpr: @unchecked args.toList } From 36c016bb9b1fa43cf548ad5ddcd0ace66eae52f6 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 31 Oct 2022 15:34:16 +0000 Subject: [PATCH 17/30] Bump circe --- build.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 740df3a5..01fd0b7c 100644 --- a/build.sbt +++ b/build.sbt @@ -175,8 +175,8 @@ lazy val circe = crossProject(JVMPlatform, JSPlatform, NativePlatform) .settings( name := "skunk-circe", libraryDependencies ++= Seq( - "io.circe" %%% "circe-core" % "0.14.2", - "io.circe" %%% "circe-parser" % "0.14.2" + "io.circe" %%% "circe-core" % "0.14.3", + "io.circe" %%% "circe-parser" % "0.14.3" ) ) From aca58c7beedf0b104ee6a56cea93c5fb6007837f Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 31 Oct 2022 15:40:19 +0000 Subject: [PATCH 18/30] Bump Scala.js --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 320b3227..7ca69d71 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -10,7 +10,7 @@ addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.3") addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.6.3") addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.3") addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.2") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.10.1") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.11.0") addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.7") addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.2.0") addSbtPlugin("com.armanbilge" % "sbt-scala-native-config-brew-github-actions" % "0.1.2") From 10f37f94148d733c899de4dc8502b16227af2e1b Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 31 Oct 2022 17:06:06 +0000 Subject: [PATCH 19/30] Poke ci From 01ec759791a242a5c6d6520575b06aca68320311 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 31 Oct 2022 17:07:25 +0000 Subject: [PATCH 20/30] Regenerate workflow --- .github/workflows/ci.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf65e467..0482d443 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -220,26 +220,16 @@ jobs: tar xf targets.tar rm targets.tar -<<<<<<< HEAD - name: Download target directories (2.13.8, rootNative) uses: actions/download-artifact@v2 with: name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.8-rootNative - name: Inflate target directories (2.13.8, rootNative) -======= - - name: Download target directories (3.2.0, rootJS) - uses: actions/download-artifact@v2 - with: - name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootJS - - - name: Inflate target directories (3.2.0, rootJS) ->>>>>>> update/scala3-library-3.2.0 run: | tar xf targets.tar rm targets.tar -<<<<<<< HEAD - name: Download target directories (3.2.0, rootJS) uses: actions/download-artifact@v2 with: @@ -266,14 +256,6 @@ jobs: name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootNative - name: Inflate target directories (3.2.0, rootNative) -======= - - name: Download target directories (3.2.0, rootJVM) - uses: actions/download-artifact@v2 - with: - name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootJVM - - - name: Inflate target directories (3.2.0, rootJVM) ->>>>>>> update/scala3-library-3.2.0 run: | tar xf targets.tar rm targets.tar From 30233a251c450e4096d5a3aef8592ffb246a9c2e Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 31 Oct 2022 17:13:58 +0000 Subject: [PATCH 21/30] Use ubuntu 22.04 in CI --- .github/workflows/ci.yml | 4 ++-- build.sbt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0482d443..74cfd291 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: name: Build and Test strategy: matrix: - os: [ubuntu-latest] + os: [ubuntu-22.04] scala: [2.12.16, 2.13.8, 3.2.0] java: [temurin@11] project: [rootJS, rootJVM, rootNative] @@ -132,7 +132,7 @@ jobs: if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') strategy: matrix: - os: [ubuntu-latest] + os: [ubuntu-22.04] scala: [2.13.8] java: [temurin@11] runs-on: ${{ matrix.os }} diff --git a/build.sbt b/build.sbt index 01fd0b7c..1cf0c3c6 100644 --- a/build.sbt +++ b/build.sbt @@ -17,6 +17,7 @@ ThisBuild / developers := List( ThisBuild / tlCiReleaseBranches := Seq("main") // publish snapshits on `main` ThisBuild / tlSonatypeUseLegacyHost := false +ThisBuild / githubWorkflowOSes := Seq("ubuntu-22.04") ThisBuild / githubWorkflowJavaVersions := Seq(JavaSpec.temurin("11")) ThisBuild / tlJdkRelease := Some(8) From 4f454d41de0074dfcbe0cdacb0ef129400e812db Mon Sep 17 00:00:00 2001 From: Michael Pilquist Date: Sun, 20 Nov 2022 14:49:59 -0500 Subject: [PATCH 22/30] Fix merge --- .github/workflows/ci.yml | 54 ++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ab80456..30d7c116 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,13 +27,8 @@ jobs: name: Build and Test strategy: matrix: -<<<<<<< HEAD os: [ubuntu-22.04] - scala: [2.12.16, 2.13.8, 3.2.0] -======= - os: [ubuntu-latest] scala: [2.12.17, 2.13.10, 3.2.1] ->>>>>>> main java: [temurin@11] project: [rootJS, rootJVM, rootNative] runs-on: ${{ matrix.os }} @@ -87,34 +82,34 @@ jobs: run: sbt githubWorkflowCheck - name: Check Headers - run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' headerCheckAll + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' headerCheckAll - name: Check headers and formatting if: matrix.java == 'temurin@11' - run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' headerCheckAll scalafmtCheckAll 'project /' scalafmtSbtCheck + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' headerCheckAll scalafmtCheckAll 'project /' scalafmtSbtCheck - name: scalaJSLink if: matrix.project == 'rootJS' - run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' Test/scalaJSLinkerResult + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' Test/scalaJSLinkerResult - name: nativeLink if: matrix.project == 'rootNative' run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' Test/nativeLink - name: Test - run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' test + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' test - name: Check binary compatibility if: matrix.java == 'temurin@11' - run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' mimaReportBinaryIssues + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' mimaReportBinaryIssues - name: Generate API documentation if: matrix.java == 'temurin@11' - run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' doc + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' doc - name: Check Doc Site (2.13.10 JVM only) if: matrix.scala == '2.13.10' && matrix.project == 'rootJVM' - run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' docs/makeSite + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' docs/makeSite - name: Make target directories if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') @@ -137,13 +132,8 @@ jobs: if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') strategy: matrix: -<<<<<<< HEAD os: [ubuntu-22.04] - scala: [2.13.8] -======= - os: [ubuntu-latest] scala: [2.13.10] ->>>>>>> main java: [temurin@11] runs-on: ${{ matrix.os }} steps: @@ -200,21 +190,17 @@ jobs: tar xf targets.tar rm targets.tar -<<<<<<< HEAD - - name: Download target directories (2.12.16, rootNative) + - name: Download target directories (2.12.17, rootNative) uses: actions/download-artifact@v2 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.16-rootNative + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.17-rootNative - - name: Inflate target directories (2.12.16, rootNative) + - name: Inflate target directories (2.12.17, rootNative) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (2.13.8, rootJS) -======= - name: Download target directories (2.13.10, rootJS) ->>>>>>> main uses: actions/download-artifact@v2 with: name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.10-rootJS @@ -234,21 +220,17 @@ jobs: tar xf targets.tar rm targets.tar -<<<<<<< HEAD - - name: Download target directories (2.13.8, rootNative) + - name: Download target directories (2.13.10, rootNative) uses: actions/download-artifact@v2 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.8-rootNative + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.10-rootNative - - name: Inflate target directories (2.13.8, rootNative) + - name: Inflate target directories (2.13.10, rootNative) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (3.2.0, rootJS) -======= - name: Download target directories (3.2.1, rootJS) ->>>>>>> main uses: actions/download-artifact@v2 with: name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.1-rootJS @@ -268,12 +250,12 @@ jobs: tar xf targets.tar rm targets.tar - - name: Download target directories (3.2.0, rootNative) + - name: Download target directories (3.2.1, rootNative) uses: actions/download-artifact@v2 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.0-rootNative + name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.1-rootNative - - name: Inflate target directories (3.2.0, rootNative) + - name: Inflate target directories (3.2.1, rootNative) run: | tar xf targets.tar rm targets.tar @@ -290,7 +272,7 @@ jobs: (echo "$PGP_PASSPHRASE"; echo; echo) | gpg --command-fd 0 --pinentry-mode loopback --change-passphrase $(gpg --list-secret-keys --with-colons 2> /dev/null | grep '^sec:' | cut --delimiter ':' --fields 5 | tail -n 1) - name: Publish - run: sbt '++ ${{ matrix.scala }}' tlRelease + run: sbt '++${{ matrix.scala }}' tlRelease coverage: name: Generate coverage report (2.13.10 JVM only) @@ -342,7 +324,7 @@ jobs: - name: Start up Postgres run: docker-compose up -d - - run: sbt '++ ${{ matrix.scala }}' coverage rootJVM/test coverageReport + - run: sbt '++${{ matrix.scala }}' coverage rootJVM/test coverageReport - name: Upload code coverage data run: 'bash <(curl -s https://codecov.io/bash)' From 214b5cea7eeb81a53e24a84364ceb21dad1ec01b Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 21 Nov 2022 18:22:29 +0000 Subject: [PATCH 23/30] Fix test --- modules/tests/shared/src/test/scala/StartupTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/tests/shared/src/test/scala/StartupTest.scala b/modules/tests/shared/src/test/scala/StartupTest.scala index c43074f3..31689c57 100644 --- a/modules/tests/shared/src/test/scala/StartupTest.scala +++ b/modules/tests/shared/src/test/scala/StartupTest.scala @@ -253,6 +253,6 @@ class StartupTest extends ffstest.FTest { host = "blergh", user = "bob", database = "nobody cares", - ).use(_ => IO.unit).assertFailsWith[UnknownHostException] + ).use(_ => IO.unit).assertFailsWith[IOException] // ideally an `UnknownHostException` } } From aa4cbcb2cf7b986f258c180c80a9ca3e924e9661 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 21 Nov 2022 18:26:32 +0000 Subject: [PATCH 24/30] Fix compile --- modules/tests/shared/src/test/scala/StartupTest.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/tests/shared/src/test/scala/StartupTest.scala b/modules/tests/shared/src/test/scala/StartupTest.scala index 31689c57..21beec06 100644 --- a/modules/tests/shared/src/test/scala/StartupTest.scala +++ b/modules/tests/shared/src/test/scala/StartupTest.scala @@ -5,13 +5,14 @@ package tests import cats.effect._ -import com.comcast.ip4s.UnknownHostException import fs2.io.net.ConnectException import natchez.Trace.Implicits.noop import skunk._ import skunk.exception.SkunkException import skunk.exception.StartupException +import java.io.IOException + class StartupTest extends ffstest.FTest { // Different ports for different authentication schemes. From bc710a36ae996df7747073c1eadfc4e87d321729 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 21 Nov 2022 18:37:13 +0000 Subject: [PATCH 25/30] Try removing executor override --- .../scala/ffstest/FFrameworkPlatform.scala | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/modules/tests/jvm/src/main/scala/ffstest/FFrameworkPlatform.scala b/modules/tests/jvm/src/main/scala/ffstest/FFrameworkPlatform.scala index 915ff897..16acda01 100644 --- a/modules/tests/jvm/src/main/scala/ffstest/FFrameworkPlatform.scala +++ b/modules/tests/jvm/src/main/scala/ffstest/FFrameworkPlatform.scala @@ -6,20 +6,4 @@ package ffstest import munit.CatsEffectSuite -import java.util.concurrent.Executors -import scala.concurrent.ExecutionContext - -trait FTestPlatform extends CatsEffectSuite { - - // ensure that we have bountiful threads - val executor = Executors.newCachedThreadPool() - - override val munitExecutionContext: ExecutionContext = - ExecutionContext.fromExecutor(executor) - - override def afterAll(): Unit = { - super.afterAll(); - executor.shutdown() - } - -} +trait FTestPlatform extends CatsEffectSuite From 2a1785b01cf7d0ceb2d157f2dbb4610647ef7bbe Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 21 Nov 2022 19:13:00 +0000 Subject: [PATCH 26/30] Remove enumeratum dep from Native --- build.sbt | 12 +- .../src/main/scala-2/SqlState.scala | 0 .../scala-2/codec/EnumCodecPlatform.scala | 0 .../native/src/main/scala-2/SqlState.scala | 1424 +++++++++++++++++ .../scala-2/codec/EnumCodecPlatform.scala | 8 + .../test/scala-2/codec/EnumCodecTest.scala | 0 6 files changed, 1440 insertions(+), 4 deletions(-) rename modules/core/{shared => js-jvm}/src/main/scala-2/SqlState.scala (100%) rename modules/core/{shared => js-jvm}/src/main/scala-2/codec/EnumCodecPlatform.scala (100%) create mode 100644 modules/core/native/src/main/scala-2/SqlState.scala create mode 100644 modules/core/native/src/main/scala-2/codec/EnumCodecPlatform.scala rename modules/tests/{shared => js-jvm}/src/test/scala-2/codec/EnumCodecTest.scala (100%) diff --git a/build.sbt b/build.sbt index 2b1d4aff..69b87a7b 100644 --- a/build.sbt +++ b/build.sbt @@ -142,12 +142,16 @@ lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform) "org.tpolecat" %%% "natchez-core" % natchezVersion, "com.armanbilge" %%% "sourcepos" % "1.0.2-SNAPSHOT", "org.scala-lang.modules" %%% "scala-collection-compat" % "2.8.1", - ) ++ Seq( - "com.armanbilge" %%% "enumeratum" % "1.7.1-SNAPSHOT", - ).filterNot(_ => tlIsScala3.value) + ) ).jvmSettings( libraryDependencies += "com.ongres.scram" % "client" % "2.1", - ).platformsSettings(JSPlatform, NativePlatform)( + ) + .platformsSettings(JVMPlatform, JSPlatform)( + libraryDependencies ++= Seq( + "com.beachape" %%% "enumeratum" % "1.7.1-SNAPSHOT", + ).filterNot(_ => tlIsScala3.value) + ) + .platformsSettings(JSPlatform, NativePlatform)( libraryDependencies ++= Seq( "com.armanbilge" %%% "saslprep" % "0.1.1", "io.github.cquiroz" %%% "scala-java-time" % "2.4.0", diff --git a/modules/core/shared/src/main/scala-2/SqlState.scala b/modules/core/js-jvm/src/main/scala-2/SqlState.scala similarity index 100% rename from modules/core/shared/src/main/scala-2/SqlState.scala rename to modules/core/js-jvm/src/main/scala-2/SqlState.scala diff --git a/modules/core/shared/src/main/scala-2/codec/EnumCodecPlatform.scala b/modules/core/js-jvm/src/main/scala-2/codec/EnumCodecPlatform.scala similarity index 100% rename from modules/core/shared/src/main/scala-2/codec/EnumCodecPlatform.scala rename to modules/core/js-jvm/src/main/scala-2/codec/EnumCodecPlatform.scala diff --git a/modules/core/native/src/main/scala-2/SqlState.scala b/modules/core/native/src/main/scala-2/SqlState.scala new file mode 100644 index 00000000..15f5e7f9 --- /dev/null +++ b/modules/core/native/src/main/scala-2/SqlState.scala @@ -0,0 +1,1424 @@ +// Copyright (c) 2018-2021 by Rob Norris +// This software is licensed under the MIT License (MIT). +// For more information see LICENSE or https://opensource.org/licenses/MIT + +package skunk + +import scala.collection.immutable.IndexedSeq +import skunk.exception.PostgresErrorException + +/** Enumerated type of Postgres error codes. See the companion object for more information. */ +sealed abstract class SqlState(val code: String) { + + def unapply(e: Throwable): Option[PostgresErrorException] = + Some(e).collect { case e: PostgresErrorException if e.code == code => e } + +} + +/** + * Enumerated type of Postgres error codes. These can be used as extractors for error handling, + * for example: + * {{{ + * doSomething.recoverWith { case SqlState.ForeignKeyViolation(ex) => ... } + * }}} + * @see [[https://www.postgresql.org/docs/10/errcodes-appendix.html PostgreSQL Error Codes]] + */ +object SqlState { + + /** + * SqlState `25001` + * @group Instances + */ + case object ActiveSqlTransaction extends SqlState("25001") + + /** + * SqlState `57P01` + * @group Instances + */ + case object AdminShutdown extends SqlState("57P01") + + /** + * SqlState `42P09` + * @group Instances + */ + case object AmbiguousAlias extends SqlState("42P09") + + /** + * SqlState `42702` + * @group Instances + */ + case object AmbiguousColumn extends SqlState("42702") + + /** + * SqlState `42725` + * @group Instances + */ + case object AmbiguousFunction extends SqlState("42725") + + /** + * SqlState `42P08` + * @group Instances + */ + case object AmbiguousParameter extends SqlState("42P08") + + /** + * SqlState `2202E` + * @group Instances + */ + case object ArraySubscriptError extends SqlState("2202E") + + /** + * SqlState `22P04` + * @group Instances + */ + case object BadCopyFileFormat extends SqlState("22P04") + + /** + * SqlState `25002` + * @group Instances + */ + case object BranchTransactionAlreadyActive extends SqlState("25002") + + /** + * SqlState `42846` + * @group Instances + */ + case object CannotCoerce extends SqlState("42846") + + /** + * SqlState `57P03` + * @group Instances + */ + case object CannotConnectNow extends SqlState("57P03") + + /** + * SqlState `55P02` + * @group Instances + */ + case object CantChangeRuntimeParam extends SqlState("55P02") + + /** + * SqlState `21000` + * @group Instances + */ + case object CardinalityViolation extends SqlState("21000") + + /** + * SqlState `20000` + * @group Instances + */ + case object CaseNotFound extends SqlState("20000") + + /** + * SqlState `22021` + * @group Instances + */ + case object CharacterNotInRepertoire extends SqlState("22021") + + /** + * SqlState `23514` + * @group Instances + */ + case object CheckViolation extends SqlState("23514") + + /** + * SqlState `F0000` + * @group Instances + */ + case object ConfigFileError extends SqlState("F0000") + + /** + * SqlState `08003` + * @group Instances + */ + case object ConnectionDoesNotExist extends SqlState("08003") + + /** + * SqlState `08000` + * @group Instances + */ + case object ConnectionException extends SqlState("08000") + + /** + * SqlState `08006` + * @group Instances + */ + case object ConnectionFailure extends SqlState("08006") + + /** + * SqlState `38001` + * @group Instances + */ + case object ContainingSqlNotPermitted extends SqlState("38001") + + /** + * SqlState `57P02` + * @group Instances + */ + case object CrashShutdown extends SqlState("57P02") + + /** + * SqlState `XX001` + * @group Instances + */ + case object DataCorrupted extends SqlState("XX001") + + /** + * SqlState `22000` + * @group Instances + */ + case object DataException extends SqlState("22000") + + /** + * SqlState `57P04` + * @group Instances + */ + case object DatabaseDropped extends SqlState("57P04") + + /** + * SqlState `42804` + * @group Instances + */ + case object DatatypeMismatch extends SqlState("42804") + + /** + * SqlState `22008` + * @group Instances + */ + case object DatetimeFieldOverflow extends SqlState("22008") + + /** + * SqlState `40P01` + * @group Instances + */ + case object DeadlockDetected extends SqlState("40P01") + + /** + * SqlState `2BP01` + * @group Instances + */ + case object DependentObjectsStillExist extends SqlState("2BP01") + + /** + * SqlState `2B000` + * @group Instances + */ + case object DependentPrivilegeDescriptorsStillExist extends SqlState("2B000") + + /** + * SqlState `01P01` + * @group Instances + */ + case object DeprecatedFeature extends SqlState("01P01") + + /** + * SqlState `53100` + * @group Instances + */ + case object DiskFull extends SqlState("53100") + + /** + * SqlState `22012` + * @group Instances + */ + case object DivisionByZero extends SqlState("22012") + + /** + * SqlState `42712` + * @group Instances + */ + case object DuplicateAlias extends SqlState("42712") + + /** + * SqlState `42701` + * @group Instances + */ + case object DuplicateColumn extends SqlState("42701") + + /** + * SqlState `42P03` + * @group Instances + */ + case object DuplicateCursor extends SqlState("42P03") + + /** + * SqlState `42P04` + * @group Instances + */ + case object DuplicateDatabase extends SqlState("42P04") + + /** + * SqlState `58P02` + * @group Instances + */ + case object DuplicateFile extends SqlState("58P02") + + /** + * SqlState `42723` + * @group Instances + */ + case object DuplicateFunction extends SqlState("42723") + + /** + * SqlState `42710` + * @group Instances + */ + case object DuplicateObject extends SqlState("42710") + + /** + * SqlState `42P05` + * @group Instances + */ + case object DuplicatePreparedStatement extends SqlState("42P05") + + /** + * SqlState `42P06` + * @group Instances + */ + case object DuplicateSchema extends SqlState("42P06") + + /** + * SqlState `42P07` + * @group Instances + */ + case object DuplicateTable extends SqlState("42P07") + + /** + * SqlState `0100C` + * @group Instances + */ + case object DynamicResultSetsReturned extends SqlState("0100C") + + /** + * SqlState `22005` + * @group Instances + */ + case object ErrorInAssignment extends SqlState("22005") + + /** + * SqlState `2200B` + * @group Instances + */ + case object EscapeCharacterConflict extends SqlState("2200B") + + /** + * SqlState `23P01` + * @group Instances + */ + case object ExclusionViolation extends SqlState("23P01") + + /** + * SqlState `38000` + * @group Instances + */ + case object ExternalRoutineException extends SqlState("38000") + + /** + * SqlState `39000` + * @group Instances + */ + case object ExternalRoutineInvocationException extends SqlState("39000") + + /** + * SqlState `0A000` + * @group Instances + */ + case object FeatureNotSupported extends SqlState("0A000") + + /** + * SqlState `22P01` + * @group Instances + */ + case object FloatingPointException extends SqlState("22P01") + + /** + * SqlState `23503` + * @group Instances + */ + case object ForeignKeyViolation extends SqlState("23503") + + /** + * SqlState `2F005` + * @group Instances + */ + case object FunctionExecutedNoReturnStatement extends SqlState("2F005") + + /** + * SqlState `42803` + * @group Instances + */ + case object GroupingError extends SqlState("42803") + + /** + * SqlState `25008` + * @group Instances + */ + case object HeldCursorRequiresSameIsolationLevel extends SqlState("25008") + + /** + * SqlState `01008` + * @group Instances + */ + case object ImplicitZeroBitPadding extends SqlState("01008") + + /** + * SqlState `25P02` + * @group Instances + */ + case object InFailedSqlTransaction extends SqlState("25P02") + + /** + * SqlState `25003` + * @group Instances + */ + case object InappropriateAccessModeForBranchTransaction extends SqlState("25003") + + /** + * SqlState `25004` + * @group Instances + */ + case object InappropriateIsolationLevelForBranchTransaction extends SqlState("25004") + + /** + * SqlState `42P18` + * @group Instances + */ + case object IndeterminateDatatype extends SqlState("42P18") + + /** + * SqlState `XX002` + * @group Instances + */ + case object IndexCorrupted extends SqlState("XX002") + + /** + * SqlState `22022` + * @group Instances + */ + case object IndicatorOverflow extends SqlState("22022") + + /** + * SqlState `42501` + * @group Instances + */ + case object InsufficientPrivilege extends SqlState("42501") + + /** + * SqlState `53000` + * @group Instances + */ + case object InsufficientResources extends SqlState("53000") + + /** + * SqlState `23000` + * @group Instances + */ + case object IntegrityConstraintViolation extends SqlState("23000") + + /** + * SqlState `XX000` + * @group Instances + */ + case object InternalError extends SqlState("XX000") + + /** + * SqlState `22015` + * @group Instances + */ + case object IntervalFieldOverflow extends SqlState("22015") + + /** + * SqlState `2201E` + * @group Instances + */ + case object InvalidArgumentForLogarithm extends SqlState("2201E") + + /** + * SqlState `22016` + * @group Instances + */ + case object InvalidArgumentForNthValueFunction extends SqlState("22016") + + /** + * SqlState `22014` + * @group Instances + */ + case object InvalidArgumentForNtileFunction extends SqlState("22014") + + /** + * SqlState `2201F` + * @group Instances + */ + case object InvalidArgumentForPowerFunction extends SqlState("2201F") + + /** + * SqlState `2201G` + * @group Instances + */ + case object InvalidArgumentForWidthBucketFunction extends SqlState("2201G") + + /** + * SqlState `28000` + * @group Instances + */ + case object InvalidAuthorizationSpecification extends SqlState("28000") + + /** + * SqlState `22P03` + * @group Instances + */ + case object InvalidBinaryRepresentation extends SqlState("22P03") + + /** + * SqlState `3D000` + * @group Instances + */ + case object InvalidCatalogName extends SqlState("3D000") + + /** + * SqlState `22018` + * @group Instances + */ + case object InvalidCharacterValueForCast extends SqlState("22018") + + /** + * SqlState `42611` + * @group Instances + */ + case object InvalidColumnDefinition extends SqlState("42611") + + /** + * SqlState `42P10` + * @group Instances + */ + case object InvalidColumnReference extends SqlState("42P10") + + /** + * SqlState `42P11` + * @group Instances + */ + case object InvalidCursorDefinition extends SqlState("42P11") + + /** + * SqlState `34000` + * @group Instances + */ + case object InvalidCursorName extends SqlState("34000") + + /** + * SqlState `24000` + * @group Instances + */ + case object InvalidCursorState extends SqlState("24000") + + /** + * SqlState `42P12` + * @group Instances + */ + case object InvalidDatabaseDefinition extends SqlState("42P12") + + /** + * SqlState `22007` + * @group Instances + */ + case object InvalidDatetimeFormat extends SqlState("22007") + + /** + * SqlState `22019` + * @group Instances + */ + case object InvalidEscapeCharacter extends SqlState("22019") + + /** + * SqlState `2200D` + * @group Instances + */ + case object InvalidEscapeOctet extends SqlState("2200D") + + /** + * SqlState `22025` + * @group Instances + */ + case object InvalidEscapeSequence extends SqlState("22025") + + /** + * SqlState `42830` + * @group Instances + */ + case object InvalidForeignKey extends SqlState("42830") + + /** + * SqlState `42P13` + * @group Instances + */ + case object InvalidFunctionDefinition extends SqlState("42P13") + + /** + * SqlState `0LP01` + * @group Instances + */ + case object InvalidGrantOperation extends SqlState("0LP01") + + /** + * SqlState `0L000` + * @group Instances + */ + case object InvalidGrantor extends SqlState("0L000") + + /** + * SqlState `22010` + * @group Instances + */ + case object InvalidIndicatorParameterValue extends SqlState("22010") + + /** + * SqlState `0F001` + * @group Instances + */ + case object InvalidLocatorSpecification extends SqlState("0F001") + + /** + * SqlState `42602` + * @group Instances + */ + case object InvalidName extends SqlState("42602") + + /** + * SqlState `42P17` + * @group Instances + */ + case object InvalidObjectDefinition extends SqlState("42P17") + + /** + * SqlState `22023` + * @group Instances + */ + case object InvalidParameterValue extends SqlState("22023") + + /** + * SqlState `28P01` + * @group Instances + */ + case object InvalidPassword extends SqlState("28P01") + + /** + * SqlState `42P14` + * @group Instances + */ + case object InvalidPreparedStatementDefinition extends SqlState("42P14") + + /** + * SqlState `42P19` + * @group Instances + */ + case object InvalidRecursion extends SqlState("42P19") + + /** + * SqlState `2201B` + * @group Instances + */ + case object InvalidRegularExpression extends SqlState("2201B") + + /** + * SqlState `0P000` + * @group Instances + */ + case object InvalidRoleSpecification extends SqlState("0P000") + + /** + * SqlState `2201W` + * @group Instances + */ + case object InvalidRowCountInLimitClause extends SqlState("2201W") + + /** + * SqlState `2201X` + * @group Instances + */ + case object InvalidRowCountInResultOffsetClause extends SqlState("2201X") + + /** + * SqlState `3B001` + * @group Instances + */ + case object InvalidSavepointSpecification extends SqlState("3B001") + + /** + * SqlState `42P15` + * @group Instances + */ + case object InvalidSchemaDefinition extends SqlState("42P15") + + /** + * SqlState `3F000` + * @group Instances + */ + case object InvalidSchemaName extends SqlState("3F000") + + /** + * SqlState `26000` + * @group Instances + */ + case object InvalidSqlStatementName extends SqlState("26000") + + /** + * SqlState `39001` + * @group Instances + */ + case object InvalidSqlstateReturned extends SqlState("39001") + + /** + * SqlState `42P16` + * @group Instances + */ + case object InvalidTableDefinition extends SqlState("42P16") + + /** + * SqlState `22P02` + * @group Instances + */ + case object InvalidTextRepresentation extends SqlState("22P02") + + /** + * SqlState `22009` + * @group Instances + */ + case object InvalidTimeZoneDisplacementValue extends SqlState("22009") + + /** + * SqlState `0B000` + * @group Instances + */ + case object InvalidTransactionInitiation extends SqlState("0B000") + + /** + * SqlState `25000` + * @group Instances + */ + case object InvalidTransactionState extends SqlState("25000") + + /** + * SqlState `2D000` + * @group Instances + */ + case object InvalidTransactionTermination extends SqlState("2D000") + + /** + * SqlState `2200C` + * @group Instances + */ + case object InvalidUseOfEscapeCharacter extends SqlState("2200C") + + /** + * SqlState `2200S` + * @group Instances + */ + case object InvalidXmlComment extends SqlState("2200S") + + /** + * SqlState `2200N` + * @group Instances + */ + case object InvalidXmlContent extends SqlState("2200N") + + /** + * SqlState `2200M` + * @group Instances + */ + case object InvalidXmlDocument extends SqlState("2200M") + + /** + * SqlState `2200T` + * @group Instances + */ + case object InvalidXmlProcessingInstruction extends SqlState("2200T") + + /** + * SqlState `58030` + * @group Instances + */ + case object IoError extends SqlState("58030") + + /** + * SqlState `0F000` + * @group Instances + */ + case object LocatorException extends SqlState("0F000") + + /** + * SqlState `F0001` + * @group Instances + */ + case object LockFileExists extends SqlState("F0001") + + /** + * SqlState `55P03` + * @group Instances + */ + case object LockNotAvailable extends SqlState("55P03") + + /** + * SqlState `2F002` + * @group Instances + */ + case object ModifyingSqlDataNotPermitted2F extends SqlState("2F002") + + /** + * SqlState `38002` + * @group Instances + */ + case object ModifyingSqlDataNotPermitted38 extends SqlState("38002") + + /** + * SqlState `2200G` + * @group Instances + */ + case object MostSpecificTypeMismatch extends SqlState("2200G") + + /** + * SqlState `42622` + * @group Instances + */ + case object NameTooLong extends SqlState("42622") + + /** + * SqlState `25P01` + * @group Instances + */ + case object NoActiveSqlTransaction extends SqlState("25P01") + + /** + * SqlState `25005` + * @group Instances + */ + case object NoActiveSqlTransactionForBranchTransaction extends SqlState("25005") + + /** + * SqlState `02001` + * @group Instances + */ + case object NoAdditionalDynamicResultSetsReturned extends SqlState("02001") + + /** + * SqlState `02000` + * @group Instances + */ + case object NoData extends SqlState("02000") + + /** + * SqlState `P0002` + * @group Instances + */ + case object NoDataFound extends SqlState("P0002") + + /** + * SqlState `22P06` + * @group Instances + */ + case object NonstandardUseOfEscapeCharacter extends SqlState("22P06") + + /** + * SqlState `2200L` + * @group Instances + */ + case object NotAnXmlDocument extends SqlState("2200L") + + /** + * SqlState `23502` + * @group Instances + */ + case object NotNullViolation extends SqlState("23502") + + /** + * SqlState `01003` + * @group Instances + */ + case object NullValueEliminatedInSetFunction extends SqlState("01003") + + /** + * SqlState `22002` + * @group Instances + */ + case object NullValueNoIndicatorParameter extends SqlState("22002") + + /** + * SqlState `22004` + * @group Instances + */ + case object NullValueNotAllowed extends SqlState("22004") + + /** + * SqlState `39004` + * @group Instances + */ + case object NullValueNotAllowed39 extends SqlState("39004") + + /** + * SqlState `22003` + * @group Instances + */ + case object NumericValueOutOfRange extends SqlState("22003") + + /** + * SqlState `55006` + * @group Instances + */ + case object ObjectInUse extends SqlState("55006") + + /** + * SqlState `55000` + * @group Instances + */ + case object ObjectNotInPrerequisiteState extends SqlState("55000") + + /** + * SqlState `57000` + * @group Instances + */ + case object OperatorIntervention extends SqlState("57000") + + /** + * SqlState `53200` + * @group Instances + */ + case object OutOfMemory extends SqlState("53200") + + /** + * SqlState `P0000` + * @group Instances + */ + case object PlpgsqlError extends SqlState("P0000") + + /** + * SqlState `01007` + * @group Instances + */ + case object PrivilegeNotGranted extends SqlState("01007") + + /** + * SqlState `01006` + * @group Instances + */ + case object PrivilegeNotRevoked extends SqlState("01006") + + /** + * SqlState `54000` + * @group Instances + */ + case object ProgramLimitExceeded extends SqlState("54000") + + /** + * SqlState `2F003` + * @group Instances + */ + case object ProhibitedSqlStatementAttempted2F extends SqlState("2F003") + + /** + * SqlState `38003` + * @group Instances + */ + case object ProhibitedSqlStatementAttempted38 extends SqlState("38003") + + /** + * SqlState `08P01` + * @group Instances + */ + case object ProtocolViolation extends SqlState("08P01") + + /** + * SqlState `57014` + * @group Instances + */ + case object QueryCanceled extends SqlState("57014") + + /** + * SqlState `P0001` + * @group Instances + */ + case object RaiseException extends SqlState("P0001") + + /** + * SqlState `25006` + * @group Instances + */ + case object ReadOnlySqlTransaction extends SqlState("25006") + + /** + * SqlState `2F004` + * @group Instances + */ + case object ReadingSqlDataNotPermitted2F extends SqlState("2F004") + + /** + * SqlState `38004` + * @group Instances + */ + case object ReadingSqlDataNotPermitted38 extends SqlState("38004") + + /** + * SqlState `42939` + * @group Instances + */ + case object ReservedName extends SqlState("42939") + + /** + * SqlState `23001` + * @group Instances + */ + case object RestrictViolation extends SqlState("23001") + + /** + * SqlState `3B000` + * @group Instances + */ + case object SavepointException extends SqlState("3B000") + + /** + * SqlState `25007` + * @group Instances + */ + case object SchemaAndDataStatementMixingNotSupported extends SqlState("25007") + + /** + * SqlState `40001` + * @group Instances + */ + case object SerializationFailure extends SqlState("40001") + + /** + * SqlState `08001` + * @group Instances + */ + case object SqlClientUnableToEstablishSqlConnection extends SqlState("08001") + + /** + * SqlState `2F000` + * @group Instances + */ + case object SqlRoutineException extends SqlState("2F000") + + /** + * SqlState `08004` + * @group Instances + */ + case object SqlServerRejectedEstablishmentOfSqlConnection extends SqlState("08004") + + /** + * SqlState `03000` + * @group Instances + */ + case object SqlStatementNotYetComplete extends SqlState("03000") + + /** + * SqlState `39P02` + * @group Instances + */ + case object SrfProtocolViolated extends SqlState("39P02") + + /** + * SqlState `40003` + * @group Instances + */ + case object StatementCompletionUnknown extends SqlState("40003") + + /** + * SqlState `54001` + * @group Instances + */ + case object StatementTooComplex extends SqlState("54001") + + /** + * SqlState `22026` + * @group Instances + */ + case object StringDataLengthMismatch extends SqlState("22026") + + /** + * SqlState `22001` + * @group Instances + */ + case object StringDataRightTruncation extends SqlState("22001") + + /** + * SqlState `01004` + * @group Instances + */ + case object StringDataRightTruncation01 extends SqlState("01004") + + /** + * SqlState `22011` + * @group Instances + */ + case object SubstringError extends SqlState("22011") + + /** + * SqlState `00000` + * @group Instances + */ + case object SuccessfulCompletion extends SqlState("00000") + + /** + * SqlState `42601` + * @group Instances + */ + case object SyntaxError extends SqlState("42601") + + /** + * SqlState `42000` + * @group Instances + */ + case object SyntaxErrorOrAccessRuleViolation extends SqlState("42000") + + /** + * SqlState `54023` + * @group Instances + */ + case object TooManyArguments extends SqlState("54023") + + /** + * SqlState `54011` + * @group Instances + */ + case object TooManyColumns extends SqlState("54011") + + /** + * SqlState `53300` + * @group Instances + */ + case object TooManyConnections extends SqlState("53300") + + /** + * SqlState `P0003` + * @group Instances + */ + case object TooManyRows extends SqlState("P0003") + + /** + * SqlState `40002` + * @group Instances + */ + case object TransactionIntegrityConstraintViolation extends SqlState("40002") + + /** + * SqlState `08007` + * @group Instances + */ + case object TransactionResolutionUnknown extends SqlState("08007") + + /** + * SqlState `40000` + * @group Instances + */ + case object TransactionRollback extends SqlState("40000") + + /** + * SqlState `39P01` + * @group Instances + */ + case object TriggerProtocolViolated extends SqlState("39P01") + + /** + * SqlState `09000` + * @group Instances + */ + case object TriggeredActionException extends SqlState("09000") + + /** + * SqlState `27000` + * @group Instances + */ + case object TriggeredDataChangeViolation extends SqlState("27000") + + /** + * SqlState `22027` + * @group Instances + */ + case object TrimError extends SqlState("22027") + + /** + * SqlState `42703` + * @group Instances + */ + case object UndefinedColumn extends SqlState("42703") + + /** + * SqlState `58P01` + * @group Instances + */ + case object UndefinedFile extends SqlState("58P01") + + /** + * SqlState `42883` + * @group Instances + */ + case object UndefinedFunction extends SqlState("42883") + + /** + * SqlState `42704` + * @group Instances + */ + case object UndefinedObject extends SqlState("42704") + + /** + * SqlState `42P02` + * @group Instances + */ + case object UndefinedParameter extends SqlState("42P02") + + /** + * SqlState `42P01` + * @group Instances + */ + case object UndefinedTable extends SqlState("42P01") + + /** + * SqlState `23505` + * @group Instances + */ + case object UniqueViolation extends SqlState("23505") + + /** + * SqlState `22024` + * @group Instances + */ + case object UnterminatedCString extends SqlState("22024") + + /** + * SqlState `22P05` + * @group Instances + */ + case object UntranslatableCharacter extends SqlState("22P05") + + /** + * SqlState `01000` + * @group Instances + */ + case object Warning extends SqlState("01000") + + /** + * SqlState `42P20` + * @group Instances + */ + case object WindowingError extends SqlState("42P20") + + /** + * SqlState `44000` + * @group Instances + */ + case object WithCheckOptionViolation extends SqlState("44000") + + /** + * SqlState `42809` + * @group Instances + */ + case object WrongObjectType extends SqlState("42809") + + /** + * SqlState `2200F` + * @group Instances + */ + case object ZeroLengthCharacterString extends SqlState("2200F") + + val values: IndexedSeq[SqlState] = Vector( + ActiveSqlTransaction, + AdminShutdown, + AmbiguousAlias, + AmbiguousColumn, + AmbiguousFunction, + AmbiguousParameter, + ArraySubscriptError, + BadCopyFileFormat, + BranchTransactionAlreadyActive, + CannotCoerce, + CannotConnectNow, + CantChangeRuntimeParam, + CardinalityViolation, + CaseNotFound, + CharacterNotInRepertoire, + CheckViolation, + ConfigFileError, + ConnectionDoesNotExist, + ConnectionException, + ConnectionFailure, + ContainingSqlNotPermitted, + CrashShutdown, + DataCorrupted, + DataException, + DatabaseDropped, + DatatypeMismatch, + DatetimeFieldOverflow, + DeadlockDetected, + DependentObjectsStillExist, + DependentPrivilegeDescriptorsStillExist, + DeprecatedFeature, + DiskFull, + DivisionByZero, + DuplicateAlias, + DuplicateColumn, + DuplicateCursor, + DuplicateDatabase, + DuplicateFile, + DuplicateFunction, + DuplicateObject, + DuplicatePreparedStatement, + DuplicateSchema, + DuplicateTable, + DynamicResultSetsReturned, + ErrorInAssignment, + EscapeCharacterConflict, + ExclusionViolation, + ExternalRoutineException, + ExternalRoutineInvocationException, + FeatureNotSupported, + FloatingPointException, + ForeignKeyViolation, + FunctionExecutedNoReturnStatement, + GroupingError, + HeldCursorRequiresSameIsolationLevel, + ImplicitZeroBitPadding, + InFailedSqlTransaction, + InappropriateAccessModeForBranchTransaction, + InappropriateIsolationLevelForBranchTransaction, + IndeterminateDatatype, + IndexCorrupted, + IndicatorOverflow, + InsufficientPrivilege, + InsufficientResources, + IntegrityConstraintViolation, + InternalError, + IntervalFieldOverflow, + InvalidArgumentForLogarithm, + InvalidArgumentForNthValueFunction, + InvalidArgumentForNtileFunction, + InvalidArgumentForPowerFunction, + InvalidArgumentForWidthBucketFunction, + InvalidAuthorizationSpecification, + InvalidBinaryRepresentation, + InvalidCatalogName, + InvalidCharacterValueForCast, + InvalidColumnDefinition, + InvalidColumnReference, + InvalidCursorDefinition, + InvalidCursorName, + InvalidCursorState, + InvalidDatabaseDefinition, + InvalidDatetimeFormat, + InvalidEscapeCharacter, + InvalidEscapeOctet, + InvalidEscapeSequence, + InvalidForeignKey, + InvalidFunctionDefinition, + InvalidGrantOperation, + InvalidGrantor, + InvalidIndicatorParameterValue, + InvalidLocatorSpecification, + InvalidName, + InvalidObjectDefinition, + InvalidParameterValue, + InvalidPassword, + InvalidPreparedStatementDefinition, + InvalidRecursion, + InvalidRegularExpression, + InvalidRoleSpecification, + InvalidRowCountInLimitClause, + InvalidRowCountInResultOffsetClause, + InvalidSavepointSpecification, + InvalidSchemaDefinition, + InvalidSchemaName, + InvalidSqlStatementName, + InvalidSqlstateReturned, + InvalidTableDefinition, + InvalidTextRepresentation, + InvalidTimeZoneDisplacementValue, + InvalidTransactionInitiation, + InvalidTransactionState, + InvalidTransactionTermination, + InvalidUseOfEscapeCharacter, + InvalidXmlComment, + InvalidXmlContent, + InvalidXmlDocument, + InvalidXmlProcessingInstruction, + IoError, + LocatorException, + LockFileExists, + LockNotAvailable, + ModifyingSqlDataNotPermitted2F, + ModifyingSqlDataNotPermitted38, + MostSpecificTypeMismatch, + NameTooLong, + NoActiveSqlTransaction, + NoActiveSqlTransactionForBranchTransaction, + NoAdditionalDynamicResultSetsReturned, + NoData, + NoDataFound, + NonstandardUseOfEscapeCharacter, + NotAnXmlDocument, + NotNullViolation, + NullValueEliminatedInSetFunction, + NullValueNoIndicatorParameter, + NullValueNotAllowed, + NullValueNotAllowed39, + NumericValueOutOfRange, + ObjectInUse, + ObjectNotInPrerequisiteState, + OperatorIntervention, + OutOfMemory, + PlpgsqlError, + PrivilegeNotGranted, + PrivilegeNotRevoked, + ProgramLimitExceeded, + ProhibitedSqlStatementAttempted2F, + ProhibitedSqlStatementAttempted38, + ProtocolViolation, + QueryCanceled, + RaiseException, + ReadOnlySqlTransaction, + ReadingSqlDataNotPermitted2F, + ReadingSqlDataNotPermitted38, + ReservedName, + RestrictViolation, + SavepointException, + SchemaAndDataStatementMixingNotSupported, + SerializationFailure, + SqlClientUnableToEstablishSqlConnection, + SqlRoutineException, + SqlServerRejectedEstablishmentOfSqlConnection, + SqlStatementNotYetComplete, + SrfProtocolViolated, + StatementCompletionUnknown, + StatementTooComplex, + StringDataLengthMismatch, + StringDataRightTruncation, + StringDataRightTruncation01, + SubstringError, + SuccessfulCompletion, + SyntaxError, + SyntaxErrorOrAccessRuleViolation, + TooManyArguments, + TooManyColumns, + TooManyConnections, + TooManyRows, + TransactionIntegrityConstraintViolation, + TransactionResolutionUnknown, + TransactionRollback, + TriggerProtocolViolated, + TriggeredActionException, + TriggeredDataChangeViolation, + TrimError, + UndefinedColumn, + UndefinedFile, + UndefinedFunction, + UndefinedObject, + UndefinedParameter, + UndefinedTable, + UniqueViolation, + UnterminatedCString, + UntranslatableCharacter, + Warning, + WindowingError, + WithCheckOptionViolation, + WrongObjectType, + ZeroLengthCharacterString, + ) + +} \ No newline at end of file diff --git a/modules/core/native/src/main/scala-2/codec/EnumCodecPlatform.scala b/modules/core/native/src/main/scala-2/codec/EnumCodecPlatform.scala new file mode 100644 index 00000000..20674360 --- /dev/null +++ b/modules/core/native/src/main/scala-2/codec/EnumCodecPlatform.scala @@ -0,0 +1,8 @@ +// Copyright (c) 2018-2021 by Rob Norris +// This software is licensed under the MIT License (MIT). +// For more information see LICENSE or https://opensource.org/licenses/MIT + +package skunk +package codec + +trait EnumCodecPlatform diff --git a/modules/tests/shared/src/test/scala-2/codec/EnumCodecTest.scala b/modules/tests/js-jvm/src/test/scala-2/codec/EnumCodecTest.scala similarity index 100% rename from modules/tests/shared/src/test/scala-2/codec/EnumCodecTest.scala rename to modules/tests/js-jvm/src/test/scala-2/codec/EnumCodecTest.scala From 1b6954fc9a0e79bd9dd30da36c58c7c480b54013 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 21 Nov 2022 19:18:43 +0000 Subject: [PATCH 27/30] Fix enumeratum version --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 69b87a7b..eeb7389c 100644 --- a/build.sbt +++ b/build.sbt @@ -148,7 +148,7 @@ lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform) ) .platformsSettings(JVMPlatform, JSPlatform)( libraryDependencies ++= Seq( - "com.beachape" %%% "enumeratum" % "1.7.1-SNAPSHOT", + "com.beachape" %%% "enumeratum" % "1.6.1", ).filterNot(_ => tlIsScala3.value) ) .platformsSettings(JSPlatform, NativePlatform)( From b73af3d15d8591989f6027724c50790a64bfa485 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 21 Nov 2022 19:39:36 +0000 Subject: [PATCH 28/30] Bump sourcepos --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index eeb7389c..a8851ce6 100644 --- a/build.sbt +++ b/build.sbt @@ -140,7 +140,7 @@ lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform) "org.scodec" %%% "scodec-core" % (if (tlIsScala3.value) "2.2.0" else "1.11.10"), "org.scodec" %%% "scodec-cats" % "1.2.0", "org.tpolecat" %%% "natchez-core" % natchezVersion, - "com.armanbilge" %%% "sourcepos" % "1.0.2-SNAPSHOT", + "org.tpolecat" %%% "sourcepos" % "1.1.0", "org.scala-lang.modules" %%% "scala-collection-compat" % "2.8.1", ) ).jvmSettings( From 3c67115cb0ebd5a254b77da315aaef585af33d8c Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 21 Nov 2022 19:40:57 +0000 Subject: [PATCH 29/30] Build cleanups --- build.sbt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/build.sbt b/build.sbt index a8851ce6..80bba815 100644 --- a/build.sbt +++ b/build.sbt @@ -35,11 +35,6 @@ lazy val setupCertAndDocker = Seq( ) ) -val isLinux = { - val osName = Option(System.getProperty("os.name")) - osName.exists(_.toLowerCase().contains("linux")) -} - ThisBuild / githubWorkflowBuildPreamble ++= setupCertAndDocker ThisBuild / githubWorkflowBuild ~= { steps => WorkflowStep.Sbt( @@ -72,8 +67,6 @@ ThisBuild / githubWorkflowAddedJobs += ) ) -ThisBuild / resolvers ++= Resolver.sonatypeOssRepos("snapshots") - // https://github.com/sbt/sbt/issues/6997 ThisBuild / libraryDependencySchemes ++= Seq( "org.scala-lang.modules" %% "scala-xml" % VersionScheme.Always From af779fe5b6e53b4c6a52ce47ea54de9d949ee926 Mon Sep 17 00:00:00 2001 From: Michael Pilquist Date: Thu, 24 Nov 2022 09:19:17 -0500 Subject: [PATCH 30/30] Bump natchez --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 80bba815..8f4fe0e5 100644 --- a/build.sbt +++ b/build.sbt @@ -74,7 +74,7 @@ ThisBuild / libraryDependencySchemes ++= Seq( // This is used in a couple places lazy val fs2Version = "3.4.0" -lazy val natchezVersion = "0.2.0" +lazy val natchezVersion = "0.2.2" // Global Settings lazy val commonSettings = Seq(