Parallel Stages and Failure Semantics

Scenario: Independent suites run sequentially for forty minutes while executors sit idle.

Pipeline example

stage('Tests') { failFast true; parallel { stage('Unit') { steps { sh './unit.sh' } }; stage('API') { steps { sh './api.sh' } } } }

Parallelize only independent work

Declarative parallel executes named sibling stages concurrently when eligible executors exist. Every branch needs isolated files, ports, test accounts, and report paths. Tests that mutate one database become order-dependent flakes when parallelized. Publish distinct results after all branches or in branch post blocks. The runtime approaches the longest branch plus queue and setup overhead, not zero and not the sequential sum.

FailFast aborts siblings after one branch fails. That conserves capacity when any failure invalidates the build, but discards compatibility evidence. Let expensive suites finish when seeing the full failure surface is more valuable. Reports must distinguish a genuinely failed branch from one aborted due to a sibling.

Capacity limits useful fan-out

Ten branches targeting two executors mostly create queueing and repeated setup. APIs, licenses, registries, and controller step processing may bottleneck before CPU. Measure queue and execution time per branch, then cap concurrency around the actual constrained resource.

Do not parallelize non-idempotent deployment against one target without locks and conflict semantics. Retry only safe failed branches where possible; restarting the entire fan-out can repeat completed external actions. Prove isolation with repeated concurrent runs and deliberately injected failures rather than one green execution.

Goal: Practice the concrete behavior in jenkins-labeled-parallel-tests. Learn sections have no Jenkins terminal; the Jenkins lab opens the real shared service in a new full-screen tab inside your private folder.