Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

act — Administrator & Developer Guide

Generated May 2026 from nektos/act at bd86152

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

1. Architecture Overview

act is a Go CLI that reads GitHub Actions workflow files (.github/workflows/*.yml), parses them into an execution plan of stages and jobs, and runs each job inside a Docker container configured to emulate GitHub's hosted runner environment. The tool reproduces environment variables, filesystem layout, event payloads, matrix fan-out, secret masking, and action resolution — all driven from a single binary with zero external dependencies beyond Docker.

How It Works

CLI (cmd/root.go)
  ├── Workflow Parser (pkg/model/)
  │     ├── planner.go  — reads YAML, builds Plan of Stages/Runs
  │     ├── workflow.go — Job, Step, Strategy, Matrix deserialization
  │     └── action.go   — action.yml parsing (node/docker/composite)
  │
  ├── Runner Engine (pkg/runner/)
  │     ├── runner.go         — NewPlanExecutor, concurrent stage dispatch
  │     ├── job_executor.go   — single job lifecycle (setup → steps → post)
  │     ├── run_context.go    — job-level state (env, secrets, contexts)
  │     ├── step_run.go       — `run:` steps (shell commands)
  │     ├── step_action_local.go  — `uses: ./path` local actions
  │     ├── step_action_remote.go — `uses: owner/repo@ref` remote actions
  │     ├── step_docker.go    — `uses: docker://` steps
  │     ├── action_composite.go   — composite action expansion
  │     ├── expression.go     — ${{ }} expression evaluation
  │     └── reusable_workflow.go  — workflow_call support
  │
  ├── Container Layer (pkg/container/)
  │     ├── docker_run.go     — container lifecycle (create/start/exec/remove)
  │     ├── docker_pull.go    — image pulling with auth
  │     ├── docker_build.go   — local Dockerfile builds
  │     ├── docker_network.go — network create/remove
  │     ├── host_environment.go — host-mode execution (no container)
  │     └── docker_socket.go  — socket discovery and validation
  │
  ├── Services
  │     ├── Artifact Server (pkg/artifacts/)   — v1 + v4 HTTP endpoints
  │     ├── Cache Server (pkg/artifactcache/)  — GitHub Actions cache API
  │     └── Expression Parser (pkg/exprparser/) — GitHub expression language
  │
  └── Utilities
        ├── pkg/common/       — executor framework, logging, auth tokens
        ├── pkg/model/        — GitHub context, planner, workflow types
        ├── pkg/filecollector/ — tar/copy with gitignore support
        ├── pkg/workflowpattern/ — glob pattern matching for triggers
        ├── pkg/schema/       — JSON Schema validation for workflows
        ├── pkg/lookpath/     — cross-platform executable lookup
        └── pkg/gh/           — GitHub CLI token retrieval

Component Inventory

Component Path Role
CLI entry point main.go → cmd/root.go Cobra command setup, flag parsing, .actrc loading
Workflow model pkg/model/ YAML parsing, planning, job/step type system
Runner engine pkg/runner/ Job execution, step dispatch, expression evaluation
Container layer pkg/container/ Docker API interactions, host env fallback
Artifact server pkg/artifacts/ Local HTTP server emulating GitHub Artifacts API
Cache server pkg/artifactcache/ Local HTTP server emulating GitHub Actions Cache API
Expression parser pkg/exprparser/ ${{ }} expression interpreter
Schema validator pkg/schema/ JSON Schema validation for workflow/action YAML
File collector pkg/filecollector/ Tar archive creation with .gitignore support
Workflow patterns pkg/workflowpattern/ Path filter pattern matching

Technology Stack

Layer Technology
Language Go 1.25
CLI framework spf13/cobra + spf13/pflag
Docker client moby/moby/client
Git operations go-git/go-git/v5
YAML parsing gopkg.in/yaml.v3
Logging sirupsen/logrus
Schema validation rhysd/actionlint + xeipuuv/gojsonschema
Interactive prompts AlecAivazis/survey/v2
Persistent cache DB go.etcd.io/bbolt via timshannon/bolthold
Protobuf (artifacts v4) google.golang.org/protobuf

Note

act uses the Docker Engine API directly — it does not shell out to the docker CLI. This means Docker Desktop, Colima, Podman (with Docker-compatible socket), or any Docker API-compatible daemon works.

Data Flow: Workflow Execution

1. CLI parses args + .actrc → Input struct
2. WorkflowPlanner reads .github/workflows/*.yml → Plan (Stages → Runs)
3. Runner.NewPlanExecutor dispatches Stages sequentially
4. Each Stage runs its Runs (jobs) concurrently (up to --concurrent-jobs)
5. JobExecutor for each Run:
   a. Creates Docker container with platform image
   b. Copies workspace (or bind-mounts)
   c. Resolves and caches actions
   d. Executes steps: run → shell exec, uses → action dispatch
   e. Evaluates ${{ }} expressions, if conditions
   f. Collects outputs, manages step results
   g. Runs post-steps in reverse order
   h. Removes container (unless --reuse)
6. Artifact/Cache servers handle uploads/downloads during execution

2. System Requirements

Component Requirement
Docker Engine v17.09+ (API v1.25+), v20.10+ recommended
Docker API v1.41+ required for --container-architecture
Go (build only) 1.25+
Git Required for repository operations
Operating System Linux, macOS, Windows (WSL2 recommended)
Platform support linux/amd64 (native), linux/arm64, others via QEMU

Important

On Windows, act requires WSL2 or Docker Desktop with WSL2 backend. Native Windows containers are not supported. The Docker socket location varies by platform — see Docker Socket Discovery below.

3. Configuration Reference

CLI Flags — Complete Reference

Operational Flags

Flag Short Type Default Description
[event] positional push Event name to trigger. Falls back to push; if workflow handles only one event, uses that
--job -j string Run a specific job by ID
--watch -w bool false Watch working directory and re-run on file changes
--list -l bool false List workflows (tabular: Stage, Job ID, Job name, Workflow, File, Events)
--graph -g bool false Draw ASCII workflow dependency graph
--validate bool false Validate workflow YAML without running
--strict bool false Enable strict schema validation
--dryrun -n bool false Validate workflows without creating containers
--detect-event bool false Auto-detect event type from the first workflow

Container Configuration

Flag Short Type Default Description
--platform -P string[] Map runner labels to Docker images (e.g., -P ubuntu-latest=image:tag)
--container-architecture string host arch OS/architecture for containers (e.g., linux/amd64)
--container-daemon-socket string auto-detect Docker daemon socket URI (e.g., unix://~/.docker/run/docker.sock, or - to disable mount)
--container-options string Extra docker run options passed to job containers
--container-cap-add string[] Kernel capabilities to add (e.g., SYS_PTRACE). Deprecated — use --container-options --cap-add=SYS_PTRACE
--container-cap-drop string[] Kernel capabilities to remove. Deprecated — use --container-options
--privileged bool false Run containers in privileged mode. Deprecated — use --container-options --privileged
--userns string User namespace mode. Deprecated — use --container-options
--network string host Docker network name for job containers
--reuse -r bool false Keep containers after successful runs
--rm bool false Auto-remove containers/volumes on workflow failure
--bind -b bool false Bind-mount working directory instead of copying
--pull -p bool true Pull Docker images even if present locally
--rebuild bool true Rebuild local Docker action images even if present

Warning

--privileged, --userns, --container-cap-add, and --container-cap-drop are deprecated. Use --container-options with Docker CLI syntax instead. These flags will be removed in a future version.

Secrets, Env, Variables, and Inputs

Flag Short Type Default Description
--secret -s string[] Secret with optional value (e.g., -s NAME=value or -s NAME)
--secret-file string .secrets Path to secrets file (dotenv or YAML)
--env string[] Environment variable with optional value
--env-file string .env Path to environment file (dotenv or YAML)
--var string[] Variable with optional value
--var-file string .vars Path to variables file
--input string[] Action input (e.g., --input name=value)
--input-file string .input Path to inputs file
--insecure-secrets bool false Print secrets in logs (not recommended)

Path and Workflow Configuration

Flag Short Type Default Description
--directory -C string . Working directory
--workflows -W string ./.github/workflows/ Path to workflow files
--no-recurse bool false Don't search workflow subdirectories
--eventpath -e string Path to event JSON file
--defaultbranch string auto-detect Main branch name
--remote-name string origin Git remote name for repo URL detection

Actor and GitHub Instance

Flag Short Type Default Description
--actor -a string nektos/act User that triggered the event
--github-instance string github.com GitHub instance (for GHE)
--replace-ghe-action-with-github-com string[] GHE actions to redirect to github.com
--replace-ghe-action-token-with-github-com string PAT for private github.com actions (used with above)

Artifact Server

Flag Type Default Description
--artifact-server-path string (disabled) Storage directory. Server only starts if set
--artifact-server-addr string outbound IP Bind address
--artifact-server-port string 34567 Listen port

Cache Server

Flag Type Default Description
--no-cache-server bool false Disable the built-in cache server
--cache-server-path string ~/.cache/actcache Cache storage directory
--cache-server-addr string outbound IP Bind address
--cache-server-port uint16 0 (random) Listen port
--cache-server-external-url string External URL if behind a proxy

Action Cache

Flag Type Default Description
--action-cache-path string ~/.cache/act Directory for cached actions and host workspaces
--action-offline-mode bool false Use cached actions without fetching. Disables --pull
--use-new-action-cache bool false Enable Go-git-based action cache
--local-repository string[] Map remote action refs to local paths

Output and Logging

Flag Short Type Default Description
--verbose -v bool false Debug-level output
--quiet -q bool false Suppress step output
--json bool false JSON-formatted log output
--log-prefix-job-id bool false Use job ID instead of full name in log prefix

Execution Control

Flag Type Default Description
--matrix string[] Filter matrix combinations (e.g., --matrix os:ubuntu-latest)
--no-skip-checkout bool false Run actions/checkout instead of local file copy
--use-gitignore bool true Exclude .gitignore paths from container copy
--concurrent-jobs int num CPUs Maximum concurrent jobs

Utility Flags

Flag Type Description
--bug-report bool Print system info for bug reports
--man-page bool Print generated man page to stdout
--list-options bool Print flags as JSON
--version bool Print version
--help bool Print help

Environment Variables

Variable Purpose
DOCKER_HOST Docker daemon URI (overridden by --container-daemon-socket)
ACT_DISABLE_VERSION_CHECK Set to 1 to suppress startup version notices
XDG_CACHE_HOME Override cache base directory (default: ~/.cache)
CLICOLOR Controls colored output in graph drawing
NORAW Disables raw terminal mode for Docker attach

Tip

Variables ACT_ACTOR, ACT_REPOSITORY, and ACT_OWNER are used in tests to override the actor, repository, and owner. They are not part of the normal user-facing API.

Configuration File Format

The .actrc file is a line-per-flag format with environment variable expansion:

# Comments are not supported — every non-empty line is treated as an argument
-P ubuntu-latest=catthehacker/ubuntu:act-latest
-P ubuntu-22.04=catthehacker/ubuntu:act-22.04
--container-architecture linux/amd64
--artifact-server-path ${HOME}/.act-artifacts
--action-offline-mode

Lines starting with - are split at the first whitespace to separate flag from value. Lines without - prefix are ignored when split=true (the default for config loading).

4. Deployment & Scaling

Building from Source

git clone https://github.com/nektos/act.git
cd act
go build -o act .
# Verify
./act --version

The VERSION file at the repository root is embedded at compile time via //go:embed.

GoReleaser Configuration

act uses GoReleaser (.goreleaser.yml) for cross-platform release builds. Release artifacts include binaries for Linux, macOS, and Windows across amd64/arm64, plus a Chocolatey NuGet package (act-cli.nuspec).

Docker Socket Discovery

act searches for the Docker socket in a platform-specific order:

  1. DOCKER_HOST environment variable (if set)
  2. --container-daemon-socket flag (if provided)
  3. Common socket locations checked in order:
    • /var/run/docker.sock
    • /run/podman/podman.sock
    • $HOME/.docker/run/docker.sock
    • $HOME/.colima/default/docker.sock
    • $XDG_RUNTIME_DIR/docker.sock
    • $XDG_RUNTIME_DIR/podman/podman.sock
    • \\.\pipe\docker_engine (Windows)

Note

If --container-daemon-socket is set to -, act will not bind-mount the Docker socket into job containers. This is useful for security-sensitive environments where container-in-container access should be prevented.

Scaling Considerations

  • Concurrent jobs: Controlled by --concurrent-jobs. Defaults to CPU count. Each job creates its own container.
  • Disk usage: Each job copies the workspace into the container (unless --bind is used). Large repos multiply disk usage by job count.
  • Network: The host network mode (default) shares the host network stack. Named networks provide isolation but require address configuration for artifact/cache servers.
  • Cache server: Uses BoltDB (bbolt) for metadata and filesystem for blobs. Not designed for multi-process concurrent access.

5. Operations

Cache Management

Action cache (~/.cache/act/ by default):

  • Stores cloned action repositories (bare git repos when using --use-new-action-cache)
  • Host workspaces for jobs
  • Clean with: rm -rf ~/.cache/act/

Artifact cache (~/.cache/actcache/ by default):

  • BoltDB database + artifact blob files
  • Stores GitHub Actions cache entries (keys, versions, content)
  • Clean with: rm -rf ~/.cache/actcache/

Tip

The cache server supports garbage collection internally. Caches that haven't been accessed are candidates for removal based on the BoltDB Complete and UsedAt timestamps.

Monitoring Execution

Use --verbose (-v) for debug-level logs showing:

  • Docker API calls (pull, create, start, exec)
  • Expression evaluation results
  • Action resolution and caching decisions
  • Environment variable loading

Use --json for structured log output parseable by tools like jq:

act --json 2>&1 | jq 'select(.msg | contains("Run Main"))'

Note

Log output goes to stderr. Step output (the actual command outputs) goes to stdout. Use --quiet to suppress step output.

Version Notices

act checks https://api.nektosact.com/notices on each run (unless ACT_DISABLE_VERSION_CHECK=1). The check uses HTTP conditional GET (ETag caching) to minimize bandwidth. Notices are displayed after the workflow run with a 1-second timeout — they never block execution.

6. Performance

Image Pull Optimization

  • Default: --pull=true — always pulls images (ensures latest version)
  • Fast iteration: --pull=false — uses local image if available
  • Offline: --action-offline-mode — no network at all

Workspace Copy vs Bind

Mode Flag Speed Safety
Copy (default) none Slower start, full isolation Workflows cannot modify host files
Bind mount --bind / -b Instant start Workflows can modify host files

Action Caching

Two cache implementations:

Cache Flag Method Best for
Default none git clone via shell Reliability
Go-git --use-new-action-cache In-process bare git + go-git Speed, offline mode

The Go-git cache resolves refs to SHAs, stores bare repos, and extracts files via tree walking — avoiding shell subprocess overhead.

Offline Mode

--action-offline-mode skips all network fetches:

  • Docker pull is forced off
  • Action cache uses existing clones without fetch
  • Requires prior run to populate caches

7. Security

Secret Handling

  • Secrets are masked in output by default using pattern matching against the *[]string masks context
  • --insecure-secrets disables masking (logs will show secret values)
  • Secrets are case-insensitive (stored as uppercase keys internally)
  • Secret values can be provided interactively (terminal password prompt) if not set inline or via environment

Caution

--insecure-secrets should never be used in CI pipelines or shared terminal sessions. Secret values will be visible in all log output.

Docker Socket Access

By default, act bind-mounts the Docker socket into job containers. This provides Docker-in-Docker capability but gives containers full Docker API access.

  • Use --container-daemon-socket - to disable socket mounting
  • Use --container-cap-drop or --container-options --cap-drop=ALL to restrict capabilities

GitHub Token

If no GITHUB_TOKEN secret is provided, act attempts to retrieve one from the gh CLI by running gh auth token. This uses the logged-in user's token.

Warning

Be aware that the auto-detected token may be scoped to a different GitHub instance (e.g., GHE) than expected. Pass tokens explicitly in multi-instance environments. (See GitHub issue #6077)

Authorization Tokens (Internal)

The artifact cache server uses JWT tokens for request authorization:

  • Tokens are signed with HMAC-SHA256 using a randomly generated key per session
  • Token claims include TaskID, RunID, JobID, and ac (action cache scope)
  • Tokens are validated on every cache API request

Path Traversal Protection

The artifact server uses safeResolve() to prevent path traversal attacks:

func safeResolve(baseDir string, relPath string) string {
    return filepath.Join(baseDir, filepath.Clean(filepath.Join(string(os.PathSeparator), relPath)))
}

Symlink resolution in action steps enforces depth limits (max depth %d of symlinks exceeded) and boundary checks (symlink tries to access file outside of).

Input Validation

  • Workflow YAML is validated against JSON Schema (pkg/schema/workflow_schema.json, pkg/schema/action_schema.json)
  • Expression parser validates function calls against known function signatures with arity checks
  • Job names are validated against the regex pattern [a-zA-Z_][a-zA-Z0-9_-]*

8. Developer Internals

Repository Structure

act/
├── main.go                  — entry point, embeds VERSION
├── main_test.go             — smoke test
├── Makefile                 — build targets
├── go.mod / go.sum          — Go module definition
├── VERSION                  — version string (embedded at compile)
├── install.sh               — shell installer script
├── .goreleaser.yml          — release automation config
├── .golangci.yml            — linter configuration
├── .actrc                   — default config (project-level)
├── act-cli.nuspec           — Chocolatey package spec
│
├── cmd/                     — CLI layer
│   ├── root.go              — Cobra root command, all flags, run logic
│   ├── input.go             — Input struct (all CLI options)
│   ├── secrets.go           — Secret parsing with interactive prompt
│   ├── platforms.go         — Default platform mapping
│   ├── list.go              — `--list` tabular output
│   ├── graph.go             — `--graph` ASCII art
│   ├── notices.go           — Version notice fetching (nektosact.com)
│   └── dir.go               — Home/cache directory resolution
│
├── pkg/model/               — Workflow data model
│   ├── workflow.go          — Workflow, Job, Step, Strategy, Defaults types
│   ├── action.go            — Action definition (runs.using, inputs, outputs)
│   ├── planner.go           — WorkflowPlanner: read YAML → Plan/Stages/Runs
│   ├── github_context.go    — GitHub context (ref, sha, repository, owner)
│   ├── job_context.go       — Job context type
│   ├── step_result.go       — Step result status enum
│   └── anchors.go           — YAML anchor/alias cycle detection
│
├── pkg/runner/              — Execution engine
│   ├── runner.go            — Runner interface, Config struct, plan executor
│   ├── job_executor.go      — Job lifecycle (container → steps → cleanup)
│   ├── run_context.go       — RunContext: state, env, binds, GitHub context
│   ├── step.go              — Step interface, conditional evaluation
│   ├── step_run.go          — Shell command execution
│   ├── step_action_local.go — Local action dispatch
│   ├── step_action_remote.go— Remote action fetch + dispatch
│   ├── step_docker.go       — docker:// URL action dispatch
│   ├── step_factory.go      — Step type routing
│   ├── action.go            — Action reading (action.yml/yaml/Dockerfile)
│   ├── action_composite.go  — Composite action step expansion
│   ├── action_cache.go      — GoGitActionCache (bare git repos)
│   ├── action_cache_offline_mode.go — Offline cache wrapper
│   ├── local_repository_cache.go   — Local repo override cache
│   ├── expression.go        — Expression evaluator wiring
│   ├── reusable_workflow.go — workflow_call support
│   ├── command.go           — Workflow command processing (set-env, add-path, etc.)
│   └── logger.go            — Job/step logging with secret masking
│
├── pkg/container/           — Docker abstraction layer
│   ├── container_types.go   — NewContainerInput, FileEntry, build/pull inputs
│   ├── docker_run.go        — Container lifecycle (create/start/exec/copy/remove)
│   ├── docker_pull.go       — Image pull with auth
│   ├── docker_build.go      — Dockerfile build executor
│   ├── docker_images.go     — Image existence/removal
│   ├── docker_network.go    — Network create/remove
│   ├── docker_volume.go     — Volume removal
│   ├── docker_auth.go       — Docker registry auth from config
│   ├── docker_cli.go        — Container option parsing (1,135 lines)
│   ├── docker_logger.go     — Docker log message parsing
│   ├── docker_socket.go     — Socket discovery + SocketAndHost
│   ├── docker_stub.go       — Stub implementations (unsupported platforms)
│   ├── host_environment.go  — Host execution mode (no Docker)
│   ├── executions_environment.go — ExecutionsEnvironment interface
│   ├── linux_container_environment_extensions.go — Container path helpers
│   ├── parse_env_file.go    — Environment file parser (GITHUB_ENV format)
│   ├── util.go              — UID/GID detection (Linux)
│   ├── util_windows.go      — Windows UID stub
│   ├── util_openbsd_mips64.go — OpenBSD stub
│   └── util_plan9.go        — Plan9 stub
│
├── pkg/artifacts/           — Artifact server (v1 + v4)
│   ├── server.go            — HTTP routes for upload/download (v1 API)
│   ├── artifacts_v4.go      — Protobuf-based v4 API routes
│   └── artifact.pb.go       — Generated protobuf types
│
├── pkg/artifactcache/       — Cache server
│   ├── handler.go           — HTTP handler, BoltDB storage, JWT auth
│   ├── model.go             — Cache request/response types
│   ├── storage.go           — Blob storage (filesystem)
│   └── doc.go               — Package documentation
│
├── pkg/exprparser/          — Expression language interpreter
│   ├── interpreter.go       — ${{ }} evaluation engine
│   └── functions.go         — Built-in functions (contains, startsWith, hashFiles, etc.)
│
├── pkg/schema/              — Workflow validation
│   ├── schema.go            — JSON Schema validator
│   ├── workflow_schema.json — GitHub Actions workflow schema
│   └── action_schema.json   — GitHub Actions action.yml schema
│
├── pkg/filecollector/       — File collection for container copy
│   └── file_collector.go    — TarCollector, CopyCollector with gitignore
│
├── pkg/workflowpattern/     — Path filter patterns
│   └── workflow_pattern.go  — Glob-style pattern matching for triggers
│
├── pkg/common/              — Shared utilities
│   ├── executor.go          — Executor functional pattern (Pipeline, Parallel, Conditional)
│   ├── context.go           — Graceful cancellation (SIGINT/SIGTERM)
│   ├── logger.go            — Context-scoped logging
│   ├── auth.go              — JWT token generation/validation
│   ├── draw.go              — ASCII box/arrow drawing
│   ├── dryrun.go            — Dry-run context flag
│   ├── file.go              — CopyFile/CopyDir helpers
│   ├── job_error.go         — Job error context
│   ├── line_writer.go       — Line-buffered writer
│   ├── outbound_ip.go       — Outbound IP detection
│   └── cartesian.go         — Cartesian product (matrix expansion)
│
├── pkg/lookpath/            — Cross-platform executable lookup
│   ├── lp_unix.go           — Unix PATH lookup
│   ├── lp_windows.go        — Windows PATH + PATHEXT lookup
│   ├── lp_plan9.go          — Plan9 stub
│   └── lp_js.go             — JS/WASM stub
│
└── pkg/gh/                  — GitHub CLI integration
    └── gh.go                — Token retrieval via `gh auth token`

Architecture Deep Dive

Executor Pattern

The core abstraction is common.Executor — a function func(context.Context) error. All operations (container create, step run, file copy) are executors composed with combinators:

  • NewPipelineExecutor(a, b, c) — sequential
  • NewParallelExecutor(n, a, b, c) — concurrent with limit n
  • NewConditionalExecutor(cond, ifTrue, ifFalse) — branching
  • .Then(next) — chaining
  • .If(cond) / .IfNot(cond) — conditional execution
  • .Finally(cleanup) — guaranteed cleanup
  • .OnError(handler) — error handling

This makes the execution pipeline declarative and composable while keeping error propagation clean.

Workflow Planning

WorkflowPlanner (pkg/model/planner.go) reads all YAML files, builds a dependency graph based on needs: declarations, and produces a Plan:

type Plan struct {
    Stages []*Stage  // Stages run sequentially
}

type Stage struct {
    Runs []*Run      // Runs within a stage run concurrently
}

type Run struct {
    Workflow *Workflow
    JobID    string
}

Planning supports filtering by event name (PlanEvent), job ID (PlanJob), or all jobs (PlanAll).

Expression Evaluation

The pkg/exprparser/ package implements the full GitHub Actions expression language:

  • Literals: null, true, false, numbers, strings
  • Operators: ==, !=, &&, ||, !, <, >, <=, >=
  • Contexts: github, env, secrets, steps, matrix, needs, inputs, vars, runner, job
  • Functions: contains(), startsWith(), endsWith(), format(), join(), toJSON(), fromJSON(), hashFiles(), success(), failure(), cancelled(), always()

The interpreter uses rhysd/actionlint for parsing and implements its own evaluation with type coercion matching GitHub's behavior.

Container Options Parsing

pkg/container/docker_cli.go (1,135 lines) implements a comprehensive Docker CLI option parser that accepts all standard docker run flags. This is used when --container-options is passed to transform CLI-style flags into Docker API container.Config and container.HostConfig structs. Supported flags include volumes, ports, devices, memory limits, healthchecks, network config, security options, and more.

Action Resolution

Actions are resolved in order:

  1. Local actions (uses: ./path): Read from workspace, follow symlinks (depth-limited)
  2. Remote actions (uses: owner/repo@ref): Clone from GitHub (or cache), extract action.yml
  3. Docker URL (uses: docker://image): Pull and run directly
  4. Composite actions: Expand steps recursively with isolated run contexts

The action reader looks for action.yml → action.yaml → Dockerfile (synthetic action) → trampoline.js (synthetic node action with args).

Service Containers

Service containers (job.services) are started before the job and connected to the job's Docker network. Health checks are supported — the job waits for services to become healthy before proceeding with steps.

Module Reference

cmd/root.go — CLI Entry Point (776 lines)

The central orchestration file. createRootCommand() defines all 60+ flags. newRunCommand() is the main run handler that:

  1. Discovers Docker socket
  2. Loads envs, secrets, vars, inputs from files
  3. Auto-retrieves GITHUB_TOKEN from gh CLI
  4. Plans workflow execution
  5. Configures runner with Config struct
  6. Starts artifact/cache servers
  7. Dispatches execution (or watch mode)

pkg/runner/runner.go — Runner Engine (226 lines)

Defines Runner interface with NewPlanExecutor() method. The runnerImpl dispatches stages sequentially and jobs within each stage concurrently (up to ConcurrentJobs). Failed jobs are reported with Job '%s' failed errors.

pkg/runner/run_context.go — Job State (1,153 lines)

The RunContext struct holds all job-level state:

  • Container reference and environment
  • Step results and outputs
  • GitHub context (event, ref, sha, etc.)
  • Expression evaluator factory
  • Service container management
  • Binds and mounts resolution

Key method Executor() builds the job lifecycle executor: container setup → step execution → cleanup.

pkg/runner/expression.go — Expression Wiring (401 lines)

Bridges the runner context with the expression parser. Populates the EvaluationEnvironment with all GitHub Actions contexts (github.*, env.*, secrets.*, steps.*, matrix.*, needs.*, runner.*, job.*, inputs.*, vars.*).

pkg/container/docker_run.go — Container Lifecycle (913 lines)

Implements the full Docker container lifecycle:

  • NewContainer() — creates container reference
  • Create() — Docker API container creation with config
  • Start() — starts container with optional attach
  • Exec() — runs commands inside container
  • Copy() / CopyDir() — file transfer to container
  • Remove() — cleanup
  • GetDockerClient() — creates Docker API client from DOCKER_HOST

pkg/artifactcache/handler.go — Cache Server (569 lines)

Implements the GitHub Actions cache API:

  • POST /_apis/artifactcache/cache — reserve cache entry
  • PATCH /_apis/artifactcache/caches/:id — upload cache blob
  • POST /_apis/artifactcache/caches/:id — commit cache
  • GET /_apis/artifactcache/cache — lookup cache by key/version

Uses BoltDB for metadata storage and filesystem for blob storage. JWT authorization protects all endpoints.

Code Patterns and Conventions

Pattern Usage
Executor composition All side effects wrapped in common.Executor functions
Context-scoped state Logger, dry-run flag, job errors stored in context.Context
Interface-based DI ExecutionsEnvironment interface enables Docker/host/stub swapping
Functional options Executor combinators (.Then(), .If(), .Finally())
Embed directives VERSION file, trampoline.js, schema JSON embedded at compile
Table-driven tests All test files use t.Run() with test case tables
Platform build tags util_windows.go, util_openbsd_mips64.go, lp_unix.go etc.

Testing Strategy

  • Unit tests: Extensive in every package. Table-driven with testify/assert.
  • Integration tests: pkg/runner/runner_test.go (782 lines) runs real workflows against Docker.
  • Test fixtures: pkg/runner/testdata/ contains 100+ workflow scenarios covering:
    • Matrix strategies, composite actions, reusable workflows
    • Service containers, environment files, secret handling
    • Docker actions (local, remote, URL), Node.js actions (12/16/20)
    • Shell variants (bash, sh, python, pwsh, cmd)
    • Edge cases (spaces in paths, nested composites, symlinks)
  • Mock containers: container_mock_test.go provides test doubles for the container interface.
  • Linting: golangci-lint (.golangci.yml), codespell (.codespellrc), markdownlint, megalinter, prettierrc.

Potential Improvements

Based on code analysis and community issues:

  • OIDC token support: Currently unsupported — actions needing ACTIONS_ID_TOKEN_REQUEST_URL fail. Would require a local OIDC provider or mock.
  • Job-level strategy.job-index / strategy.job-total: Missing from strategy context (GitHub issue #5976).
  • Git worktree support: .git file reconstitution for container mounts (GitHub issue #6074).
  • Concurrent instance locking: No coordination between multiple act processes (GitHub issue #6061).
  • Network-scoped artifact/cache servers: When --network is not host, servers need explicit address configuration (GitHub issue #5996).
  • docker_cli.go complexity: At 1,135 lines, the container options parser is a large single file that could benefit from decomposition.

Contributing

  • Code: Go 1.25+, run make for build, make test for tests
  • Linting: golangci-lint run (configuration in .golangci.yml)
  • Tests: Add test workflows in pkg/runner/testdata/ for new features
  • Schema: Update pkg/schema/workflow_schema.json / action_schema.json for new workflow syntax

9. Integration Points

Docker Engine API

act communicates directly with the Docker Engine API via moby/moby/client. Required API operations:

  • Container: Create, Start, Remove, Exec, Inspect, CopyToContainer
  • Image: Pull, Build, List, Remove
  • Network: Create, Remove
  • Volume: Remove
  • System: Info (for bug reports)

GitHub CLI (gh)

act calls gh auth token to retrieve the user's GitHub token when no GITHUB_TOKEN secret is provided. This is a one-time call wrapped in common.EarlyCancelContext with cancellation support.

Artifact Server Endpoints (Internal)

Method Path Protocol Purpose
POST /_apis/pipelines/workflows/:runId/artifacts v1 Create artifact container
PUT /upload/:runId v1 Upload artifact blob
PATCH /_apis/pipelines/workflows/:runId/artifacts v1 Finalize artifact
GET /_apis/pipelines/workflows/:runId/artifacts v1 List artifacts
GET /download/:container v1 Download artifact
GET /artifact/*path v1 Serve artifact file

v4 endpoints use protobuf-encoded requests at /twirp/github.actions.results.api.v1.ArtifactService/*.

Version Notice API

GET https://api.nektosact.com/notices?os={os}&arch={arch}&version={version}

Returns JSON array of {"level": "info|warning", "message": "..."}. Supports ETag-based conditional GET.

10. Troubleshooting

Diagnostic Checklist

  • [ ] Docker daemon is running (docker info)
  • [ ] Docker socket is accessible (ls -la /var/run/docker.sock)
  • [ ] Workflow files exist at the expected path (act -l)
  • [ ] Required secrets are set (-s or --secret-file)
  • [ ] Platform mapping matches runs-on labels (-P)
  • [ ] Network connectivity for action downloads (or --action-offline-mode)
  • [ ] Sufficient disk space for runner images

Error: cache %d: not reserved

Cause: The cache server received a commit request for a cache ID that was never reserved.

Solution: This is typically a race condition in the action. Retry the workflow. If persistent, check that ACTIONS_CACHE_URL is accessible from within the container.

Warning

When using custom Docker networks (--network), the cache server's auto-detected address may not be reachable from containers. Use --cache-server-addr with an address that is routable from the container network.

Error: workflow is not valid. '%s': Job name '%s' is invalid

Cause: Job names must start with a letter or _ and contain only [a-zA-Z0-9_-].

Solution: Rename the job in your workflow YAML to use valid characters.

Error: Actions YAML Schema Validation Error detected

Cause: Workflow YAML doesn't conform to the GitHub Actions schema.

Solution: Visit https://nektosact.com/usage/schema.html for details. Use --validate --strict for detailed error output.

Note

Schema validation errors include context paths showing exactly which YAML key failed validation. The --strict flag enables additional checks that GitHub might not enforce but represent best practices.

Error: unable to determine outbound IP address

Cause: The cache/artifact server couldn't detect the host's outbound IP for binding.

Solution: Specify addresses explicitly:

act --artifact-server-addr 0.0.0.0 --cache-server-addr 0.0.0.0

11. Reference

Supported Action Types

runs.using value Description
node12 Node.js 12 action
node16 Node.js 16 action
node20 Node.js 20 action
docker Docker container action
composite Composite action (nested steps)

Supported Event Types

act supports all GitHub Actions event types. The event name is passed as the first positional argument. Default is push. If a workflow handles only one event, that event becomes the default.

Expression Functions

Function Signature Description
contains contains(search, item) Case-insensitive string/array search
startsWith startsWith(str, prefix) String prefix check
endsWith endsWith(str, suffix) String suffix check
format format(fmt, args...) String formatting with {0} placeholders
join join(array, separator) Array to string
toJSON toJSON(value) Value to JSON string
fromJSON fromJSON(str) JSON string to value
hashFiles hashFiles(patterns...) SHA-256 hash of matching files
success success() Previous steps all succeeded
failure failure() Any previous step failed
cancelled cancelled() Workflow was cancelled
always always() Always true

Workflow Commands Supported

Command Syntax Description
set-env ::set-env name=NAME::VALUE Set environment variable
set-output ::set-output name=NAME::VALUE Set step output
add-path ::add-path::PATH Prepend to PATH
add-mask ::add-mask::VALUE Mask a value in logs
save-state ::save-state name=NAME::VALUE Save state for post steps
stop-commands ::stop-commands::TOKEN Pause command processing
debug ::debug::MESSAGE Debug message
warning ::warning::MESSAGE Warning annotation
error ::error::MESSAGE Error annotation
group ::group::TITLE Begin log group
endgroup ::endgroup:: End log group