In the docs
Workflow files
The format of .lorx/actions/*.yml, every key a job takes, and what each does.
For agents: this page as MarkdownA workflow is a YAML file in .lorx/actions/ in your repository, such as .lorx/actions/ci.yml. The file's name is the workflow's name. You can have as many workflows as you like: each plans its own jobs, and needs names jobs in the same file.
Each top-level key is a job. The shortest job is a name and a command:
lint: npm run lint
test: npm testThe longer form is a map:
test:
needs: [lint]
paths: ["src/**", "package.json"]
steps:
- npm ci
- name: unit tests
run: npm test
timeout: 20mOn a push, Lorx runs the jobs whose paths the push touched (every job without paths) on the branches they allow. Jobs start in levels: a job waits for everything in its needs to pass, and if one fails, the jobs that need it don't run.
Job keys
| Key | Takes | What it does |
|---|---|---|
run |
a command | The job's one step. Use run or steps, not both. |
steps |
a list | Each item is a command, or name: plus run:. Steps run in order in the same directory, and the job stops at the first that fails. |
needs |
job names | Jobs in the same file that must pass first. |
paths |
globs | Run on a push only when a changed file matches one of them. Globs are relative to the repository root. |
branches |
globs | Run on pushes to matching branches only. |
matrix |
axes and values | Run the job once per combination: matrix: { os: [linux, macos], node: [20, 22] } makes four instances. Each gets its values as environment variables named MATRIX_<AXIS>, such as MATRIX_OS. |
env |
names and values | Environment variables for every step. |
image |
an image name | Run the steps in this container image, with docker or podman, instead of on the machine itself. |
cache |
directories | Directories kept between runs on the same machine: container volumes for jobs with an image, shared by every job of the repository with the same image. |
cache_inputs |
commands | Commands whose output is part of each step's cache key, for what the files don't pin, such as clang --version. See The step cache. |
runner |
a label | Only a runner with this label takes the job, such as runner: gpu. See Runners. |
timeout |
a duration | 30 or 30m is minutes, 2h hours, 90s seconds, up to a day. The job is stopped when it runs over. |
if |
a condition | Run only when it holds. See below. |
on |
a schedule | on: schedule 0 3 * * * (five cron fields) makes a scheduled job, which never runs on pushes. See the note below. |
secrets |
names | The secrets the job is given, as environment variables. See Secrets. |
artifacts |
paths | Not supported yet: a warning says the files aren't kept. |
A key Lorx doesn't know is a warning, not an error: the rest of the workflow still runs. A GitHub Actions file (with top-level on: and jobs:) is an error that says so: Lorx's format is the one on this page.
A command with : in it needs the whole value quoted, as YAML requires: lint: 'echo "lint: 0 warnings"', or a block with lint: | and the command on the next line. bit ci check shows both for the line in question.
Conditions
if compares what set the run off. It knows two names:
branch: the branch pushed to (empty for a schedule);event:push,scheduleormanual.
Values are quoted, with 'single' or "double" quotes, and comparisons combine with &&, ||, ! and parentheses:
deploy:
needs: [test]
if: branch == 'main' && event != 'schedule'
run: ./deploy.shEvery step's environment
| Variable | Value |
|---|---|
CI, LORX |
true |
LORX_JOB |
The job instance, such as test (os=linux) |
LORX_WORKFLOW |
The workflow's name |
MATRIX_<AXIS> |
Each matrix value |
Your own env comes last, and wins.
The step cache
A step that passed before with the same inputs is skipped, on your machine and on runners. Its inputs are:
- its command, and the steps before it in its job;
- its environment, matrix values included;
- every file in the checkout, by content;
- for a job with an
image, the image by digest, so a movedlatestis a new image; - for a job in the machine's own shell, the versions of the well-known tools its commands call, asked of each tool in the checkout:
cargoandrustc(so arust-toolchain.tomlcounts),node,bun,go,python3,git,clangand more. A new compiler on the runner runs the step again; - the output of the job's
cache_inputs.
A skipped step says what it matched on: skipped, it passed before with the same inputs (cargo 1.98.0, rustc 1.98.0). bit run --no-cache runs every step anyway.
Secrets
secrets: [DEPLOY_TOKEN] gives the job's steps $DEPLOY_TOKEN, and only the secrets it names.
- On a runner, they come from the repository's secrets, then its owner's account's: a repository's secret overrides an account's of the same name. They are encrypted at rest and sent only to the runner that holds the job.
- An account's secret reaches only the repositories you list for it. A new one reaches none until you give it some. That way, someone who can write to one of your repositories can't get at a secret meant for another.
- Only code on a branch or tag is given secrets. A run you start by hand at any other commit (an imported pull request's, say) runs without them, and its jobs that need them fail saying why.
- With
bit run, they come from your environment, then from.lorx/secrets.envin the checkout. See Run jobs on your machine. - Every value is replaced with
***in the job's log, along with its base64 and URL-encoded forms. Values under 4 characters aren't masked, so keep secrets longer than that. - A job with secrets is never cached: its steps run every time, and a container job mounts no shared cache volume.
- A job that names a secret nobody set fails before its first step, naming it.
Scheduled jobs
A job with on: schedule … is left out of push runs. Lorx does not fire schedules yet, so today a scheduled job runs only when you name it: bit run nightly.
Check a workflow
bit ci checkThis prints every problem with its line and column, the way compilers do, and shows the plan a push would make. It exits with status 1 when there are errors. See Run CI on your machine.