Skip to content
Docs / dflux Runner
ContactGet started

CI integration

dflux Runner gates CI pipelines with a deterministic exit code and optional machine-readable reports. This guide covers exit-code semantics, -output json|junit, useful flags, and snippet templates for common CI systems.

How to gate a pipeline

For one-shot CI, drive the CLI directly. No control plane, no local database, no web UI:

  • Exit coderun-flow exits on the flow verdict; run-suite and check exit non-zero when something fails. Gate the job on $?.
  • Structured report — pass -output json or -output junit (optionally -output-file <path>). The report is written before the process exits, so CI can upload the artifact and still fail the job on the exit code.
Note
Prefer CLI one-shots for PR gates. Agent mode attaches a long-lived worker to the control plane for a continuous lab test plane — not for ephemeral CI jobs.

Exit codes

run-flow exits on the flow verdict (the same answer printed first in the report), not on the narrower all_passed flag:

Exit codeMeaning
0Verdict pass — the flow ran correctly
1Verdict fail, or the run errored (json/junit reports still write first)
2Usage error — bad flags or an unusable -output format
3Verdict unsupported — the core does not implement this scenario. Not a failure.

A strict gate treats only 0 as green. A permissive gate that already knows the core is incomplete can accept 0 or 3:

Bash

run-suite and check do not use the third code. run-suite exits 0 only when every cycle's AllPassed is true (a step's success_when can override that step's own pass/fail). check exits 1 if any transport probe failed, 2 on usage errors.

Machine-readable output

FlagPurpose
-output text|json|junitResult format (default text)
-output-file <path>Write the json/junit report to a file; the human summary still prints to stdout
Bash

JUnit XML is suitable for GitLab reports.junit and similar consumers. JSON is the full engine result shape for custom assertions (latency fields, post-checks, event log).

Useful flags for CI

FlagPurpose
-repetitions <n>Number of flow starts (default 1)
-rate <n>Flow starts per second (0 = burst all at once)
-timeout <dur>Per-flow timeout (default 30s); raise it for slow cores
-gen-subscriberSynthesize a subscriber per UE in memory; skip a subscribers file
-output json|junitStructured report for artifacts / test views
-output-file <path>Write that report to a file (human summary still on stdout)
-traceTX/RX hex dumps for failed-run forensics — strip from green pipelines
-metrics-port <n>Optional Prometheus runner_* endpoint for the lifetime of the process

There is no -db flag and no local report catalog — the process is stateless. For latency or path assertions, encode them as post-run checks in the flow or suite YAML so they feed the exit code. See the flow schema.

GitHub Actions example

YAML

The job fails when run-flow exits non-zero. Exit 3 (unsupported) is also non-zero, so a strict Actions job treats a missing-feature verdict as red unless the script maps it. if: always() keeps the artifact upload firing on red builds so the JUnit report is available for triage.

GitLab CI example

YAML

The job's pass/fail tracks the run-flow exit code. reports.junit feeds GitLab's test view from the same file.

Suites in CI

run-suite follows the same exit-code and -output contract. Use a suite when one logical pipeline check needs several flows in order — for example: provision PCC rules, run a load burst, then tear the rules down. Each step's workload lives in the suite YAML; run-suite has no suite-level -rate. -repetitions on the command line means full suite cycles.

Bash

Determinism and isolation

  • Use -gen-subscriber for runs that don't depend on real auth, to avoid needing a shared credential file.
  • Pin the templates directory; a stale catalog can mask a flow rename. See the flow and suite catalog.
  • Each job is an isolated process — no shared local DB to clean between jobs.
  • Set D3X_LICENSE_FILE (or install ~/.dflux/runner.lic / /etc/dflux/runner.lic / the matching d3x.lic compound file) so licensed entrypoints start cleanly.

Troubleshooting

Flaky timeouts on small cores — the AMF takes longer to respond under cold load. Raise -timeout 60s on the first run of the day, or warm the core with a check invocation first.

The exit code is 1 but the run "should" have passed — read the printed verdict and the json/junit report. all_passed only means no check failed; UEs that never reached a terminal state, a failed final_checks assertion, or a failed post-run latency threshold all verdict-fail. Add -trace for TX/RX hex dumps.

Exit code 3 — verdict unsupported. The core answered that it does not implement the scenario. Treat it as skip in a permissive gate; do not rewrite it to 0 unless that is the policy you want.

The captured log is empty — the run hard-failed before printing. Redirect stderr (2>&1) into the same file so the error is captured alongside the summary.

Exit code 2 — bad flags (missing -templates / -c, unknown -output). Fix the invocation rather than treating it as a test failure.

Where to go next