# Run CI on your machine

bit run runs your workflows with the same engine Lorx uses, skipping steps that already passed.

`bit run` runs your workflows here, with the engine Lorx runs them with, so what passes on your machine is what will pass after you push.

```sh
bit run              # what a push from here would run: jobs whose paths changed
bit run test         # one job, and what it needs first
bit run ci:test      # a job in a particular workflow
bit run --all        # every push job, whatever changed
bit run --list       # the plan, and what would be skipped, without running anything
```

## Steps that already passed are skipped

Every step remembers what it ran with: the files it reads, its command and its settings. If none of that has changed since it last passed, it is skipped instantly. A step that several jobs share runs once.

`bit run --no-cache` runs every step anyway (their results are still remembered).

## Options

| Option | What it does |
|---|---|
| `--all` | Every push job, whatever changed |
| `--no-cache` | Run every step, even ones that passed with the same inputs |
| `--list` | Show the plan without running anything |
| `--json` | Print the plan and results as JSON (step output still goes to stderr) |
| `--file <file>` | One workflow file instead of every one in `.lorx/actions/` |
| `-w, --workflow <name>` | Only this workflow |

Jobs with an `image` run in that container with docker or podman: bit uses `LORX_CONTAINER` if set, otherwise whichever is installed.

## Secrets

A job's `secrets:` come from your environment first, then from `.lorx/secrets.env` in the checkout, one `NAME=value` per line:

```
# .lorx/secrets.env
DEPLOY_TOKEN=tok-...
export API_KEY="with spaces"
```

bit never fetches them from Lorx.

- **Keep the file out of git.** Add `.lorx/secrets.env` to `.gitignore`. Whenever the file exists, `bit run` refuses to start if git would commit it, if it is already tracked, or if it is a symbolic link.
- **The format.** `#` starts a comment, on its own line or after an unquoted value. Quotes around a value are removed, but nothing inside them is unescaped, and a value is one line. A later line for the same name wins.
- **Empty means unset.** An empty variable in your environment falls through to the file; an empty one in the file counts as missing.
- **Only what a job names.** Each step gets only its own job's secrets. The ones other jobs name are taken out of its environment, even if your shell exports them.
- **Masked and never cached.** Values appear as `***` in the output; ones under 4 characters can't be masked, and bit warns about them. A job with secrets never has its steps cached.
- **Missing.** A secret found in neither place fails its job, naming it.

## See the pipeline

```sh
bit ci graph                 # Mermaid: paste into Markdown or mermaid.live
bit ci graph --format dot    # Graphviz
bit ci graph --format json
```

The graph shows every job as a node, `needs` as edges and levels as ranks, and what the step cache would skip.

## Check workflows for mistakes

```sh
bit ci check
```

This prints each problem with its file, line and column, and exits 1 on errors. Run it before you push, or in a git hook.
