- Proposal: LE-002
- Status: Implemented in v0.0.19
- Author: @vknabel
This proposal adds some basic subcommands to the lithia
CLI to allow user defined scripts to be executed.
Every project has specific jobs to be done. These jobs are often repetitive and can be automated. This proposal aims to provide simple access to these scripts.
Within the Potfile
, new commands that execute a specific Lithia file as a script can be defined using the pots.cmds.add
function. Additional help context can be provided inside a builder function. The command can be executed using lithia [script]
or lithia run [script]
.
cmds.add "test", { c =>
c.script "cmd/test.lithia"
c.summary "runs all tests"
c.env "LITHIA_TESTS", "1"
c.flag "verbose", { f =>
f.short "v"
f.summary "verbose logging"
}
}
cmds.add "build", { c =>
c.bin "docker"
c.args ["build", "-t", "my-image", "."]
c.summary "builds the project using docker"
}
Similar, the pots.cmds.bin
function can be used to define a command that executes a binary. Under the hood /usr/bin/env
will be used to lookup the binary. In case of lithia
itself, the currently executed lithia
binary will be used.
cmds.bin "example", ["lithia", "test"]
The user adds the commands of their choice to their Potfile
.
The Lithia interpreter will now execute it and will proceed working on the internal store structure.
The execution of the Potfile takes place in a sandboxed environment which whitelists possible external module imports to avoid direct access to the file system and other resources. It will also be time-restricted to at most one second using Go context.Context
.
To avoid privilege escalation, scripts declared in the Potfile
with overridden LITHIA_TIMEOUT
or LITHIA_EXTERNAL_DEFINITIONS
, can only restrict the environment further. They cannot allow more access to the environment.
Under the hood, the default bin
target will be lithia itself.
Adds a new module pot.cmds
:
- func
add name, conf
- returns aCommand
. - data
CommandBuilder
- func
summary text
- sets the summary text for the command. - func
flag name, conf
- adds a flag to the command. - func
env name, value
- adds an environment variable to the command. - func
bin name
- sets the binary to be executed. - func
script path
- sets the script to be executed. - func
args args
- sets the arguments to be passed to the binary.
- func
- data
FlagBuilder
- func
short name
- sets the short name of the flag. - func
summary text
- sets the summary text for the flag. - func
default value
- sets the default value for the flag. - func
required bool
- sets the flag to be required.
- func
- data
Command
- let
name
- the name of the command. - let
summary
- the summary text of the command. - let
flags
- a dict of flags. - let
envs
- a dict of environment variables. - let
bin
- the name of the binary to be executed. - let
args
- the arguments to be passed to the binary.
- let
- data
Flag
- let
name
- the name of the flag. - let
short
- the short name of the flag. - let
summary
- the summary text of the flag. - let
default
- the default value of the flag. - let
required
- whether the flag is required.
- let
Other non-final additions are internal and include:
- let
store
- a stateful application store which stores the commands and in the future more commands.
pot [script]
,lithia run [script]
orlithia pot [script]
But also regarding the api used in the Potfile
itself, there was an alternative considered:
let testCmd = cmds.script "test", "cmd/test.lithia"
testCmd.summary "runs all tests"
testCmd.flag "verbose", "verbose logging"
testCmd.env "LITHIA_TESTS", "1"
npm run [script]
, yarn [script]
, swift run [target]
and
archery [script]
.