Skip to content

Step Context

Leonard Ramminger edited this page Aug 10, 2026 · 2 revisions

Step Context

Lua step callbacks receive one argument: the step context table, conventionally named ctx.

step({
    name = "lint",
    phase = "qa",
    scope = "default",
    run = function(ctx)
        return 0
    end,
})

Only available inside Lua run callbacks. Shell steps do not get ctx.

Properties

Member Type Description
project_root string Absolute path to project root

ctx.get_config()

Returns the merged step config table, or nil if none.

local config = ctx.get_config()
local patterns = config.patterns

See Configure Step.

ctx.glob(patterns)

Expand glob patterns relative to project_root.

local files = ctx.glob({ "src/**/*.cpp", "include/**/*.hpp" })
Argument Type Description
patterns string array Glob patterns (same syntax as step input/output)

Returns a 1-based Lua array of relative file paths (sorted). Empty if nothing matches.

Uses the glob metadata cache when enabled in performance settings.

Workers

Run shell commands in parallel from a Lua callback. Use colon syntax (:) for these methods.

Full reference: Lua API Workers.

ctx:spawn(spec)

Start a background worker. Returns a handle (integer).

Field Required Type Description
cmd yes string or string array Shell command(s)
inputs no string array Input paths for worker cache key
outputs no string array Output paths for worker cache key
name no string Override auto name {step}-{n}

ctx:wait(handle [, options])

Wait for one worker. Pass an options table to select return fields:

Option Return field
exitCode result.exitCode
output result.output (captured stdout/stderr)
duration result.duration
cached result.cached
local result = ctx:wait(job, { exitCode = true, output = true })
if result.exitCode ~= 0 then
    error(result.output)
end

Omit options to wait without a return value. On success, records worker duration for cache_file_success().

ctx:wait_all(handles [, options])

Wait for multiple workers. Returns a 1-based array of result tables (same options as wait).

local jobs = {}
for _, file in ipairs(files) do
    jobs[#jobs + 1] = ctx:spawn({ cmd = "lint " .. file })
end
for _, result in ipairs(ctx:wait_all(jobs, { exitCode = true })) do
    if result.exitCode ~= 0 then return result.exitCode end
end

Workers require the worker pool (available during Lua step execution). If unavailable, spawn throws worker pool is not available in this step context.

Success cache API

Per-file or per-key incremental cache inside a Lua callback. Stored under .cache/success/. Disabled when --no-cache or cache.enabled = false.

ctx.file_success_cached(path)

Returns true if relative file path path was previously cached as successful.

if ctx.file_success_cached(source_path) then
    skipped = skipped + 1
else
    -- run tool on source_path
end

ctx.cache_file_success(path)

Mark path as successfully processed. Uses pending worker duration from the last ctx:wait() when applicable.

ctx.cache_file_success(source_path)

ctx.success_cached(key)

Generic string key success check (not file-based).

ctx.cache_success(key)

Mark generic key as successful.

ctx.record_file_cache_miss(path)

Record that path failed, so the next run re-checks it even if other files are cached.

ctx.record_cache_miss(key)

Record generic key miss.

ctx.get_cache_misses()

Returns a 1-based array of paths/keys that failed in the previous run (for incremental re-check).

local misses = ctx.get_cache_misses()
for _, entry in ipairs(misses) do
    print("re-checking: " .. entry)
end

Bump a revision field in configure_step() when the tool or rules change without source file changes.

Method syntax

Call style Functions
Dot (ctx.glob) glob, get_config, success cache helpers
Colon (ctx:spawn) spawn, wait, wait_all

Example: parallel workers

run = function(ctx)
    local files = ctx.glob({ "src/**/*.cpp" })
    local jobs = {}
    for _, file in ipairs(files) do
        jobs[#jobs + 1] = ctx:spawn({
            cmd = "g++ -c " .. file,
            inputs = { file },
            outputs = { file .. ".o" },
        })
    end
    for _, result in ipairs(ctx:wait_all(jobs, { exitCode = true })) do
        if result.exitCode ~= 0 then return result.exitCode end
    end
    return 0
end

Next steps

Clone this wiki locally