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

Add ScalaJS support #604

Merged
merged 16 commits into from
Nov 24, 2023
40 changes: 37 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
os: [ubuntu-latest]
scala: [2.12, 2.13, 3]
java: [temurin@11, temurin@17]
project: [rootJVM]
project: [rootJS, rootJVM]
runs-on: ${{ matrix.os }}
timeout-minutes: 60
steps:
Expand Down Expand Up @@ -72,6 +72,10 @@ jobs:
if: matrix.java == 'temurin@11' && matrix.os == 'ubuntu-latest'
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

- name: Test
run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' test

Expand All @@ -85,11 +89,11 @@ jobs:

- name: Make target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master')
run: mkdir -p fs2/target zio/target core/target interop/target project/target
run: mkdir -p zio/.js/target interop/.jvm/target interop/.js/target core/.js/target zio/.jvm/target core/.jvm/target fs2/.js/target fs2/.jvm/target project/target

- name: Compress target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master')
run: tar cf targets.tar fs2/target zio/target core/target interop/target project/target
run: tar cf targets.tar zio/.js/target interop/.jvm/target interop/.js/target core/.js/target zio/.jvm/target core/.jvm/target fs2/.js/target fs2/.jvm/target project/target

- name: Upload target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master')
Expand Down Expand Up @@ -139,6 +143,16 @@ jobs:
if: matrix.java == 'temurin@17' && steps.setup-java-temurin-17.outputs.cache-hit == 'false'
run: sbt +update

- name: Download target directories (2.12, rootJS)
uses: actions/download-artifact@v3
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-2.12-rootJS

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

- name: Download target directories (2.12, rootJVM)
uses: actions/download-artifact@v3
with:
Expand All @@ -149,6 +163,16 @@ jobs:
tar xf targets.tar
rm targets.tar

- name: Download target directories (2.13, rootJS)
uses: actions/download-artifact@v3
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-2.13-rootJS

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

- name: Download target directories (2.13, rootJVM)
uses: actions/download-artifact@v3
with:
Expand All @@ -159,6 +183,16 @@ jobs:
tar xf targets.tar
rm targets.tar

- name: Download target directories (3, rootJS)
uses: actions/download-artifact@v3
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-3-rootJS

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

- name: Download target directories (3, rootJVM)
uses: actions/download-artifact@v3
with:
Expand Down
95 changes: 50 additions & 45 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,33 @@ val scala_212 = "2.12.18"
val scala_213 = "2.13.12"
val scala_3 = "3.3.1"

val versionOf = new {
val V = new {
val cats = "2.10.0"
val catsEffect = "3.5.2"
val fs2 = "3.9.3"
val log4cats = "2.6.0"
val log4s = "1.10.0"
val scalaCheck = "1.17.0"
val scalaTest = "3.2.17"
val zio = "2.0.19"
val scribe = "3.12.2"
val zio = "2.0.19"
}

lazy val coreDependencies = Seq(
"org.log4s" %% "log4s" % versionOf.log4s,
"com.outr" %% "scribe" % versionOf.scribe
).map(_.withSources)

lazy val fs2Dependencies = Seq(
"org.log4s" %% "log4s" % versionOf.log4s,
"com.outr" %% "scribe" % versionOf.scribe,
"org.typelevel" %% "cats-core" % versionOf.cats,
"org.typelevel" %% "cats-effect" % versionOf.catsEffect,
"co.fs2" %% "fs2-core" % versionOf.fs2
).map(_.withSources)

lazy val zioDependencies = Seq(
"org.log4s" %% "log4s" % versionOf.log4s,
"com.outr" %% "scribe" % versionOf.scribe,
"dev.zio" %% "zio" % versionOf.zio
).map(_.withSources)

lazy val interopDependencies = Seq(
"org.typelevel" %% "log4cats-core" % versionOf.log4cats,
"org.typelevel" %% "log4cats-slf4j" % versionOf.log4cats % Test,
"org.typelevel" %% "cats-effect" % versionOf.catsEffect % Test
).map(_.withSources)

lazy val testDependencies = Seq(
"org.scalacheck" %% "scalacheck" % versionOf.scalaCheck % Test,
"org.scalatest" %% "scalatest" % versionOf.scalaTest % Test,
"org.log4s" %% "log4s-testing" % versionOf.log4s % Test
).map(_.withSources)
val D = new {
lazy val `cats-core` = Def.setting("org.typelevel" %%% "cats-core" % V.cats)
lazy val `cats-effect` = Def.setting("org.typelevel" %%% "cats-effect" % V.catsEffect)
lazy val `fs2-core` = Def.setting("co.fs2" %%% "fs2-core" % V.fs2)
lazy val `log4cats-core` = Def.setting("org.typelevel" %%% "log4cats-core" % V.log4cats)
lazy val `log4cats-testing` = Def.setting("org.typelevel" %%% "log4cats-testing" % V.log4cats)
lazy val log4s = Def.setting("org.log4s" %%% "log4s" % V.log4s)
lazy val `log4s-testing` = Def.setting("org.log4s" %%% "log4s-testing" % V.log4s)
lazy val scalacheck = Def.setting("org.scalacheck" %%% "scalacheck" % V.scalaCheck)
lazy val scalatest = Def.setting("org.scalatest" %%% "scalatest" % V.scalaTest)
lazy val scribe = Def.setting("com.outr" %%% "scribe" % V.scribe)
lazy val zio = Def.setting("dev.zio" %%% "zio" % V.zio)
}

ThisBuild / tlBaseVersion := "0.17"
ThisBuild / tlBaseVersion := "0.18"
ThisBuild / tlCiReleaseBranches := Seq("master")
ThisBuild / tlVersionIntroduced := Map("3" -> "0.16.3")
ThisBuild / tlSonatypeUseLegacyHost := true
Expand All @@ -62,43 +45,65 @@ ThisBuild / githubWorkflowJavaVersions := Seq(
ThisBuild / githubWorkflowBuildMatrixExclusions := Seq()
ThisBuild / Test / parallelExecution := false

ThisBuild / libraryDependencies ++= testDependencies
ThisBuild / libraryDependencies ++= Seq(
D.scalacheck.value % Test,
D.scalatest.value % Test
)

lazy val root = tlCrossRootProject
.aggregate(core, fs2, zio, interop)
.settings(
addCommandAlias("fmt", "scalafmt;Test/scalafmt;scalafmtSbt"),
addCommandAlias("checkFormat", "scalafmtCheck;Test/scalafmtCheck;scalafmtSbtCheck"),
addCommandAlias("check", "checkFormat;clean;test")
addCommandAlias("fmt", "scalafmt; Test/scalafmt; scalafmtSbt"),
addCommandAlias("checkFormat", "scalafmtCheck; Test/scalafmtCheck; scalafmtSbtCheck"),
addCommandAlias("check", "checkFormat; clean; test")
)

lazy val core = project
lazy val core = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Pure)
.in(file("core"))
.settings(
name := "log-effect-core",
libraryDependencies ++= coreDependencies
libraryDependencies ++= Seq(D.log4s.value, D.scribe.value)
)

lazy val fs2 = project
lazy val fs2 = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Pure)
.in(file("fs2"))
.dependsOn(core)
.settings(
name := "log-effect-fs2",
libraryDependencies ++= fs2Dependencies
libraryDependencies ++= Seq(
D.`cats-core`.value,
D.`cats-effect`.value,
D.`fs2-core`.value,
D.log4s.value,
D.scribe.value
)
)

lazy val zio = project
lazy val zio = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Pure)
.in(file("zio"))
.dependsOn(core)
.settings(
name := "log-effect-zio",
libraryDependencies ++= zioDependencies
libraryDependencies ++= Seq(
D.log4s.value,
D.`log4s-testing`.value % Test,
D.scribe.value,
D.zio.value
)
)

lazy val interop = project
lazy val interop = crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Pure)
.in(file("interop"))
.dependsOn(core, fs2)
.settings(
name := "log-effect-interop",
libraryDependencies ++= interopDependencies
libraryDependencies ++= Seq(
D.`cats-effect`.value % Test,
D.`log4cats-core`.value,
D.`log4cats-testing`.value % Test
)
)
3 changes: 1 addition & 2 deletions fs2/src/test/scala/log/effect/fs2/TestLogCapture.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@ package fs2
import java.io.{ByteArrayOutputStream, PrintStream}

import cats.effect.IO
import cats.effect.unsafe.implicits.global

trait TestLogCapture {

protected final def capturedConsoleOutOf(aWrite: IO[Unit]): String = {
val lowerStream = new ByteArrayOutputStream()
val outStream = new PrintStream(lowerStream)

Console.withOut(outStream)(aWrite.unsafeRunSync())
Console.withOut(outStream)(aWrite.syncStep(Int.MaxValue).unsafeRunSync())

lowerStream.toString
}
Expand Down
8 changes: 0 additions & 8 deletions interop/src/test/resources/logback-test.xml

This file was deleted.

34 changes: 15 additions & 19 deletions interop/src/test/scala/InteropLogSelectorTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,12 @@

import cats.effect.{IO, Resource, Sync}
import cats.syntax.flatMap._
import org.typelevel.log4cats.SelfAwareStructuredLogger
import org.typelevel.log4cats.slf4j.Slf4jLogger
import log.effect.fs2.LogSelector
import log.effect.interop.TestLogCapture
import org.typelevel.log4cats.testing.StructuredTestingLogger
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
import org.slf4j.Logger

final class InteropLogSelectorTest extends AnyWordSpecLike with Matchers with TestLogCapture {
final class InteropLogSelectorTest extends AnyWordSpecLike with Matchers {

private[this] sealed trait ALoggingClient[F[_]] {
def address: String
Expand All @@ -49,34 +46,33 @@ final class InteropLogSelectorTest extends AnyWordSpecLike with Matchers with Te
)(_ => F.unit)
}

private[this] def testLogger[F[_]: Sync]: F[StructuredTestingLogger[F]] =
Sync[F].pure(StructuredTestingLogger.impl())

"Log selector can infer the correct log if a log4cats Logger is in scope" in {
import log.effect.interop.log4cats._

def buildLog4catsLogger[F[_]: Sync](logger: Logger): F[SelfAwareStructuredLogger[F]] =
Slf4jLogger.fromSlf4j[F](logger)

def useLoggingClient[F[_]: Sync](address: String)(logger: Logger): F[Unit] =
buildLog4catsLogger[F](logger) >>= { implicit l =>
def useLoggingClient[F[_]: Sync](address: String): F[StructuredTestingLogger[F]] =
testLogger[F].flatTap { implicit l =>
ALoggingClient[F](address).use(_.useIt)
}

val logged = capturedLog4sOutOf(useLoggingClient[IO]("an address")).map(_.message)
val logged =
useLoggingClient[IO]("an address").flatMap(_.logged).syncStep(Int.MaxValue).unsafeRunSync()

logged shouldBe Seq("this is a test")
logged shouldBe Right(Seq(StructuredTestingLogger.INFO("this is a test", None, Map.empty)))
}

"Log selector will default to no logs if no log4cats Logger is in scope" in {

def buildLog4catsLogger[F[_]: Sync](logger: Logger): F[SelfAwareStructuredLogger[F]] =
Slf4jLogger.fromSlf4j[F](logger)

def useLoggingClient[F[_]: Sync](address: String)(logger: Logger): F[Unit] =
buildLog4catsLogger[F](logger) >>= { _ =>
def useLoggingClient[F[_]: Sync](address: String): F[StructuredTestingLogger[F]] =
testLogger[F].flatTap { _ =>
ALoggingClient[F](address).use(_.useIt)
}

val logged = capturedLog4sOutOf(useLoggingClient[IO]("an address"))
val logged =
useLoggingClient[IO]("an address").flatMap(_.logged).syncStep(Int.MaxValue).unsafeRunSync()

logged shouldBe Seq()
logged shouldBe Right(Seq())
}
}
Loading