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

Allow adding generic global variables #86

Open
cuotos opened this issue Mar 16, 2021 · 5 comments
Open

Allow adding generic global variables #86

cuotos opened this issue Mar 16, 2021 · 5 comments

Comments

@cuotos
Copy link

cuotos commented Mar 16, 2021

Similar to #73.

It would be nice to be able to add generic variables to the tusk file that can be used throughout, such as a command or username or anything else that gets used repeatedly

For example my file calls a command with different arguments depending on the Task being run. It would be nice to make the "root" command (the command name plus 2 args) a variable somewhere and be able to append to it as required.

This is currently possible by creating a Private Option globally, but it is a bit confusing to people new to Tusk. I would envisage that global vars would be overridden by those declared by options within a Task block, in the same way they would be with function variables shadowing global ones in most languages.

variables:
  rootCommand: "binary --option1 /always/the/same -v"
tasks:
  do-it:
    run: ${rootCommand} more arguments
  do-another:
    run: ${rootCommand} do another
@smyrman
Copy link

smyrman commented Mar 16, 2021

You can already do this by using a private global option with a default value.

@cuotos
Copy link
Author

cuotos commented Mar 16, 2021

I'm aware, and use them often, "This is currently possible by creating a Private Option globally, but it is a bit confusing to people new to Tusk."
It feels like a work around though, using an "option" to hold a fixed variable...

#73 raises the idea of this for Env vars, I believe this functionality would be good to use for variables too.

@rliebz
Copy link
Owner

rliebz commented Mar 17, 2021

I definitely hear you that private options can be confusing to use. It's hard to tell what's obvious/intuitive to folks approaching the tool from the outside, so the feedback on that front is much appreciated.

In general, my design philosophy with tusk is to try to give capabilities to do the things that you need to be able to do while keeping the learning curve as small as possible. My apprehension around introducing the concept of a global variable in addition to a global option is that it increases the surface area of the config file and mental model without providing any functionality that isn't already available. In other words, one more thing to learn.

That said, I've been pretty happy with some of the short-hand syntaxes that tusk already provides, such as being able to use strings instead of lists of strings, or strings to represent the most commonly defined field of a map, should that make sense. For example, this:

tasks:
  foo:
    run: echo foo

Is technically a shorthand for this:

tasks:
  foo:
    run:
      - command:
        - echo foo

We could imagine a similar shorthand for defining an option:

options:
  root-command: "binary --option1 /always/the/same -v"

Which in its most verbose form would translate to:

options:
  root-command:
    default:
    - value: "binary --option1 /always/the/same -v"

I have opted not defined that shorthand syntax for options specifically because I want to discourage people from using options without defining the usage text for those options. In other words, if you define an option for the CLI, I want you to also include the usage as documentation.

That philosophy doesn't really apply if those options are private, but the challenge is, you can only specify one property to a key if we're talking about a shorthand syntax. I don't think it would be intuitive to define different defaults for an option depending on whether the option was defined using the short-form or long-form syntax, such as having option-name: option-value imply private: true, so we're stuck without a short form for private variables.

Another syntax I've considered is coercing options with leading underscores in their name to private options. So _root-command would be private by default, while root-command would be public by default. Combining the shorthand syntax with the private-by-default syntax, the most terse version of what you're describing that I can imagine fitting this model would look like this:

options:
  _root-command: "binary --option1 /always/the/same -v"
  
tasks:
  do-it:
    run: ${_root-command} more arguments
  do-another:
    run: ${_root-command} do another

The problems I see with that pattern are twofold:

  • This continues to leave open a syntax to easily define an option without defining its usage statement, which leads to tusk configurations that are easier to write but harder to use.
  • I'm not necessarily convinced that this lowers the learning curve for folks.

Given that context, I'd be curious to hear your thoughts. My intuition right now is that the best approach to making this a better experience at least in the short term is improving the docs to make this usage pattern more obvious, although I realize that's not necessarily a satisfying response.

@smyrman
Copy link

smyrman commented Mar 17, 2021

If we do have a way for setting top-level variables (or constants) though, I would very much like for it to be different than options. I.e. instead of only allowing simple types, allow complex types like objects or arrays, and ideally, also imports like described in #85.

That would allow tusk to directly use configuration that is generated/intended for something else, as long as the file format is still YAML/JSON.

@smyrman
Copy link

smyrman commented Mar 17, 2021

Plausible syntax?

constants:
  _root-command: "binary --option1 /always/the/same -v"
  _root2:
     command: "binary"
     args: "--option1 /always/the/same -v"

imports: // for #85 
  _root3: config.yaml
     
tasks:
  do-it:
    run: ${_root-command} more arguments
  do-another:
    run: ${_root2.command} -needs-to-be-first ${_root2.args}
      do-another:
  run: ${_root3.command} -needs-to-be-first ${_root3.args}

Plausible precedence order:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants