Pipeline syntax
Complete reference for the OpsNexus YAML pipeline file, with every key, type, default, limit and expression.
On this page
An OpsNexus pipeline file is a YAML file that lists stages and steps. A build agent checks out your code, runs each step in a shell and streams the output back to OpsNexus. This page describes every key the server accepts. The same reference, with a live validator, is in the app under CI/CD → Pipeline syntax.
The file
- The file is YAML. It can have any name ending in
.ymlor.yamland can live in any folder of the repository. - The default path is
.opsnexus.yml. You can set another path per pipeline, for exampleci/build.yaml. - If the file is not found, OpsNexus also tries the other extension (
.opsnexus.ymlalso finds.opsnexus.yaml, and the other way round). - The path must be inside the repository: no leading
/and no... - The file can be at most 256 KB.
- The top level must be a mapping with a
stages:list. - Unknown keys are errors. OpsNexus lists every problem it finds, with the place it found it (for example
stages[2].steps[0].shell).
Instead of keeping the file in Git, you can paste it into the pipeline's settings (Pipeline script). The format is the same. See Pipelines.
Limits
| Item | Limit |
|---|---|
| File size | 256 KB |
| Stages | 50 |
Steps per stage (and per post list) |
100 |
artifacts patterns |
50, each at most 300 characters |
timeout_minutes (anywhere) |
Whole number from 1 to 1440 |
| Stage name | 120 characters (longer names are cut) |
| Parameter value | 10,000 characters |
| Console output stored per build | 5 MB (the rest is not stored) |
Complete example
# .opsnexus.yml (any name ending in .yml or .yaml)
name: web-app
agent: # which build agent runs it (optional)
labels: [linux, docker] # every label must match; os, name and pool count as labels
# pool: linux-build
parameters: # shown on "Build with parameters"
- name: DEPLOY_ENV
type: choice # string | text | choice | boolean | password
options: [dev, staging, prod]
default: dev
description: Where to deploy
environment: ${{ params.DEPLOY_ENV }} # vars.* are read for this environment
env: # environment variables for every step
NODE_ENV: production
API_URL: ${{ vars.API_URL }} # Secrets & variables → Variables
NPM_TOKEN: ${{ secrets.npm-token }} # Secrets & variables → Secrets (masked in logs)
options:
timeout_minutes: 45 # whole build (approval waits don't count)
clean_workspace: false
stages:
- name: Install
steps:
- run: npm ci
- name: Test
steps:
- name: Unit tests
run: npm test
continue_on_error: true # carry on even if it fails
- run: npm run lint
timeout_minutes: 5
- name: Build
steps:
- run: |
npm run build
tar czf dist.tgz dist
- name: Approve production
when:
branch: [main, release/*] # also: not_branch, environment, params
params: { DEPLOY_ENV: prod }
approval:
message: Deploy build ${{ run.number }} to production?
steps:
- run: echo "approved"
- name: Deploy
environment: ${{ params.DEPLOY_ENV }}
env:
AWS_ACCESS_KEY_ID: ${{ secrets.aws-deployer.access_key_id }} # one field of a secret
AWS_SECRET_ACCESS_KEY: ${{ secrets.aws-deployer.secret_access_key }}
steps:
- run: ./scripts/deploy.sh "$DEPLOY_ENV"
shell: bash # bash | sh | pwsh | powershell | cmd | python
working_directory: infra
artifacts: # files to keep with the build
- dist.tgz
post: # after the stages
always:
- run: echo "done"
success:
- run: echo "it worked"
failure:
- run: echo "it failed"Top-level keys
| Key | Type | Default | Description |
|---|---|---|---|
name |
text | none | Display name. Optional. |
agent |
any, a label, or a mapping |
any agent | Which build agent may run the build. See agent. |
parameters |
list | none | Inputs shown on Build with parameters. See parameters. |
environment |
text | the pipeline's Variables environment setting | The environment that ${{ vars.* }} values are read from, for example dev, staging or prod. Expressions are allowed. |
env |
mapping | none | Environment variables for every step. See env. |
options |
mapping | see options | timeout_minutes and clean_workspace. |
stages |
list | required | At least one stage. See stages. |
post |
mapping | none | Steps that run after the stages. See post. |
artifacts |
text or list | none | Files to archive after the build. See artifacts. |
triggers |
any | none | Accepted by the parser but not used. Set triggers on the pipeline's Configure tab. |
agent
agent decides which build agents can take the build.
| Form | Meaning |
|---|---|
agent: any or no agent key |
Any agent with free executors. |
agent: linux |
Agents that have the label linux. |
agent: { labels: [linux, docker] } |
Agents that have every listed label. |
agent: { pool: linux-build } |
Agents in the pool linux-build. |
agent: { pool: linux-build, labels: [docker] } |
Both conditions. |
Rules:
labelscan be one text value or a list.- An agent matches only if it has all the labels. Label matching ignores case.
- An agent's operating system (
linux,windows,macos), its name and its pool also count as labels. poolmust match the agent's pool exactly.- The pipeline's own agent settings (Build environment → Agent pool / Agent labels) still apply. Labels from both places are combined. A
poolin the file replaces the pool from the settings. - For a file read from Git, the labels are known only after checkout. If the agent that checked out the code does not match, the build goes back to the queue for a matching agent.
options
| Key | Type | Default | Description |
|---|---|---|---|
timeout_minutes |
whole number, 1 to 1440 | the pipeline's Timeout (minutes) setting (60 if not set) | Limit for the whole build. Time spent waiting for an approval does not count. |
clean_workspace |
true / false |
false |
Delete the workspace before the build. It is also cleaned when the pipeline setting Delete the workspace before each build is on. |
env
env is a mapping of NAME: value.
- Names use letters, digits and
_, and do not start with a digit. - Values must be text, a number or
true/false. Lists and mappings are errors.true/falsebecome the texttrue/false. An empty value becomes an empty string. - Values can use expressions.
env can appear at the top level, on a stage and on a step. When the same name is set in several places, the most specific one wins:
- Built-in variables and parameter values (see Built-in environment variables)
- Top-level
env - Stage
env - Step
env
WORKSPACE and ONX_WORKSPACE are always set by the agent and cannot be overridden.
parameters
Each parameter is a mapping:
| Key | Type | Default | Description |
|---|---|---|---|
name |
text | required | Letters, digits and _, not starting with a digit. Must be unique. |
type |
string, text, choice, boolean, password |
string |
text is multi-line. password is hidden in the form and masked in the log. |
options |
list of text | none | Required for choice. |
default |
depends on type | see below | The value used when nobody sets one. |
description |
text | empty | Shown under the field on Build with parameters. |
Defaults:
string,text,password: empty text whendefaultis missing.boolean:falsewhendefaultis missing.choice: the first option whendefaultis missing or is not one of the options.
How parameter values reach your steps:
- Every parameter is an environment variable in every step, with the parameter's name (for example
$DEPLOY_ENV). ${{ params.NAME }}inserts the value intorun,envand the other places expressions work.- Boolean values are the text
trueorfalse. - A
choicevalue that is not one of the options is rejected when the build starts. passwordvalues are stored encrypted, shown as••••••on the build page and masked in the console output.
Parameters can also be set on the pipeline's Configure → General tab. If the file declares a parameter with the same name, the file's definition wins. For a file kept in Git, OpsNexus learns its parameters when a build reads the file, so they appear in the Build dialog from the next build on.
parameters:
- name: TAG
type: string
default: latest
description: Image tag to push
- name: RUN_E2E
type: boolean
default: true
- name: REGION
type: choice
options: [ap-south-1, eu-west-1, us-east-1]
- name: RELEASE_NOTES
type: text
- name: SIGNING_PASSWORD
type: passwordstages
stages is a list. Stages run in order. Each stage is a mapping:
| Key | Type | Default | Description |
|---|---|---|---|
name |
text | Stage <n> |
Must be unique in the file. Shown in the stage view. |
steps |
list | required | At least one step. See steps. |
when |
mapping | none | Run the stage only when the conditions hold. See when. |
approval |
true, false or mapping |
none | Pause before the stage until someone approves. See approval. |
env |
mapping | none | Environment variables for this stage's steps. |
environment |
text | the top-level environment | Read ${{ vars.* }} from another environment in this stage. Expressions are allowed. |
timeout_minutes |
whole number, 1 to 1440 | none | Limit for this stage. |
When a step fails (and does not have continue_on_error: true), the stage fails, the remaining steps are skipped, and every later stage is skipped. post steps still run.
when
when makes a stage conditional. If a condition does not hold, the stage is skipped and the build page shows the reason (for example branch feature/x doesn't match main, release/*). When you give several conditions, all of them must hold.
| Key | Type | Description |
|---|---|---|
branch |
text or list | Run only when the branch matches one of the patterns. |
not_branch |
text or list | Skip when the branch matches one of the patterns. |
environment |
text or list | Run only when the stage's environment is one of these. |
params |
mapping NAME: value |
Run only when each parameter has exactly this value. Write booleans as true / false. |
Branch patterns are wildcards: * matches any characters (including /), ? matches one character. Matching is case-sensitive. release/* matches release/1.4.
- name: Publish
when:
branch: [main, release/*]
not_branch: release/experimental
params: { PUBLISH: true }
steps:
- run: ./publish.shapproval
An approval pauses the build before the stage's steps run. The build status becomes Waiting for approval, and OpsNexus sends the build.approval notification event. Someone then approves or rejects it on the build page.
| Form | Meaning |
|---|---|
approval: true |
Ask with the message Continue to <stage name>? |
approval: { message: Deploy to production? } |
Ask with your own message. Expressions are allowed. |
approval: false or no approval key |
No approval. |
- Approving runs the stage.
- Rejecting stops the build. The stage and the build are marked cancelled, and the
post.failuresteps run. - There is no approval timeout. The build waits until someone decides or stops it. Waiting time does not count towards
timeout_minutes. - A stage with an approval still needs at least one step. A placeholder such as
- run: echo "Approved"is fine. - If the stage's
whenconditions skip it, there is no approval.
Who can approve, and where, is described in Builds and approvals.
steps
A step is either a command (run) or a plugin (uses), never both.
Command steps
| Key | Type | Default | Description |
|---|---|---|---|
run |
text | required | The command or script. Use a YAML block scalar for several lines (see the example above). Expressions are allowed. |
name |
text | the first line of run (up to 60 characters) |
Label in the stage view and console. |
shell |
bash, sh, pwsh, powershell, cmd, python |
see below | The interpreter for run. |
working_directory |
text | the workspace root | A folder inside the workspace. No ... |
env |
mapping | none | Environment variables for this step only. |
continue_on_error |
true / false |
false |
When true, a failure is logged and the stage carries on. |
timeout_minutes |
whole number, 1 to 1440 | none | Limit for this step. A step that times out fails. |
A step can also be written as plain text. These two steps are the same:
steps:
- npm ci
- run: npm ciA step fails when its command exits with a non-zero code.
Shells
shell |
Runs as |
|---|---|
| not set | bash on Linux and macOS (sh if bash is missing); pwsh on Windows (powershell if pwsh is missing) |
bash |
bash with -e -o pipefail: the step stops at the first failing command, including inside pipes |
sh |
sh -e |
pwsh |
PowerShell 7 with $ErrorActionPreference = 'Stop'; the step exits with $LASTEXITCODE |
powershell |
Windows PowerShell, same rules as pwsh |
cmd |
Windows cmd |
python |
The agent's Python 3, with run as the script |
stages:
- name: Build
steps:
- run: dotnet build --configuration Release
shell: pwsh
- name: Summarise
shell: python
run: |
import json
print(json.dumps({"ok": True}))Plugin steps
A plugin step runs a reusable plugin with inputs under with:.
| Key | Type | Default | Description |
|---|---|---|---|
uses |
text | required | name@version, for example slack-notify@1. |
with |
mapping | none | The plugin's inputs. Unknown inputs are errors. |
name |
text | the plugin's title | Label in the stage view. |
env |
mapping | none | Extra environment variables. |
continue_on_error |
true / false |
false |
Same as for command steps. |
timeout_minutes |
whole number, 1 to 1440 | none | Same as for command steps. |
working_directory |
text | the workspace root | Same as for command steps. |
Plugin steps do not take shell or run. Version references:
uses: |
Picks |
|---|---|
slack-notify@1 |
The newest installed 1.x version |
slack-notify@1.2 |
The newest installed 1.2.x version |
slack-notify@1.2.3 |
Exactly 1.2.3 |
slack-notify@latest or slack-notify |
The newest installed version |
The version is resolved when the build starts, and the build page shows the exact version it used.
post:
failure:
- uses: slack-notify@1
with:
webhook: slack-webhook # the name of a Secret text credential
status: failure
message: "Build #${{ run.number }} of ${{ job.name }} failed on ${{ git.branch }}"Every input, and how plugins check them, is described in Plugins.
post
post steps run after the stages, also after a failure, a timeout or a stop.
| Key | Runs when |
|---|---|
always |
After every build |
success |
When every stage succeeded |
failure |
When the build failed, timed out, was stopped or an approval was rejected |
- Each key is a list of steps, written like stage steps (command or plugin steps).
alwayssteps run first, thensuccessorfailure.- Every post step runs, even when an earlier post step fails.
- Post steps get at least 15 more minutes, even when the build already reached its timeout.
- Post steps see the top-level
envand environment, not a stage's. - Any other key under
postis an error.
artifacts
artifacts lists files to keep with the build. They are uploaded after the build, including failed builds, and appear on the build page and on Artifacts → Build artifacts.
artifacts:
- dist/*.zip
- reports/**/*.xml
- coverage/summary.json- One text value or a list of workspace-relative paths or globs.
- No leading
/and no... - At most 50 patterns.
- Expressions are allowed, for example
dist/app-${{ run.number }}.zip. - Files under
.onx/(the agent's own folder) are never archived. - Plugins can declare their own report files; those are archived too.
- Server limits apply:
ARTIFACT_MAX_MBper file (default 100) and at most 200 files per build.
See Artifacts.
Expressions
Expressions have the form ${{ context.key }}. They are filled in when an agent picks up the build. Values are never stored with the build.
| Expression | Value |
|---|---|
${{ secrets.NAME }} |
A secret from Secrets & variables. For a secret with one field, its value. Always masked as •••••• in the console. |
${{ secrets.NAME.field }} |
One field of a multi-field secret, for example secrets.aws-deployer.access_key_id. |
${{ vars.KEY }} |
A variable for the pipeline's environment, or one set for all. |
${{ params.NAME }} |
A build parameter. The parameter must be declared. |
${{ git.branch }} |
The branch being built. |
${{ git.commit }} |
The commit SHA. |
${{ git.short_commit }} |
The first 7 characters of the commit SHA. |
${{ git.message }} |
The commit message. |
${{ run.number }} |
The build number. |
${{ run.id }} |
The build's unique ID. |
${{ run.url }} |
A link to the build in OpsNexus. |
${{ run.trigger }} |
What started it: manual, webhook, cron, poll, scan or replay. |
${{ run.triggered_by }} |
Who or what started it. |
${{ job.name }} |
The pipeline's name. |
${{ job.full_name }} |
The full name, including folders (for example acme/web/main). |
Where expressions are filled in: run, env values (top level, stage and step), environment (top level and stage), approval.message, artifacts, and plugin with: inputs. name values are plain labels and are never evaluated.
Errors:
- An unknown context (anything other than
secrets,vars,params,git,run,job) or a malformed${{is a validation error. - A missing secret, variable or undeclared parameter fails the build when it starts, with a message that says what to add.
Secrets
- Secrets come from Settings → Secrets & variables: the project's own secrets and the ones shared with all projects. See Secrets and variables.
- Secret names can contain dots. OpsNexus first looks for a secret with the full name, then treats the last part as a field.
- If a secret has several fields and you do not name one, the build fails and asks you to use
${{ secrets.NAME.<field> }}. - For a Secret file credential,
${{ secrets.NAME }}(or.path) is the path of a file the agent writes for the build.${{ secrets.NAME.content }}is the file's text. - Every secret value, and every line of a multi-line secret, is masked in the console output.
Variables
${{ vars.KEY }}looks for a variable with that key in the build's environment, or in the environmentall. A variable for the exact environment wins overall, and a project variable wins over a shared one.- The environment is the stage's
environment, else the top-levelenvironment, else the pipeline's Variables environment setting. - A variable whose value is
vault:<secret>orvault:<secret>.<field>is read from that secret and masked like one.
Built-in environment variables
Every step gets these variables:
| Variable | Value |
|---|---|
CI, OPSNEXUS |
Always true |
BUILD_NUMBER, ONX_RUN_NUMBER |
Build number |
BUILD_ID |
Build number |
ONX_RUN_ID |
The build's unique ID |
JOB_NAME, ONX_JOB_NAME |
Full pipeline name, for example acme/web/main |
BRANCH_NAME, GIT_BRANCH, ONX_BRANCH |
Branch being built (when there is one) |
GIT_COMMIT, ONX_COMMIT |
Commit SHA after checkout (when there is one) |
BUILD_URL, ONX_RUN_URL |
Link to this build in OpsNexus |
ONX_TRIGGER |
What started the build (manual, webhook, cron, poll, scan, replay) |
WORKSPACE, ONX_WORKSPACE |
The checkout folder on the agent |
| Each parameter name | The parameter's value, for example DEPLOY_ENV |
Templates
The editor offers four starting points under Start from a template…: Node.js build & test, Docker image build & push, Build, approve, deploy and Windows (.NET). The Docker template:
name: api-image
agent:
labels: [docker]
parameters:
- name: TAG
type: string
default: latest
description: Image tag to push
env:
IMAGE: ${{ vars.REGISTRY }}/api
stages:
- name: Build image
steps:
- run: docker build -t "$IMAGE:${{ params.TAG }}" .
- name: Push
when:
branch: [main, release/*]
env:
REGISTRY_USER: ${{ secrets.registry.username }}
REGISTRY_PASSWORD: ${{ secrets.registry.password }}
steps:
- run: echo "$REGISTRY_PASSWORD" | docker login "${{ vars.REGISTRY }}" -u "$REGISTRY_USER" --password-stdin
- run: docker push "$IMAGE:${{ params.TAG }}"The build, approve, deploy template:
name: release
parameters:
- name: DEPLOY_ENV
type: choice
options: [dev, staging, prod]
default: dev
environment: ${{ params.DEPLOY_ENV }}
options:
timeout_minutes: 45
stages:
- name: Build
steps:
- run: make build
- name: Approve
when:
params:
DEPLOY_ENV: prod
approval:
message: Deploy build ${{ run.number }} to production?
steps:
- run: echo "Approved"
- name: Deploy
env:
AWS_ACCESS_KEY_ID: ${{ secrets.aws-deployer.access_key_id }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.aws-deployer.secret_access_key }}
AWS_REGION: ${{ vars.AWS_REGION }}
steps:
- name: Deploy
run: ./scripts/deploy.sh "${{ params.DEPLOY_ENV }}"
timeout_minutes: 20Validating a file
- On CI/CD → Pipeline syntax, paste a file into Try it: validate a pipeline file and press Validate. Nothing runs.
- In the Pipeline script editor on a pipeline's Configure tab, press Validate.
- From a script, call
POST /api/ci/validatewith{"content": "<yaml>"}. The answer is{"ok": true, "summary": {...}}or{"ok": false, "problems": [...]}.
A valid result shows the stages, parameters, secrets, variables, approvals and plugins the file uses. Plugin steps are checked against the plugins installed in the current project.
curl -s -X POST "https://opsnexus.example.com/api/ci/validate" \
-H "X-API-Key: $OPSNEXUS_API_KEY" \
-H "Content-Type: application/json" \
--data "$(jq -Rs '{content: .}' .opsnexus.yml)"Coming from Jenkins
| Jenkins | OpsNexus |
|---|---|
agent { label 'x' } |
agent: { labels: [x] } |
stage('X') { steps { sh '…' } } |
- name: X with steps: [- run: …] |
withCredentials / credentials() |
${{ secrets.NAME }}, or Credential bindings in a Freestyle project |
parameters { choice(...) } |
parameters: - { name, type: choice, options } |
when { branch 'main' } |
when: { branch: [main] } |
input message: '…' |
approval: { message: … } |
post { always / success / failure } |
post: { always, success, failure } |
triggers { cron('H 2 * * *') } |
Build periodically on the pipeline's Configure tab (same cron syntax, H included) |
Plugins such as slackSend, junit, withAWS |
- uses: slack-notify@1, junit-report@1, aws-cli@1 |