Skip to content

Guardrails / Collectors

Jenkins pipelines ​

The Jenkinsfiles the repository carries, read in Jenkins's own vocabulary: whether each is a declarative pipeline or a scripted one, the agent it asks for, the stages in the order they are declared with the steps inside them, the timeouts its options blocks declare, the shared libraries it loads and how tightly each is pinned, and the credential ids it reaches for. A Jenkinsfile is Groovy rather than a declaration, so it is read by pattern and scanned says so. Names and ids only, never a credential, an environment value or a parameter value.

Facts keyjenkins
Versionv1
Scriptjenkins.py
Timeout60 seconds

Inputs ​

InputDescriptionDefaultEnvironment
jenkinsfilesComma separated globs matched against every file in the working directory and against bare file names, naming the Jenkinsfiles to read. Narrows what discovery finds; a file it matches whose name is not Jenkinsfile, Jenkinsfile.<something> or <something>.Jenkinsfile is still left out.Jenkinsfile,Jenkinsfile.*,*.JenkinsfileGUARDRAIL_INPUT_JENKINSFILES

When a guardrail declares an input with the same name, it passes its value through. That means you set these values in the guardrail's configuration in buildnote.json.

A guardrail asks for these facts by name and reads them back by the same name:

json
{
  "collect": ["jenkins"]
}
python
jenkins = guardrail.facts("jenkins")

Facts ​

These are the fields of the document jenkins collects. In a path, [] means each entry of the list before it, and [path] means a key of the object before it.

FactMeaning
sourcereport when a Jenkinsfile was read, none when there was none.
reasonWhy nothing was read, present only when source is none.
reportsEvery Jenkinsfile that was read, in path order.
reports[].pathPath of the Jenkinsfile, relative to the directory the CLI runs in.
reports[].modifiedWhen it was last written, ISO 8601.
reports[].formatAlways jenkins.
scannedEvery Jenkinsfile that was read by pattern, which is all of them. A Jenkinsfile is Groovy rather than a declaration, so a stage, a step or a library built by a condition, a loop or a method call is not seen. Anything listed was found, but something missing may still be there: a finding is real, an absence is not proof.
pipelinesThe pipelines themselves, one entry per file that was read.
pipelines[].pathPath of the file, relative to the directory the CLI runs in.
pipelines[].styledeclarative when the file declares a top level pipeline block, scripted when it does not. Almost nothing below is readable in a scripted pipeline, where a stage is a method call inside arbitrary Groovy: stages, agent, timeout, environment, triggers and tools are all left empty for one, and only the libraries and credential ids a pattern can find are collected.
pipelines[].agentThe agent the pipeline declares, whitespace collapsed: any, none, or the body of the agent block such as label 'linux' or docker { image 'maven:3.9' }. null when it declares none, which a declarative pipeline is not allowed to do and a scripted one always does.
pipelines[].timeoutThe timeout(...) call the pipeline level options block declares, exactly as written, or null when it declares none. Jenkins imposes no timeout of its own, so null means a hung build holds its executor until somebody aborts it.
pipelines[].timeoutMinutesThe same timeout in whole minutes, or null when the pipeline declares none or writes a duration that could not be read. timeout(time: N) with no unit is minutes, which is what Jenkins defaults to.
pipelines[].environmentNames of the variables the pipeline level environment block assigns. Names only, never values: a value there is often credentials('id'), and the ids are collected separately.
pipelines[].triggersThe trigger types the triggers block declares, such as cron, pollSCM or upstream. Types only, never the schedule.
pipelines[].toolsThe tool types the tools block asks Jenkins to install, such as jdk, maven or nodejs. Types only, never the installation name they select.
pipelines[].librariesEvery shared library the file loads, from @Library(...) and from the library step, in the order they appear. A library loaded conditionally in Groovy is not here; see scanned.
pipelines[].libraries[].nameThe part of the reference before the @, which is the library name configured on the Jenkins controller.
pipelines[].libraries[].refWhat follows the @, whatever it names, or null when the reference names nothing and Jenkins resolves the default version from its own configuration.
pipelines[].libraries[].pinnedWhether ref names a fixed point by its shape: a 40 character hex commit sha, or a version such as 1.4.2 or v1.4.2. A branch name, an interpolated expression and no ref at all are not. Jenkins cannot tell a tag from a branch by name, so this reads the shape of the ref rather than what the SCM resolves it to.
pipelines[].libraries[].sourceannotation for an @Library(...) at the top of the file, step for a library '...' call inside it.
pipelines[].credentialsThe credential ids the file reaches for, from credentials('id') and from every credentialsId: a withCredentials binding names, in the order they appear. Ids only, never a credential: the facts are attached to the run event.
pipelines[].stagesEvery stage the pipeline declares, flattened in source order. A stage nested inside a parallel or a nested stages block appears after the stage holding it and names it in parent, so the tree is still readable and a parallel branch is a stage of its own.
pipelines[].stages[].nameThe name the stage(...) call gives itself, or null when it is written as an expression rather than a literal.
pipelines[].stages[].parentPosition in this list of the stage this one is nested inside, through a parallel or a nested stages block, or null for a stage declared directly under the pipeline. It is a position, not a name, because a stage written as an expression has no readable name and would otherwise be indistinguishable from the pipeline itself. What a parent declares, an options timeout included, covers everything nested inside it.
pipelines[].stages[].agentThe agent the stage declares for itself, whitespace collapsed, or null when it takes the pipeline's.
pipelines[].stages[].timeoutThe timeout(...) call the stage's own options block declares, exactly as written, or null when it declares none.
pipelines[].stages[].timeoutMinutesThe same timeout in whole minutes, or null when the stage declares none or writes a duration that could not be read.
pipelines[].stages[].whenWhether a when block guards the stage, so it is skipped rather than run on some builds.
pipelines[].stages[].stepsThe steps the stage's steps block runs, flattened in source order. A step that wraps others, such as withCredentials, dir, retry or script, is recorded and so is every step inside it.
pipelines[].stages[].steps[].nameThe step as it is written, such as sh, bat, powershell, checkout, echo or withCredentials.
pipelines[].stages[].steps[].bodyThe shell body of a sh, bat, powershell or pwsh step, read as the string literal the call passes and truncated to 2000 characters. null for every other step.
counts.pipelinesFiles that were read.
counts.stagesStages across every pipeline, nested ones included.
counts.stepsSteps across every stage.
unparsedFiles that matched but were not read, because the pipeline block they open is never closed and nothing below it could be located. A file listed here is not an empty file: nothing was read from it, so draw no verdict about it.
unparsed[].pathPath of the file that was not read.
unparsed[].reasonWhat stopped the reader, and the line it gave up on.

If a collector can't finish, it prints what it gathered so far along with an incomplete key that says why. Facts after the point where it stopped are missing, so a check that depends on them should read incomplete first.

Example facts ​

Here are the facts the jenkins collector gathers from an example project:

json
{
  "source": "report",
  "reports": [
    {
      "path": "Jenkinsfile",
      "modified": "2026-03-04T10:15:00Z",
      "format": "jenkins"
    }
  ],
  "scanned": [
    "Jenkinsfile"
  ],
  "pipelines": [
    {
      "path": "Jenkinsfile",
      "style": "declarative",
      "agent": "docker { image 'maven:3.9.6-eclipse-temurin-21' }",
      "timeout": "timeout(time: 30, unit: 'MINUTES')",
      "timeoutMinutes": 30,
      "environment": [
        "GRADLE_OPTS",
        "SONAR_TOKEN"
      ],
      "triggers": [
        "cron"
      ],
      "tools": [
        "jdk"
      ],
      "libraries": [
        {
          "name": "company-pipeline",
          "ref": "1.4.2",
          "pinned": true,
          "source": "annotation"
        }
      ],
      "credentials": [
        "sonar-token",
        "registry"
      ],
      "stages": [
        {
          "name": "Build",
          "parent": null,
          "agent": null,
          "timeout": null,
          "timeoutMinutes": null,
          "when": false,
          "steps": [
            {
              "name": "checkout",
              "body": null
            },
            {
              "name": "sh",
              "body": "./gradlew --no-daemon build"
            }
          ]
        },
        {
          "name": "Verify",
          "parent": null,
          "agent": null,
          "timeout": null,
          "timeoutMinutes": null,
          "when": false,
          "steps": []
        },
        {
          "name": "Test",
          "parent": 1,
          "agent": null,
          "timeout": null,
          "timeoutMinutes": null,
          "when": false,
          "steps": [
            {
              "name": "sh",
              "body": "./gradlew --no-daemon test"
            }
          ]
        },
        {
          "name": "Lint",
          "parent": 1,
          "agent": null,
          "timeout": "timeout(time: 5, unit: 'MINUTES')",
          "timeoutMinutes": 5,
          "when": false,
          "steps": [
            {
              "name": "sh",
              "body": "./gradlew --no-daemon detekt"
            }
          ]
        },
        {
          "name": "Publish",
          "parent": null,
          "agent": null,
          "timeout": "timeout(time: 10, unit: 'MINUTES')",
          "timeoutMinutes": 10,
          "when": true,
          "steps": [
            {
              "name": "withCredentials",
              "body": null
            },
            {
              "name": "sh",
              "body": "./gradlew --no-daemon publish"
            }
          ]
        }
      ]
    }
  ],
  "counts": {
    "pipelines": 1,
    "stages": 5,
    "steps": 6
  },
  "unparsed": []
}

Collected for ​

GuardrailCategoryInputs
jenkins/job-timeout-setjenkinsjenkinsfiles
jenkins/shared-library-pinnedjenkinsjenkinsfiles

All collectors

Buildnote Limited
Registered in England and Wales, Reg: 16140412