Workflow Syntax
run: steps
Shell scripts executed via bash (or configured shell)
uses: actions
GitHub actions, local actions, composite actions, Node.js actions
Job dependencies
needs: with DAG resolution and concurrent executionMatrix strategy
Cartesian product expansion with include/exclude
Expression engine
Full expression evaluation with contexts, operators, and functions
Environment variables
env: at workflow, job, and step levels + $GITHUB_ENVStep outputs
$GITHUB_OUTPUT with multiline delimiter supportJob outputs
jobs.*.outputs evaluated from step outputsConditions
Full expression evaluation in
if: with status functionsTimeouts
timeout-minutes at job and step levelcontinue-on-error
Step failures don’t fail the job
GitHub context
github.sha, github.ref, github.repository, github.actor, etc.Secrets
secrets.* context populated from server environment variablesConcurrency
concurrency: groups with cancel-in-progress supportPermissions
permissions: field parsed at workflow and job levelContainer
container: runs job steps inside a Docker containerServices
services: starts sidecar containers alongside the jobArtifacts
actions/upload-artifact and actions/download-artifact built-in shimsReusable workflows
workflow_call with inputs and secret inheritanceBranch filters
on: push: branches: and branches-ignore: filters$GITHUB_PATH
PATH modifications persist across steps (including in VMs)
Expression Functions
| Function | Description |
|---|---|
contains(search, item) | Case-insensitive string/array search |
startsWith(string, prefix) | Case-insensitive prefix check |
endsWith(string, suffix) | Case-insensitive suffix check |
format(string, args...) | String formatting with {0}, {1} placeholders |
join(array, separator) | Join array elements |
toJSON(value) | Convert to JSON string |
fromJSON(string) | Parse JSON string |
success() | True if job has not failed |
failure() | True if any previous step failed |
always() | Always true |
cancelled() | True if workflow was cancelled |
Expression Contexts
| Context | Description |
|---|---|
github.* | Repository, commit, ref, actor, event info |
env.* | Environment variables |
steps.* | Step outputs and outcomes |
needs.* | Dependent job outputs and results |
matrix.* | Current matrix combination values |
runner.* | Runner OS, architecture, temp directory |
job.* | Current job status |
inputs.* | Workflow/action inputs |
secrets.* | Secret values from server configuration |
Action Support
| Type | Example | Status |
|---|---|---|
| GitHub actions | actions/checkout@v4 | Supported (built-in shim) |
| Setup actions | actions/setup-node@v4, actions/setup-go@v5 | Supported (built-in shim, tools pre-installed) |
| Artifact actions | actions/upload-artifact@v4, actions/download-artifact@v4 | Supported (built-in shim, local storage) |
| Local actions | ./my-action | Supported |
| Composite actions | runs.using: composite | Supported |
| Node.js actions | runs.using: node20 | Supported (requires Node on PATH) |
| Docker actions | docker://image | Not supported |
CI Server Features
| Feature | Description |
|---|---|
| GitHub webhooks | Receives push and pull_request events with branch filtering |
| Commit statuses | Reports pass/fail via the Statuses API |
| Checks API | Full log output per workflow (requires GitHub App) |
| MicroVM isolation | Each job runs in an ephemeral CloudHypervisor VM |
| Parallel VMs | Independent jobs run concurrently, configurable via VM_MAX_PARALLEL |
| virtiofs sharing | Workspace shared between host and VM |
| Web dashboard | Real-time build status with per-step log viewing |
| SSE updates | Live streaming of build progress to the browser |
| Concurrency groups | Prevents concurrent runs of the same workflow/branch |
| Secrets management | SECRET_* env vars exposed as secrets.* context |
| Artifacts | Local artifact storage shared between jobs |
| Container jobs | Run steps inside Docker containers |
| Service containers | Sidecar containers for databases, caches, etc. |
| Reusable workflows | Call other workflow files with inputs and secrets |
Secrets
Secrets are loaded from environment variables on the server. Any env var prefixed withSECRET_ is exposed in the secrets.* context with the prefix stripped.
For example:
${{ secrets.SSH_PRIVATE_KEY }} and ${{ secrets.STRIPE_KEY }}.
Container Support
Jobs can specify a Docker container image. Allrun: steps execute inside the container with the workspace mounted:
localhost:
Container and service support requires Docker to be installed in the VM rootfs.