Audience: Zetken CI/CD Studio beta users and pipeline authors
Current schema: zetken/v1
1. Minimal Studio-managed pipeline
For a pipeline created inside the Zetken browser UI:
schema: zetken/v1
stages:
- name: build
jobs:
- name: test
steps:
- name: Hello
run: echo hello
The Studio stores the pipeline name as managed metadata. A managed pipeline.yaml should not need a duplicate top-level name: field.
2. Core hierarchy
Pipeline
└── stages[]
└── jobs[]
└── steps[]
Rules:
- A pipeline must contain at least one stage.
- A stage must contain at least one job.
- A job must contain at least one step.
- A step must define exactly one executable action.
Executable step actions are:
run
dockerBuild
downloadArtifacts
cache
3. Top-level fields
| Field | Type | Required | Purpose |
|---|---|---|---|
schema |
string | Recommended | Current value: zetken/v1. |
name |
string | Standalone | Standalone pipeline name; Studio-managed pipelines use metadata. |
parameters |
list | No | Runtime parameters. |
workingDir |
string | No | Default working directory. |
shell |
string | No | Default shell. |
envFiles |
list | No | Environment files. |
env |
map | No | Pipeline environment variables. |
stages |
list | Yes | Pipeline stages. |
Use explicitly:
schema: zetken/v1
A missing schema is currently treated as implicit zetken/v1, but Zetken warns that the explicit schema should be added.
4. Stage
Example:
stages:
- name: test
maxParallel: 2
workingDir: .
shell: bash
env:
STAGE_MODE: test
jobs:
...
Fields:
| Field | Type | Required | Purpose |
|---|---|---|---|
name |
string | Yes | Stage name. |
maxParallel |
integer >= 1 | No | Maximum jobs running simultaneously. Default is 1. |
workingDir |
string | No | Stage working directory. |
shell |
string | No | Stage shell. |
env |
map | No | Stage environment variables. |
jobs |
list | Yes | At least one job. |
5. Job
Example:
jobs:
- name: integration-test
needs:
- build
workingDir: backend
shell: bash
env:
TEST_MODE: integration
steps:
...
Fields:
| Field | Type | Required | Purpose |
|---|---|---|---|
name |
string | Yes | Unique job name inside the stage. |
needs |
list or inline value | No | Same-stage dependencies. |
workingDir |
string | No | Job working directory. |
shell |
string | No | Job shell. |
env |
map | No | Job environment variables. |
strategy.matrix |
map | No | Matrix variants. |
steps |
list | Yes | At least one step. |
Dependency validation rejects:
Unknown jobs
Self-dependencies
Duplicate needs entries
Dependency cycles
Specific expanded matrix variants in needs
Use the matrix job's base name when depending on a matrix job.
6. Step
Example:
steps:
- name: Run tests
workingDir: backend
shell: bash
env:
MODE: test
timeout: 5m
retries: 1
retryDelay: 2s
if: success()
continueOnError: false
run: go test ./...
artifacts:
- test-result.txt
Fields:
| Field | Type | Required | Purpose |
|---|---|---|---|
name |
string | Yes | Step name. |
workingDir |
string | No | Step working directory. |
shell |
string | No | Step shell. |
env |
map | No | Step environment variables. |
run |
string/block | One action | Execute a shell command/script. |
dockerBuild |
object | One action | Build a Docker image. |
downloadArtifacts |
object | One action | Download dependency artifacts. |
cache |
object | One action | Restore or save cache. |
artifacts |
list | No | Store files/directories after the action. |
timeout |
duration | No | Maximum step duration. |
retries |
integer >= 0 | No | Retry count after the initial attempt. |
retryDelay |
duration | No | Delay between attempts. |
if |
string | No | Step condition. |
continueOnError |
boolean | No | Continue after this step fails. |
A step must define exactly one of:
run:
dockerBuild:
downloadArtifacts:
cache:
7. run
Single command:
- name: Test
run: go test ./...
Multiline command:
- name: Test and build
run: |
go test ./...
go build ./...
The final run command cannot be empty.
8. Shells
Supported native shell values are currently:
default
cmd
powershell
pwsh
bash
sh
Example:
shell: bash
Shell can be set at:
pipeline
stage
job
step
A more specific value overrides the broader value.
Default shell
Windows:
COMSPEC, otherwise cmd.exe
Linux/macOS:
$SHELL, otherwise /bin/sh
The requested shell executable must exist on PATH. Zetken does not install or bundle external shells.
PowerShell versions
powershell selects Windows PowerShell. pwsh selects PowerShell 7+ and is supported on Windows, Linux, and macOS when the pwsh executable is available on PATH. The values are distinct; Zetken does not fall back from pwsh to powershell.
- name: PowerShell 7 version
shell: pwsh
run: |
Write-Output "PowerShell 7"
$PSVersionTable.PSVersion
9. Environment variables
Pipeline scope:
env:
BUILD_MODE: release
Stage scope:
stages:
- name: build
env:
COMPONENT: backend
Job scope:
jobs:
- name: compile
env:
TARGET: local
Step scope:
steps:
- name: Build
env:
OUTPUT: app
run: echo ${OUTPUT}
Reference an environment variable with:
${VARIABLE}
Environment resolution starts from the operating-system process environment, then applies Zetken environment files and pipeline/stage/job/step values, with more specific scopes overriding broader values.
10. Environment files
Example:
envFiles:
- .env.local
Typical file content:
API_URL=http://localhost:8080
MODE=test
Environment files may contain sensitive values.
Do not intentionally place them into:
artifacts
cache paths
shared reports
source content intended for distribution
11. Parameters
Example:
parameters:
- name: target
type: string
default: dev
allowed:
- dev
- staging
- prod
description: Deployment target
- name: packageName
type: string
required: true
- name: apiToken
type: string
secret: true
Current supported parameter type:
string
Parameter name pattern:
^[A-Za-z_][A-Za-z0-9_]*$
Reference:
${params.target}
Example:
run: echo Deploying ${params.packageName} to ${params.target}
Standalone CLI:
zci run --param target=prod --param packageName=my-app
When allowed is defined, supplied/default values must be in that list.
12. Sensitive values
A parameter can be explicitly marked:
secret: true
Names containing sensitive terms such as:
secret
token
password
passwd
api_key
apikey
private_key
credential
are also treated as sensitive in several masking/protection paths.
Avoid putting secrets into:
artifact names/paths
cache keys
cache paths
Docker image tags
source-controlled YAML
Secret masking is a protection layer, not a substitute for safe secret handling.
13. workingDir
Example at job level:
jobs:
- name: backend-test
workingDir: backend
It may be set at:
pipeline
stage
job
step
The resolved working directory must stay within the project safety boundary.
Do not use parent traversal such as:
../outside-project
14. Parallel jobs with maxParallel
Example:
stages:
- name: test
maxParallel: 3
Default:
1
maxParallel must be an integer greater than or equal to 1.
Only jobs whose dependencies are satisfied are eligible to run.
15. Job dependencies with needs
List:
needs:
- build
- lint
Single inline value is also parsed:
needs: build
Example:
stages:
- name: ci
jobs:
- name: build
steps:
- name: Build
run: go build ./...
- name: test
needs:
- build
steps:
- name: Test
run: go test ./...
If a dependency fails, the dependent job is skipped.
needs currently refers to jobs in the same stage.
16. Matrix jobs
Example:
strategy:
matrix:
dev:
target: dev
mode: debug
prod:
target: prod
mode: release
References:
${matrix.target}
${matrix.mode}
${matrix.name}
Matrix variant name pattern:
^[A-Za-z_][A-Za-z0-9_-]*$
Matrix variable name pattern:
^[A-Za-z_][A-Za-z0-9_]*$
Matrix values should be strings.
Complete example:
stages:
- name: package
maxParallel: 2
jobs:
- name: build
strategy:
matrix:
dev:
target: dev
prod:
target: prod
steps:
- name: Build
run: echo Built ${matrix.target}
- name: summary
needs:
- build
steps:
- name: Summary
run: echo Matrix completed
The dependent summary job depends on the matrix base job build.
17. Conditions
Supported:
success()
failure()
always()
Example:
- name: Cleanup
if: always()
run: echo cleanup
When if is omitted, the default condition is:
success()
18. Timeout and retries
Timeout:
timeout: 2m
Retries:
retries: 2
retryDelay: 5s
Durations use Go-style duration syntax, for example:
250ms
10s
5m
1h
retries: 2 means a maximum of:
3 total attempts
(initial attempt + 2 retries).
19. continueOnError
Example:
- name: Optional check
continueOnError: true
run: ./optional-check
The failure is still recorded, but Zetken can continue with later eligible steps.
20. Artifacts
Example:
- name: Package
run: |
mkdir -p output
echo result > output/result.txt
artifacts:
- output/result.txt
Artifact paths must remain safe relative project paths.
Do not use:
paths outside the project
Zetken runtime storage
environment files
secret-bearing files
21. Job outputs
For a run action, Zetken supplies the temporary environment variable:
ZCI_OUTPUT
Write output values as:
name=value
Output-key pattern:
^[A-Za-z_][A-Za-z0-9_]*$
Bash/sh example:
- name: Produce output
shell: bash
run: |
echo "package=backend.txt" >> "$ZCI_OUTPUT"
PowerShell example:
- name: Produce output
shell: powershell
run: |
Add-Content $env:ZCI_OUTPUT "package=backend.txt"
Consumer:
needs:
- producer
Reference:
${needs.producer.outputs.package}
A job may reference outputs only from jobs listed in its needs.
22. downloadArtifacts
Example:
- name: Download producer artifact
downloadArtifacts:
from: producer
to: downloaded
files:
- backend.txt
overwrite: true
Fields:
| Field | Required | Purpose |
|---|---|---|
from |
Yes | Producer job name. |
to |
Yes | Destination path. |
files |
No | Optional artifact subset. |
overwrite |
No | Replace existing target content. |
The from job must:
- exist in the stage; and
- be included in the consumer job's
needs.
23. Cache
Restore example:
- name: Restore cache
cache:
action: restore
key: go-${hashFiles("go.sum")}
restoreKeys:
- go-
paths:
- .cache/go
overwrite: true
failOnMiss: false
Save example:
- name: Save cache
cache:
action: save
key: go-${hashFiles("go.sum")}
paths:
- .cache/go
Fields:
| Field | Required | Purpose |
|---|---|---|
action |
Yes | restore or save. |
key |
Yes | Exact cache key. |
paths |
Yes | Relative files/directories. |
restoreKeys |
No | Prefix fallbacks during restore. |
overwrite |
No | Restore overwrite behavior. |
failOnMiss |
No | Fail if restore has no match. |
Do not cache environment/secret files or Zetken runtime storage.
24. hashFiles()
Single input:
${hashFiles("go.sum")}
Multiple inputs:
${hashFiles("package-lock.json", "package.json")}
Typical use:
key: node-${hashFiles("package-lock.json", "package.json")}
The fingerprint changes when the matched file content changes, making it useful for cache invalidation.
25. Docker image build
Preferred native syntax:
- name: Build Docker image
dockerBuild:
context: .
dockerfile: Dockerfile
tag: my-app:local
args:
- VERSION=1.0.0
Fields:
| Field | Required | Purpose |
|---|---|---|
context |
No | Build context; empty resolves to .. |
dockerfile |
Yes | Dockerfile path. |
tag |
Yes | Image tag. |
args |
No | Docker build arguments. |
Docker must be installed when this action executes.
The current parser also contains a docker alias, but new pipeline definitions should prefer:
dockerBuild:
26. Expression reference summary
Environment:
${VARIABLE}
Parameter:
${params.name}
Matrix:
${matrix.name}
Dependency output:
${needs.job.outputs.output}
File hash:
${hashFiles("path")}
Malformed or unknown supported-expression references are validation errors.
27. Environment/shell/working-directory inheritance
Zetken supports these values at multiple scopes:
pipeline
→ stage
→ job
→ step
For example:
shell: bash
workingDir: src
env:
MODE: pipeline
stages:
- name: test
env:
MODE: stage
jobs:
- name: unit
workingDir: backend
steps:
- name: Run
env:
MODE: step
run: echo ${MODE}
The more specific scope overrides the broader scope.
Operating-system environment variables are also available unless overridden by Zetken-defined values.
28. Complete Studio-managed example
schema: zetken/v1
parameters:
- name: target
type: string
default: dev
allowed:
- dev
- prod
env:
APP_NAME: demo-app
stages:
- name: validate
maxParallel: 2
jobs:
- name: test
steps:
- name: Test
shell: bash
run: |
echo "Testing ${APP_NAME}"
go test ./...
- name: lint
steps:
- name: Lint
shell: bash
continueOnError: true
run: echo "Run linter here"
- name: package
jobs:
- name: package
steps:
- name: Create package
shell: bash
run: |
mkdir -p output
echo "${APP_NAME}-${params.target}" > output/package.txt
artifacts:
- output/package.txt
Note that needs is job-level and currently references jobs within the same stage. Stages themselves are executed in pipeline order.
29. Cross-platform guidance
The YAML structure can stay the same across operating systems, but shell commands may differ.
Portable example:
schema: zetken/v1
stages:
- name: test
jobs:
- name: go-test
steps:
- name: Run tests
run: go test ./...
This can run on Windows, Linux, and macOS when Go is installed.
OS-specific examples:
Windows:
shell: powershell
run: |
New-Item -ItemType Directory -Force output
Linux/macOS:
shell: bash
run: |
mkdir -p output
A Zetken pipeline does not automatically install the required shell or external CLI.
30. Validation checklist
Before running:
[ ] schema: zetken/v1 is present
[ ] Managed pipeline does not duplicate its UI name unnecessarily
[ ] Standalone pipeline has name:
[ ] Pipeline has at least one stage
[ ] Every stage has at least one job
[ ] Every job has at least one step
[ ] Every step has exactly one executable action
[ ] Every needs target exists in the same stage
[ ] No dependency cycles
[ ] Selected shell is supported
[ ] Selected shell exists on the machine
[ ] workingDir stays inside the project
[ ] Environment variables are defined
[ ] Parameter references are valid
[ ] Matrix references are valid
[ ] Artifact paths are safe
[ ] Cache paths/keys contain no secrets
[ ] External tools used by run commands are installed
In Studio, select:
Validate
Standalone:
zci validate
31. Useful beta findings to report
Please report cases where:
- Migration Assistant says Converted but generated YAML fails native validation.
- Migration generates an unsupported native shell.
needsordering or parallel execution is incorrect.- Environment inheritance behaves unexpectedly.
- A secret is visible in logs.
- An artifact/cache path escapes expected project boundaries.
- An empty stage/job/step is generated during migration.
- Source line numbers point to the wrong location.
- A supposedly portable pipeline behaves differently on Windows, Linux, and macOS.