CI/CD Diagram Guide

Jenkins pipeline diagram: draw the Jenkinsfile, not the last run

By the engineer who builds Datadef, from client work on data platforms · Reviewed August 21, 2026

Jenkins already draws your pipeline twice, in Stage View and in the Pipeline Graph View plugin, and both drawings describe one build that has already finished. What a team needs on its wiki is the standing map: the stages declared in the Jenkinsfile, the parallel blocks, the agent labels that decide where each stage runs, the input steps that gate promotion, and the shared library that supplies half the steps you never see in the file.

7 min readFor teams whose Jenkinsfile has outlived the person who wrote it

See it as a diagram

Everything below, as a diagram you can edit. Describe yours and see it in seconds.

243/20003 credits left
Try:

No account needed · Editable canvas, not a picture

What Stage View gives you, and what it cannot

Stage View and the newer Pipeline Graph View render the stages of a completed run with timings and status colours. Blue Ocean did the same thing more prettily and has stopped taking new features, so Pipeline Graph View, which needs Jenkins 2.479.3 or later, is where this view now lives. For diagnosing why last night's build failed, any of them is the right tool and no drawn diagram beats them.

They cannot show the stages that did not execute. A stage guarded by a when clause, a deploy that only runs on the release branch, a cleanup that only runs on failure: all of them are absent from the picture of a run in which they did not fire, and absent in a way the reader cannot detect. The standing map has to come from the file.

They also stop at the job boundary. A multibranch pipeline is a family of jobs, a downstream build triggered with the build step is a separate job with its own view, and a pipeline that calls a shared library step sees that step as a single line. None of those relationships appear in a run view, and all of them belong on a wiki diagram.

Reading a Jenkinsfile as a diagram

Declarative pipelines map to shapes almost one to one. Each stage block is a node. A parallel block is a fan-out and fan-in pair, and its branch names are the node labels. An agent directive, whether at pipeline level or overridden per stage, is a property worth writing on the node, because "runs on the docker-arm64 label" explains failures that stage names never will.

Two constructs deserve gate shapes rather than plain nodes. The input step is a manual approval and should be drawn with its submitter list and timeout, exactly like an approval gate on any other pipeline. A when clause that restricts a stage to a branch or a tag is a condition on the edge into that stage, and writing the condition on the arrow saves the reader a trip to the file.

Post blocks are the part people forget. A post section with always, success, and failure branches is where notifications, cleanup, and artifact archiving live, and on a diagram it is a small cluster hanging off the end rather than another stage in the main line.

@Library('platform-ci@v3') _          // half the steps come from here

pipeline {
  agent { label 'linux-amd64' }       // default node placement
  stages {
    stage('Build') { steps { sh 'make build' } }
    stage('Test') {                    // one fan-out, two branches
      parallel {
        stage('Unit')        { steps { sh 'make test-unit' } }
        stage('Integration') { agent { label 'docker' }
                               steps { sh 'make test-int' } }
      }
    }
    stage('Publish') { steps { publishArtifact() } }   // shared library step
    stage('Approve') {                 // draw this as a gate, not a stage
      steps { input message: 'Deploy to prod?', submitter: 'release-managers' }
    }
    stage('Deploy prod') {
      when { branch 'main' }           // condition belongs on the edge
      agent { label 'prod-egress' }
      steps { deployService(env: 'prod') }
    }
  }
  post { failure { notifySlack() } }   // small cluster off the end
}

The invisible half: shared libraries and multibranch

A mature Jenkins setup moves most real logic into a shared library, so the Jenkinsfile becomes a list of custom steps. deployService() might resolve credentials, run a helm upgrade, wait for rollout, and post to a channel, and none of that is visible in the pipeline file. A diagram drawn only from the Jenkinsfile will therefore be accurate and useless at the same time.

The fix is to expand the library steps that matter. Read vars/deployService.groovy, decide which of its actions are architecturally interesting (which systems it touches, which credentials it uses), and draw those as a sub-cluster behind the step node. Pin the library version on the diagram too, since @Library('platform-ci@v3') means the drawing is only true for v3.

Multibranch and folder-level configuration are the other half of the invisible surface. Branch discovery rules, folder credentials, and shared environment variables set at folder level change what a pipeline does without changing the Jenkinsfile. Note them as annotations on the diagram rather than pretending the file is the whole story.

Keeping the Jenkins diagram true after the file changes

A Jenkinsfile changes far more often than the architecture it deploys, which is exactly the condition under which hand-drawn diagrams rot. Two mechanisms keep it current without a person redrawing it.

The first is an agent loop. Datadef exposes an MCP server with 36 tools: nine outcome-level ones, including create_diagram, edit_diagram, export_diagram, repo_status and repo_refresh, and 27 canvas_* tools for node-by-node edits. An assistant such as Claude Code or Cursor reads the Jenkinsfile and the shared library in the working tree and updates the existing canvas rather than drawing a new one. Running that as a post-merge step filtered to the Jenkinsfile path keeps the drift window to one merge. The handshake and the tool listing answer without a key, so a client can inspect the surface before anyone issues one. The setup is covered in the MCP diagram server guide.

The second is publication. Publish the diagram as a live embed and point the README, the Confluence page, and the onboarding doc at the same URL. When the canvas updates, all three follow, and nobody has to remember which pages held a copy of the old PNG.

Pin the library version on the canvas

A diagram of a pipeline that calls a shared library is only correct for one library version. Writing the pinned ref on the canvas turns a silent inaccuracy into a visible, checkable claim.

FAQ

How do I create a diagram of a Jenkins pipeline?

Read the Jenkinsfile rather than a completed run. Each stage block becomes a node, each parallel block becomes a fan-out and fan-in with its branch names as labels, each input step becomes an approval gate with its submitter list, and each when clause becomes a condition written on the incoming edge. Agent labels go on the nodes they govern.

Why not just use Stage View or Blue Ocean?

Both render a specific completed run, so any stage that did not execute is missing without the reader being able to tell. They also stop at the job boundary, which hides multibranch families, downstream builds triggered from the pipeline, and everything a shared library step does internally. Blue Ocean has also stopped receiving new features, with Pipeline Graph View taking over that view on Jenkins 2.479.3 and later.

How do I represent a Jenkins shared library on the diagram?

Draw the custom step as a node and expand what it actually does behind it, based on the corresponding file under vars in the library repository: which systems it touches and which credentials it uses. Pin the library version on the canvas, since a diagram of a pipeline calling a shared library is only true for the version the pipeline references.

How should parallel stages be drawn?

As a fan-out from the preceding stage into one node per parallel branch, then a fan-in to the next stage. Use the branch names from the parallel block as node labels. Do not attempt to show which branches happened to run at the same time in a given build, since that depends on executor availability.

How do I keep the Jenkins diagram current?

Trigger a regeneration when the Jenkinsfile or the shared library changes rather than on a calendar. A post-merge step that asks an MCP-connected assistant to update the diagram from the current files keeps the drift window to one merge, and publishing the result as an embed URL means every page that shows the diagram follows automatically.