Skip to content
BETAGuardrails are in beta. The library, the configuration format and the CLI command can still change.

Guardrails / jenkins

Shared libraries are loaded at a fixed revision

jenkins/shared-library-pinned@v1

Every @Library annotation and library step names a tag or a commit sha rather than a branch, so the library code a build runs cannot change underneath it.

Idjenkins/shared-library-pinned
Versionv1
Categoryjenkins
Default severityerror
Interpreterpython3
Timeout30 seconds
Violations tolerated0
Collectsjenkins

Collectors

This guardrail gathers nothing itself. It depends on the collectors below, which the CLI runs once per build before any check, and reads what they found out of GUARDRAIL_FACTS. A collector that collects nothing skips this guardrail rather than failing it.

CollectorGathersInputs it is given
jenkinsThe 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.jenkinsfiles

The inputs above are this guardrail's own, passed straight through. Configuring one in buildnote.json changes what is collected, and two guardrails configured the same way share the one collection.

Configuration

json
{
  "guardrails": {
      "failOn": "error",
      "comment": true,
      "checks": [
          {
              "use": "jenkins/shared-library-pinned@v1",
              "severity": "error",
              "with": {
                  "jenkinsfiles": "Jenkinsfile,Jenkinsfile.*,*.Jenkinsfile",
                  "allow": ""
              },
              "exemptions": []
          }
      ]
  }
}

Inputs

InputDescriptionDefaultEnvironment variable
jenkinsfilesComma separated globs naming the Jenkinsfiles to read.Jenkinsfile,Jenkinsfile.*,*.JenkinsfileGUARDRAIL_INPUT_JENKINSFILES
allowComma separated shared library names exempt from pinning, for the ones your own organisation publishes. acme-* is a glob.``GUARDRAIL_INPUT_ALLOW

How to fix

Name the version you mean, and make it one that does not move:

groovy
@Library('acme-pipeline@1.4.2') _

A library loaded from a branch is code that whoever can push to that branch runs inside your build, with every credential the job has in scope, and two builds of the same commit can run different library code. A reference with no version at all is worse: it takes the default version configured on the controller, which is usually a branch and lives outside this repository, so nobody reading the Jenkinsfile can tell what ran.

Jenkins cannot tell a tag from a branch by name, so this reads the shape of the ref: a 40 character commit sha, or a version such as 1.4.2 or v1.4.2. Protect the tags you pin to, because git lets a tag move as well.

A scripted pipeline is read too, but only by pattern: a library it loads through ordinary Groovy is not read, so a finding there is real and an absence is not proof. Nothing is suppressed because a sibling file is scripted, and the check skips only when every Jenkinsfile is scripted and none of them names a library that could be read.

More in jenkins

  • jenkins/job-timeout-set. Every declarative pipeline declares how long it may run, on the pipeline itself or on every stage, so a hung build is cut off rather than holding an executor.

All 2 jenkins guardrails

Buildnote Limited
Registered in England and Wales, Reg: 16140412