Manifest.mf specification

Specification of manifest.mf file

What is a manifest.mf file?

A manifest.mf file is a file located at the root of your command launcher package. It describes the commands packaged in the zip file. When cola installs a package, it reads the manifest file and registers the commands in the manifest file.

Format of manifest.mf

manifest.mf is in JSON or YAML format. It contains 3 fields:

  • pkgName: a unique name of your package
  • version: the version of your package
  • cmds: a list of command definition, see command definition section

Here is an example

{
    "pkgName": "hotfix",
    "version": "1.0.0-44231",
    "cmds": [ ... ]
}

Command Definition

Command launcher is implemented with cobra. It follows the same command concepts:

Commands represent actions, Args are things and Flags are modifiers for those actions.

The best applications read like sentences when used, and as a result, users intuitively know how to interact with them.

The pattern to follow is APPNAME VERB NOUN –ADJECTIVE or APPNAME COMMAND ARG –FLAG.

Each package contains multiple command definitions. You can specify following definition for your command:

Command properties list

PropertyRequiredDescription
nameyesthe name of your command
typeyesthe type of the command, group or executable
groupnothe group of your command belongs to, default, command launcher root
shortyesa short description of your command, it will be display in auto-complete options
longnoa long description of your command
argsUsagenocustom the one line usage in help
examplesnoa list of example entries
executableyes for executablethe executable to call when executing your command
argsnothe argument list to pass to the executable, command launcher arguments will be appended to the list
validArgsnothe static list of options for auto-complete the arguments
validArgsCmdnoarray of string, command to run to get the dynamic auto-complete options for arguments
requiredFlagsnothe static list of options for the command flags (deprecated in 1.9)
flagsnothe flag list (available in 1.9+)
exclusiveFlagsnogroup of exclusive flags (available in 1.9+)
groupFlagsnogroup of grouped flags, which must be presented together (available in 1.9+)
checkFlagsnowhether check the flags defined in manifest before calling the command, default false
requestedResourcesnothe resources that the command requested, ex, USERNAME, PASSWORD

Command properties

name

The name of the command. A user uses the group and the name of the command to run it:

cola {group} {name}

You must make sure your command’s group and name combination is unique

type

There are three types of commands: group, executable, or system

An executable type of command is meant to be executed. You must fill the executable and args fields of an executable command.

A group type of command is used to group executable commands.

A system type of command is an executable command which extends the built-in command-launcher functions. More details see system package

group

The group of your command. A user uses the group and the name of your command to run it:

cola {group} {name}

You must make sure your command’s group and name combination is unique

To registry a command at the root level of command launcher, set group to empty string.

Note: command launcher only supports one level of group, the “group” field of a “group” type command is ignored.

Example

{
  ...
  "cmds": [
    {
      "name": "infra",
      "type": "group"
    },
    {
      "name": "reintall",
      "type": "executable",
      "group": "infra",
      "executable": "{{.PackageDir}}/bin/reinstall",
      "args": []
    }
    ...
  ]
}

The above manifest snippet registered a command: cola infra reinstall, when triggered, it will execute the reinstall binary located in the package’s bin folder

short

The short description of the command. It is mostly used as the description in auto-complete options and the list of command in help output. Please keep it in a single line.

long

The long description of the command. In case your command doesn’t support “-h” or “–help” flags, command launcher will generate one help command for you, and render your long description in the output.

argsUsage

Custom the one-line usage message. By default, command launcher will generate a one-line usage in the format of:

Usage:
  APP_NAME group command_name [flags]

For some commands that accept multiple types of arguments, it would be nice to have a usage that show the different argument names and their orders. For example, for a command that accepts the 1st argument as country, and 2nd argument as city name, we can custom the usage message with following manifest:

{
  ...
  "cmds": [
    {
      "name": "get-city-population",
      "type": "executable",
      "executable": "{{.PackageDir}}/bin/get-city-population.sh",
      "args": [],
      "argsUsage": "country city"
    }
    ...
  ]
}

The help message looks like:

Usage:
  cola get-city-population country city [flags]

examples

You can add examples to your command’s help message. The examples property defines a list of examples for your command. Each example contains two fields: scenario and command:

  • scenario, describes the use case.
  • cmd, demonstrates the command to apply for the particular use case.

For example:

{
  ...
  "cmds": [
    {
      "name": "get-city-population",
      "type": "executable",
      "executable": "{{.PackageDir}}/bin/get-city-population.sh",
      "args": [],
      "argsUsage": "country city"
      "examples": [
        {
          "scenario": "get the city population of Paris, France",
          "cmd": "get-city-population France Paris"
        }
      ]
    }
    ...
  ]
}

The help message looks like:

...

Usage:
  cola get-city-population country city [flags]

Example:
  # get the city population of Paris, France
  get-city-population France Paris

...

executable

The executable to call when your command is trigger from command launcher. You can inject predefined variables in the executable location string. More detail about the variables see Manifest Variables

Example

{
  ...
  "cmds": [
    {
      "executable": "{{.PackageDir}}/bin/my-binary{{.Extension}}"
    }
  ]
}

args

The arguments that to be appended to the executable when the command is triggered. The other arguments passed from command launcher will be appeneded after these arguments that are defined in args field.

Example

{
  ...
  "cmds": [
    {
      "name": "crawler",
      "type": "executable",
      "group": "",
      "executable": "java",
      "args": [ "-jar", "{{.PackageDir}}/bin/crawler.jar"]
    }
  ]
}

When we call this command from command launcher:

cola crawler --url https://example.com

It executes following command:

java -jar {{package path}}/bin/crawler.jar --url https://example.com

Note: you can use variables in args fields as well. See Variables

validArgs

A static list of the arguments for auto-complete.

Example

{
  "cmds": [
    {
      "name": "population",
      "type": "executable",
      "group": "city",
      "executable": "get-city-population",
      "args": [],
      "validArgs": [
        "paris",
        "rome",
        "london"
      ]
    }
  ]
}

Once you have configured auto-complete for command launcher, the command described above will have auto-complete for its arguments.

When you type: [cola] city population [TAB], your shell will prompt options: paris, rome, and london

validArgsCmd

A command to execute to get the dynamic list of arguments.

Example

{
  "cmds": [
    {
      "name": "population",
      "type": "executable",
      "group": "city",
      "executable": "{{.PackageDir}}/bin/get-city-population",
      "args": [],
      "validArgsCmd": [
        "{{.PackageDir}}/bin/population-cities.sh",
        "-H",
      ]
    }
  ]
}

When you type [cola] city poplution [TAB], command launcher will run the command specified in this field, and append all existing flags/arguments to the validArgsCmd.

More details see: Auto-Complete

flags

Available in 1.9+

Define flags (options) of the command. Each flags could have the following properties

PropertyRequiredDescription
nameyesflag name
shortnoflag short name, usually one letter
descnoflag description
typenoflag type, default “string”, currently support “string” and bool"
defaultnoflag default value, only available for string type, bool flag’s default is always false
requirednoboolean, is the flag required, default false
valuesnolist of values for the flag for Auto-Complete. Available in 1.10.0+
valuesCmdnolist of string. The command to call to get available values for auto-complete. Available in 1.10.0+

Example

{
   "cmds": [
    {
      "name": "population",
      "type": "executable",
      "group": "city",
      "executable": "get-city-population",
      "args": [],
      "validArgs": [
        "paris",
        "rome",
        "london"
      ],
      "flags": [
        {
          "name": "human",
          "short": "H",
          "desc": "return the human readabe format",
          "type": "bool"
        }
      ]
    }
  ]
}

exclusiveFlags

Available in 1.9+

Declare two or more flags are mutually exclusive. For example, a flag json that outputs JSON format will be exclusive to the flag text, which outputs in plain text format.

Example

{
  "cmds": [
    {
      "name": "population",
      "type": "executable",
      "group": "city",
      "executable": "get-city-population",
      "args": [],
      "validArgs": [
        "paris",
        "rome",
        "london"
      ],
      "flags": [
        {
          "name": "human",
          "short": "H",
          "desc": "return the human readabe format",
          "type": "bool"
        },
        {
          "name": "json",
          "short": "j",
          "desc": "return the JSON format",
          "type": "bool"
        }
      ],
      "exclusiveFlags": [
        [ "human", "json" ]
      ]
    }
  ]
}

groupFlags

Available in 1.9+

Ensure that two or more flags are presented at the same time.

Example

{
  "cmds": [
    {
      "name": "population",
      "type": "executable",
      "group": "city",
      "executable": "get-city-population",
      "args": [],
      "flags": [
        {
          "name": "country",
          "short": "c",
          "desc": "country name",
          "required": true
        },
        {
          "name": "city",
          "short": "t",
          "desc": "city name"
        }
      ],
      "groupFlags": [
        [ "country", "city" ]
      ]
    }
  ]
}

requiredFlags

Deprecated in 1.9, see flags property

The static list of flags for your command

Example

{
  "cmds": [
    {
      "name": "population",
      "type": "executable",
      "group": "city",
      "executable": "get-city-population",
      "args": [],
      "validArgs": [
        "paris",
        "rome",
        "london"
      ],
      "requiredFlags": [
        "human\t H\t return the human readable format",
      ]
    }
  ]
}

It declares a --human flags with a short form: -H

The flag definition string uses \t to separate different fields. A complete fields can be found in the following table

field positionfield namefield description
1flag full namethe full name of the flags, usually in format of x-y-z, note: no need to include -- in the name
2flag short nameoptional, the short name (one letter) for the flag
3flag descriptionoptional, the description of the flag name
4flag typeoptional, the flag type, one of string and bool. Default: string
5flag default valueoptional, the default value if not specified

Beside the complete form, it is also possible to have a short form:

  1. only the full name: ex. “user-name”
  2. full name + description: ex. “user-name\t the user name”
  3. full name + short name + description: ex. “user-name\t u\t the user name”

checkFlags

Whether parse and check flags before execute the command. Default: false.

The requiredFlags (deprecated in 1.9), flags, validArgs and validArgsCmd are mainly used for auto completion. Command launcher will not parse the flag and arguments by default, it will simply pass through them to the callee command. In other words, in this case, it is the callee command’s responsibility to parse the flags and arguments. This works fine when the command is implemented with languages that has advanced command line supports, like golang.

For some cases, arguments parsing is difficult or has less support, for example, implementing the command in shell script. Enable checkFlags will allow command launcher to parse the arguments and catch errors. Further more, command launcher will pass the parsed flags and arguments to the callee command through environment variables:

  • For flags: COLA_FLAG_[FLAG_NAME] (’-’ is replaced with ‘_’). Example: flag --user-name is passed through environment variable COLA_FLAG_USER_NAME

  • For arguments: COLA_ARG_[INDEX] where the index starts from 1. Example: command cola get-city-population France Paris will get environment variable COLA_ARG_1=France and COLA_ARG_2=Paris. An additional environment variable COLA_NARGS (available in 1.9+) is available as well to get the number of arguments.

Even checkFlags is set to true, command launcher will still pass through the original arguments to the callee command as well, in addition, to the original arguments, parsed flags and arguments are passed to the callee as environment variables.

Another behavior change is that once checkFlags is enabled, the -h and --help flags are handled by command launcher. The original behavior is managed by the callee command itself.

requestedResources

Under the user consent, command launcher can pass several resources to the callee command, for example, the user credential collected and stored securely by the built-in login command. The requestedResources is used to request such resources. Command launcher will prompt user consent for the first time, and pass requested resources value to the callee command through environment variable. More detail see: Manage resources

The following snippet requests to access the user name and password resources.

{
  "cmds": [
    {
      "name": "population",
      "type": "executable",
      "group": "city",
      "executable": "get-city-population",
      "args": [],
      "requestedResources": [ "USERNAME", "PASSWORD" ]
    }
  ]
}

System commands

Besides the system command defined in a system package. You can define package level system command as a lifecycle hook.

__setup__

When a package is installed, sometimes it requires some setups to make it work properly. For example, a command written in javascript could require a npm install to install all its dependencies. You can define a system command __setup__ in your package as a normal command, with type system, it will be called when the package is installed. (You can disable this behavior, by turning the configuration enable_package_setup_hook to false). You can also manually trigger it through the built-in command: cola package setup

Make sure the setup hook is idempotent, when a new version is installed the setup hook will be called again.

Example

pkgName: package-demo
version: 1.0.0
cmds:
    - name: __setup__
      type: system
      executable: "{{.PackageDir}}/hooks/setup-hook"
      args: [ "predefined-arg1", "predefined-arg2" ]
    - name: other-commands
      type: executable
      executable: "{{.PackageDir}}/scripts/other-cmd.sh"