Chapter 25Lesson 01180–240 min

CI/CD Integration with GitHub Actions, GitLab CI, and Jenkins: Core Concepts and Mental Model

Build a provider-neutral mental model for running Robot Framework in CI/CD: the same pinned command, exit status, and evidence contract should work locally and be wrapped by GitHub Actions, GitLab CI/CD, or Jenkins without changing the suite architecture.

Robot Framework 7.4.2CI contractExit statusArtifactsxUnitProvider-neutral

Learning objectives

  • Trace a CI run from trigger and workspace through a pinned Python/Robot runtime, system-under-test interaction, Robot exit code, result artifacts, and delivery gate.
  • Distinguish Robot suite/test state from CI workspace, runner, secret store, cache, artifact store, and deployment environment state.
  • Explain why provider YAML or Jenkinsfile code should orchestrate a portable local command rather than contain the test architecture.
  • Interpret Robot Framework return codes and preserve non-zero failure status while still retaining output.xml, log.html, report.html, and xUnit evidence.
  • Recognize where optional Pabot parallelism fits—and why parallel execution must not be introduced before mutable state is isolated.
Compatibility baseline

This chapter is written against Robot Framework 7.4.2. Pabot 5.2.2 is optional. Provider examples use the current major GitHub Actions generations (checkout@v7, setup-python@v7, upload-artifact@v7) as of 2026-08-31. GitLab and Jenkins examples intentionally stay close to stable platform primitives rather than vendor-specific plugins.

1. The practical problem: a green pipeline must mean the Robot contract actually passed

Running robot suites/ on a laptop is only the beginning. In CI, a delivery decision is made by another process: a runner checks out a commit, creates a workspace, installs dependencies, invokes Robot Framework, interprets the process return code, stores evidence, and decides whether later stages may proceed. A suite can be perfectly written and still become operationally misleading if the wrapper ignores the return code, discards the failure artifacts, changes dependency versions, or points at a different target.

The safest architecture therefore starts with a provider-neutral run contract. The contract says exactly which interpreter executes which command, where dependencies come from, which environment variables are inputs, which system is allowed to be touched, which artifacts must be written, and which exit codes mean the gate is closed. GitHub Actions YAML, GitLab YAML, and a Jenkinsfile are then thin orchestration layers around that contract.

2. Inspect before changing CI state

Before adding any pipeline file, prove that the local execution surface is understood. CI magnifies hidden assumptions about the working directory, Python executable, import path, environment, and artifact location.

# Read-only preflight. Run from the repository root.
python --version
python -m pip --version
python -m robot --version
python -m robot --help

# Optional only if Chapter 24 parallelism is justified:
pabot --version

# Inspect source and existing evidence without deleting anything.
python -c "from pathlib import Path; print('cwd=', Path.cwd())"
python -c "from pathlib import Path; print([str(p) for p in Path('suites').glob('**/*.robot')])"
python -c "from pathlib import Path; print('artifacts_exists=', Path('artifacts/robot').exists())"

Record these observations in CI as well. “Works locally” is not evidence of equivalence unless the interpreter, Robot version, dependency set, command, working directory, selected suite, variables, and target configuration are comparable.

3. Mental model: CI orchestration around the Robot execution contract

Portable Robot Framework CI/CD flow
flowchart TD
A[Commit / pipeline trigger] --> B[CI workspace]
B --> C[Pinned Python + dependencies]
C --> D[Provider-neutral robot or pabot command]
D --> E[Disposable / allowed SUT environment]
E --> D
D --> F[Process return code]
D --> G[output.xml / log.html / report.html / xUnit]
F --> H[Delivery gate]
G --> I[CI artifact / test-report store]
J[Secret store] -. injected input .-> D
K[Cache] -. optional dependency acceleration .-> C
L[GitHub / GitLab / Jenkins config] -. orchestrates .-> B

The solid arrows are the execution path. The dotted arrows are orchestration inputs. The CI provider does not change Robot semantics: Robot still resolves suites, libraries, variables, keywords, failures, and outputs. The provider owns the workspace, process environment, credentials injection, caches, job lifecycle, artifact retention, and gate transitions.

4. Separate the state stores

State store Owner Typical mutation What to record
Robot suite/test/task state Robot execution keyword status, variables, setup/teardown state output.xml plus log/report
Python environment runner / virtualenv / image installed wheel versions python/pip/robot version manifest
CI workspace provider runner checkout, generated files, caches commit SHA, cwd, artifact path
External test environment SUT or local fixture records, files, sessions target ID/URL and cleanup proof
Secret store CI provider/operator credential injection name/presence only; never value
Artifact store CI provider upload/download/retention artifact name, paths, run/job identity
Pabot worker state Pabot subprocess isolated result directories and mutable resources worker-safe resource IDs when parallelism is used

A Robot suite variable is not a CI variable. A CI secret is not a Robot secret automatically. An uploaded artifact is not the same thing as the files still present in a runner workspace. These boundaries explain many “CI-only” failures.

5. Robot Framework return codes are the primary gate signal

When execution starts normally, Robot Framework returns 0 if all tests pass. Codes 1 through 249 represent the number of failed tests, 250 means 250 or more failures, and higher reserved codes describe help/version output, invalid input, interruption, or an unexpected internal error. The exact failure details belong in output.xml and the human-readable log/report; the process return code is the machine-level gate.

Return code Meaning for the CI wrapper Correct response
0 Robot execution passed Gate may continue if other checks also passed
1–250 One or more tests failed Fail the Robot gate; retain artifacts
252 Invalid test data/CLI input Fail as configuration/execution error; inspect console and artifacts
253 Execution interrupted Treat as incomplete/failed run; preserve what was produced
255 Unexpected internal error Fail and escalate with versions + first-failure evidence
Do not normalize failures away

Avoid --nostatusrc, shell || true, PowerShell error suppression, or wrapper code that always exits zero unless a later, explicit gate is guaranteed to restore the correct status. Otherwise a red Robot result can become a green delivery pipeline.

6. Evidence is part of the CI contract, not an optional report

output.xml is Robot Framework's machine-readable execution record. log.html is the detailed human diagnostic view, report.html is the higher-level summary, and an xUnit file is a derivative format useful for CI test-report surfaces. The native output remains the richest source for Robot-specific post-processing.

Artifact upload must be arranged to run on the failure path. A pipeline that uploads only after successful test execution guarantees that the runs needing evidence most are the runs with the least evidence.

7. The provider-neutral boundary

A strong repository has one command that an engineer can execute locally and that every CI provider can invoke unchanged. Provider configuration may choose triggers, runner images, secret stores, caching, retention, concurrency, and permissions, but it should not embed Robot keyword logic or invent separate test-selection semantics for each vendor.

Repository-owned contract
  requirements-ci.txt       pinned test dependencies
  suites/                   Robot suites/resources
  tools/ci_run.py           portable runner + evidence manifest
  artifacts/robot/          generated evidence (not source)

Provider-owned wrapper
  GitHub Actions            checkout/setup/upload/gate orchestration
  GitLab CI/CD              runner/image/artifacts/reports orchestration
  Jenkins                   agent/stage/post/archive/junit orchestration

8. Where Pabot belongs

Pabot is an optional parallel executor, not a CI requirement. Version 5.2.2 supports the Robot Framework CLI options plus Pabot controls such as --processes, --testlevelsplit, sharding, artifact collection, ordering, and resource coordination. Parallelism should be enabled only after suites own separate mutable state. A faster pipeline that corrupts shared data or overwrites evidence is less reliable than a slower serial gate.

For this chapter the mandatory command is serial Robot Framework. Lesson 3 shows where a measured, isolated Pabot command may replace it without changing the provider-neutral contract.

9. DevOps connection

CI/CD converts Robot results into a release control. That makes the wrapper part of the assurance system: version drift, secret handling, missing artifacts, stale caches, target selection, and ignored exit codes can all invalidate the gate even when the tests themselves are correct. The production pattern is therefore reproducible command + explicit target + non-zero failure propagation + always-retained evidence + provider-thin orchestration.

Knowledge check

A GitHub Actions job and a Jenkins job run different wrapper syntax but invoke the same python tools/ci_run.py. Which layer should define Robot suite selection?

Robot reports one failing test, but the CI job is green. Which evidence should you inspect first?

Why keep output.xml even if the provider already renders xUnit results?

When is adding Pabot to CI unsafe?

Summary and bridge

You now have the governing model: a CI provider wraps a reproducible Robot command, interprets its return code, and stores evidence without taking ownership of test architecture. Lesson 2 turns that model into a local runnable contract and concise GitHub Actions, GitLab CI/CD, and Jenkins mappings.

Next lesson

CI/CD Integration with GitHub Actions, GitLab CI, and Jenkins: Guided Hands-On Workflow

Continue with CI/CD Integration with GitHub Actions, GitLab CI, and Jenkins: Guided Hands-On Workflow. It builds directly on the state, evidence, and operating assumptions established here, so carry those constraints forward rather than treating the next page as an isolated topic.

Current primary references

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.