Skip to content

Commit

Permalink
Merge pull request #241 from viash-io/keyword_documentation
Browse files Browse the repository at this point in the history
Keyword documentation and some other improvements
  • Loading branch information
rcannood authored Sep 27, 2022
2 parents 157da5e + 476c7b0 commit cda847c
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 53 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,19 @@
- `{platform}`: the platform name (if applicable)
- `{namespace}`: the namespace of the component

## MINOR CHANGES

* Hardcoded URLs pointing to viash.io in the documentation annotations were replaced with a new keyword system
* Replaced references to "DSL" with "Dynamic Config Modding" in the `--help` output
* Added an example for Ruby based Docker setups

## BUG FIXES

* `viash ns`: Reverse exit code outputs, was returning 1 when everything was OK and 0 when errors were detected (#227).

* `viash config inject`: Fix processing of arguments when argument groups are defined (#231).
* Fixed a few typos in the CLI
* Fixed the formatting of `ns exec` documentation

# Viash 0.6.0

Expand Down
23 changes: 12 additions & 11 deletions src/main/scala/io/viash/cli/CLIConf.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,26 @@ trait ViashCommand {
short = Some('c'),
default = Some(Nil),

descr = "Modify a viash config at runtime using a custom DSL. For more information, see the online documentation."
descr = "Modify a viash config at runtime using @[config_mod](dynamic config modding)."
)
}
trait ViashNs {
_: DocumentedSubcommand =>
val query = registerOpt[String](
name = "query",
short = Some('q'),
descr = "Filter which components get selected by name and namespace. Can be a regex. Example: \"^mynamespace/component1$\".",
descr = "Filter which components get selected by component and @[namespace](namespace) name. Can be a regex. Example: \"^mynamespace/component1$\".",
default = None
)
val query_namespace = registerOpt[String](
name = "query_namespace",
short = Some('n'),
descr = "Filter which namespaces get selected by namespace. Can be a regex. Example: \"^mynamespace$\".",
descr = "Filter which namespaces get selected by @[namespace](namespace) name. Can be a regex. Example: \"^mynamespace$\".",
default = None
)
val query_name = registerOpt[String](
name = "query_name",
descr = "Filter which components get selected by name. Can be a regex. Example: \"^component1\".",
descr = "Filter which components get selected by component name. Can be a regex. Example: \"^component1\".",
default = None
)
val src = registerOpt[String](
Expand Down Expand Up @@ -94,7 +94,7 @@ trait ViashNs {
name = "config_mod",
short = Some('c'),
default = Some(Nil),
descr = "Modify a viash config at runtime using a custom DSL. For more information, see the online documentation."
descr = "Modify a viash config at runtime using @[config_mod](dynamic config modding)."
)
}
trait WithTemporary {
Expand Down Expand Up @@ -188,7 +188,7 @@ class CLIConf(arguments: Seq[String]) extends ScallopConf(arguments) {
name = "setup",
short = Some('s'),
default = None,
descr = "Which setup strategy for creating the container to use [Docker Platform only]."
descr = "Which @[docker_setup_strategy](setup strategy) for creating the container to use [Docker Platform only]."
)
val push = registerOpt[Boolean](
name = "push",
Expand Down Expand Up @@ -227,7 +227,7 @@ class CLIConf(arguments: Seq[String]) extends ScallopConf(arguments) {
val parse_argument_groups = registerOpt[Boolean](
name = "parse_argument_groups",
default = Some(false),
descr = "Whether or not to postprocess each component's argument groups."
descr = "Whether or not to postprocess each component's @[argument_groups](argument groups)."
)
}
val inject = new DocumentedSubcommand("inject") with ViashCommand {
Expand Down Expand Up @@ -261,7 +261,7 @@ class CLIConf(arguments: Seq[String]) extends ScallopConf(arguments) {
val setup = registerOpt[String](
name = "setup",
default = None,
descr = "Which setup strategy for creating the container to use [Docker Platform only]."
descr = "Which @[docker_setup_strategy](setup strategy) for creating the container to use [Docker Platform only]."
)
val push = registerOpt[Boolean](
name = "push",
Expand Down Expand Up @@ -317,7 +317,7 @@ class CLIConf(arguments: Seq[String]) extends ScallopConf(arguments) {
val parse_argument_groups = registerOpt[Boolean](
name = "parse_argument_groups",
default = Some(false),
descr = "Whether or not to postprocess each component's argument groups."
descr = "Whether or not to postprocess each component's @[argument_groups](argument groups)."
)
}

Expand All @@ -327,7 +327,8 @@ class CLIConf(arguments: Seq[String]) extends ScallopConf(arguments) {
"""Execute a command for all found Viash components.
|The syntax of this command is inspired by `find . -exec echo {} \;`.
|
|The following fields are automatically replaced:
|The following fields are automatically replaced:
|
| * `{}` | `{path}`: path to the config file
| * `{abs-path}`: absolute path to the config file
| * `{dir}`: path to the parent directory of the config file
Expand Down Expand Up @@ -392,7 +393,7 @@ class CLIConf(arguments: Seq[String]) extends ScallopConf(arguments) {
val cli_schema = new DocumentedSubcommand("cli_schema") {
banner(
"viash export cli_schema",
"""Export tje schema of the Viash CLI as a JSON""".stripMargin,
"""Export the schema of the Viash CLI as a JSON""".stripMargin,
"""viash export cli_schema [--output file.json]""".stripMargin
)
val output = registerOpt[String](
Expand Down
31 changes: 26 additions & 5 deletions src/main/scala/io/viash/cli/DocumentedSubcommand.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,27 @@ class DocumentedSubcommand(commandNameAndAliases: String*) extends Subcommand(co
var command: Option[String] = None
var description: Option[String] = None
var usage: Option[String] = None
var footerText: Option[String] = None

def banner(command: String, description: String, usage: String): Unit = {
this.command = Some(command)
this.description = Some(description)
this.usage = Some(usage)

super.banner(s"$command\n$description\n\nUsage:\n $usage\n\nArguments:")
super.banner(
s"""$command
|${removeMarkup(description)}
|
|Usage:
| ${usage.split("\n").mkString("\n ")}
|
|Arguments:""".stripMargin
)
}

override def footer(text: String): Unit = {
footerText = Some(text)
super.footer(removeMarkup(text))
}


Expand All @@ -52,6 +66,13 @@ class DocumentedSubcommand(commandNameAndAliases: String*) extends Subcommand(co
super.addSubcommand(conf)
}

def removeMarkup(text: String): String = {
val markupRegex = raw"@\[.*\]\((.*)\)".r
val backtickRegex = "`(\"[^`\"]*\")`".r
val textWithoutMarkup = markupRegex.replaceAllIn(text, "$1")
backtickRegex.replaceAllIn(textWithoutMarkup, "$1")
}

// We need to get the TypeTag[A], which changes the interface of 'opt', however since we have default values we can't just overload the methods.
// The same goes for 'trailArgs'. Not really for 'choice' but it's better to keep the same change in naming schema here too.

Expand Down Expand Up @@ -86,7 +107,7 @@ class DocumentedSubcommand(commandNameAndAliases: String*) extends Subcommand(co
optType = "opt"
)
registeredOpts = registeredOpts :+ registeredOpt
opt(name, short.getOrElse('\u0000'), descr, default, validate, required, argName, hidden, short.isEmpty, group)
opt(name, short.getOrElse('\u0000'), removeMarkup(descr), default, validate, required, argName, hidden, short.isEmpty, group)
}

def registerChoice(
Expand Down Expand Up @@ -119,7 +140,7 @@ class DocumentedSubcommand(commandNameAndAliases: String*) extends Subcommand(co
optType = "choice"
)
registeredOpts = registeredOpts :+ registeredOpt
choice(choices, name, short.getOrElse('\u0000'), descr, default, required, argName, hidden, short.isEmpty, group)
choice(choices, name, short.getOrElse('\u0000'), removeMarkup(descr), default, required, argName, hidden, short.isEmpty, group)
}

def registerTrailArg[A](
Expand Down Expand Up @@ -151,7 +172,7 @@ class DocumentedSubcommand(commandNameAndAliases: String*) extends Subcommand(co
optType = "trailArgs"
)
registeredOpts = registeredOpts :+ registeredOpt
trailArg[A](name, descr, validate, required, default, hidden, group)
trailArg[A](name, removeMarkup(descr), validate, required, default, hidden, group)
}

def toRegisteredCommand: RegisteredCommand =
Expand All @@ -160,7 +181,7 @@ class DocumentedSubcommand(commandNameAndAliases: String*) extends Subcommand(co
bannerCommand = command,
bannerDescription = description,
bannerUsage = usage,
footer = builder.foot,
footer = footerText,
subcommands = registeredSubCommands.map(_.toRegisteredCommand),
opts = registeredOpts
)
Expand Down
23 changes: 12 additions & 11 deletions src/main/scala/io/viash/functionality/Functionality.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ case class Functionality(
@example("name: this_is_my_component", "yaml")
name: String,

@description("Namespace this component is a part of. See the [Namespaces guide](/documentation/guide/component/namespaces.html) for more information on namespaces.")
@description("Namespace this component is a part of. See the @[namespace](Namespaces guide) for more information on namespaces.")
@example("namespace: fancy_components", "yaml")
namespace: Option[String] = None,

Expand Down Expand Up @@ -115,13 +115,13 @@ case class Functionality(
@description(
"""A list of arguments for this component. For each argument, a type and a name must be specified. Depending on the type of argument, different properties can be set. See these reference pages per type for more information:
|
| - [string](/documentation/reference/config/arguments/string.html)
| - [file](/documentation/reference/config/arguments/file.html)
| - [integer](/documentation/reference/config/arguments/integer.html)
| - [double](/documentation/reference/config/arguments/double.html)
| - [boolean](/documentation/reference/config/arguments/boolean.html)
| - [boolean_true](/documentation/reference/config/arguments/boolean_true.html)
| - [boolean_false](/documentation/reference/config/arguments/boolean_false.html)
| - @[arg_string](string)
| - @[arg_file](file)
| - @[arg_integer](integer)
| - @[arg_double](double)
| - @[arg_boolean](boolean)
| - @[arg_boolean_true](boolean_true)
| - @[arg_boolean_false](boolean_false)
|""".stripMargin)
@example(
"""arguments:
Expand All @@ -131,6 +131,7 @@ case class Functionality(
| description: Description of foo
| default: "/foo/bar"
| must_exist: true
| direction: output
| required: false
| multiple: true
| multiple_sep: ","
Expand Down Expand Up @@ -192,7 +193,7 @@ case class Functionality(
argument_groups: List[ArgumentGroup] = Nil,

@description(
"""[Resources](/documentation/guide/component/resources.html) are files that support the component. The first resource should be [the script](/documentation/guide/component/languages.html) that will be executed when the functionality is run. Additional resources will be copied to the same directory.
"""@[resources](Resources) are files that support the component. The first resource should be @[scripting_languages](a script) that will be executed when the functionality is run. Additional resources will be copied to the same directory.
|
|Common properties:
|
Expand Down Expand Up @@ -225,7 +226,7 @@ case class Functionality(
@example("usage: Place the executable in a directory containing TSV files and run it", "yaml")
usage: Option[String] = None,

@description("""One or more [scripts](/documentation/guide/component/languages.html) to be used to test the component behaviour when `viash test` is invoked. Additional files of type `file` will be made available only during testing. Each test script should expect no command-line inputs, be platform-independent, and return an exit code >0 when unexpected behaviour occurs during testing. See the [Unit Testing guide](/documentation/guide/component/unit-testing.html) for more info.""")
@description("""One or more @[scripting_language](scripts) to be used to test the component behaviour when `viash test` is invoked. Additional files of type `file` will be made available only during testing. Each test script should expect no command-line inputs, be platform-independent, and return an exit code >0 when unexpected behaviour occurs during testing. See @[unit_testing](Unit Testing) for more info.""")
@example(
"""test_resources:
| - type: bash_script
Expand All @@ -237,7 +238,7 @@ case class Functionality(
"yaml")
test_resources: List[Resource] = Nil,

@description("A map for storing custom annotation.")
@description("A map for storing custom annotations.")
@example("info: {twitter: wizzkid, appId: com.example.myApplication}", "yaml")
@since("Viash 0.4.0")
info: Map[String, String] = Map.empty[String, String],
Expand Down
36 changes: 29 additions & 7 deletions src/main/scala/io/viash/platforms/DockerPlatform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,28 @@ case class DockerPlatform(
@description("The working directory when starting the container. This doesn’t change the Dockerfile but gets added as a command-line argument at runtime.")
@example("workdir: /home/user", "yaml")
workdir: Option[String] = None,

@description(
"""The Docker setup strategy to use when building a container.
+
+| Strategy | Description |
+|-----|----------|
+| `alwaysbuild` / `build` / `b` | Always build the image from the dockerfile. This is the default setup strategy.
+| `alwayscachedbuild` / `cachedbuild` / `cb` | Always build the image from the dockerfile, with caching enabled.
+| `ifneedbebuild` | Build the image if it does not exist locally.
+| `ifneedbecachedbuild` | Build the image with caching enabled if it does not exist locally, with caching enabled.
+| `alwayspull` / `pull` / `p` | Try to pull the container from [Docker Hub](https://hub.docker.com) or the @[docker_registry](specified docker registry).
+| `alwayspullelsebuild` / `pullelsebuild` | Try to pull the image from a registry and build it if it doesn't exist.
+| `alwayspullelsecachedbuild` / `pullelsecachedbuild` | Try to pull the image from a registry and build it with caching if it doesn't exist.
+| `ifneedbepull` | If the image does not exist locally, pull the image.
+| `ifneedbepullelsebuild` | If the image does not exist locally, pull the image. If the image does exist, build it.
+| `ifneedbepullelsecachedbuild` | If the image does not exist locally, pull the image. If the image does exist, build it with caching enabled.
+| `push` | Push the container to [Docker Hub](https://hub.docker.com) or the @[docker_registry](specified docker registry).
+| `pushifnotpresent` | Push the container to [Docker Hub](https://hub.docker.com) or the @[docker_registry](specified docker registry) if the @[docker_tag](tag) does not exist yet.
+| `donothing` / `meh` | Do not build or pull anything.
+
+""".stripMargin('+'))
@example("setup_strategy: alwaysbuild", "yaml")
setup_strategy: DockerSetupStrategy = IfNeedBePullElseCachedBuild,
privileged: Boolean = false,

Expand All @@ -106,13 +128,13 @@ case class DockerPlatform(
@description(
"""A list of requirements for installing the following types of packages:
|
| - apt
| - apk
| - yum
| - R
| - Python
| - JavaScript
| - Docker setup instructions
| - @[apt_req](apt)
| - @[apk_req](apk)
| - @[yum_req](yum)
| - @[r_req](R)
| - @[python_req](Python)
| - @[javascript_req](JavaScript)
| - @[docker_req](Docker setup instructions)
|
|The order in which these dependencies are specified determines the order in which they will be installed.
|""".stripMargin)
Expand Down
15 changes: 9 additions & 6 deletions src/main/scala/io/viash/platforms/NextflowVdsl3Platform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,15 @@ case class NextflowVdsl3Platform(

@description(
"""Automated processing flags which can be toggled on or off:
|
| - `simplifyInput`: If `true`, an input tuple only containing only a single File (e.g. `["foo", file("in.h5ad")]`) is automatically transformed to a map (i.e. `["foo", [ input: file("in.h5ad") ] ]`). Default is `true`.
| - `simplifyOutput`: If `true`, an output tuple containing a map with a File (e.g. `["foo", [ output: file("out.h5ad") ] ]`) is automatically transformed to a map (i.e. `["foo", file("out.h5ad")]`). Default is `true`.
| - `transcript`: If `true`, the module's transcripts from `work/` are automatically published to `params.transcriptDir`. If not defined, `params.publishDir + "/_transcripts"` will be used. Will throw an error if neither are defined. Default is `false`.
| - `publish`: If `true`, the module's outputs are automatically published to `params.publishDir`. Will throw an error if `params.publishDir` is not defined. Default is `false`.
|""".stripMargin)
+
+| Flag | Description | Default |
+|---|---------|----|
+| `simplifyInput` | If `true`, an input tuple only containing only a single File (e.g. `["foo", file("in.h5ad")]`) is automatically transformed to a map (i.e. `["foo", [ input: file("in.h5ad") ] ]`). | `true` |
+| `simplifyOutput` | If `true`, an output tuple containing a map with a File (e.g. `["foo", [ output: file("out.h5ad") ] ]`) is automatically transformed to a map (i.e. `["foo", file("out.h5ad")]`). | `true` |
+| `transcript` | If `true`, the module's transcripts from `work/` are automatically published to `params.transcriptDir`. If not defined, `params.publishDir + "/_transcripts"` will be used. Will throw an error if neither are defined. | `false` |
+| `publish` | If `true`, the module's outputs are automatically published to `params.publishDir`. Will throw an error if `params.publishDir` is not defined. | `false` |
+
+""".stripMargin('+'))
@example(
"""auto:
| publish: true""".stripMargin,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ import io.viash.helpers.Circe._
import io.viash.schemas._

@description("Specify which Ruby packages should be available in order to run the component.")
@example(
"""setup:
| - type: ruby
| packages: [ rspec ]
|""".stripMargin,
"yaml")
case class RubyRequirements(
packages: OneOrMore[String] = Nil,
`type`: String = "ruby"
Expand Down
8 changes: 4 additions & 4 deletions src/viash/viash_build/config.vsh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ functionality:
- name: "--query"
alternatives: [ "-q" ]
type: string
description: "Filter which components get selected by name and namespace. Can be a regex."
description: "Filter which components get selected by component and namespace name. Can be a regex."
example: "^mynamespace/component1$"
- name: "--query_namespace"
alternatives: [ "-n" ]
type: string
description: "Filter which namespaces get selected by namespace. Can be a regex."
description: "Filter which namespaces get selected by namespace name. Can be a regex."
example: "^mynamespace$"
- name: "--query_name"
type: string
description: "Filter which components get selected by name. Can be a regex."
description: "Filter which components get selected by component name. Can be a regex."
example: "^component1$"
- name: "--tag"
alternatives: [ "-t" ]
Expand Down Expand Up @@ -69,7 +69,7 @@ functionality:
type: string
multiple: true
multiple_sep: ";"
description: "Modify a viash config at runtime using a custom DSL. For more information, see the online documentation."
description: "Modify a viash config at runtime using a custom DSL."
- name: "--no_cache"
alternatives: [ "-nc", "--no-cache" ]
type: boolean_true
Expand Down
2 changes: 1 addition & 1 deletion src/viash/viash_install/config.vsh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ functionality:
type: string
multiple: true
multiple_sep: ";"
description: "Modify a viash config at runtime using a custom DSL. For more information, see the online documentation."
description: "Modify a viash config at runtime using a custom DSL."
- name: "--tag"
alternatives: [ "-t" ]
type: string
Expand Down
Loading

0 comments on commit cda847c

Please sign in to comment.