Coder Social home page Coder Social logo

tusk's Introduction

Tusk

GitHub release CircleCI AppVeyor license Gitter

Tusk is a yaml-based task runner. By creating a tusk.yml in the root of a repository, Tusk becomes a custom command line tool with minimal configuration.

Details on the usage and configuration options can be found in the project documentation.

Features

  • Customizable: Specify your own tasks and options with support for command-line flags, environment variables, conditional logic, and more.
  • Explorable: All the help you need to get started is available straight from the command line. Help documentation is generated dynamically, and support for Bash and Zsh tab completion is available.
  • Accessible: Built for usability with a simple YAML configuration, familiar syntax for passing options, Bash-like variable interpolation, and a colorful terminal output.
  • Zero Dependencies: All you need is a single binary file to get started on Linux, macOS, or Windows.

Getting Started

Installation

Go

With Go 1.21+ installed:

go install github.com/rliebz/tusk@latest

Homebrew

On macOS, installation is also available through homebrew:

brew install rliebz/tusk/tusk

With Homebrew, tab completion is installed automatically.

Compiled Releases

The latest version can be downloaded from the releases page.

To install automatically:

curl -sL https://git.io/tusk | bash -s -- -b /usr/local/bin latest

To pin to a specific version, replace latest with the tag for that version.

To install to another directory, change the path passed to -b.

Installing Tab Completion

For bash:

tusk --install-completion bash

For fish:

tusk --install-completion fish

For zsh:

tusk --install-completion zsh

Completions can be uninstalled with the --uninstall-completion flag.

Usage

Create a tusk.yml file in the root of a project repository:

tasks:
  greet:
    usage: Say hello to someone
    options:
      name:
        usage: A person to say "Hello" to
        default: World
    run: echo "Hello, ${name}!"

As long as there is a tusk.yml file in the working or any parent directory, tasks can be run:

$ tusk greet --name friend
Running: echo "Hello, friend!"
Hello, friend!

Help messages are dynamically generated based on the YAML configuration:

$ tusk --help
tusk - the modern task runner

Usage:
   tusk [global options] <task> [task options]

Tasks:
   greet  Say hello to someone

Global Options:
   -f, --file <file>  Set file to use as the config file
   -h, --help         Show help and exit
   ...

Individual tasks have help messages as well:

$ tusk greet --help
tusk greet - Say hello to someone

Usage:
   tusk greet [options]

Options:
   --name <value>  A person to say "Hello" to

Additional information on the configuration spec can be found in the project documentation.

For more detailed examples, check out the project's own tusk.yml file.

Contributing

Set-up instructions for a development environment and contribution guidelines can be found in CONTRIBUTING.md.

tusk's People

Contributors

ansemjo avatar dependabot[bot] avatar rliebz avatar three7six avatar wolfulus avatar zliebowitz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

tusk's Issues

evaluate environment variables in shared options

Is your feature request related to a problem? Please describe.

For in house tools which we wrap using tusk, we would like to select different configuration profiles (and other things) by default based on the USERNAME or LOGNAME of the current user. And yet allow that choice to be overriden. We would ideally like other environment variables to be possible also.

Describe the solution you'd like

Environment variables referenced in the shared options would be evaluated in the default values. It is ok if this is done 'lazily', when the shared options are referenced by a task.

options:
  configname:
    usage: "selected configuration"
    short: "c"
    default: "dev-${USER}"

Additional context
The ability to evaluate shell expressions would also be welcome.

plugin support?

dose tusk support develop custome plugin like ansible plugin?

Add support for sub commands

Is your feature request related to a problem? Please describe.
No

Describe the solution you'd like
I would like to have a feature where I can add a subcommand to a task, like you see with kubectl or gcloud.

So that I can do the following
customctl command subcommand --argument value

Additional context
Just like

kubectl config get-contexts

If there is any other way I can do this, please let me know :-)

windows

i need a make golang equivalent for both mac and windows.

Does this work on windows ?

Support unsetting environment variables globally

and can't decide if environment unsetting should be a feature.
because sh support, can prepend unset {no,NO,all,ALL,http,HTTP}{s,}_{proxy,PROXY}; to command, which is cool because it's terse, but uncool because it's not consistent or as orthogonal as the existing environment function (can't use globally).

Question: when variable set/unset

related to #15, but about options for a specific task

Currently we can do things if an environment variable is not set:

tasks:
  foo:
    run:
      when:
        environment:
          BAR: ~
      command: do-thing-when-no-bar

But how can we do the same for options on a task that are not set?

tasks:
  foo:
    options:
      bar:
        usage: visit them all
    run:
      when:
        option:
          bar: ~
      command: do-thing-when-no-bar

Provide help documentation for argument usage

Related: #12

While positional arguments are supported, the command-line help documentation is extremely minimal.

Given the following config:

tasks:
  greet:
    args:
      name:
        usage: The person to greet
    run: echo "Hello, ${name}!"

We see the following documentation:

$ tusk greet --help
tusk greet

Usage:
    tusk greet <name>

Documentation should include the argument usage in a format similar to how flags are currently printed. For example:

$ tusk greet --help
tusk greet

Usage:
    tusk greet <name>

Arguments:
    name  The person to greet

Tab completion for customcli (alias for tusk)

I have installed tab completion using tusk -f /customcli/Tusk.yml --install-completion, so the tasks are completed when I type tusk -f /customcli/Tusk.yml

But I have an alias voor my CLI.

alias customcli='tusk -f /customcli/Tusk.yml'

How can I enable tab completion for my customcli, so my tasks will be available after customcli task?

Quiet mode on tusk.yml

Is your feature request related to a problem? Please describe.

There are some sensitive commands that shouldn't be logged to the console. But we're still interested in seeing logs from other commands.

Describe the solution you'd like

Provide a way permanently supress tusk output (inside root yaml, without having to pass -q) to supress logging and a way to override the output of specific commands inside run keys.

Import arbitrarty YAML/JSON

Is your feature request related to a problem? Please describe.

Sometimes it would be nice to be able to import arbitrary data from other YAML (or JSON) files, and use values from these files without having to duplicate configuration.

One concrete example that we will look at below, is how to use a config files generated by appctl. This file looks something like this:

cluster_name: <name>
project: <project>
compute:  # choose "region" or "zone"
   region: <region>
namespace: <namespace>
no_pr_approval_required: false

It would be nice to be able to extrat and work with these variables in tusk in one way or another.

Describe the solution you'd like

It's not important to me how this works. But here is one possible syntax:

imports: # new section imports
   <name>: # name of import
     path: <file> # path to file to import
     expose: # map of values to expose, and what to expose them as.
       <local name/alias>: <dotted path in file>

Full example:

imports: # new section imports
  delivery-dev:
    path: delivery/envs/dev.yaml
    expose: &delivery-expose # Using a YAML anchor to keep things DRY
      cluster: cluster_name
      project: project
      region: compute.region
      namespace: namespace
 delivery-staging: 
    path: delivery/envs/staging.yaml
    expose: *delivery-expose
  delivery-prod:
    path: delivery/envs/prod.yaml
    expose: *delivery-expose
    
tasks:  
  use-context:
    usage: "Switch to the cluster belonging to a particular deployment"

    args:
      env:
        usage: Name of environment
        values:
          - dev
          - staging
          - prod

    run:
      - command: kubectl config use-context gke_${delivery.project}_${delivery.region}_${delivery.cluster}
         with-alias: # another feature to alias variables (not strictly needed for this, just reduce code).
           delivery: "imports.delivery-${env}"

The final run line without an "alias" feature:

    run:
      - command: kubectl config use-context gke_${imports.delivery-dev.project}_${imports.delivery-dev.region}_${imports.delivery-dev.cluster}
         when:
         - {"equal":  {"env": "dev"}
      - command: kubectl config use-context gke_${imports.delivery-staging.project}_${imports.delivery-staging.region}_${imports.delivery-staging.cluster}
         when:
         - {"equal":  {"env": "staging"}
      - command: kubectl config use-context gke_${imports.delivery-prod.project}_${imports.delivery-prod.region}_${imports.delivery-prod.cluster}
         when:
         - {"equal":  {"env": "prod"}

The purpose of this syntax example is not to propose an actual syntax, but to explain the feature.

Additional context

Possible concern with example syntax:

  • As options are not scoped in ${} clauses, an option named "imports" would conflict with the imports section.

Possible solutions:

  • Make imports part of options.
  • Include imports in same namespace as options and set a priority; e.g. global option over imports, local options over global options. I.e. we refer to "${delivery-dev}" not "${imports.delivery-dev}".

When "OR" equals query

my task has a list of options, I want to run the task if either of two are provided. It doesn't appear to be possible to add multiple "equal" checks to a single When statement.

The documented example covers "if os AND/OR an option is equal, but not a case of multiple equals.

Is these another way this can be done?

    options:
      check:
        default: all
        values: 
          - all
          - option1
          - option2
    run: 
      - when:
          - equal: {check: all}
             equal: {check: option1} # cannot unmarshal if this exists.
        command: echo hi  

Allow adding generic global variables

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

Argument ordering

Describe the bug
I'm having issues with arguments... seems like its not being sorted/passed properly.

If I run several times a command for example command arg1 arg2 and arg1 accepts a list "x, y, z", it will eventually throw me an exception saying
Value "bla" for argument arg1 must be one of [x, y, z]

To Reproduce
Just use args with a list of values, run sevenral times

Expected behavior
Always have the same order passed to the task

Environment

  • OS: Windows
  • Version (tusk --version): 0.4.6

Compiled custom binary export

Is your feature request related to a problem? Please describe.

I'm really interested about your CLI metadata feature, giving me the possibility to create a good QoL boosted cli tool with ease, and thanks for that! ๐Ÿ‘

But the current solution has some lack in my opinion:

  • You must setup an alias to a tusk command. It may be not easier to anybody not familiar with the Linux CLI env.
  • You are dependent of a tusk.yml configuration file. The user will have to get the configuration file manually or via a custom script. It's kind of a TOIL thing.

Describe the solution you'd like

I would like the possibility to "compile" a dependencies/configuration free binary to be ready to use "out of the box" without having to deal with the go language.

Something like that:

$ tusk -f /path/to/tusk.yml --export=mycli
$ ./my-cli
mycli - A custom aliased command-line application

Usage:
  mycli [global options] <task> [task options]

Tasks:
  ...

Would not it be awesome?! ๐Ÿ˜„

Additional context

I'm currently not a Go expert, but I might thing this is gonna help : https://github.com/gobuffalo/packr/tree/master/v2

If you think this as no place to take on tusk, a cook book may be written instead.

Regards

Support for any/all behavior with `when` clauses

Currently, within when clauses, some list behavior works if any of some list/map are true, while other behavior requires all of the list/map to be true. This is not as composable or intuitive as it should be.

The current proposed solution is that when will accept a list of when clauses, all of which must pass for the when clause to be considered true. Within each when item, any of the conditionals can be true for that item to be true.

Like the rest of the spec, one-item lists should be implicit.

# Any file
when:
  exists:
    - one.txt
    - two.txt

# All files
when:
  - exists: one.txt
  - exists: two.txt

I'm currently undecided on whether command should accept a list, since this is is inconsistent with other uses of command and may cause confusion. Most likely it will remain unimplemented in the first iteration of this.

Because this is a breaking change that could silently alter behavior, the following steps should be taken, in order, while keeping the README up to date:

  • Add support for lists of when clauses, which all must evaluate to true.
  • For the following features that used to require all to pass, add a deprecation warning in favor of the new syntax:
    • Lists of command
    • Lists of exists
    • Lists of equal (currently undocumented)
    • Lists of not_equal (currently undocumented)
    • Combining different conditions (e.g., exists + equal + command) in a single when item
  • After sufficient time, replace the behavior for the items above by passing the when item if any of the conditions pass.

Arguments/Parameters

Is there a way to get any parameter passed to a task?
I have this task:

  app: 
    usage: access app container and execute commands 
    args: 
      command: 
        usage: the command that app will run 
    run: docker-compose exec app ${command} 

And when I try to rund this task with tusk app php artisan I got this error Error task "app" requires exactly 1 args, got 2.
I have managed to fix this problem with tusk app "php artisan", but I want to know if there is a way like in shell script with $@ to get all parameters?

Support of variables and foreach

Is your feature request related to a problem? Please describe.
Id like to see an option to set variables like real option values as shared variable.

Example:

vars:
  enabled-environments: &enabled-environments
    - dev
    - prod
    - all

tasks:
  build:
    options:
      environment:
        values: *enabled-environments
    run:
      - when: 
            equal: { environment: 'all' }
         task: build-all
      - when:
          not-equal: { environment: 'all' }
        run:
           yarn build:${environment}
  build-all:
    run:
      - foreach:
           list: ${vars.enabled-environments}
           as: current-environment
           task: # or run:
              name: build
              options:
                 environment: ${current-environment}

Describe the solution you'd like
This makes it easier to build a cli with an include all or specific option.

Allow changing working directory as configuration

This is a bit of a design challenge due to the number of places that the working directory can be defined, and the ambiguity of which definition should take precedent and how it should propagate to nested members.

Here is my current proposal, in order from lowest to highest priority to determine directory (higher numbers override lower numbers):

  1. At the root of the config file, which would change the default working directory for all commands.
  2. By command-line, as tusk -d or tusk --directory, which would have the same properties as and override 1.
  3. At the task level, which would change the working directory for all task options and commands, but not global options or sub-tasks.
  4. At the sub-task level, to override the default directory for the sub-task which is being run.
  5. At the command level, only for that specific command.

Alternatively, it is possible to do one of the following combinations of the above for a slightly less complicated spec:

  • 1
  • 1, 2
  • 1, 2, 5
  • 1, 3
  • 1, 3, 4
  • 1, 5
  • 5

All relative paths will be relative to tusk.yml and not the working directory.

The YAML syntax for those scenarios would look like this:

# 1
directory: path/to/foo

options:
  global-opt:
    default:
      command:
        # Could also be `text`, `exec`, `script`, etc.
        string: pwd
        # 5
        directory: path/to/foo

tasks:
  sub-task:
    # 3
    directory: path/to/foo
  main-task:
    directory: path/to/foo
    run:
      task:
        name: sub-task
        # 4
        directory: path/to/foo

And from the CLI:

# 2
tusk --directory path/to/foo main-task

"sh": executable file not found in %PATH%

I'm trying to use tusk on WIndows 10, but I'm getting this error:

exec: "sh": executable file not found in %PATH%
Error exec: "sh": executable file not found in %PATH%

this is my tusk (yml) file tusk.txt.
When I try to run tusk setup I got the error above. I checked if I could run all the commands manually and I can, So I think this error is related to tusk. I hope someone can help me. ๐Ÿ‘

Add when (files) changed conditoin

If one could easily determine if a task is up-to-date, tusk could potentially become more useful as a build tool, especially if such a feature is later paired with a dependency calculation system.

tasks:
  build:
    options:
      targetOS:
      targetArch:
    when:
      changed:
        - file.txt
        - **/iin_root_folder_or_any_level_down.txt
        - */one_folder_down.txt

If one could hash these files and store it using the task ane and passed in options (with a predictable sorting) as a key, that would be the most useful approach to calculate the difference I think. Maybe something like this:

#.tusk/cache
build{targetArch:amd64,targetOs:linux}|<sha1>

PS! Not using tusk atm., I use another tool https://github.com/go-task/task, so this is just a friendly suggestion. I like the design of tusk so far though:-)

Expose shared options from sub-task to CLI flags

Currently, a shared option is only exposed if the task that is directly invoked requires that option. While task-specific options can be set on the sub-task, there is no way to allow a shared option to be configurable from the parent task unless the parent task happens to use it.

For example, for the following config file, while single and double are configurable, mytask is not:

options:
  foo:
    default: hello

tasks:
  single:
    run: echo ${foo}
  double:
    run: echo ${foo} ${foo}
  mytask:
    run:
      - task: single
      - task: double

To preserve the ability to dynamically call sub-tasks through interpolation, it is not possible to know what sub-task shared options will be needed for a task when help documentation is generated.

One possible solution is to allow tasks to list shared options that should be exposed, most likely using one of these syntaxes:

options:
  foo:
    default: hello

tasks:
  syntax-a:
    options:
      foo: ~

  syntax-b:
    expose: foo  # takes a string or list

support for user-prompt

Is your feature request related to a problem? Please describe.
I'd like to see an option where a user is asked for an option in order to make the cli interactively.

Describe the solution you'd like

tasks: 
  setup:
    run: 
      - prompt:
           msg: "Please enter an api key:"
           type: string
           default: "foobar"
           var: api-key
      - command: |
           echo "export API_KEY=\'"${apiKey}\"" >>> ~/.bashrc
      - prompt: 
           msg: "Do you want to delete /home?"
           type: boolean
           default: true
           var: delete-home
       - when:
            equal: { delete-home: true }
            - command: rm -rf /home

Result:

user@machine # tusk
Please enter an api key [foobar]: barfoo
Do you want to delete /home? [Y/n]: n

Only silence the Tusk output but not the output of exec/command/run

Hi, all! First of thanks for this great tool!

I don't know if this is a feature already, but is it possible to disable the output of Tusk but not the output of the command?

Let's say I have this task:

  ls:
    run:
      exec: ls -la

The output is:

ls $ ls -la
total 16
drwxrwxrwx    2 root     root          4096 Mar 14 12:26 .
drwxrwxrwx    2 root     root          4096 Mar 14 12:22 ..
-rwxr-xr-x    1 root     root          4169 Mar 15 10:13 tusk.yml

I don't want the first line to be print, but I want the result of exec printed. When I use -s then nothing is shown.

The only thing I want is

total 16
drwxrwxrwx    2 root     root          4096 Mar 14 12:26 .
drwxrwxrwx    2 root     root          4096 Mar 14 12:22 ..
-rwxr-xr-x    1 root     root          4169 Mar 15 10:13 tusk.yml

Print default values and values list in initial help docs

Is your feature request related to a problem? Please describe.
When running a help command on a values arg or option, no information about possible values is shown. The user has first to fail the command to see the values. I'd like to see them right when asking tusk for help, not when trying to execute and fail.

Also it'll be nice if I could define a usage info for values.

This also concerns the default value, that is never stated.

Describe the solution you'd like

Options:
   -e, --environment <value>  Environment to build the artifact agains. (Default: local) 
                              Valid values: [ stub (USAGE_INFO), local (USAGE_INFO), prod (USAGE_INFO) ]

Additional context

Lint Option

A tusk lint option would be useful for verifying complex Tusk files. I'm not sure how this might be implemented though since tusk lint could potentially be a task a user has written.

Add tab completion command to gobal help output

Is your feature request related to a problem? Please describe.
Keep forgetting what the command for enabling tab completion is.

Describe the solution you'd like
add it to the output of tusk --help:

> tusk --help
...
Global Options:
   -f, --file <file>  Set file to use as the config file
   -h, --help         Show help and exit
   -q, --quiet        Only print command output and application errors
   -s, --silent       Print no output
   -V, --version      Print version and exit
   -v, --verbose      Print verbose output
   --install-completion [zsh|bash] Add tab completions to your shell profile/thing/magic/world

p.s. Love this tool.
thankyou

Allow specifying shell/interpreter

Is your feature request related to a problem? Please describe.

Using the local default shell for Tusk files hurt portability. It is especially problematic for users who are not using a Bourne Compatible shell (e.g. users using fish) if the tusk file assumes a Bourne Shell compatible variant.

Describe the solution you'd like

To opt in for somewhat better portability, it should be possible to describe the shell interpreter to use. It should be possible to specify the interpreter for the task level, or to set a default for the full tusk file (used by all tasks that don't override it).

interpreter: /usr/bin/sh # override default

tasks:
    foo:
        interpreter: /usr/bin/bash # override default

The per task interpreter definition is especially important when using "include" for tasks.

The specified interpreter must be used not only for run members, but for any commands run as part of setting defaults for options and arguments as well.

Additional context

In an environment where som users are using e.g. "fish", some "bash" and some "zsh" as their default shell, being able to specify in tusk which shell interpreter to use would be extremely useful. This is not about offering any form of complete portability, but about being able to improve it.

Option array type

Thoughts on adding a new array option type. Which would then be an array of one of the existing types.

Given the following example task definition:

run-p:
  private: true
  usage: Parallel execution helper task
  options:
    commands:
      type: string
      required: true
    jobs:
      type: string
      default: 100%
  run: |
    parallel \
      --jobs ${jobs} \
      --keep-order \
      --line-buffer \
      --halt now,fail=1 \
      {} ::: ${commands}

And an example of how I am using it:

foo:
  usage: Runs some things in parallel
  run:
    task:
      name: run-p
      options:
        commands: '
          "ping -c 4 8.8.8.8"
          "ping -c 4 8.8.4.4"
        '

While this works and does the job for now, it would be nice if I could supply an array of strings to the task like this:

foo:
  usage: Runs some things in parallel
  run:
    task:
      name: run-p
      options:
        commands:
          - ping -c 4 8.8.8.8
          - ping -c 4 8.8.4.4

And then an example of what the run-p task definition might look like:

run-p:
  private: true
  usage: Parallel execution helper task
  options:
    commands:
      type: array
      required: true
      element-type: string
      delimiter: ","
    jobs:
      type: string
      default: 100%
  run: |
    parallel \
      --jobs ${jobs} \
      --keep-order \
      --line-buffer \
      --halt now,fail=1 \
      {} ::: \"$(X="${commands}"; echo $${X//,/\" \"})\"

conditional environment?

tasks:
  build_providers:
    run:
        when:
          os: osx
        environment:
          DRONE_ARCH: darwin/amd64
    run:
      - command: mkdir -pv ${DRONE_ARCH}
      - command: ./go_buildif.sh github.com/terraform-providers/terraform-provider-http

alternatively, some kind of coalsece(ala tf) string list construct? or something to set a default if unset in the environment clause?
thought would be nice to have a tusk task that works in ci as well as local dev if you don't want to wrap in drone containers.
idk. i'm probably going to go back to original idea of breaking tasks and drone pipeline stage commands out into scripts instead. was original plan but thought tusk tasks seemed betterer.
probably is. it's not a build system or logic system, it's a task runner.

Bash Traps, on-failure tasks

I find my self doing this sort of thing:

command: >-
  set -eo pipefail;
  function cleanup {
    rm -rf /foo/bar
  };
  trap cleanup EXIT;
  run commands that might fail...

Would be nice to be able to do something like:

command:
  execute: foo
  on-failure: bar

Support positional arguments

A good implementation of this is likely not possible until the interpolation strategy is refactored as described in #11 due to the issue of handling arguments for sub-tasks.

The syntax would look like this:

tasks:
  one:
    arguments: # args?
      foo:
        usage: This is a foo
        type: string
      bar:
        usage: This is a bar
    run: echo "Arguments: ${foo} ${bar}"
  two:
    run:
      task:
        name: one
        arguments:
          - foovalue
          - barvalue

And it should have the following properties:

  • The arguments defined should be clear in the generated help documentation.
  • An argument cannot share a name with an option for that task or a global option.
  • There is no such thing as a global argument.
  • All arguments are parsed on the command-line in the order that they are defined in the YAML.
  • All arguments are passed to sub-tasks in the order that they are defined in the YAML.

For the initial implementation, it is probably easier to make every argument which is defined be required. The syntax described above should not prevent optional arguments with default values from being supported in the future.

Default values from subtask output

Is your feature request related to a problem? Please describe.

aws login

  • our aws cli is in a docker container
  • windows machines require win-bash, but this causes problems for running tusk as command parameter in options default.

  aws:
    args:
      command:
        usage: command to pass to aws cli
    run:
      - command:
          - >-
            docker run --rm -it
            -w /app
            -v ${HOME}${USERPROFILE}/.aws/:/root/.aws/
            -v ${PWD}:/app/
            <repo>/awscli
            ${command}

  aws:ecr-get-login:
    run:
      task:
        name: aws
        args: >-
          aws ecr get-login-password --region <region>

  aws:ecr-login:
    options:
      login:
        private: true
        default:
          command: tusk aws:ecr-get-login
    run:
      - echo ${login} | docker login --username AWS --password-stdin <id>.dkr.ecr.<region>.amazonaws.com

Describe the solution you'd like

options[key].default currently can have command, we'd like also to have the same task signature as run

  aws:ecr-login:
    options:
      login:
        private: true
        default:
          task:
            name: aws:ecr-get-login
    run:
      - echo ${login} | docker login --username AWS --password-stdin <id>.dkr.ecr.<region>.amazonaws.com

Additional context

Set required tusk version in the tusk file

We share tusk files in some of our projects.

It would be really nice if I could declare at the top of the tusk file the minimum version required.

I've recently added "command.Print", but would like to be able to advise users they need to update

Require flags to be passed explicitly to sub-tasks

Currently, the behavior is that flags available to a sub-task will be automatically propagated to any task that calls it. The desired future behavior is that sub-tasks will use their defaults unless explicitly overridden.

The syntax would look something like this:

tasks:
  pre-task:
    options:
      foo:
        default: foodefault
  main-task:
    run:
      task:
        name: pre-task
        options:
          foo: override

For any task main-task where its sub-task has an option foo:

  • When calling tusk main-task, the --foo flag would not be visible unless explicitly defined in main-task as an option.
  • If foo is not overridden in the configuration, it will use the default value for the sub-task.
  • Interpolation will happen independently for main-task and its sub-task. This means they can both define an option foo that can have different defaults and evaluate to different values at run time.

The config syntax can be backward compatible if name is the implicit default for a task run action. The following two snippets would then be equivalent:

# Option 1
task: pre-task

# Option 2
task:
  name: pre-task

This would also allow an easy extension of sub-task configuration, should other options become available. Below are some theoretical examples:

run:
  task:
    name: pre-task
    options:
      foo: foovalue
    args:
      - argvalue
    directory: path/to/execute

Because this removes the automatic exposing of sub-task options, it will be a breaking change for the CLI.

Support for conditional requirement of options

Is your feature request related to a problem? Please describe.
Depending on the options and args given I'd like to require additional options. For example, I have a build task that requires an option "name" in some cases, but not in all.

The structure for "when" in tasks is great already and looks suitable to the requiring of options, too.

Describe the solution you'd like

# ...
  build:
    usage: Builds a part of this product 
    args:
      artifact:
        usage: "Type of artifact to build"
        values:
          - app
          - lib
    options:
      name:
        usage: Name of the target to build
        required:
          when:
            - { artifact: 'lib' }
# ....

Allow setting environment variables globally

Is your feature request related to a problem? Please describe.

In some cases, it may be desirable to set an environment variable that applies to every task. For example, adding $PWD/.bin to the PATH so that tasks can reference a local version of an executable.

Describe the solution you'd like

Likely another top-level key, environment, that would look like this:

environment:
  PATH: $PWD/.bin:$PATH

This would set the environment variables once at the start of task execution. It might make sense to name the key set-environment for consistency with the task option. The key difference here is that a top-level key could effectively be considered declarative (i.e., it describes the environment), where the task directive is necessarily imperative to resolve ambiguities around what the environment of a sub-task should look like.

Additional context

Related: #72

While this isn't a good fix long-term for specifying an interpreter, it is better ergonomically that what we have now while we figure out a better solution, and it covers a couple other use cases mentioned.

Overwrite Default Help Message

This is more of a question than an issue. I'm working on using tusk to act as a cli wrapper for an Ansible playbook I use. I am creating an alias so the command name better fits the project. The downside is that when the help menu is shown I still see

tusk - a task runner built with simplicity in mind

Usage:
   tusk [global options] <task> [task options]

Is it possible to overwrite this message?

Support for inclusions

Is your feature request related to a problem? Please describe.
Because complex script collections can cause very long tusk.ymls, i'd like to split up those tasks into certain files

Describe the solution you'd like

tasks:
  build: 
    include: .tusk/build.yml
  test:
    run: 
      - command: yarn test

terminating a subprocess kills tusk without running Finally block

I've got a task that runs a go binary until killed by the user, that binary is listen to SIGINT and SIGTERM in order to perform from cleanup operations.

So I understand correctly, if I start the app with Tusk, and kill it with ctrl+c, I kill Tusk, and "interrupt" is sent to my binary which does its cleanup. But Tusk gets killed and will not run its Finally code.

Is there any way I can pass the ctrl+c to the running process and not kill tusk instantly?

Get PID of spawned process

Hi,

How do I spawn a process and pass the PID back so I can kill it later?

  sleep:
    run:
    - command:
      - sleep 5 & export FOO=$! && echo $FOO
      - echo $FOO

FOO gets printed in the first line, but not the 2nd line with echo.

Thoughts?

> operator not merge strings into one line

I try to write a long command in multiline string with > operator and expecting it to merge my strings into one line ... with this behavior I don't have to worry about linebreaking in shell command.

But it has no difference between | and > , I still got line breaks.

tasks:
  composer:
    run: >
      docker run --rm -u ${UID}
        -e TERM=xterm-256color
        -v ${PWD}/server/app:/app
        -w /app
        --entrypoint "composer"
        million12/nginx-php:php70
        install 

Currently, I have to take care of line breaking myself even using > operator

tasks:
  composer:
    run: >
      docker run --rm -u ${UID} \
        -e TERM=xterm-256color \
        -v ${PWD}/server/app:/app \
        -w /app \
        --entrypoint "composer" \
        million12/nginx-php:php70 \
        install 

In case you might need it.

Go version ... I use gvm on ubuntu linux machine

$ go version
go version go1.9.2 linux/amd64

I installed tusk using the following command.

$ go get github.com/rliebz/tusk

Thanks

variable containing relative path to tusk

I have a simple task that writes out to a file, the name of which is passed as an option.

But the outputted file is relative to the tusk.yaml file not the location where the tusk command was run.

Is there a simple way (that i've missed) to automatically provide the relative path from tusk.yaml to where I am when I run the command?

command: echo "something" > ${relativePath}/${outputfile}

Support marking options as secret to avoid printing by CLI

Is your feature request related to a problem? Please describe.

While it is currently possible to avoid printing shell commands through use of the print clause, it would be nice to flag that at the variable level so it happens automatically.

Describe the solution you'd like

There could be a secret flag attached to options that would cause it to get masked when printed, either as ${varname} without interpolation or something like *****.

tasks:
  foo:
    options:
      my-password:
        usage: Secret to pass to an application
        secret: true
    run:
      command: cmd --password ${my-password}

Additional context

See #54 (comment)

make the program launch directory available as a variable

Is your feature request related to a problem? Please describe.

I want to be able to pass relative paths in options and resolve them against the current working directory of the user when they invoke tusk. So I can do things like

openssl --key ${launchdir}${userpath}

Describe the solution you'd like

A well known variable that I can reference using the existing syntax would be fine. Or a pointer to how to do this with current tusk

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.