A shell DAG is a YAML file in your DAG folder. The file name is the DAG name,
so backup_files.yml becomes the backup_files DAG. For example:
# `schedule` and `on_finished_callback` are optional.
schedule: "0 3 * * *"
tasks:
- name: backup_data
run: "tar -czf backup.tar.gz /data"
cd: "/var/backups"
downstream: [upload_backup]
save: true
- name: upload_backup
run: "aws s3 cp backup.tar.gz s3://my-bucket/"
cd: "/var/backups"
env:
AWS_PROFILE: productionEach task runs its run command in a shell. Tasks without a dependency between
them run in parallel.
Task keys
name(required): unique, non-empty task name.run(required): the shell command to execute.downstream: list of task names that run after this one.save(aliasstore_result): store the task result. Defaults tofalse.
A successful task returns %{stdout: ..., stderr: ..., exit_code: 0, status: :success}.
Execution options
cd(aliasescwd,working_dir): working directory.env: mapping of environment variables. Values may be strings, numbers or booleans; they are converted to strings.user: run the command as another user (requires permissions).group: process group. Defaults to0, a new group, so child processes are killed with the task.nice: CPU priority, from-20to19.kill_timeout: seconds to wait before force-killing the process.success_exit_code: passed to erlexec. It does not make a non-zero exit code succeed.pty,pty_echo: run in a pseudo-terminal (YAML booleans).stdout,stderr,stdin:"null","close"or a file path. Output is captured by default. Quote"null", an unquotednullis rejected.executable: shell executable to use.cgroup: Linux control group.debug: erlexec debug level.
Templates
run and string env values are EEx
templates. They are checked when the DAG is parsed and rendered when each task
attempt starts, so a retry sees the current secrets and run params. A template
can use:
run_id: the current run id.run_params: the params the run was triggered with, a map with string keys. For example,gust-cli trigger_run my_dag --run_params '{"target": "arm64"}'makesrun_params["target"]return"arm64".params: the task's own params, a map with string keys. It is empty unless the task is amap_overitem or was resumed from a wait.secret!("NAME"): the value of a Gust secret. The task fails if it does not exist.task_result!("NAME"): the saved result of another task in the same run, a map with the keys"stdout","stderr","exit_code"and"status". That task must be upstream of this one, and the task fails if it does not exist. Withoutsave: trueon it, the result is an empty map, so a key like"stdout"renders as an empty string. To fail instead, check it in the template:<%= task_result!("NAME")["stdout"] || raise "NAME saved no output" %>.Flows: an alias forGust.Flows, for anything else, such asFlows.get_run!(run_id).
tasks:
- name: build_release
run: 'cargo build --release --target <%= run_params["target"] %> --token "$TOKEN"'
cd: "/project"
env:
TOKEN: '<%= secret!("CARGO_TOKEN") %>'To use one task's output in another, save it and read it downstream:
tasks:
- name: read_version
run: "cat VERSION"
cd: "/project"
save: true
downstream: [tag_image]
- name: tag_image
run: 'docker tag myapp:latest "myapp:$VERSION"'
env:
VERSION: '<%= String.trim(task_result!("read_version")["stdout"]) %>'Pass secrets and task output through env and read them as variables in the
command, as above. A secret written straight into run is visible in ps output and can
break the command if it contains spaces or quotes. Wrap templates in single
quotes in YAML, and write <%% for a literal <%.
Validation
The whole file is checked when it is parsed, before any command starts.
Unknown keys, wrong value types, duplicate task names, unknown downstream
tasks, cycles and template syntax errors are all reported as parse errors. Using two spellings of the
same option, like cd with cwd or save with store_result, is an error.
Failures
A non-zero exit code or a signal fails the task with a
GustShell.ShellExitError, which carries the exit code, stdout, stderr and
whether the process dumped core.