From 5aba0eb52b0337c342940db1682fb1baf019f9b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fede=20Fern=C3=A1ndez?= <720923+fedefernandez@users.noreply.github.com> Date: Sat, 27 May 2023 08:50:10 +0200 Subject: [PATCH] Project set-up --- .gitignore | 27 ++ build.sbt | 312 ++++++++++++++++++ .../src/main/scala/scaladays/Main.scala | 4 + .../src/main/scala/scaladays/Main.scala | 4 + project/Dependencies.scala | 106 ++++++ project/build.properties | 1 + project/plugins.sbt | 17 + project/project/Dependencies.scala | 108 ++++++ project/sbtExtensions.scala | 61 ++++ src/docker-compose.yml | 29 ++ 10 files changed, 669 insertions(+) create mode 100644 .gitignore create mode 100644 build.sbt create mode 100644 modules/client/src/main/scala/scaladays/Main.scala create mode 100644 modules/server/src/main/scala/scaladays/Main.scala create mode 100644 project/Dependencies.scala create mode 100644 project/build.properties create mode 100644 project/plugins.sbt create mode 100644 project/project/Dependencies.scala create mode 100644 project/sbtExtensions.scala create mode 100644 src/docker-compose.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f31b0ed --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +/target/ +/project/target/ +/project/project/target/ +/modules/client/target/ +/modules/client/project/target/ +/modules/common/js/target/ +/modules/common/jvm/target/ +/modules/common/shared/target/ +/modules/shared/target/ +/modules/server/target +/modules/client/dist +/modules/client/.parcel-cache +/modules/client/node_modules +.bsp +.idea +/.bloop/ +/.metals/ +/project/.bloop/ +/project/metals.sbt +/project/project/.bloop/ +/project/project/metals.sbt +/project/project/project/ +/.sbt-hydra-history +yarn.lock +/node_modules/.yarn-integrity +/.parcel-cache/ +/.vscode/ diff --git a/build.sbt b/build.sbt new file mode 100644 index 0000000..57a270b --- /dev/null +++ b/build.sbt @@ -0,0 +1,312 @@ +import scala.util.Properties +import sbt.internal.util.complete.DefaultParsers +import com.typesafe.sbt.packager.docker.* +import sbt.util.CacheImplicits.* +import sbtExtensions.* +import Dependencies.Compile.* +import Dependencies.{SbtPlugins, Versions} +import java.nio.file.Paths + +import scala.util.Try +import scala.sys.process.* + +Global / onChangedBuildSource := ReloadOnSourceChanges +ThisBuild / organization := "com.xebia-functional" + +ThisBuild / scmInfo := Some( + ScmInfo( + url("https://github.com/xebia-functional/tictactoe"), + "scm:git@github.com:xebia-functional/tictactoe.git" + ) +) + +ThisBuild / scalaVersion := "3.2.2" +ThisBuild / semanticdbEnabled := true +ThisBuild / scalafixDependencies += SbtPlugins.organizeImports + +lazy val commonJVM = common.jvm +lazy val commonJS = common.js + +lazy val `scaladays-workshop-2023` = project + .in(file(".")) + .settings( + name := "scaladays-workshop-2023", + version := "0.1.0-SNAPSHOT", + dockerComposeCommand := { + Paths + .get(Try("which docker-compose".!!).recoverWith { case _ => + Try("where docker-compose".!!) + }.get) + .toFile + }, + dockerRegistryHostPort := { + Properties + .envOrElse("SCALADAYS_WORKSHOP_DOCKER_REGISTRY_HOST_PORT", "5000") + .toInt + }, + dockerComposeFile := (Compile / baseDirectory).value / "src" / "docker-compose.yml", + dockerComposeUp := Def + .sequential( + server / Docker / setupBuildX, + server / Docker / publishLocal, + tttClient / Universal / stage, + Def.task( + streams.value.log.info( + "Docker compose file after environment variable interpolation:" + ) + ), + Def.task( + streams.value.log.info( + Process( + Seq( + "docker-compose", + "-f", + s"${dockerComposeFile.value.getAbsolutePath()}", + "config" + ), + None, + "SCALADAYS_WORKSHOP_DOCKER_REGISTRY_HOST_PORT" -> s"${dockerRegistryHostPort.value}", + "SCALADAYS_CLIENT_DIST" -> s"${(tttClient / Universal / stagingDirectory).value / "dist"}" + ).!! + ) + ), + Def.task( + streams.value.log.info( + Process( + Seq( + "docker-compose", + "-f", + s"${dockerComposeFile.value.getAbsolutePath()}", + "up", + "-d" + ), + None, + "SCALADAYS_WORKSHOP_DOCKER_REGISTRY_HOST_PORT" -> s"${dockerRegistryHostPort.value}", + "SCALADAYS_CLIENT_DIST" -> s"${(tttClient / Universal / stagingDirectory).value / "dist"}" + ).!! + ) + ) + ) + .value, + dockerComposeDown := { + val log = streams.value.log + log.info( + Process( + Seq( + "docker-compose", + "-f", + s"${dockerComposeFile.value.getAbsolutePath()}", + "down", + "--rmi", + "all" + ), + None, + "SCALADAYS_WORKSHOP_DOCKER_REGISTRY_HOST_PORT" -> s"${dockerRegistryHostPort.value}", + "SCALADAYS_CLIENT_DIST" -> s"${(tttClient / Universal / stagingDirectory).value / "dist"}" + ).!! + ) + } + ) + .aggregate(server, tttClient) + .dependsOn(server, tttClient) + +lazy val commonDependencies = Def.setting( + Seq( + Dependencies.Test.munit % Test, + Dependencies.Test.munitCats3 % Test, + Dependencies.Test.munitScalacheck % Test, + pureConfig, + "io.chrisdavenport" %%% "fuuid" % Versions.fuuid, + "io.circe" %%% "circe-core" % Versions.circe, + "io.circe" %%% "circe-generic" % Versions.circe, + "io.circe" %%% "circe-parser" % Versions.circe, + "org.http4s" %%% "http4s-circe" % Versions.http4s + ) +) + +lazy val common = + crossProject(JSPlatform, JVMPlatform) + .crossType(CrossType.Full) + .in(file("modules/common")) + .settings( + libraryDependencies ++= commonDependencies.value + ) + +lazy val server = + project + .in(file("modules/server")) + .settings( + name := "scaladays-workshop-2023-server", + resolvers += "confluent" at "https://packages.confluent.io/maven/", + dockerRegistryHostPort := { + Properties + .envOrElse("SCALADAYS_WORKSHOP_DOCKER_REGISTRY_HOST_PORT", "5000") + .toInt + }, + generateConfigToml := { + generateConfigTomlInManagedResourcesFrom( + ( + (Docker / dockerRegistryHostPort).value, + (Compile / resourceManaged).value + ) + ) + }, + (Compile / resourceGenerators) += generateConfigToml, + Docker / setupBuildX := { + (Compile / resourceGenerators).value + (Docker / setupBuildX).previous.filter(_ == "Success").getOrElse { + val log = streams.value.log + val dockerCommand = + s"${(Docker / dockerExecCommand).value.mkString("")}" + Try { + val binFmtInstall = + s"$dockerCommand run --privileged --rm tonistiigi/binfmt --install all" + log.info( + s"Setting up docker buildx appropriately: ${binFmtInstall.!!}" + ) + }.flatMap { _ => + val stopRegistry = s"$dockerCommand container stop registry" + Try(log.info(s"Stopping docker registry: ${stopRegistry.!!}")) + .recoverWith { case _ => Try("Exception") } + }.flatMap { _ => + val removeRegistry = s"$dockerCommand container rm registry" + Try(log.info(s"removing docker registry: ${removeRegistry.!!}")) + .recoverWith { case _ => + Try("Exception") + } + }.flatMap { _ => + val buildxSetup = + s"$dockerCommand buildx create --config ${(Compile / resourceManaged).value / "docker" / "registry" / "config.toml"} --driver-opt network=host --use" + Try( + log.info( + s"Setting up docker buildx appropriately: ${buildxSetup.!!}" + ) + ) + }.recover { case e: Exception => + log.error(s"${e.getMessage}") + throw e + }.map(_ => "Success") + .toOption + .getOrElse("Failure") + } + }, + libraryDependencies ++= Dependencies.Compile.serverDeps ++ commonDependencies.value, + dockerCommands := dockerCommands.value + .updatedBy( + baseImageCommand((Docker / dockerBaseImage).value).forStage("stage0"), + c => + c match { + + case Cmd("FROM", args @ _*) => + args.contains("openjdk:8") && args.contains("stage0") + case _ => false + } + ) + .updatedBy( + baseImageCommand((Docker / dockerBaseImage).value).forStage( + "mainstage" + ), + c => + c match { + + case Cmd("FROM", args @ _*) => + args.contains("openjdk:8") && args.contains("mainstage") + case _ => false + } + ) + .insertAt( + 6, + Cmd( + "ADD", + "--chmod=u=rX,g=rX", + "https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh", + "/4/opt/docker/bin/wait-for-it.sh" + ) + ) + .insertAt(10, Cmd("RUN", "stat", "/4/opt/docker")) + .insertAt(20, ExecCmd("RUN", "chmod", "+x", "/opt/docker/bin/wait-for-it.sh")) + .updatedBy( + ExecCmd( + "ENTRYPOINT", + "/opt/docker/bin/wait-for-it.sh", + "schema-registry:8081", + "--timeout=30", + "--strict", + "--", + "/opt/docker/bin/scaladays-workshop-2023-server" + ), + c => + c match { + + case ExecCmd("ENTRYPOINT", _) => true + case _ => false + } + ), + scalacOptions ++= Seq("-source", "future"), + Docker / dockerBaseImage := "eclipse-temurin:17.0.7_7-jre-jammy", + Docker / dockerBuildOptions ++= Seq("--platform=linux/amd64"), + Docker / dockerBuildCommand := (Docker / dockerExecCommand).value ++ Seq( + "buildx", + "build" + ) ++ (Docker / dockerBuildOptions).value.filterNot( + _ == "--force-rm" + ) ++ Seq(".", "--load"), + Docker / dockerBuildInit := true, + Docker / dockerExposedPorts := Seq(8080, 8081), + Docker / packageName := s"127.0.0.1:${(Docker / dockerRegistryHostPort).value}/${packageName.value}", + Docker / dockerUpdateLatest := true, + Docker / version := "latest" + ) + .dependsOn(commonJVM) + .enablePlugins(JavaAppPackaging) + .enablePlugins(DockerPlugin) + +lazy val tttClient = + project + .in(file("modules/client")) + .enablePlugins(ScalaJSPlugin) + .settings(scalaJSUseMainModuleInitializer := true) + .settings( + name := "scaladays-workshop-2023-client", + resolvers += "http4s" at "https://mvnrepository.com/artifact/org.http4s/http4s-dom", + Compile / resourceDirectories += (Compile / baseDirectory).value / "src" / "main" / "assets", + libraryDependencies ++= + commonDependencies.value ++ + Seq( + "io.indigoengine" %%% "tyrian-io" % Versions.tyrian, + "org.scala-js" %%% "scalajs-dom" % Versions.scalajsDom, + "org.http4s" %%% "http4s-dom" % Versions.http4s, + "com.github.japgolly.scalacss" %%% "core" % Versions.scalacssCore + ), + maintainer := "jack.viers@47Deg.com", + Universal / mappings ++= { + val log = streams.value.log + val report = (Compile / fullLinkJS).value + val outputDirectory = + (Compile / fullLinkJS / scalaJSLinkerOutputDirectory).value + report.data.publicModules.map { m => + log.info(s"moduleId: ${m.moduleID}") + (outputDirectory / m.jsFileName) -> s"lib/${m.jsFileName}" + }.toSeq + }, + Universal / mappings ++= { + val mappedResources = (Compile / resources).value + mappedResources.filterNot(_.getName() == "custom.scss").map { r => + r -> s"${r.getName()}" + } + }, + Universal / mappings ++= { + val mappedResources = (Compile / resources).value + mappedResources.filter(_.getName() == "custom.scss").map { r => + r -> s"scss/${r.getName()}" + } + }, + Universal / stage := { + val staging = (Universal / stage).value + Process("npm i --include-dev", (Universal / stagingDirectory).value).!! + Process("npm run build", (Universal / stagingDirectory).value).!! + staging + } + ) + .dependsOn(common.js) + .enablePlugins(UniversalPlugin) diff --git a/modules/client/src/main/scala/scaladays/Main.scala b/modules/client/src/main/scala/scaladays/Main.scala new file mode 100644 index 0000000..2358b4b --- /dev/null +++ b/modules/client/src/main/scala/scaladays/Main.scala @@ -0,0 +1,4 @@ +package scaladays + +object Main: + @main def hello() = println("Hello, World") diff --git a/modules/server/src/main/scala/scaladays/Main.scala b/modules/server/src/main/scala/scaladays/Main.scala new file mode 100644 index 0000000..b02f800 --- /dev/null +++ b/modules/server/src/main/scala/scaladays/Main.scala @@ -0,0 +1,4 @@ +package scaladays + +object Main: + @main def hello() = println("Hello, World") \ No newline at end of file diff --git a/project/Dependencies.scala b/project/Dependencies.scala new file mode 100644 index 0000000..589fd9a --- /dev/null +++ b/project/Dependencies.scala @@ -0,0 +1,106 @@ +import sbt._ +object Dependencies { + + // define versions, The variable name must be camel case by module name + object Versions { + val scalacssCore = "1.0.0" + val scalajsStubs = "1.1.0" + val react = "18.2.0" + val reactDom = "18.2.0" + val scalajsDom = "2.4.0" + val tyrian = "0.6.2" + val scalajsReactCore = "2.1.1" + val extReact = "1.0.0" + val sbtScalajsCrossProject = "0.5.0" + val sbtScalaJs = "1.13.1" + val sbtScalajsBundler = "0.21.1" + val munit = "0.7.29" + val munitCats3 = "1.0.7" + val munitScalacheck = "0.7.29" + val sbtDependencyUpdates = "1.2.7" + val scalaFmt = "2.4.6" + val scalaFix = "0.10.4" + val organizeImports = "0.6.0" + val catsEffect = "3.4.8" + val fs2 = "3.6.1" + val log4Cats = "2.5.0" + val pureConfig = "0.17.2" + val http4s = "1.0.0-M36" + val fuuid = "0.8.0-M2" + val fs2Kafka = "2.2.0" + val kafkaStreams = "2.8.0" + val circe = "0.14.5" + val logbackClassic = "1.4.1" + val vulcan = "1.9.0" + val nativePackager = "1.9.16" + } + + object Compile { + val scalajsStubs = + "org.scala-js" %% "scalajs-stubs" % Versions.scalajsStubs % "provided" + val catsEffect = "org.typelevel" %% "cats-effect" % Versions.catsEffect + val fs2Core = "co.fs2" %% "fs2-core" % Versions.fs2 + val fs2IO = "co.fs2" %% "fs2-io" % Versions.fs2 + val log4Cats = "org.typelevel" %% "log4cats-slf4j" % Versions.log4Cats + val pureConfig = + "com.github.pureconfig" %% "pureconfig-core" % Versions.pureConfig + val http4sDSL = "org.http4s" %% "http4s-dsl" % Versions.http4s + val http4sEmberServer = + "org.http4s" %% "http4s-ember-server" % Versions.http4s + val kafkaClients = + "org.apache.kafka" % "kafka-clients" % Versions.kafkaStreams + val kafkaStreams = + "org.apache.kafka" % "kafka-streams" % Versions.kafkaStreams + val kafkaStreamsScala = + "org.apache.kafka" % "kafka-streams-scala_2.13" % Versions.kafkaStreams + val logBack = "ch.qos.logback" % "logback-classic" % Versions.logbackClassic + + val fs2Kafka = "com.github.fd4s" %% "fs2-kafka" % Versions.fs2Kafka + val fs2KafkaVulcan = + "com.github.fd4s" %% "fs2-kafka-vulcan" % Versions.fs2Kafka + + val http4sDeps = Seq(http4sEmberServer, http4sDSL) + val kafkaDeps = Seq( + kafkaStreams, + kafkaStreamsScala, + fs2Kafka, + fs2KafkaVulcan, + kafkaClients + ) + val serverDeps = Seq( + scalajsStubs, + catsEffect, + fs2Core, + fs2IO, + log4Cats, + logBack + ) ++ http4sDeps ++ kafkaDeps + } + + object SbtPlugins { + val sbtScalajsCrossProject = + "org.portable-scala" % "sbt-scalajs-crossproject" % Versions.sbtScalajsCrossProject + val sbtScalaJs = "org.scala-js" % "sbt-scalajs" % Versions.sbtScalaJs + val sbtScalajsBundler = + "ch.epfl.scala" % "sbt-scalajs-bundler" % Versions.sbtScalajsBundler + val sbtDependencyUpdates = + "org.jmotor.sbt" % "sbt-dependency-updates" % Versions.sbtDependencyUpdates + val scalaFmt = "org.scalameta" % "sbt-scalafmt" % Versions.scalaFmt + val scalaFix = "ch.epfl.scala" % "sbt-scalafix" % Versions.scalaFix + val organizeImports = "com.github.liancheng" %% "organize-imports" % Versions.organizeImports + val nativePackager = "com.github.sbt" % "sbt-native-packager" % Versions.nativePackager + } + + object Npm { + val react: (String, String) = "react" -> Versions.react + val reactDom: (String, String) = "react-dom" -> Versions.reactDom + } + + object Test { + val munit: ModuleID = "org.scalameta" %% "munit" % Versions.munit + val munitCats3: ModuleID = + "org.typelevel" %% "munit-cats-effect-3" % Versions.munitCats3 + val munitScalacheck = "org.scalameta" %% "munit-scalacheck" % Versions.munitScalacheck + } + +} diff --git a/project/build.properties b/project/build.properties new file mode 100644 index 0000000..72413de --- /dev/null +++ b/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.8.3 diff --git a/project/plugins.sbt b/project/plugins.sbt new file mode 100644 index 0000000..d34513e --- /dev/null +++ b/project/plugins.sbt @@ -0,0 +1,17 @@ +import Dependencies.SbtPlugins._ +// We have scalajs cross projects that may share code with scalajvm +// projects, so we need the scalajs-crossproject plugin[1]. +addSbtPlugin(sbtScalajsCrossProject) +// We have scalajs, so we need the scalajs sbt plugin[1]. +addSbtPlugin(sbtScalaJs) +// We may want to use npm dependencies in our scalajs modules, so we +// need the latest sbt-scalajs-bundler for scalajs 1.x[2]. +addSbtPlugin(sbtScalajsBundler) +addSbtPlugin(sbtDependencyUpdates) +addSbtPlugin(scalaFmt) +addSbtPlugin(scalaFix) +addSbtPlugin(nativePackager) + + +// 1: [Example plugins.sbt configuration from portable-scala/sbt-crossproject/Readme.md](https://github.com/portable-scala/sbt-crossproject/blob/31b03a9e01abb11043d672303fa71439f868f868/README.md?plain=1#L24-L29) +// 2: [sbt-scalajs-bundler plugins.sbt setup](https://scalacenter.github.io/scalajs-bundler/) diff --git a/project/project/Dependencies.scala b/project/project/Dependencies.scala new file mode 100644 index 0000000..96e2a56 --- /dev/null +++ b/project/project/Dependencies.scala @@ -0,0 +1,108 @@ +import sbt._ +object Dependencies { + + // define versions, The variable name must be camel case by module name + object Versions { + val scalacssCore = "1.0.0" + val scalajsStubs = "1.1.0" + val react = "18.2.0" + val reactDom = "18.2.0" + val scalajsDom = "2.4.0" + val tyrian = "0.6.2" + val scalajsReactCore = "2.1.1" + val extReact = "1.0.0" + val sbtScalajsCrossProject = "0.5.0" + val sbtScalaJs = "1.13.1" + val sbtScalajsBundler = "0.21.1" + val munit = "0.7.29" + val munitCats3 = "1.0.7" + val munitScalacheck = "0.7.29" + val sbtDependencyUpdates = "1.2.7" + val scalaFmt = "2.4.6" + val scalaFix = "0.10.4" + val organizeImports = "0.6.0" + val catsEffect = "3.4.8" + val fs2 = "3.6.1" + val log4Cats = "2.5.0" + val pureConfig = "0.17.2" + val http4s = "1.0.0-M36" + val fuuid = "0.8.0-M2" + val fs2Kafka = "2.2.0" + val kafkaStreams = "2.8.0" + val circe = "0.14.5" + val logbackClassic = "1.4.1" + val vulcan = "1.9.0" + val nativePackager = "1.9.16" + } + + object Compile { + val scalajsStubs = + "org.scala-js" %% "scalajs-stubs" % Versions.scalajsStubs % "provided" + val catsEffect = "org.typelevel" %% "cats-effect" % Versions.catsEffect + val fs2Core = "co.fs2" %% "fs2-core" % Versions.fs2 + val fs2IO = "co.fs2" %% "fs2-io" % Versions.fs2 + val log4Cats = "org.typelevel" %% "log4cats-slf4j" % Versions.log4Cats + val pureConfig = + "com.github.pureconfig" %% "pureconfig-core" % Versions.pureConfig + val http4sDSL = "org.http4s" %% "http4s-dsl" % Versions.http4s + val http4sEmberServer = + "org.http4s" %% "http4s-ember-server" % Versions.http4s + val kafkaClients = + "org.apache.kafka" % "kafka-clients" % Versions.kafkaStreams + val kafkaStreams = + "org.apache.kafka" % "kafka-streams" % Versions.kafkaStreams + val kafkaStreamsScala = + "org.apache.kafka" % "kafka-streams-scala_2.13" % Versions.kafkaStreams + val logBack = "ch.qos.logback" % "logback-classic" % Versions.logbackClassic + + val fs2Kafka = "com.github.fd4s" %% "fs2-kafka" % Versions.fs2Kafka + val fs2KafkaVulcan = + "com.github.fd4s" %% "fs2-kafka-vulcan" % Versions.fs2Kafka + + val http4sDeps = Seq(http4sEmberServer, http4sDSL) + val kafkaDeps = Seq( + kafkaStreams, + kafkaStreamsScala, + fs2Kafka, + fs2KafkaVulcan, + kafkaClients + ) + val serverDeps = Seq( + scalajsStubs, + catsEffect, + fs2Core, + fs2IO, + log4Cats, + logBack, + "com.github.fd4s" %% "vulcan" % Versions.vulcan, + "com.github.fd4s" %% "vulcan-generic" % Versions.vulcan + ) ++ http4sDeps ++ kafkaDeps + } + + object SbtPlugins { + val sbtScalajsCrossProject = + "org.portable-scala" % "sbt-scalajs-crossproject" % Versions.sbtScalajsCrossProject + val sbtScalaJs = "org.scala-js" % "sbt-scalajs" % Versions.sbtScalaJs + val sbtScalajsBundler = + "ch.epfl.scala" % "sbt-scalajs-bundler" % Versions.sbtScalajsBundler + val sbtDependencyUpdates = + "org.jmotor.sbt" % "sbt-dependency-updates" % Versions.sbtDependencyUpdates + val scalaFmt = "org.scalameta" % "sbt-scalafmt" % Versions.scalaFmt + val scalaFix = "ch.epfl.scala" % "sbt-scalafix" % Versions.scalaFix + val organizeImports = "com.github.liancheng" %% "organize-imports" % Versions.organizeImports + val nativePackager = "com.github.sbt" % "sbt-native-packager" % Versions.nativePackager + } + + object Npm { + val react: (String, String) = "react" -> Versions.react + val reactDom: (String, String) = "react-dom" -> Versions.reactDom + } + + object Test { + val munit: ModuleID = "org.scalameta" %% "munit" % Versions.munit + val munitCats3: ModuleID = + "org.typelevel" %% "munit-cats-effect-3" % Versions.munitCats3 + val munitScalacheck = "org.scalameta" %% "munit-scalacheck" % Versions.munitScalacheck + } + +} diff --git a/project/sbtExtensions.scala b/project/sbtExtensions.scala new file mode 100644 index 0000000..e9c7d50 --- /dev/null +++ b/project/sbtExtensions.scala @@ -0,0 +1,61 @@ +import com.typesafe.sbt.packager.docker._ +import sbt._ +import sbt.util.CacheImplicits._ +import sbt.Keys._ +import java.nio.file.Files +import sbt.util.CacheStore + + +object sbtExtensions{ + implicit class SeqExtensions[A](val underlying: Seq[A]){ + def updatedBy(a: A, pred: A => Boolean): Seq[A] = underlying.map{ + case item if pred(item) => a + case item => item + } + def insertAt(index: Int, item: A): Seq[A] = { + val (left, right) = underlying.splitAt(index) + left ++ Seq(item) ++ right + } + } + + def baseImageCommand(baseImage: String) = { + new ForStage{ + def forStage(stage: String): CmdLike = Cmd("FROM", "--platform=$BUILDPLATFORM", baseImage, "as", stage) + } + } + + abstract class ForStage { + def forStage(stage: String): CmdLike + } + + lazy val setupBuildX = taskKey[String]("Sets up the buildx appropriately.") + + lazy val dockerRegistryHostPort = settingKey[Int]("The docker registry host port. By default it is 5000, but you can change it either by setting this setting with sbt set or wwith the environment variable `SCALADAYS_WORKSHOP_DOCKER_REGISTRY_HOST_PORT`") + + lazy val dockerComposeFile = settingKey[File]("The docker compose yml file.") + lazy val dockerComposeUp = taskKey[Unit]("Runs docker compose.") + lazy val dockerComposeDown = taskKey[Unit]("Shuts down docker compose.") + lazy val dockerComposeRestart = inputKey[Unit]("""|Usage: `scaladays-workshop-2023>dockerComposeRestart + |[ + | + |... ]`. Restarts + |the service(s) named + |in the docker + |compose for the + |project.""".stripMargin) + lazy val dockerComposeCommand = taskKey[File]("The docker compose command.") + + lazy val generateConfigToml = taskKey[Seq[File]]("Generates the config.toml so that the cross platform builder necessary for supporting mac m1s doesn't fail.") + + lazy val configTomlCacheStore = taskKey[CacheStore]("The cache store for config file generation.") + + def generateConfigTomlInManagedResourcesFrom(registryPortAndManagedResourcesDir:(Int, File)): Seq[File] = { + val (registryPort, managedResourcesDir) = registryPortAndManagedResourcesDir + val file = managedResourcesDir / "docker" / "registry" /"config.toml" + IO.delete(file) + IO.append(file, s"""|[registry."127.0.0.1:$registryPort"] + |http = true""".stripMargin) + Seq(file) + } + +} diff --git a/src/docker-compose.yml b/src/docker-compose.yml new file mode 100644 index 0000000..6aa784a --- /dev/null +++ b/src/docker-compose.yml @@ -0,0 +1,29 @@ +version: "3.5" +services: + zookeeper-1: + image: confluentinc/cp-zookeeper:latest + environment: + ZOOKEEPER_SERVER_ID: 1 + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_TICK_TIME: 2000 + ZOOKEEPER_INIT_LIMIT: 5 + ZOOKEEPER_SYNC_LIMIT: 2 + ZOOKEEPER_SERVERS: zookeeper-1:22888:23888;zookeeper-2:32888:33888;zookeeper-3:42888:43888 + zookeeper-2: + image: confluentinc/cp-zookeeper:latest + environment: + ZOOKEEPER_SERVER_ID: 2 + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_TICK_TIME: 2000 + ZOOKEEPER_INIT_LIMIT: 5 + ZOOKEEPER_SYNC_LIMIT: 2 + ZOOKEEPER_SERVERS: zookeeper-1:22888:23888;zookeeper-2:32888:33888;zookeeper-3:42888:43888 + zookeeper-3: + image: confluentinc/cp-zookeeper:latest + environment: + ZOOKEEPER_SERVER_ID: ??? + ZOOKEEPER_CLIENT_PORT: ??? + ZOOKEEPER_TICK_TIME: 2000 + ZOOKEEPER_INIT_LIMIT: 5 + ZOOKEEPER_SYNC_LIMIT: 2 + ZOOKEEPER_SERVERS: ??? \ No newline at end of file