CI workflows defined in code instead of YAML.
The builder produces exactly the file bsdkrun ci (and tangled's spindle)
consumes — yaml/1 is that file, save/2 commits it to
.tangled/workflows/, and run/1 executes it in a microVM without a file
ever touching the repository:
Bsdkrun.CI.workflow("test")
|> Bsdkrun.CI.on_push("main")
|> Bsdkrun.CI.deps(["elixir", "erlang"])
|> Bsdkrun.CI.env("MIX_ENV", "test")
|> Bsdkrun.CI.step("deps", "mix deps.get")
|> Bsdkrun.CI.step("test", "mix test")
|> Bsdkrun.CI.run()Code is the source of truth and YAML the wire format, in that order — which
is why save/2 writes a generated-file header: a hand-edit there will be
overwritten by the next save.
Summary
Functions
Set the clone depth (default 1).
Add nixpkgs dependencies — the toolchain the steps run against.
Add dependencies from a custom registry (a flake reference).
Override the engine (nixery by default).
Set a workflow-level environment variable.
The workflow file name save/2 writes: <name>.yml.
Add a pull_request trigger targeting the given branch(es).
Add a push trigger for the given branch(es).
Execute the workflow in a microVM, streaming output.
Write into <repo>/.tangled/workflows/ and return the path.
Skip the checkout entirely.
Append a step; steps run serially in one VM, from the workspace root.
Start a CI workflow definition.
Render the workflow file.
Types
Functions
@spec clone_depth(t(), pos_integer()) :: t()
Set the clone depth (default 1).
Add nixpkgs dependencies — the toolchain the steps run against.
Add dependencies from a custom registry (a flake reference).
Override the engine (nixery by default).
Set a workflow-level environment variable.
The workflow file name save/2 writes: <name>.yml.
Add a pull_request trigger targeting the given branch(es).
Add a push trigger for the given branch(es).
Execute the workflow in a microVM, streaming output.
The YAML never touches the repository — it goes to a temp file and
bsdkrun ci run -f. Returns :ok, or {:error, exit_code} when a step
fails.
Write into <repo>/.tangled/workflows/ and return the path.
Skip the checkout entirely.
Append a step; steps run serially in one VM, from the workspace root.
Start a CI workflow definition.
Render the workflow file.
Scalars are emitted as JSON strings — valid YAML by construction — and commands as literal blocks when safe, so the SDK needs no YAML dependency.