Run Tool

A multi-purpose tool to aid developers in executing common tasks. Aiming to suit modern requirements, whilst not replicating make.

Whilst fairly stable, it is still in development and features may change

Features

  • Configuration uses YAML
  • Per project configuration file (if added at root of project)
  • Supporting a global configuration (per user)
  • Customisable targets
    • Arguments
    • Environment variables
    • Settable current working directory
    • Hooks (before and after target run)
    • Conditional runs (only run target when conditions are met)

Use Case

  • Running a project
  • Building a project
  • Run tests
  • One-off commands, e.g. downloading test data

Goals

  • Fast and easy to use
  • Human readable configuration
  • Cross-platform (for core functionality)
  • Support mono-repos
  • Support use in CI/CD

Non-Goals

  • Be a complete replacement to make

Install

Currently the only way to install is using Cargo:

From crates.io (stable releases only):

cargo install run-tool

From repository (may include unstable):

cargo install --git https://github.com/enchant97/run-tool.git

Add --tag vx.x.x to install a specific version

Configuration

This chapter will go through everything supported in a "Run Tool" configuration file.

When running "Run Tool" unless overridden it will search the current directory for a file matching the defined configuration file names. If it does not find one it will move on to the parent directory; continuing until either no parents are left or a config has been located.

After a configuration file has been found the target will run from the current working directory of the configuration file, this allows for a mono-repo to have one file at the root of the project responsible for the whole project that can be loaded from any child directory.

Configuration Files

By default these will be either .run-tool.yml or .run-tool.yaml. You may adjust this globally by using the RUN_TOOL_FILENAME environment variable or by passing as an argument when launching the app.

The File

There are many different configuration values that can be used to provide different functionality, this section documents them.

Reference

targets:
  <target_name>:
    # - optional, string
    # - give the target a description
    description: null
    # - required, string
    # - program to execute
    program: ""
    # - optional, string or array of strings
    # - arguments to give program
    args: []
    # - optional, dictionary (var_key: var_val)
    # - environment variables to give program
    env: null
    # - optional, string or array of strings
    # - path to environment files to load
    env_file: []
    # - optional, string (default to loaded config file cwd)
    # - current working directory to set for application
    cwd: null
    # - optional, array of strings
    # - other targets to run before running this one
    before_hooks: []
    # - optional, array of strings
    # - other targets to run after running this one
    after_hooks: []
    # - optional, array of dictionaries
    # checks to meet before running target (including hooks)
    run_when:
        -
          # - required, string
          # - check name
          when: ""
          # - optional, boolean
          # - whether to invert the check
          invert: false
          # - optional, dictionary
          # - extra fields to give to check (depends on specified check)
          fields: {}

Checks

Checks are used in the run_when configuration. They decide whether to run the selected target or not.

Explanations in this section will assume the check has not been inverted.

Execution OK

Will allow target to run when the execution returns a status code of success (zero).

when: exec_ok
fields:
  # required, string
  # - program to execute
  program: ""
  # - optional, string or array of strings
  # - arguments to give program
  args: []
  # - optional, dictionary (var_key: var_val)
  # - environment variables to give program
  env: null
  # - optional, string or array of strings
  # - path to environment files to load
  env_file: []
  # - optional, string (default to loaded config file cwd)
  # - current working directory to set for application
  cwd: null

Path Exists

Will allow target to run when given path exists, could mean it is a directory or file.

when: path_exists
fields:
  # - required, string
  # - path to check
  path: ""

Path Is File

Will allow target to run when given path exists and is a file.

when: path_is_file
fields:
  # - required, string
  # - path to check
  path: ""

Path Is Directory

Will allow target to run when given path exists and is a directory.

when: path_is_dir
fields:
  # - required, string
  # - path to check
  path: ""

Example

Here is an example for building a project in a mono-repo.

#
# my-project/.run-tool.yml
#

targets:
  clean-build:
    program: cargo
    args:
      - build
      - --release
    env:
        CARGO_HOME: /mnt/cache/.cargo
    cwd: backend/
    before_hooks:
      - clean

  clean:
    program: cargo
    args:
      - clean
    cwd: backend/

Global Configuration

To utilise the global configuration functionality, you can place a "Run Tool" config in your home folder shown below:

Linux/Unix

$XDG_CONFIG_HOME/run-tool/
$HOME/.config/run-tool/

Darwin (MacOS)

$HOME/.config/run-tool/

Windows

%%USERPROFILE%%/.config/run-tool/

Usage

Whilst the application has in-build help (by running run-tool help), this section will provide a rough overview of available commands.

Running A Target

run-tool run <target name>

You can also provide extra arguments to the targets executable appending to any specified in the config.

run-tool run <target name> -- --release

Viewing Config

To view the currently loaded configuration in a human readable format use this command:

run-tool config

Or view a more minimal version:

run-tool config -m

Tips

  • Add an alias in your shell, e.g. alias rt='run-tool run'
  • You can name your config either: .run-tool.yaml or .run-tool.yml

Contributions

This project is open to contributions! So long as the simple rules are followed:

  • Check existing contributions (open issues and pull requests) before posting your own
  • Contributions must be licensed under the same as the project
  • Make titles and commit messages clear, e.g. "changed x to allow for y"
  • Fits the project goals & non-goals

Modifying Checks

  • When adding a new check it should be positive e.g. "path exists" not "path missing", this allows for uniform checks since the user can set "invert" field.
  • Adding new fields is permitted
  • Removing fields unless they are deprecated is not permitted