Skip to content

Commit

Permalink
Get sbt-riddl up to standard (#175)
Browse files Browse the repository at this point in the history
* Simplify it to just run any command from string options
* Validate 3 things in 2 runs
* Provide verbose output when a command completes so we can test for it
* Fix a problem in path handling when the conf dir is in .
* Document the ways to obtain riddlc
  • Loading branch information
reid-spencer authored Sep 9, 2022
1 parent 4195dea commit 3e37000
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ object CommandPlugin {
): Either[Messages, Unit] = {
val result = loadCommandNamed(name, commonOptions, pluginsDir)
.flatMap { cmd => cmd.run(args, commonOptions, log) }
if (commonOptions.verbose) {
val rc = if (result.isRight) "yes" else "no"
println(s"Ran: ${args.mkString(" ")}: success=$rc")
}
result
}

Expand Down Expand Up @@ -309,7 +313,10 @@ abstract class CommandPlugin[OPT <: CommandOptions: ClassTag](
): OPT = {
options.inputFile match {
case Some(inFile) =>
val parent = configFile.getParent.toAbsolutePath
val parent = Option(configFile.getParent) match {
case Some(path) => path
case None => Path.of(".")
}
val input = parent.resolve(inFile)
val result = replaceInputFile(options, input)
if (commonOptions.debug) {
Expand Down
1 change: 1 addition & 0 deletions doc/src/hugo/content/audience/implementors-guide/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ availability of technical talent, strategic partners, and so on are all
extremely important and may conflict with the choices of the implementation
team and sound reactive architecture.

{{< toc-tree >}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
title: "Different Ways To Get/Use RIDDL"
description: "RIDDL documentation focused on implementors' usage"
date: 2022-08-06T10:50:32-07:00
draft: false
weight: 30
---

There are several ways to get riddl software on to your computer, depending
on how you want to work.

{{< toc >}}

## Download
This is the simplest way to get `riddlc`. It should run on Windows, Mac
and Linux. Follow these steps:
* Go to [the riddlc downloads page](https://github.com/reactific/riddl/releases)
* Select the release you want to install
* Scroll down to the "Assets" section
* Download the riddlc-{version}.zip file
* Unzip that file on your computer
* Place the riddlc-{version}/bin directory in your path

## Staged
To use `riddlc` locally and be able to update it with new changes without a
large download, use this approach:
* `git clone https://github.com/reactific/riddl.git`
* `cd riddl`
* Put the `./riddlc/target/universal/stage/bin` directory in your PATH
variable using a full path instead of "."
* Run `sbt stage` to build the program
* To update, run `git pull` from the `riddl` cloned repository directory and
rerun `sbt stage` to rebuild.

This allows you to both make local changes and pull in changes from others to
keep your local copy of `riddlc` up to date.

## Integrate With SBT

TBD.

## RiddlSbtPlugin
To use the sdt-plugin you must first have installed riddlc by one of the above
methods. This approach allows you to run `riddlc` commands from a sbt based
project. The command you configure will run first when you use the `compile`
command in sbt. Follow these steps:

* In your `plugins.sbt` file, add:
`addSbtPlugin("com.reactific" % "sbt-riddl" % "{version}"). You can find
the [available version here](https://github.com/reactific/riddl/releases)
* In your `build.sbt` file, use `enablePlugins(SbtRiddlPlugin)` on your project
* Set the following sbt settings:
* `riddlcPath := file("...")` This defaults to "riddlc" which is
appropriate if the right version is in your path; otherwise specify the
full path to the `riddlc` command
* `riddlcOptions := Seq("from", "path/to/config/file", "hugo")` This is
just an example, you can put any command or options you want in that
sequence. Use `riddlc help` to find out what commands you can use.
* To run a translator in this way, put a `riddlc.conf` file next to the top
level `.riddl` file you want to translate. The content of that file can
specify common options and the commands you want to support from
`sbt-riddl`, like the example below, taken from the
[`riddl-examples` project](https://github.com/reactifi/riddl-examples).
These files use
[Human-Oriented-CONfiguration](https://github.com/lightbend/config)

```hocon
common {
show-times = true
verbose = true
quiet = false
dry-run = false
show-warnings = true
show-missing-warnings = false
show-style-warnings = false
}
hugo {
input-file = "ReactiveBBQ.riddl"
output-dir = "target/hugo/ReactiveBBQ"
project-name = "Reactive BBQ"
site-title = "Reactive BBQ Generated Specification"
site-description = "This site provides a specification for the Reactive BBQ application as generated by riddlc"
site-logo-path = "images/RBBQ.png"
erase-output = true
base-url = "https://bbq.riddl.tech"
source-url = "https://github.com/reactific/riddl"
edit-path = "/-/blob/main/src/riddl/ReactiveBBQ"
}
validate {
input-file = "ReactiveBBQ.riddl"
```


Original file line number Diff line number Diff line change
Expand Up @@ -29,103 +29,36 @@ object RiddlSbtPlugin extends AutoPlugin {

object autoImport {

sealed trait RIDDLCOption
case object Verbose extends RIDDLCOption
case object Quiet extends RIDDLCOption
case object SuppressWarnings extends RIDDLCOption
case object SuppressMissingWarnings extends RIDDLCOption
case object SuppressStyleWarnings extends RIDDLCOption
case object ShowTimes extends RIDDLCOption

lazy val riddlcPath = settingKey[File]("Path to `riddlc` compiler")
lazy val riddlcOptions = settingKey[Seq[RIDDLCOption]]("Options for the riddlc compiler")
lazy val fileToTranslate =
settingKey[String]("Name of top level file to translate to documentation")
lazy val outDir = settingKey[File]("Path to riddlc output directory")
lazy val configFile = settingKey[File]("Path to riddlc configuration file")

lazy val riddlcOptions = {
settingKey[Seq[String]]("Options for the riddlc compiler")
}
}

import autoImport.*
override lazy val globalSettings: Seq[Setting[?]] = {
Seq(
riddlcPath := file("riddlc"),
riddlcOptions := Seq.empty[RIDDLCOption],
fileToTranslate := "top",
outDir := (target.value / "riddl" / "doc"),
configFile := (Compile / sourceDirectory).value / "riddl" /
(fileToTranslate.value + ".config")
)
}

lazy val compileTask = taskKey[Seq[File]]("A task to invoke riddlc compiler")

override lazy val projectSettings: Seq[Setting[?]] =
Seq((Compile / compile) := ((Compile / compile) dependsOn compileTask).value)
lazy val compileTask = taskKey[Unit]("A task to invoke riddlc compiler")

compileTask := {
val srcFile = (Compile / sourceDirectory).value / "riddl" / (fileToTranslate.value + ".riddl")
val execPath = riddlcPath.value
val options = riddlcOptions.value
val output = outDir.value
val configF: File = configFile.value
val log: ManagedLogger = streams.value.log
translateToDoc(execPath, options, srcFile, output, configF, log)
}
override lazy val projectSettings: Seq[Setting[_]] = Seq(
riddlcPath := file("riddlc"),
riddlcOptions := Seq("from", "src/main/riddl/riddlc.conf"),
compileTask := {
val execPath = riddlcPath.value
val options = riddlcOptions.value
val log: ManagedLogger = streams.value.log
translateToDoc(execPath, options, log)
}
)

def translateToDoc(
riddlc: sbt.File,
options: Seq[RIDDLCOption],
src: File,
outDir: sbt.File,
config: sbt.File,
options: Seq[String],
log: ManagedLogger
): Seq[File] = {
import sys.process.*
val flags = options.map {
case Verbose => "--verbose"
case Quiet => "--quiet"
case SuppressWarnings => "--suppress-warnings"
case SuppressMissingWarnings => "--suppress-missing-warnings"
case SuppressStyleWarnings => "--suppress-style-warnings"
case ShowTimes => "--show-times"
}.mkString(" ")
val command = riddlc.toString + " " + flags + " translate" + " -i " + src.toString + " -c " +
config.toString + " -o " + outDir.toString
log.info(s"Executing command: $command")
val result: String = command !!

log.info(s"Command Result:\n$result")
Seq[File](outDir)
): Unit = {
import scala.sys.process.*
val command = riddlc.toString + " " + options.mkString(" ")
val logger = ProcessLogger(println(_))
command.lineStream(logger)
}
}

/*
riddlc [parse|validate|translate] [options] <args>...
-h, --help
-v, --verbose
-q, --quiet
-w, --suppress-warnings
-m, --suppress-missing-warnings
-s, --suppress-style-warnings
-t, --show-times
Command: parse [options]
Parse the input for syntactic compliance with riddl language
-i, --input-file <value>
required riddl input file to compile
Command: validate [options]
-i, --input-file <value>
required riddl input file to compile
Command: translate [options] kind
translate riddl as specified in configuration file
kind The kind of output to generate during translation
-i, --input-file <value>
required riddl input file to compile
-c, --configuration-file <value>
configuration that specifies how to do the translation
Process finished with exit code 0
*/
40 changes: 38 additions & 2 deletions sbt-riddl/src/sbt-test/sbt-riddl/simple/build.sbt
Original file line number Diff line number Diff line change
@@ -1,2 +1,38 @@
lazy val root = (project in file(".")).enablePlugins(RiddlSbtPlugin)
.settings(version := "0.1", scalaVersion := "2.12.16")
import scala.sys.process.Process

lazy val root = (project in file(".")).enablePlugins(RiddlSbtPlugin).settings(
version := "0.1",
scalaVersion := "2.12.6",
TaskKey[Unit]("checkInfoOutput") := {
val i = Seq("--verbose", "info")
val p1 = Process("riddlc", i)
val out1 = (p1 !!).trim
println(out1)
if (!out1.contains("name: riddlc")) {
sys.error("output should contain 'name: riddlc'")
}
val plugin_version = sys.props.get("plugin.version").getOrElse("0")
if (!out1.contains(s"version: $plugin_version")) {
sys.error(s"output should contain 'version: $plugin_version")
}
val v = Seq(
"--verbose",
"--suppress-missing-warnings",
"from",
"src/main/riddl/riddlc.conf",
"validate"
)
val p2 = Process("riddlc", v)
val out2 = (p2 !!).trim
println(out2)
if (
!out2
.contains("Ran: from src/main/riddl/riddlc.conf validate: success=yes")
) {
sys.error(
"riddlc output did not contain 'Ran: from riddlc.conf validate: success=yes'"
)
}
()
}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
validate {
input-file = "./simple.riddl"
}
info {}
2 changes: 1 addition & 1 deletion sbt-riddl/src/sbt-test/sbt-riddl/simple/test
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Put in sbt-test scripted checks in this file
# See: https://www.scala-sbt.org/1.x/docs/Testing-sbt-plugins.html for options
> compile
# $ exists target/scala-2.12/foo.jar
> checkInfoOutput

0 comments on commit 3e37000

Please sign in to comment.