Skip to content

Commit

Permalink
Advance parsing of ElmProject (#296)
Browse files Browse the repository at this point in the history
* Introduce about command

* MorphirConfig

* Upgrade to 0.12.0

* Add some custom types around the hosting package

* Add the EnvironmentNameSpec

* Clean up Hosting types a bit

* Cleanup the CLI a bit

* Tidying up CLI related items

* Adding additional subcommands for morphir-elm

* Adding ElmCaching related items

* Experiment with jsoniter-scala

* Have an example of using neotype with jsoniter-scala

* Added version number parsing and Conf codec

* Ensure ElmVersion JSON serialization/deserialization works

* Ensure JsonCodec and JsonKeyCodec for ElmDependencyMap works

* Cleanup the ElmModuleName and ElmPackageVersion a bit

* Setting up testing for ElmDependencyMap

* Including validation of ElmDependencyMap

* Did some basic work on ElmApplication
  • Loading branch information
DamianReeves authored Sep 24, 2024
1 parent 3b51b5d commit 2753034
Show file tree
Hide file tree
Showing 60 changed files with 1,358 additions and 429 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: CI - Check
on:
push:
branches: [main]
branches: [main,releases/**,spree/**,spree*]
pull_request:
branches: [main]
branches: [main,releases/**,spree/**,spree*]

jobs:
lint:
Expand Down
25 changes: 22 additions & 3 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ object Settings {}
object MorphirAliases extends Aliases {
@inline def lint = checkfmt
def fmt = alias("mill.scalalib.scalafmt.ScalafmtModule/reformatAll __.sources", "finos.morphir.elmFormat")
def fmtScala = alias("mill.scalalib.scalafmt.ScalafmtModule/reformatAll __.sources")
def checkfmt = alias("mill.scalalib.scalafmt.ScalafmtModule/checkFormatAll __.sources")
def test = alias("morphir.__.test")
def testApps = alias("morphir.cli.test", "morphir.elm.test")
Expand Down Expand Up @@ -41,7 +42,8 @@ object morphir extends CrossPlatform { root =>
ivy"org.scalameta::metaconfig-core::${V.metaconfig}",
ivy"org.scalameta::metaconfig-sconfig::${V.metaconfig}",
ivy"io.github.kitlangton::neotype::${V.neotype}",
ivy"org.graalvm.polyglot:js:${V.`graal-polyglot`}"
ivy"org.graalvm.polyglot:js:${V.`graal-polyglot`}",
ivy"com.github.losizm::t2:${V.t2}"
)
}

Expand Down Expand Up @@ -95,34 +97,51 @@ object morphir extends CrossPlatform { root =>
def ivyDeps = Agg(
ivy"com.lihaoyi::os-lib::${V.oslib}",
ivy"com.github.j-mie6::parsley:${V.parsley}",
ivy"com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-core:${V.`jsoniter-scala`}",
ivy"com.outr::scribe::${V.scribe}",
ivy"io.bullet::borer-core:${V.borer}",
ivy"io.bullet::borer-derivation:${V.borer}",
ivy"io.getkyo::kyo-core::${V.kyo}",
ivy"io.getkyo::kyo-combinators::${V.kyo}",
ivy"io.getkyo::kyo-direct::${V.kyo}",
ivy"io.github.kitlangton::neotype::${V.neotype}",
ivy"io.github.kitlangton::neotype-jsoniter:0.3.5",
ivy"io.github.iltotore::iron:${V.iron}",
ivy"org.typelevel::literally::${V.literally}",
ivy"io.kevinlee::just-semver::${V.`just-semver`}",
ivy"org.scalameta::metaconfig-core::${V.metaconfig}",
ivy"org.scalameta::metaconfig-sconfig::${V.metaconfig}"
)

def compileIvyDeps = Agg(
ivy"com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-macros:${V.`jsoniter-scala`}"
)

override def platformModuleDeps: Seq[CrossPlatform] = Seq(core)
}

object jvm extends ScalaJvmProject with Shared {
override def ivyDeps = super.ivyDeps() ++ Agg(
ivy"dev.dirs:directories:${V.`directories-jvm`}"
)
object test extends ScalaTests with MorphirTests {}
object test extends ScalaTests with MorphirTests {
def ivyDeps = super.ivyDeps() ++ Agg(
ivy"io.github.kitlangton::neotype-jsoniter:0.3.5",
ivy"com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-macros:${V.`jsoniter-scala`}"
)
}
}

object core extends CrossPlatform {
trait Shared extends ScalaLibraryModule with PlatformAwareScalaProject with MorphirLibraryPublishModule {
def scalaVersion = V.Scala.scala3LTSVersion
def ivyDeps = Agg(
ivy"org.typelevel::cats-core::${V.cats}"
ivy"org.typelevel::cats-core::${V.cats}",
ivy"com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-core:${V.`jsoniter-scala`}"
)

def compileIvyDeps = Agg(
ivy"com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-macros:${V.`jsoniter-scala`}"
)
}

Expand Down
11 changes: 9 additions & 2 deletions mill-build/src/org/finos/morphir/build/common_modules.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.finos.morphir.build
import mill._
import mill.scalalib._
import mill.scalalib.scalafmt._
import mill.contrib.buildinfo.BuildInfo

trait CommonModule extends Module {
final def projectName: T[String] = T {projectNameParts().mkString("-")}
Expand Down Expand Up @@ -32,9 +33,15 @@ trait MorphirLibraryPublishModule extends MorphirPublishModule { self: CommonMod
def publishLibraryArtifacts = T { publishArtifacts() }
}

trait MorphirApplicationPublishModule extends MorphirPublishModule { self:CommonModule =>
trait MorphirApplicationPublishModule extends MorphirPublishModule with BuildInfo { self:CommonModule with ScalaModule =>
val buildInfoPackageName = "org.finos.morphir.build"
override def artifactNameParts: T[Seq[String]] = projectNameParts()
def publishApplicationArtifacts = T { publishArtifacts()}
def publishApplicationArtifacts = T { publishArtifacts()}
def buildInfoMembers = Seq(
BuildInfo.Value("scalaVersion", scalaVersion()),
BuildInfo.Value("version", publishVersion()),
BuildInfo.Value("buildTime", java.time.Instant.now.toString)
)
}

trait MorphirTestModule extends TestModule.ZioTest {
Expand Down
36 changes: 20 additions & 16 deletions mill-build/src/org/finos/morphir/build/versions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,27 @@ package org.finos.morphir.build

object V {

val borer = "1.14.1"
val cats = "2.12.0"
val borer = "1.14.1"
val caliban = "2.8.1"
val cats = "2.12.0"
val `directories-jvm` = "26"
val `case-app` = "2.1.0-M29"
val `just-semver` = "1.0.0"
val kyo = "0.11.1"
val iron = "2.6.0"
val metaconfig = "0.13.0"
val oslib = "0.10.6"
val parsley = "4.5.2"
val pprint = "0.9.0"
val neotype = "0.3.0"
val `scala-uri` = "4.0.3"
val scribe = "3.15.0"
val `graal-polyglot` = "24.0.2"
val scalatest = "3.2.19"
val zio = "2.1.9"
val `case-app` = "2.1.0-M29"
val `graal-polyglot` = "24.0.2"
val iron = "2.6.0"
val `jsoniter-scala` = "2.30.11"
val `just-semver` = "1.0.0"
val kyo = "0.12.0"
val literally = "1.2.0"
val metaconfig = "0.13.0"
val oslib = "0.10.6"
val parsley = "4.5.2"
val pprint = "0.9.0"
val neotype = "0.3.5"
val `scala-uri` = "4.0.3"
val scribe = "3.15.0"
val scalatest = "3.2.19"
val t2 = "2.0.0"
val zio = "2.1.9"

object Scala {
val scala3LTSVersion = "3.3.3"
Expand Down
20 changes: 5 additions & 15 deletions morphir/cli/src/org/finos/morphir/cli/Main.scala
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
package org.finos.morphir.cli
import org.finos.morphir.cli.command.*
import caseapp.*
import caseapp.core.help.*
object Main extends CommandsEntryPoint:

override def commands: Seq[Command[?]] = Seq(
Make,
Develop,
Setup,
Config
)

override def helpFormat: HelpFormat =
super.helpFormat.copy(sortedCommandGroups = Some(Seq("Main", "Setup & Configuration")))

// TODO: Use the BuildInfo plugin to get the progName
override def progName: String = "morphir"
import commands.{About, Config, Develop, Make, Setup}
object Main:
def main(args: Array[String]): Unit =
val commands = new MorphirCliCommands("morphir-cli", "morphir-cli", "Morphir CLI")
commands.main(args)
20 changes: 20 additions & 0 deletions morphir/cli/src/org/finos/morphir/cli/MorphirCliCommand.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.finos.morphir.cli
import caseapp.*
import kyo.*
import org.finos.morphir.config.*
import org.finos.morphir.cli.options.OptionGroup
import caseapp.core.help.HelpFormat

abstract class MorphirCliCommand[T](using parser: Parser[T], help: Help[T]) extends Command[T]()(parser, help):

def run(options: T, remainingArgs: RemainingArgs): Unit =
KyoApp.run(runEffect(options, remainingArgs))

def runEffect(options: T, remainingArgs: RemainingArgs): Unit < (Async & Resource & Abort[Throwable])

override def helpFormat: HelpFormat = super.helpFormat.copy(
sortedGroups = Some(OptionGroup.order)
)

object MorphirCliCommand:
type Effects = KyoApp.Effects & Env[MorphirConfig]
35 changes: 35 additions & 0 deletions morphir/cli/src/org/finos/morphir/cli/MorphirCliCommands.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.finos.morphir.cli
import caseapp.CommandsEntryPoint
import caseapp.core.app.Command
import caseapp.core.help.*
import commands.{About, Config, Develop, Make, Setup}
import org.finos.morphir.cli.options.*
import org.finos.morphir.cli.commands.ConfigSet
import org.finos.morphir.cli.commands.ConfigSet.ConfigGet
import org.finos.morphir.cli.MorphirCliCommand

class MorphirCliCommands(
val progName: String,
val baseRunnerName: String,
val fullRunnerName: String
) extends CommandsEntryPoint {

private def allCommands: Seq[MorphirCliCommand[?]] = Seq(
About,
Make,
Develop,
Setup,
ConfigGet,
Config,
ConfigSet
)

def commands: Seq[Command[?]] = allCommands

override def helpFormat: HelpFormat =
super.helpFormat.copy(
sortedGroups = Some(OptionGroup.order),
sortedCommandGroups = Some(Seq("Main", "Setup & Configuration"))
)

}
13 changes: 0 additions & 13 deletions morphir/cli/src/org/finos/morphir/cli/command/config.scala

This file was deleted.

14 changes: 0 additions & 14 deletions morphir/cli/src/org/finos/morphir/cli/command/setup.scala

This file was deleted.

44 changes: 44 additions & 0 deletions morphir/cli/src/org/finos/morphir/cli/commands/about.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.finos.morphir.cli.commands

import caseapp.*
import kyo.*
import org.finos.morphir.build.BuildInfo
import org.finos.morphir.cli.{given, *}

@HelpMessage("Display information about the Morphir CLI")
final case class AboutOptions()

object About extends MorphirCliCommand[AboutOptions]:
override def group = "Information"
def runEffect(options: AboutOptions, remainingArgs: RemainingArgs) =
defer {
println("_____________________________________________________________")
println("Morphir CLI - A command line interface for Morphir.")
println("_____________________________________________________________")

val table = t2.TableBuilder()
.add("#", "Property", "Value")
.add("1", "Version", BuildInfo.version)
.add("2", "Scala Version", BuildInfo.scalaVersion)
.add("3", "Build Time", BuildInfo.buildTime)
.add("4", "Java Version", await(System.property[String]("java.version", "N/A")))
.add("5", "Java Home", await(System.property[String]("java.home", "N/A")))
.add("6", "OS", s"${await(System.property[String]("os.name"))} ${await(System.property[String]("os.version"))}")
.add("7", "User", await(System.property[String]("user.name", "N/A")))
// TODO: Add info about Morphir Home and Setup state
.build()

// Create table writer with supplied configuration
val writer = t2.TableWriter(
"ansiColorEnabled" -> "true",
"tableBorderColor" -> "cyan",
"tableHeaderColor" -> "black,yellowBackground",
"bodyRuleColor" -> "yellow",
"rowHeaderEnabled" -> "true",
"rowHeaderColor" -> "bold,cyan",
"maxValueSize" -> "60",
"truncateEnabled" -> "false"
)

writer.write(java.lang.System.out, table)
}
46 changes: 46 additions & 0 deletions morphir/cli/src/org/finos/morphir/cli/commands/config.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.finos.morphir.cli.commands

import caseapp.*
import kyo.*
import org.finos.morphir.cli.{given, *}
import caseapp.core.Arg

@HelpMessage("Work with Morphir related configuration")
final case class ConfigOptions()

object Config extends MorphirCliCommand[ConfigOptions]:
override def group = "Setup & Configuration"
def runEffect(options: ConfigOptions, remainingArgs: RemainingArgs) =
defer {
pprint.log("ConfigOptions:")
pprint.log(options)
pprint.log("Remaining Args:")
pprint.log(remainingArgs)
}

@HelpMessage("Set configuration options")
final case class ConfigSetOptions(key: String)
object ConfigSet extends MorphirCliCommand[ConfigSetOptions]:
override def names: List[List[String]] = List(List("config", "set"))
override def group = "Setup & Configuration"
def runEffect(options: ConfigSetOptions, remainingArgs: RemainingArgs) =
defer {
pprint.log("ConfigSetOptions:")
pprint.log(options)
pprint.log("Remaining Args:")
pprint.log(remainingArgs)
}

@HelpMessage("Get configuration options")
@ArgsName("key")
final case class ConfigGetOptions()
object ConfigGet extends MorphirCliCommand[ConfigGetOptions]:
override def names: List[List[String]] = List(List("config", "get"))
override def group = "Setup & Configuration"
def runEffect(options: ConfigGetOptions, remainingArgs: RemainingArgs) =
defer {
pprint.log("ConfigGetOptions:")
pprint.log(options)
pprint.log("Remaining Args:")
pprint.log(remainingArgs)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package org.finos.morphir.cli.command
package org.finos.morphir.cli.commands
import org.finos.morphir.*
import caseapp.*
import org.finos.morphir.cli.given
import kyo.*
import org.finos.morphir.cli.{given, *}

@HelpMessage("Start up a web server and expose developer tools through a web UI.")
final case class DevelopOptions(
Expand All @@ -16,9 +17,11 @@ final case class DevelopOptions(
projectDir: FilePath = FilePath.parse(os.pwd.toString)
)

object Develop extends Command[DevelopOptions]:
def run(options: DevelopOptions, remainingArgs: RemainingArgs): Unit =
pprint.log("DevelopOptions:")
pprint.log(options)
pprint.log("Remaining Args:")
pprint.log(remainingArgs)
object Develop extends MorphirCliCommand[DevelopOptions]:
def runEffect(options: DevelopOptions, remainingArgs: RemainingArgs) =
defer {
pprint.log("DevelopOptions:")
pprint.log(options)
pprint.log("Remaining Args:")
pprint.log(remainingArgs)
}
Loading

0 comments on commit 2753034

Please sign in to comment.