actrun

MVP GitHub Actions-compatible push CI runner with bitflow lowering, native execution, and bit workspace materialization.

github-actions
workflow
runner
ci
moon add mizchi/actrun@0.30.1
Download zip
Author
Version
0.30.1
License
Apache-2.0
Last updated
2 months ago
Downloads
602
README

#actrun

A local GitHub Actions runner built with MoonBit. Run and debug GitHub Actions workflows locally with a gh-compatible CLI.

actrun keeps its release contract as close as possible to existing GitHub Actions semantics. Workflow YAML and action metadata stay on a GitHub-compatible surface, while WASM support is treated as a self-hosted runner optimization. See docs/public-api.md for the contract boundary and ADR 0001 for the rationale.

#Install

# npx (no install required) npx @mizchi/actrun workflow run .github/workflows/ci.yml # curl (Linux / macOS) curl -fsSL https://raw.githubusercontent.com/mizchi/actrun/main/install.sh | sh # Docker docker run --rm -v "$PWD":/workspace -w /workspace ghcr.io/mizchi/actrun workflow run .github/workflows/ci.yml # npm global install npm install -g @mizchi/actrun # Nix (run without installing) nix run github:mizchi/actrun -- workflow run .github/workflows/ci.yml # Nix (install into profile) nix profile install github:mizchi/actrun # moon install moon install mizchi/actrun/cmd/actrun # Build from source git clone https://github.com/mizchi/actrun.git && cd actrun moon build src/cmd/actrun --target native

#Nix

#Run directly

nix run github:mizchi/actrun -- workflow run .github/workflows/ci.yml

#Build from source

nix build github:mizchi/actrun ./result/bin/actrun workflow run .github/workflows/ci.yml

#Development shell

With direnv and nix-direnv:

echo "use flake" > .envrc direnv allow

Or without direnv:

nix develop

#Adding the overlay to your flake.nix

{ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; actrun.url = "github:mizchi/actrun"; }; outputs = { nixpkgs, actrun, ... }: let system = "aarch64-darwin"; # or "x86_64-linux" pkgs = import nixpkgs { inherit system; overlays = [ actrun.overlays.default ]; }; in { packages.${system}.default = pkgs.actrun; devShells.${system}.default = pkgs.mkShell { packages = [ pkgs.actrun ]; }; }; }

#Without flakes

# default.nix provides a ready-to-use derivation let actrun = import (builtins.fetchTarball "https://github.com/mizchi/actrun/archive/main.tar.gz") { }; in actrun

#Quick Start

# Run a workflow locally actrun workflow run .github/workflows/ci.yml # Show execution plan without running actrun workflow run .github/workflows/ci.yml --dry-run # Emit flow cache plan JSON for an external orchestrator actrun workflow run .github/workflows/ci.yml \ --dry-run \ --json \ --flow-cache-store /tmp/flow-cache.json \ --flow-signature build=sig-build # Skip actions not needed locally (e.g. setup tools already installed) actrun workflow run .github/workflows/ci.yml \ --skip-action actions/checkout \ --skip-action extractions/setup-just # Run in isolated worktree actrun workflow run .github/workflows/ci.yml \ --workspace-mode worktree # Generate config file actrun init # View results actrun run view run-1 actrun run logs run-1 --task build/test

#Configuration

actrun init generates an actrun.toml in the current directory:

# Workspace mode: local, worktree, tmp, docker workspace_mode = "local" # Skip actions not needed locally local_skip_actions = ["actions/checkout"] # Trust all third-party actions without prompt trust_actions = true # Nix integration: "auto" (force), "off" (disable), or empty (auto-detect) nix_mode = "" # Additional nix packages nix_packages = ["python312", "jq"] # Container runtime: docker, podman, container, lima, nerdctl container_runtime = "docker" # Include uncommitted changes in worktree/tmp workspace # include_dirty = true # Default local GitHub context when `--event` is omitted # [local_context] # repository = "owner/repo" # ref_name = "main" # before_rev = "HEAD^" # after_rev = "HEAD" # actor = "your-name" # Override actions with local commands # [override."actions/setup-node"] # run = "echo 'using local node' && node --version" # Affected file patterns per workflow # [affected."ci.yml"] # patterns = ["src/**", "package.json"]

When --event is omitted, actrun auto-detects github.repository, github.ref_name, github.sha, and github.actor from the local git repository when possible. Use [local_context] only when you need to pin or override those values. See Local GitHub Context for precedence and examples.

CLI flags always override actrun.toml settings. See Cheatsheet for quick reference and Advanced Workflow for details.

#Flow Cache

Use --flow-cache-store <path> together with one or more --flow-signature <job-or-task>=<fingerprint> flags to exchange task cache state with the embedded bitflow planner.

--dry-run --json includes a flow_cache.plan payload with per-task hit/miss information. A normal run writes successful task fingerprints back to the same store and persists both the plan and writeback result under run.json as flow_cache.plan and flow_cache.writeback.

#CLI Reference

#Workflow Commands

actrun workflow list # List workflows in .github/workflows/ actrun workflow run <workflow.yml> # Run a workflow locally

#Run Commands

actrun run list # List past runs actrun run view <run-id> # View run summary actrun run view <run-id> --json # View run as JSON actrun run watch <run-id> # Watch until completion actrun run logs <run-id> # View all logs actrun run logs <run-id> --task <id> # View specific task log actrun run download <run-id> # Download all artifacts

#Analysis Commands

# Lint: type check expressions and detect dead code actrun lint # Lint all .github/workflows/*.yml actrun lint .github/workflows/ci.yml # Lint a specific file actrun lint --ignore W001 # Suppress a rule (repeatable) # Visualize: render workflow job dependency graph actrun viz .github/workflows/ci.yml # ASCII art (terminal) actrun viz .github/workflows/ci.yml --mermaid # Mermaid text (for Markdown) actrun viz .github/workflows/ci.yml --detail # Mermaid with step subgraphs actrun viz .github/workflows/ci.yml --svg # SVG image actrun viz .github/workflows/ci.yml --svg --theme github-light

#Lint Diagnostics

RuleSeverityDescription
undefined-contexterrorUndefined context (e.g. foobar.x)
wrong-arityerrorWrong function arity (e.g. contains('one'))
unknown-functionerrorUnknown function (e.g. myFunc())
unknown-propertywarningUnknown property (e.g. github.nonexistent)
type-mismatchwarningComparing incompatible types
unreachable-stepwarningUnreachable step (if: false)
future-step-referrorReference to future step
undefined-step-referrorReference to undefined step
undefined-needserrorUndefined needs job reference
circular-needserrorCircular needs dependency
unused-outputswarningUnused job outputs
duplicate-step-iderrorDuplicate step IDs in same job
missing-runs-onerrorMissing runs-on
empty-joberrorEmpty job (no steps)
uses-and-runerrorStep has both uses and run
empty-matrixwarningMatrix with empty rows
invalid-useserrorInvalid uses syntax
invalid-globwarningInvalid glob pattern in trigger filter
redundant-conditionwarningAlways-true/false condition
script-injectionwarningScript injection risk (untrusted input in run:)
permissive-permissionswarningOverly permissive permissions
deprecated-commandwarningDeprecated workflow command (::set-output etc.)
missing-prt-permissionswarningpull_request_target without explicit permissions
if-alwayswarningBare always() — prefer success() \|\| failure()
dangerous-checkout-in-prterrorCheckout PR head in pull_request_target
secrets-to-third-partywarningSecrets passed via env to third-party action
missing-timeoutwarningNo timeout-minutes (opt-in: --strict)
mutable-action-refwarningTag ref instead of SHA pin (opt-in: --online)
action-not-founderrorAction ref not found on GitHub (opt-in: --online)

Configure lint behavior in actrun.toml:

[lint] preset = "default" # default, strict, oss ignore_rules = ["unknown-property", "unused-outputs"]

PresetIncludes
defaultAll rules except missing-timeout and online checks
strictdefault + missing-timeout
ossstrict + mutable-action-ref / action-not-found (network)

#Visualization Example

$ actrun viz .github/workflows/release.yml ┌───────┐ ┌────────┐ │ build │ │ docker │ └───────┘ └────────┘ └┐ │ ┌─────────┐ │ release │ └─────────┘

#Artifact & Cache Commands

actrun artifact list <run-id> # List artifacts actrun artifact download <run-id> --name <name> # Download artifact actrun cache list # List cache entries actrun cache prune --key <key> # Delete cache entry

#Workflow Run Flags

FlagDescription
--dry-runShow execution plan without running
--skip-action <pattern>Skip actions matching pattern (repeatable)
--workspace-mode <mode>worktree (default), local, tmp, docker
--repo <path>Run from a git repository
--event <path>Push event JSON file
--repository <owner/repo>GitHub repository name
--ref <ref>Git ref name
--run-root <path>Run record storage root
--nixForce nix wrapping for run steps
--no-nixDisable nix wrapping even if flake.nix/shell.nix exists
--nix-packages <pkgs>Ad-hoc nix packages (space-separated)
--container-runtime <name>Container runtime: docker, podman, container, lima, nerdctl
--wasm-runner <kind>Wasm runner kind: wasmtime, deno, v8
--affected [base]Only run if files matching patterns changed (see below)
--retryRe-run only failed jobs from the latest run
--include-dirtyInclude uncommitted changes in worktree/tmp workspace
--jsonJSON output for read commands and --dry-run

#Affected Runs

Skip workflows when no relevant files have changed. Patterns are resolved in order:

  1. actrun.toml [affected."<workflow>"] patterns
  2. on:push:paths from the workflow file (automatic fallback)

# Compare against last successful run (default) actrun ci.yml --affected # Compare against a specific rev actrun ci.yml --affected HEAD~3 actrun ci.yml --affected abc1234 # Preview what would happen (shows plan even if skipped) actrun ci.yml --affected HEAD~1 --dry-run

Configure patterns in actrun.toml:

[affected."ci.yml"] patterns = ["src/**", "package.json"] [affected.".github/workflows/lint.yml"] patterns = ["src/**", "*.config.*"]

If actrun.toml has no patterns, on:push:paths from the workflow is used automatically:

on: push: paths: ["src/**", "*.toml"] # actrun --affected uses these

#Workspace Modes

ModeDescription
localRun in-place in the current directory
worktreeCreate an isolated git worktree for execution (default)
tmpClone to a temp directory via git clone
dockerRun in a Docker container

#Container Runtime

actrun supports multiple container runtimes for job container:, services:, and docker:// actions.

RuntimeBinaryNotes
dockerdockerDefault
podmanpodmanDocker-compatible CLI
containercontainerApple container runtime (macOS)
nerdctlnerdctlcontainerd CLI
limalima nerdctlLima VM with nerdctl (wrapper script auto-generated)

# CLI flag actrun workflow run ci.yml --container-runtime podman # actrun.toml container_runtime = "podman" # Environment variable (also works) ACTRUN_CONTAINER_RUNTIME=podman actrun workflow run ci.yml

#Supported GitHub Actions

#Builtin Actions (deterministic emulation)

ActionSupported Inputs
actions/checkout@*path, ref, fetch-depth, clean, sparse-checkout, submodules, lfs, fetch-tags, persist-credentials, set-safe-directory, show-progress
actions/upload-artifact@*name, path, if-no-files-found, overwrite, include-hidden-files
actions/download-artifact@*name, path, pattern, merge-multiple
actions/cache@*key, path, restore-keys, lookup-only, fail-on-cache-miss
actions/cache/save@*key, path
actions/cache/restore@*key, path, restore-keys, lookup-only, fail-on-cache-miss
actions/setup-node@*node-version, node-version-file, cache, registry-url, always-auth, scope

#Remote Actions (fetch + execute)

  • GitHub repo node actions with pre/main/post lifecycle
  • GitHub repo docker actions with pre-entrypoint/entrypoint/post-entrypoint lifecycle
  • Composite actions (local and remote)
  • docker://image direct execution

#Self-Hosted WASM Optimization

  • A self-hosted runner may prefer a sibling *.wasm file next to a standard node* action runs.main
  • The same action still runs on GitHub Actions through the normal JS fallback path
  • The runtime family is selected with --wasm-runner / ACTRUN_WASM_RUNNER

Protocol extensions such as wasm://... and runs-on: wasi are experimental / internal and are not part of the release contract. See docs/public-api.md for details.

#Local-Only Execution Flag

actrun sets ACTRUN_LOCAL=true in the execution environment. Use this in if: conditions to skip steps locally or run steps only locally:

steps: # Skipped when running locally (runs on GitHub Actions) - uses: actions/checkout@v5 if: ${{ !env.ACTRUN_LOCAL }} # Runs only locally (skipped on GitHub Actions) - run: echo "local debug info" if: ${{ env.ACTRUN_LOCAL }}

On GitHub Actions, ACTRUN_LOCAL is not set, so !env.ACTRUN_LOCAL evaluates to true and all steps run normally.

#Action Overrides

Replace specific uses: action steps with custom run: commands via actrun.toml. This is useful when you have tools installed locally and want to skip the action's setup logic.

[override."actions/setup-node"] run = "echo 'using local node' && node --version"

When a workflow step matches uses: actions/setup-node@*, actrun replaces it with the specified run: command before execution.

Combine with local_skip_actions for full control:

local_skip_actions = ["actions/checkout"] [override."actions/setup-node"] run = "echo 'using local node'" [override."actions/setup-python"] run = "python3 --version"

#Secrets & Variables

# Provide secrets via environment variables ACTRUN_SECRET_MY_TOKEN=xxx actrun workflow run ci.yml # Provide variables ACTRUN_VAR_MY_VAR=value actrun workflow run ci.yml

Secrets are automatically masked in stdout, stderr, logs, and run store. The ::add-mask:: workflow command is also supported.

#Environment Variables

VariableDescription
ACTRUN_SECRET_<NAME>${{ secrets.<name> }}
ACTRUN_VAR_<NAME>${{ vars.<name> }}
ACTRUN_NODE_BINNode.js binary path
ACTRUN_DOCKER_BINDocker binary path
ACTRUN_WASM_RUNNERWasm runner kind: wasmtime, deno, v8
ACTRUN_WASM_BINWasm runtime binary (default: wasmtime)
ACTRUN_GIT_BINGit binary path
ACTRUN_GITHUB_BASE_URLGitHub API base URL
ACTRUN_ARTIFACT_ROOTArtifact storage root
ACTRUN_CACHE_ROOTCache storage root
ACTRUN_GITHUB_ACTION_CACHE_ROOTRemote action cache root
ACTRUN_ACTION_REGISTRY_ROOTCustom registry root
ACTRUN_NIXSet to false to disable nix wrapping

ACTRUN_WASM_RUNNER を指定した場合、default bin は wasmtime / deno / ACTRUN_NODE_BIN (v8) に切り替わります。ACTRUN_WASM_BIN を併用すると、runner kind は固定したまま実行 binary だけ上書きできます。

#Nix Integration

actrun automatically detects flake.nix or shell.nix in the workspace root and wraps run: steps in the corresponding nix environment. This lets workflows written for ubuntu-latest run locally with nix-managed toolchains.

#Auto-detection

ConditionWrapping
flake.nix existsnix develop --command <shell> <script>
shell.nix existsnix-shell --run '<shell> <script>'
Neither existsNo wrapping (host environment)

Detection requires nix to be installed. If nix is not found, wrapping is silently skipped.

#Examples

# Auto-detect flake.nix / shell.nix actrun workflow run .github/workflows/ci.yml # Disable nix wrapping actrun workflow run .github/workflows/ci.yml --no-nix # Ad-hoc packages without flake.nix actrun workflow run .github/workflows/ci.yml --nix-packages "python312 jq" # Disable via environment variable ACTRUN_NIX=false actrun workflow run .github/workflows/ci.yml

#Typical flake.nix for Rust

{ inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; outputs = { self, nixpkgs }: let systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; forAllSystems = nixpkgs.lib.genAttrs systems; in { devShells = forAllSystems (system: let pkgs = nixpkgs.legacyPackages.${system}; in { default = pkgs.mkShell { packages = [ pkgs.rustc pkgs.cargo ]; }; }); }; }

#Typical flake.nix for Python + uv

{ inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; outputs = { self, nixpkgs }: let systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; forAllSystems = nixpkgs.lib.genAttrs systems; in { devShells = forAllSystems (system: let pkgs = nixpkgs.legacyPackages.${system}; in { default = pkgs.mkShell { packages = [ pkgs.python312 pkgs.uv ]; }; }); }; }

#Notes

  • Only run: steps are wrapped. uses: action steps are not affected.
  • Job container: steps skip nix wrapping (container has its own environment).
  • nix develop / nix-shell is invoked per step, so the nix environment is consistent across steps.

#Workflow Features

  • Push trigger filter (branches, paths)
  • strategy.matrix (axes, include, exclude, fail-fast, max-parallel)
  • Job/step if conditions (success(), always(), failure(), cancelled())
  • needs dependencies with output/result propagation
  • Reusable workflows (workflow_call) with inputs, outputs, secrets, secrets: inherit, nested expansion
  • Job container and services with Docker networking
  • Expression functions: contains, startsWith, endsWith, fromJSON, toJSON, hashFiles
  • File commands: GITHUB_ENV, GITHUB_PATH, GITHUB_OUTPUT, GITHUB_STEP_SUMMARY
  • Shell support: bash, sh, pwsh, custom templates ({0})
  • step.continue-on-error, steps.*.outcome / steps.*.conclusion

#Performance

Benchmark on Apple Silicon (M-series):

ModeStartupCPU (Node.js)Write 1k files
local~0.13s644ms52ms
nix-packages~0.70s629ms47ms
apple-container~0.93s502ms14ms

  • local — lowest overhead, best for fast iteration
  • nix-packages — +0.6s startup for nix develop; execution speed identical to local
  • apple-container — +0.9s startup; many-file I/O is 3-4x faster (ext4 vs APFS metadata)

See docs/perf.md for full benchmark details.

# Try it yourself nix run github:mizchi/actrun -- workflow run .github/workflows/ci.yml

#Development

just # check + test just fmt # format code just check # type check just test # run tests just e2e # run E2E scenarios just release-check # fmt + info + check + test + e2e

#Live Compatibility Testing

# One-shot: dispatch, wait, download, compare just gha-compat-live compat-checkout-artifact.yml # Step by step just gha-compat-dispatch compat-checkout-artifact.yml just gha-compat-download <run-id> just gha-compat-compare compat-checkout-artifact.yml _build/gha-compat/<run-id>

#Architecture

FilePurpose
src/lib.mbtContract types
src/parser.mbtWorkflow YAML parser
src/trigger.mbtPush trigger matcher
src/lowering.mbtBitflow IR lowering, action/reusable workflow expansion
src/executor.mbtNative host executor
src/runtime.mbtGit workspace materialization
src/lint/Expression parser, type checker, dead code detection, workflow visualization
src/cmd/actrun/main.mbtCLI entry point
testdata/Compatibility fixtures

#Prior Art

  • actionlint — Static checker for GitHub Actions workflow files. actrun lint is inspired by its rule design and type system.

#License

Apache-2.0

#actrun

MVP の GitHub Actions 互換 push CI ランナー向けコア API。

The release-contract principle is: keep GitHub Actions-compatible surface area stable, and keep runner optimizations or protocol extensions internal / experimental.

この package は push workflow の subset を parse し、bitflow IR に lower し、native target では host shell 上で実行できます。

  • push trigger のフィルタ判定
  • workflow YAML subset parser
  • workflow/job/step 契約型
  • ActionRef / resolver
  • bitflow IR への lowering
  • bitflow task cache plan / writeback の CLI 連携 (--flow-cache-store, --flow-signature)
  • workflow list の最小 read-only CLI
  • workflow run の最小 subcommand
  • strategy.matrix の最小対応 (axes / include / exclude / mixed axes + include / fail-fast / max-parallel)
  • matrix job に対する needs fan-in と aggregated ${{ needs.<job>.result }} / ${{ needs.<job>.outputs.* }}
  • minimal job-level if: (success() default, always() / failure() / cancelled(), simple github.* / needs.* comparison)
  • minimal step-level if: (success() default, always() / failure() / cancelled())
  • minimal expression functions (contains, startsWith, endsWith, fromJSON, toJSON, hashFiles)
  • ${{ vars.* }} の最小対応 (ACTRUN_VAR_<NAME> から供給)
  • ${{ secrets.* }} の最小対応 (ACTRUN_SECRET_<NAME> から供給, if: 直接参照は未対応)
  • workflow_call trigger と inputs / outputs / secrets の parse / contract 対応
  • local / remote reusable workflow (jobs.<job_id>.uses) の最小実行 (with, workflow_call.inputsrequired / implicit default / type validation, caller job の strategy.matrix, matrix caller 上の workflow_call.outputs 集約, workflow_call.outputs, secrets mapping, secrets: inherit, nested reusable workflow, remote reusable workflow 内 local action)
  • job container の string / mapping form の parse / contract 対応と、run step / GitHub repo node* action を docker adapter で実行する最小対応
  • job container 配下の GitHub repo / direct runs.using: docker action を sibling container として実行し、job container の volume mount を共有する最小対応
  • job container 配下で actions/checkout@* が host 側に materialize した workspace を後続 container run step から見える形で扱う最小対応
  • job container 配下で actions/upload-artifact@* / actions/download-artifact@* の roundtrip を後続 container run step から扱う最小対応
  • job services の mapping form の parse / contract 対応、service container の最小 lifecycle 実行、${{ job.services.<id>.ports[...] }} context、health check wait、job container との docker network 共有の最小対応
  • workflow/job permissions / concurrency の parse / contract 対応と lowering reject
  • step-level continue-on-error
  • ${{ steps.<id>.outcome }} / ${{ steps.<id>.conclusion }} の最小対応
  • native host executor
  • CLI run store の最小対応 (--run-root, _build/actrun/runs/<run-id>/run.json, jobs.json, artifacts.json, caches.json, tasks/*.stdout.log|stderr.log|summary.md, jobs/artifacts/caches index, timestamps, run list, run view, run watch, run logs, run download, artifact list, artifact download, cache list, cache prune)
  • local injection point の CLI flag 対応 (--artifact-root, --cache-root, --github-action-cache-root, --registry-root)
  • bit repo から push commit を materialize する runtime
  • uses: actions/checkout@*uses: builtin://checkout の最小 builtin 対応
  • actions/checkoutpath / sparse-checkout / sparse-checkout-cone-mode / fetch-depth / ref / clean / submodules の最小 builtin 対応
  • uses: actions/upload-artifact@* / uses: actions/download-artifact@* の最小 builtin 対応 (directory, wildcard path, if-no-files-found, overwrite, download-all directory mode, merge-multiple)
  • uses: actions/setup-node@* の最小 builtin 対応 (node-version, cache: npm, registry-url)
  • job container 配下で actions/setup-node@* が PATH shim と output を後続 run step に伝播する最小対応
  • uses: actions/cache@* / actions/cache/restore@*restore-keys, lookup-only, fail-on-cache-miss 対応
  • job container 配下で actions/cache@* の miss -> deferred save -> next job restore を後続 container run step から扱う最小対応
  • native prefetch による owner/repo[/path]@ref GitHub repo action の remote fetch / cache fill
  • cache 済み owner/repo[/path]@ref GitHub repo composite action の workspace-aware 展開
  • cache 済み / prefetched owner/repo[/path]@ref GitHub repo node* action の最小実行
  • cache 済み / prefetched owner/repo[/path]@ref GitHub repo runs.using: docker action の最小実行
  • uses: ./path の local composite action 展開
  • local composite action 内の nested uses 展開
  • local composite action の with${{ inputs.* }} の最小対応
  • CI, GITHUB_ACTIONS, GITHUB_WORKSPACE, GITHUB_WORKFLOW, GITHUB_JOB の基本 env 注入
  • GITHUB_ACTION の最小対応
  • cached / prefetched GitHub action 向けの GITHUB_ACTION_REPOSITORY, GITHUB_ACTION_REF 注入
  • local composite action inner step への GITHUB_ACTION_PATH 注入
  • local composite action inner step 間に閉じた GITHUB_STATE の最小対応
  • cache 済み / prefetched GitHub repo node* action の pre / main / post lifecycle と GITHUB_STATE 共有
  • cache 済み / prefetched GitHub repo runs.using: docker action の pre-entrypoint / entrypoint / post-entrypoint lifecycle と GITHUB_STATE 共有
  • GITHUB_ENV, GITHUB_PATH, GITHUB_OUTPUT, GITHUB_STEP_SUMMARY の file command 対応
  • native run step における ${{ env.* }} の最小対応
  • direct dependency に対する ${{ needs.<job>.outputs.<name> }}, ${{ needs.<job>.result }} の最小対応
  • push workflow における ${{ github.ref }}, ${{ github.ref_name }}, ${{ github.sha }}GITHUB_REF, GITHUB_REF_NAME, GITHUB_SHA の最小対応
  • push workflow における ${{ github.event_name }}GITHUB_EVENT_NAME の最小対応
  • push workflow における ${{ github.repository }}GITHUB_REPOSITORY の最小対応
  • push workflow における ${{ github.repository_owner }}GITHUB_REPOSITORY_OWNER の最小対応
  • push workflow における ${{ github.actor }}GITHUB_ACTOR の最小対応
  • native run step における ${{ github.workflow }}, ${{ github.job }}, ${{ github.workspace }} の最小対応
  • native run step における ${{ github.action }} の最小対応
  • cached / prefetched GitHub action 文脈での ${{ github.action_repository }}, ${{ github.action_ref }} の最小対応
  • local composite action inner step における ${{ github.action_path }} の最小対応
  • native run step における ${{ runner.os }}, ${{ runner.arch }}, ${{ runner.temp }}, ${{ runner.environment }} の最小対応
  • file-based な bash / sh / pwsh 実行と {0} 付き custom shell template の最小対応
  • job 内の後続 step に対する ${{ steps.<id>.outputs.<name> }} の最小対応
  • uses: docker://... の native docker 実行
  • MVP 範囲外機能の明示的 reject

CLI では actrun workflow list --repo /path/to/repo.github/workflows/*.yml|*.yaml を列挙できます。name が空なら file stem を fallback に使います。actrun workflow run .github/workflows/ci.yml は従来の actrun .github/workflows/ci.yml と同じ実行経路を subcommand で呼ぶ入口です。actrun .github/workflows/ci.yml --repo /path/to/repo --workspace /tmp/work --before <sha> の形で、repo 上の commit snapshot を materialize してから実行できます。--event /path/to/push-event.json を渡すと GitHub push webhook payload から PushEvent を組み立てます。--changed を省略した場合は changed paths を自動計算します。${{ github.repository }} / GITHUB_REPOSITORY--repository で明示 override でき、未指定なら repo root の origin remote URL から自動推測します。--run-root を渡すと local run record の保存先を上書きでき、現時点では <run-root>/run-<n>/run.json, jobs.json, artifacts.json, caches.jsontasks/*.stdout.log|stderr.log|summary.md を保存し、run.json には started_at_ms / finished_at_ms, exit_code, job 状態、artifact/cache index も含みます。--flow-cache-store <path>--flow-signature <job-or-task>=<fingerprint> と併用すると、dry-run 時は bitflow task cache の plan を計算し、--json 出力や run.jsonflow_cache.plan を含めます。通常実行では successful な task を同じ store に writeback し、その結果を flow_cache.writeback として run record に残します。actrun run list は保存済み run を新しい順に列挙し、actrun run view <run-id> は run store を要約表示し、--json 付きなら run.json をそのまま返します。actrun run watch <run-id> は run store が終端状態になるまで poll し、完了時に run view と同じ要約、--json 付きなら run.json を返し、failed/cancelled 系 state では non-zero で終了します。actrun run logs <run-id> --task <task-id> は保存済み task log / summary を読み戻し、--json 付きなら task ごとの stdout / stderr / summary payload を返します。actrun run download <run-id> はその run の全 artifact を <dir>/<artifact-name>/... に展開し、--json 付きなら download 結果の summary を返します。actrun artifact list <run-id> はその run の artifact index を列挙し、actrun artifact download <run-id> --name <artifact> は保存済み artifact を指定 directory に展開し、--json 付きなら copied file の summary を返します。actrun cache list は cache root 配下の workspace ごとの cache key と file 一覧を列挙し、actrun cache prune --key <cache-key> は一致する cache entry を削除します。--artifact-root / --cache-root は builtin artifact/cache store の保存先を、--github-action-cache-root / --registry-root は remote action cache / custom registry root をそれぞれ上書きします。--workspace-mode は contract だけ先に入っていて、local workflow 実行では worktree--repo 実行では tmp が default です。

#

///|
test {
let workflow = new_workflow(
"ci",
[
new_job("build", [
new_run_step("install", "pnpm install"),
new_run_step("test", "pnpm test"),
]),
new_job("lint", [new_run_step("lint", "pnpm lint")], needs=["build"]),
],
trigger=new_push_trigger(branches=["main"], paths=["src/*"]),
defaults=new_run_defaults(shell=Some("bash")),
)

let event = new_push_event("main", ["src/lib.mbt"])
inspect(matches_push_trigger(workflow.trigger, event), content="true")

let src =
#|on: push
#|jobs:
#| build:
#| runs-on: ubuntu-latest
#| steps:
#| - run: pnpm test
let parsed = parse_workflow_yaml(src)
let lowered = lower_push_workflow(parsed.workflow.unwrap())
@debug.debug_inspect(lowered.errors, content="[]")
@debug.debug_inspect(lowered.ir.tasks.length(), content="2")
}

#MVP 非対応

  • pwsh binary が存在しない環境での PowerShell workflow 実行
  • reusable workflow の広い互換対応
  • custom registry action の remote fetch / registry protocol 解決

parse_action_ref distinguishes GitHub repo refs, local paths, docker://..., and custom registry refs. A custom registry action (bit://std/cache@v1) resolves its manifest from ACTRUN_ACTION_REGISTRY_ROOT/<scheme>/<name>/<version>. On the release-contract surface, the stable WASM-related API is GitHub-compatible workflow / action metadata plus runner-local configuration (ACTRUN_WASM_RUNNER, ACTRUN_WASM_BIN). The native executor may prefer a sibling *.wasm next to a standard node* action runs.main as a self-hosted runner optimization. ACTRUN_WASM_RUNNER accepts wasmtime, deno, or v8, and the default binary becomes wasmtime, deno, or ACTRUN_NODE_BIN (node) respectively. ./local-action reads action.yml / action.yaml from the workspace and expands to composite steps while wiring with into ${{ inputs.* }}. prefetch_workflow_github_actions_native clones owner/repo[/path]@ref into _build/actrun/github_actions or ACTRUN_GITHUB_ACTION_CACHE_ROOT; composite manifests are expanded, runs.using: node* executes runs.main and pre / post, and runs.using: docker executes runs.image / runs.args / runs.entrypoint / runs.pre-entrypoint / runs.post-entrypoint from the native executor. The prefetch path uses ACTRUN_GIT_BIN; the native executor uses ACTRUN_NODE_BIN / ACTRUN_DOCKER_BIN / ACTRUN_WASM_BIN; setup-node uses ACTRUN_SETUP_NODE_BIN; ${{ vars.* }} comes from ACTRUN_VAR_<NAME>; ${{ secrets.* }} comes from ACTRUN_SECRET_<NAME>; and the GitHub host can be overridden by ACTRUN_GITHUB_BASE_URL. wasm://... and runs-on: wasi may still exist inside the repo but are not part of the release contract and are treated as internal / experimental. ResolvedAction separates the backend string from the capability model (host / docker / wasm).

#
ActionRef

pub enum ActionRef {
GitHubRepo(String, String, String, String?)
LocalPath(String)
DockerImage(String)
Registry(String, String, String)
}

#
ActionRefParseResult

pub struct ActionRefParseResult {
action : ActionRef?
errors : Array[String]
}

#
ActionResolutionResult

pub struct ActionResolutionResult {
action : ResolvedAction?
errors : Array[String]
}

#
BackendCapabilities

pub struct BackendCapabilities {
host : Bool
docker : Bool
wasm : Bool
}

#
BitChangedPathsResult

pub struct BitChangedPathsResult {
paths : Array[String]
base_sha : String
head_sha : String
errors : Array[String]
}

#
BitWorkspace

pub struct BitWorkspace {
repo_root : String
git_dir : String
workspace_root : String
commit_sha : String
refname : String
remote_url : String
}

#
BitWorkspaceResult

pub struct BitWorkspaceResult {
workspace : BitWorkspace?
errors : Array[String]
}

#
ConcurrencySpec

pub struct ConcurrencySpec {
group : String
cancel_in_progress : String?
}

#
ExecutionPlan

pub struct ExecutionPlan {
tasks : Array[TaskPlan]
job_outputs : Map[String, Map[String, String]]
job_if_conditions : Map[String, String]
job_needs : Map[String, Array[String]]
job_need_targets : Map[String, Map[String, Array[String]]]
job_virtual_targets : Map[String, Array[String]]
job_virtual_output_targets : Map[String, Map[String, Array[String]]]
job_matrix_groups : Map[String, String]
job_matrix_fail_fast : Map[String, Bool]
job_containers : Map[String, JobContainerSpec]
job_services : Map[String, Map[String, JobContainerSpec]]
composite_output_mappings : Map[String, Map[String, String]]
}

#
GitHubActionPrefetchResult

pub struct GitHubActionPrefetchResult {
fetched : Array[String]
errors : Array[String]
}

#
JobContainerCredentialsSpec

pub struct JobContainerCredentialsSpec {
username : String
password : String
}

#
JobContainerSpec

pub struct JobContainerSpec {
image : String
credentials : JobContainerCredentialsSpec?
env : Map[String, String]
ports : Array[String]
volumes : Array[String]
options : String?
}

#
JobMatrixSpec

pub struct JobMatrixSpec {
rows : Array[Map[String, String]]
fail_fast : Bool
max_parallel : Int?
}

#
JobSpec

pub struct JobSpec {
id : String
name : String
if_condition : String
needs : Array[String]
outputs : Map[String, String]
permissions : PermissionsSpec?
concurrency : ConcurrencySpec?
runs_on : Array[String]
env : Map[String, String]
defaults : RunDefaults
steps : Array[StepSpec]
matrix : JobMatrixSpec?
reusable_workflow : String?
reusable_workflow_with : Map[String, String]
reusable_workflow_secrets : Map[String, String]
reusable_workflow_inherit_secrets : Bool
services : Map[String, JobContainerSpec]
container : JobContainerSpec?
container_image : String?
timeout_minutes : Int
environment : String
}

#
LocalActionParseResult

pub struct LocalActionParseResult {
action : LocalActionSpec?
errors : Array[String]
}

#
LocalActionSpec

pub struct LocalActionSpec {
name : String
inputs : Map[String, String]
outputs : Map[String, String]
steps : Array[StepSpec]
}

#
LoweringResult

pub struct LoweringResult {
ir :
FlowIr

plan : ExecutionPlan
errors : Array[String]
}

#
PermissionsSpec

pub struct PermissionsSpec {
values : Map[String, String]
}

#
PlanJob

pub struct PlanJob {
id : String
needs : Array[String]
runs_on : Array[String]
steps : Array[PlanStep]
}

#
PlanResult

pub struct PlanResult {
workflow_name : String
errors : Array[String]
jobs : Array[PlanJob]
}

#
PlanStep

pub struct PlanStep {
id : String
kind : String
name : String
shell : String
script : String
uses : String
backend : String
if_condition : String
env : Map[String, String]
with_values : Map[String, String]
}

#
PushEvent

pub struct PushEvent {
ref_name : String
before_sha : String
after_sha : String
changed_paths : Array[String]
repository : String
actor : String
}

#
PushEventJsonParseResult

pub struct PushEventJsonParseResult {
event : PushEvent?
errors : Array[String]
}

#
PushTrigger

pub struct PushTrigger {
branches : Array[String]
branches_ignore : Array[String]
paths : Array[String]
paths_ignore : Array[String]
tags : Array[String]
tags_ignore : Array[String]
}

#
ResolvedAction

pub struct ResolvedAction {
uses : String
action_ref : ActionRef
kind : String
backend : String
capabilities : BackendCapabilities
action_path : String?
entrypoint : String?
image : String?
args : Array[String]
}

#
RunDefaults

pub struct RunDefaults {
shell : String?
working_directory : String?
}

#
ShellEnv

pub struct ShellEnv {
vars : Map[String, String]
cwd : String
stdout_buf : Array[String]
stderr_buf : Array[String]
exit_code : Int
exit_called : Bool
write_file : (String, String, Bool) -> Bool
read_file : (String) -> String?
file_exists : (String) -> Bool
is_dir : (String) -> Bool
mkdir : (String) -> Bool
remove : (String) -> Bool
}

#
StepSpec

pub struct StepSpec {
id : String
name : String
run : String?
uses : String?
shell : String?
working_directory : String?
env : Map[String, String]
with_values : Map[String, String]
if_condition : String
continue_on_error : String
timeout_minutes : Int
}

#
StoreEnvEntry

pub struct StoreEnvEntry {
key : String
value : String
} derive(ToJson,
Debug
,
FromJson
)

Env update: maps to GITHUB_ENV (key=value or heredoc) HTTP: POST /runs/{run_id}/env body: {"key": "...", "value": "..."}

#
StoreMode

pub enum StoreMode {
FileStore
HttpStore(String)
}

#
StoreOutputEntry

pub struct StoreOutputEntry {
key : String
value : String
} derive(ToJson,
Debug
,
FromJson
)

Step output: maps to GITHUB_OUTPUT (key=value per line) HTTP: POST /steps/{step_id}/outputs body: {"key": "...", "value": "..."}

#
StorePathEntry

pub struct StorePathEntry {
path : String
} derive(ToJson,
Debug
,
FromJson
)

Path update: maps to GITHUB_PATH (one path per line) HTTP: POST /runs/{run_id}/path body: {"path": "..."}

#
StoreStepResult

pub struct StoreStepResult {
outputs : Map[String, String]
env_updates : Map[String, String]
path_entries : Array[String]
summary : String
} derive(ToJson,
Debug
,
FromJson
)

Collected results for a step execution. In file mode: parsed from GITHUB_OUTPUT/GITHUB_ENV files. In HTTP mode: GET /steps/{step_id}/result

#
StoreSummaryEntry

pub struct StoreSummaryEntry {
content : String
} derive(ToJson,
Debug
,
FromJson
)

Step summary: maps to GITHUB_STEP_SUMMARY (markdown text) HTTP: POST /steps/{step_id}/summary body: {"content": "..."}

#
TaskPlan

pub struct TaskPlan {
id : String
kind : String
job_id : String
step_id : String
name : String
script : String
shell : String
working_directory : String
if_condition : String
runs_on : Array[String]
env : Map[String, String]
with_values : Map[String, String]
action : ResolvedAction?
action_scope : String?
requires_action_started : Bool
continue_on_error : String
timeout_minutes : Int
}

#
TaskRunReport

pub struct TaskRunReport {
id : String
kind : String
status : String
code : Int
duration_ms : UInt64
shell : String
script : String
cwd : String
stdout : String
stderr : String
summary : String
}

#
WasmDceReport

pub struct WasmDceReport {
removable_functions : Int
removable_bytes : Int
ok : Bool
error : String
}

#
WasmModuleInfo

pub struct WasmModuleInfo {
total_bytes : Int
function_count : Int
import_count : Int
export_count : Int
valid : Bool
error : String
}

#
WasmOptimizeResult

pub struct WasmOptimizeResult {
original_size : Int
optimized_size : Int
optimized_bytes : Bytes
ok : Bool
error : String
}

#
WasmSandbox

pub struct WasmSandbox {
tempdir : String
env_path : String
output_path : String
path_path : String
summary_path : String
state_path : String
}

#
WasmSandboxResult

pub struct WasmSandboxResult {
env_updates : Map[String, String]
path_entries : Array[String]
output_values : Map[String, String]
state_updates : Map[String, String]
summary : String
}

#
WorkflowCallInputSpec

pub struct WorkflowCallInputSpec {
description : String
required : Bool
default_value : String?
input_type : String
}

#
WorkflowCallOutputSpec

pub struct WorkflowCallOutputSpec {
description : String
value : String
}

#
WorkflowCallSecretSpec

pub struct WorkflowCallSecretSpec {
required : Bool
}

#
WorkflowCallSpec

pub struct WorkflowCallSpec {
inputs : Map[String, WorkflowCallInputSpec]
outputs : Map[String, WorkflowCallOutputSpec]
secrets : Map[String, WorkflowCallSecretSpec]
}

#
WorkflowParseResult

pub struct WorkflowParseResult {
workflow : WorkflowSpec?
errors : Array[String]
}

#
WorkflowRunReport

pub struct WorkflowRunReport {
ok : Bool
state : String
order : Array[String]
steps : Array[WorkflowStepReport]
issues : Array[String]
task_reports : Array[TaskRunReport]
}

#
WorkflowSpec

pub struct WorkflowSpec {
name : String
run_name : String
trigger : PushTrigger
pull_request_trigger : PushTrigger?
workflow_call : Bool
workflow_call_spec : WorkflowCallSpec?
permissions : PermissionsSpec?
concurrency : ConcurrencySpec?
env : Map[String, String]
defaults : RunDefaults
jobs : Array[JobSpec]
}

#
WorkflowStepReport

pub struct WorkflowStepReport {
id : String
status : String
required : Bool
duration_ms : UInt64
message : String
}

#
analyze_wasm_dead_code

fn analyze_wasm_dead_code(bytes : Bytes) -> WasmDceReport

#
backend_capabilities_for

fn backend_capabilities_for(backend : String) -> BackendCapabilities

#
build_sandboxed_wasmtime_args

fn build_sandboxed_wasmtime_args(sandbox : WasmSandbox, env : Map[String, String], module_path : String) -> Array[String]

Build wasmtime arguments for sandboxed execution. Only the tempdir is mounted — no access to host filesystem.

#
cleanup_run_temp_files

fn cleanup_run_temp_files(workspace_root : String) -> Unit

#
cleanup_wasm_sandbox

fn cleanup_wasm_sandbox(sandbox : WasmSandbox) -> Unit

Clean up the sandbox tempdir after use.

#
collect_secret_values

fn collect_secret_values() -> Array[String]

#
compute_bit_changed_paths

fn compute_bit_changed_paths(rfs : &
RepoFileSystem
, repo_root : String, event : PushEvent) -> BitChangedPathsResult

#
compute_bit_changed_paths_native

fn compute_bit_changed_paths_native(repo_root : String, event : PushEvent) -> BitChangedPathsResult

#
create_wasm_sandbox

fn create_wasm_sandbox(step_id : String) -> WasmSandbox?

#
dump_workflow_context_json

async fn dump_workflow_context_json(workflow_name : String, plan : ExecutionPlan, workspace_root : String, push_event : PushEvent, dispatch_inputs? : Map[String, String], event_name? : String) -> String

#
empty_step_result

fn empty_step_result() -> StoreStepResult

#
execute_lowered_native

async fn execute_lowered_native(lowered : LoweringResult, workspace_root? : String, push_event? : PushEvent?, event_name? : String, dispatch_inputs? : Map[String, String], nix_mode? : String, nix_packages? : Array[String], sandbox_mode? : String, sandbox_writable? : Array[String], allow_destructive_checkout_clean? : Bool) -> WorkflowRunReport

#
extract_add_mask_values

fn extract_add_mask_values(report : WorkflowRunReport) -> Array[String]

#
filter_workflow_jobs

fn filter_workflow_jobs(workflow : WorkflowSpec, skip_job_ids : Array[String]) -> WorkflowSpec

#
filter_workflow_steps

fn filter_workflow_steps(workflow : WorkflowSpec, skip_patterns : Array[String]) -> WorkflowSpec

#
find_task_plan

fn find_task_plan(plan : ExecutionPlan, id : String) -> TaskPlan?

#
find_task_run_report

fn find_task_run_report(report : WorkflowRunReport, id : String) -> TaskRunReport?

#
find_workflow_step_report

fn find_workflow_step_report(report : WorkflowRunReport, id : String) -> WorkflowStepReport?

#
inspect_wasm_module

fn inspect_wasm_module(bytes : Bytes) -> WasmModuleInfo

#
lower_push_workflow

fn lower_push_workflow(workflow : WorkflowSpec) -> LoweringResult

#
lower_push_workflow_in_workspace

fn lower_push_workflow_in_workspace(workflow : WorkflowSpec, workspace_root : String) -> LoweringResult

#
mask_report_secrets

fn mask_report_secrets(report : WorkflowRunReport, secret_values : Array[String]) -> WorkflowRunReport

#
mask_secrets

fn mask_secrets(text : String, secret_values : Array[String]) -> String

#
matches_push_trigger

fn matches_push_trigger(trigger : PushTrigger, event : PushEvent) -> Bool

#
materialize_bit_push_workspace

fn materialize_bit_push_workspace(fs : &
FileSystem
, rfs : &
RepoFileSystem
, repo_root : String, event : PushEvent, workspace_root : String, remote_url? : String) -> BitWorkspaceResult

#
materialize_bit_push_workspace_native

fn materialize_bit_push_workspace_native(repo_root : String, event : PushEvent, workspace_root : String, remote_url? : String) -> BitWorkspaceResult

#
new_backend_capabilities

fn new_backend_capabilities(host? : Bool, docker? : Bool, wasm? : Bool) -> BackendCapabilities

#
new_concurrency_spec

fn new_concurrency_spec(group : String, cancel_in_progress? : String?) -> ConcurrencySpec

#
new_job

fn new_job(id : String, steps : Array[StepSpec], name? : String, if_condition? : String, needs? : Array[String], outputs? : Map[String, String], permissions? : PermissionsSpec?, concurrency? : ConcurrencySpec?, runs_on? : Array[String], env? : Map[String, String], defaults? : RunDefaults, matrix? : JobMatrixSpec?, reusable_workflow? : String?, reusable_workflow_with? : Map[String, String], reusable_workflow_secrets? : Map[String, String], reusable_workflow_inherit_secrets? : Bool, container? : JobContainerSpec?, container_image? : String?, services? : Map[String, JobContainerSpec], timeout_minutes? : Int, environment? : String) -> JobSpec

#
new_job_container_credentials_spec

fn new_job_container_credentials_spec(username : String, password : String) -> JobContainerCredentialsSpec

#
new_job_container_spec

fn new_job_container_spec(image : String, credentials? : JobContainerCredentialsSpec?, env? : Map[String, String], ports? : Array[String], volumes? : Array[String], options? : String?) -> JobContainerSpec

#
new_job_matrix

fn new_job_matrix(rows : Array[Map[String, String]], fail_fast? : Bool, max_parallel? : Int?) -> JobMatrixSpec

#
new_local_action

fn new_local_action(steps : Array[StepSpec], name? : String, inputs? : Map[String, String], outputs? : Map[String, String]) -> LocalActionSpec

#
new_permissions_spec

fn new_permissions_spec(values? : Map[String, String]) -> PermissionsSpec

#
new_push_event

fn new_push_event(ref_name : String, changed_paths : Array[String], before_sha? : String, after_sha? : String, repository? : String, actor? : String) -> PushEvent

#
new_push_trigger

fn new_push_trigger(branches? : Array[String], branches_ignore? : Array[String], paths? : Array[String], paths_ignore? : Array[String], tags? : Array[String], tags_ignore? : Array[String]) -> PushTrigger

#
new_run_defaults

fn new_run_defaults(shell? : String?, working_directory? : String?) -> RunDefaults

#
new_run_step

fn new_run_step(id : String, run : String, name? : String, shell? : String?, working_directory? : String?, env? : Map[String, String], if_condition? : String, with_values? : Map[String, String], continue_on_error? : String, timeout_minutes? : Int) -> StepSpec

#
new_shell_env

fn new_shell_env(vars : Map[String, String], cwd? : String, write_file? : (String, String, Bool) -> Bool, read_file? : (String) -> String?, file_exists? : (String) -> Bool, is_dir? : (String) -> Bool, mkdir? : (String) -> Bool, remove? : (String) -> Bool) -> ShellEnv

#
new_task_plan

fn new_task_plan(id : String, kind : String, job_id : String, step_id : String, name : String, script : String, shell : String, working_directory : String, if_condition : String, runs_on : Array[String], env : Map[String, String], with_values? : Map[String, String], action? : ResolvedAction?, action_scope? : String?, requires_action_started? : Bool, continue_on_error? : String, timeout_minutes? : Int) -> TaskPlan

#
new_uses_step

fn new_uses_step(id : String, uses : String, name? : String, env? : Map[String, String], if_condition? : String, with_values? : Map[String, String], continue_on_error? : String, timeout_minutes? : Int) -> StepSpec

#
new_workflow

fn new_workflow(name : String, jobs : Array[JobSpec], run_name? : String, trigger? : PushTrigger, pull_request_trigger? : PushTrigger?, workflow_call? : Bool, workflow_call_spec? : WorkflowCallSpec?, permissions? : PermissionsSpec?, concurrency? : ConcurrencySpec?, env? : Map[String, String], defaults? : RunDefaults) -> WorkflowSpec

#
new_workflow_call_input_spec

fn new_workflow_call_input_spec(description? : String, required? : Bool, default_value? : String?, input_type? : String) -> WorkflowCallInputSpec

#
new_workflow_call_output_spec

fn new_workflow_call_output_spec(description? : String, value? : String) -> WorkflowCallOutputSpec

#
new_workflow_call_secret_spec

fn new_workflow_call_secret_spec(required? : Bool) -> WorkflowCallSecretSpec

#
new_workflow_call_spec

fn new_workflow_call_spec(inputs? : Map[String, WorkflowCallInputSpec], outputs? : Map[String, WorkflowCallOutputSpec], secrets? : Map[String, WorkflowCallSecretSpec]) -> WorkflowCallSpec

#
optimize_wasm_module

fn optimize_wasm_module(bytes : Bytes, level? : String) -> WasmOptimizeResult

#
override_workflow_steps

fn override_workflow_steps(workflow : WorkflowSpec, overrides : Map[String, String]) -> WorkflowSpec

#
parse_action_ref

fn parse_action_ref(text : String) -> ActionRefParseResult

#
parse_github_push_event_json

fn parse_github_push_event_json(text : String) -> PushEventJsonParseResult

#
parse_local_action_yaml

fn parse_local_action_yaml(text : String) -> LocalActionParseResult

#
parse_workflow_yaml

fn parse_workflow_yaml(text : String) -> WorkflowParseResult

#
plan_result_to_json

fn plan_result_to_json(result : PlanResult) -> String

#
plan_workflow

fn plan_workflow(yaml_text : String, workspace_root? : String) -> PlanResult

#
prefetch_workflow_github_actions_native

async fn prefetch_workflow_github_actions_native(workflow : WorkflowSpec, workspace_root : String, git_bin? : String?, github_base_url? : String?) -> GitHubActionPrefetchResult

#
read_sandbox_results

fn read_sandbox_results(sandbox : WasmSandbox) -> WasmSandboxResult

Read results from the sandbox after WASM execution.

#
registry_module_path

fn registry_module_path(name : String, version : String) -> String

WASM module registry route. GET /modules/{name}/{version}/main.wasm → binary

#
resolve_action_ref

fn resolve_action_ref(action : ActionRef) -> ActionResolutionResult

#
resolve_action_uses

fn resolve_action_uses(text : String) -> ActionResolutionResult

#
resolve_wasm_runner_command

fn resolve_wasm_runner_command(wasm_bin : String, wasm_args : Array[String], workspace_root : String) -> (String, Array[String])

Backward-compatible wrapper that infers runner kind from the configured binary.

#
select_workflow_job

fn select_workflow_job(workflow : WorkflowSpec, job_id : String) -> WorkflowSpec

#
select_workflow_step

fn select_workflow_step(workflow : WorkflowSpec, job_id : String, step_id : String) -> WorkflowSpec

#
shell_exec

fn shell_exec(env : ShellEnv, script : String) -> Int

#
shell_stderr

fn shell_stderr(env : ShellEnv) -> String

#
shell_stdout

fn shell_stdout(env : ShellEnv) -> String

#
step_matches_skip_pattern

fn step_matches_skip_pattern(step : StepSpec, patterns : Array[String]) -> Bool

#
store_env_path

fn store_env_path(run_id : String) -> String

#
store_mode_from_env

fn store_mode_from_env(env : Map[String, String]) -> StoreMode

#
store_outputs_path

fn store_outputs_path(run_id : String, step_id : String) -> String

HTTP API route definitions. These are path templates — the dispatcher fills in {run_id} and {step_id}.

#
store_path_path

fn store_path_path(run_id : String) -> String

#
store_step_result_path

fn store_step_result_path(run_id : String, step_id : String) -> String

#
store_summary_path

fn store_summary_path(run_id : String, step_id : String) -> String

#
strip_unsupported_workflow_fields

fn strip_unsupported_workflow_fields(workflow : WorkflowSpec) -> WorkflowSpec