Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scala Native #703

Merged
merged 33 commits into from
Nov 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
922c92c
It cross-compiles
armanbilge Sep 11, 2022
d131ca6
fix HMAC use
armanbilge Sep 11, 2022
56e6868
official scodec-cats
armanbilge Sep 11, 2022
6df3471
temporal codec test cross-compiles now
armanbilge Sep 11, 2022
083acc2
Bump fs2
armanbilge Sep 12, 2022
171e6e6
Version bumps
armanbilge Sep 12, 2022
9a9ccf5
Regenerate workflow
armanbilge Sep 12, 2022
80b9ad4
cats-time on Scala 3
armanbilge Sep 12, 2022
a0153d7
Fix natchez dep
armanbilge Sep 12, 2022
8b41648
Bump base version
armanbilge Sep 12, 2022
83ddbdb
bumps
armanbilge Sep 13, 2022
74245ea
Merge branch 'main' into feature/native
armanbilge Oct 31, 2022
faa392b
bumps
armanbilge Oct 31, 2022
3b2e8c9
Setup brew plugin
armanbilge Oct 31, 2022
7de6c9b
Cleanup old/redundant settings
armanbilge Oct 31, 2022
b15e44a
Bump Scala 3
armanbilge Oct 31, 2022
7eb53b4
Fix compile
armanbilge Oct 31, 2022
36c016b
Bump circe
armanbilge Oct 31, 2022
aca58c7
Bump Scala.js
armanbilge Oct 31, 2022
f459cb5
Merge branch 'update/scala3-library-3.2.0' into feature/native
armanbilge Oct 31, 2022
10f37f9
Poke ci
armanbilge Oct 31, 2022
01ec759
Regenerate workflow
armanbilge Oct 31, 2022
30233a2
Use ubuntu 22.04 in CI
armanbilge Oct 31, 2022
6161b7f
Merge branch 'main' into feature/native
mpilquist Nov 20, 2022
4f454d4
Fix merge
mpilquist Nov 20, 2022
214b5ce
Fix test
armanbilge Nov 21, 2022
aa4cbcb
Fix compile
armanbilge Nov 21, 2022
bc710a3
Try removing executor override
armanbilge Nov 21, 2022
2a1785b
Remove enumeratum dep from Native
armanbilge Nov 21, 2022
1b6954f
Fix enumeratum version
armanbilge Nov 21, 2022
b73af3d
Bump sourcepos
armanbilge Nov 21, 2022
3c67115
Build cleanups
armanbilge Nov 21, 2022
af779fe
Bump natchez
mpilquist Nov 24, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 52 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ jobs:
name: Build and Test
strategy:
matrix:
os: [ubuntu-latest]
os: [ubuntu-22.04]
scala: [2.12.17, 2.13.10, 3.2.1]
java: [temurin@11]
project: [rootJS, rootJVM]
project: [rootJS, rootJVM, rootNative]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout current branch (full)
Expand Down Expand Up @@ -66,6 +66,10 @@ jobs:
~/Library/Caches/Coursier/v1
key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }}

- 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: |
chmod 600 world/server.key
Expand All @@ -78,38 +82,42 @@ 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')
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')
Expand All @@ -124,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.10]
java: [temurin@11]
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -182,6 +190,16 @@ jobs:
tar xf targets.tar
rm targets.tar

- name: Download target directories (2.12.17, rootNative)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.17-rootNative

- name: Inflate target directories (2.12.17, rootNative)
run: |
tar xf targets.tar
rm targets.tar

- name: Download target directories (2.13.10, rootJS)
uses: actions/download-artifact@v2
with:
Expand All @@ -202,6 +220,16 @@ jobs:
tar xf targets.tar
rm targets.tar

- name: Download target directories (2.13.10, rootNative)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.10-rootNative

- name: Inflate target directories (2.13.10, rootNative)
run: |
tar xf targets.tar
rm targets.tar

- name: Download target directories (3.2.1, rootJS)
uses: actions/download-artifact@v2
with:
Expand All @@ -222,6 +250,16 @@ jobs:
tar xf targets.tar
rm targets.tar

- name: Download target directories (3.2.1, rootNative)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.1-rootNative

- name: Inflate target directories (3.2.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
Expand All @@ -234,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)
Expand Down Expand Up @@ -286,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)'
75 changes: 32 additions & 43 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ 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)

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"),
Expand Down Expand Up @@ -69,8 +73,8 @@ ThisBuild / libraryDependencySchemes ++= Seq(
)

// This is used in a couple places
lazy val fs2Version = "3.3.0"
lazy val natchezVersion = "0.1.6"
lazy val fs2Version = "3.4.0"
lazy val natchezVersion = "0.2.2"

// Global Settings
lazy val commonSettings = Seq(
Expand All @@ -97,45 +101,21 @@ 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.*",

// 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")) / "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 _ => 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
.settings(name := "skunk")
.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)
Expand All @@ -153,22 +133,26 @@ lazy val core = crossProject(JVMPlatform, JSPlatform)
"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,
"org.tpolecat" %%% "sourcepos" % "1.0.1",
"org.tpolecat" %%% "sourcepos" % "1.1.0",
"org.scala-lang.modules" %%% "scala-collection-compat" % "2.8.1",
) ++ Seq(
"com.beachape" %%% "enumeratum" % "1.6.1",
).filterNot(_ => tlIsScala3.value)
)
).jvmSettings(
libraryDependencies += "com.ongres.scram" % "client" % "2.1",
).jsSettings(
)
.platformsSettings(JVMPlatform, JSPlatform)(
libraryDependencies ++= Seq(
"com.beachape" %%% "enumeratum" % "1.6.1",
).filterNot(_ => tlIsScala3.value)
)
.platformsSettings(JSPlatform, NativePlatform)(
libraryDependencies ++= Seq(
"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)
Expand All @@ -180,7 +164,7 @@ lazy val refined = crossProject(JVMPlatform, JSPlatform)
)
)

lazy val circe = crossProject(JVMPlatform, JSPlatform)
lazy val circe = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.crossType(CrossType.Pure)
.in(file("modules/circe"))
.dependsOn(core)
Expand All @@ -194,7 +178,7 @@ lazy val circe = crossProject(JVMPlatform, JSPlatform)
)
)

lazy val tests = crossProject(JVMPlatform, JSPlatform)
lazy val tests = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.crossType(CrossType.Full)
.in(file("modules/tests"))
.dependsOn(core, circe)
Expand All @@ -203,21 +187,26 @@ 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.4",
"org.typelevel" %%% "munit-cats-effect-3" % "1.0.7",
"org.scalameta" %%% "munit" % "1.0.0-M6",
"org.scalameta" % "junit-interface" % "1.0.0-M6",
"org.typelevel" %%% "scalacheck-effect-munit" % "2.0.0-M2",
"org.typelevel" %%% "munit-cats-effect" % "2.0.0-M3",
"org.typelevel" %%% "cats-free" % "2.9.0",
"org.typelevel" %%% "cats-laws" % "2.9.0",
"org.typelevel" %%% "discipline-munit" % "1.0.9",
) ++ Seq(
"io.chrisdavenport" %%% "cats-time" % "0.3.4",
).filterNot(_ => scalaVersion.value.startsWith("3.")),
"org.typelevel" %%% "discipline-munit" % "2.0.0-M3",
"org.typelevel" %%% "cats-time" % "0.5.1",
),
testFrameworks += new TestFramework("munit.Framework")
)
.jsSettings(
Test / scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule)),
)
.nativeEnablePlugins(ScalaNativeBrewedConfigPlugin)
.nativeSettings(
libraryDependencies += "com.armanbilge" %%% "epollcat" % "0.0-ab1026e",
Test / nativeBrewFormulas ++= Set("s2n", "utf8proc"),
Test / envVars ++= Map("S2N_DONT_MLOCK" -> "1")
)

lazy val example = project
.in(file("modules/example"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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

Expand Down Expand Up @@ -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)
Expand Down
Loading