Chapter 22Lesson 02~190 minutes

Multibranch Pipelines, Branch Sources, Pull Request Discovery, Jenkinsfile Trust, and Branch Indexing: Guided Hands-On Workflow and Core Operations

Create a disposable local repository, index multiple branches, prove which Jenkinsfile/source revision each branch job executes, change one branch safely, inspect indexing evidence, and practice bounded orphaned-item retention. A PR-like branch models discovery locally while provider-specific fork trust remains a separate security control.

Hands-onLocal GitBranch jobsIndexing logsSource SHAOrphaned items

Learning objectives

  • Create a disposable local Git repository suitable for a Multibranch Pipeline lab.
  • Discover branches, inspect indexing logs and verify exact Jenkinsfile/source revisions.
  • Change one branch Jenkinsfile and prove only the expected child revision changes.
  • Simulate an untrusted contribution without making protected credentials available.
  • Delete a branch and verify bounded orphaned-item behavior.

1. Lab topology and preflight

The mandatory path stays free and local. Use the existing disposable Jenkins 2.568.3 LTS controller with Java 21, one disposable low-privilege agent labeled ch22-untrusted, Git 5.10.1 and Git Client 6.6.1. The controller and agent must both be able to read the same local bare repository path /lab-scm/ch22-lab.git. For containerized Jenkins, bind-mount the same synthetic repository path into the controller and agent lab containers.

No real secrets: do not add cloud, registry, signing or production credentials to this Multibranch project. The local branch-only simulation cannot reproduce provider fork trust, so the safe lab proves behavior with zero protected secrets available.

2. Create a synthetic bare repository

Run these commands outside Jenkins in a disposable lab directory. They create a bare remote and three branches with intentionally visible Jenkinsfile markers.

set -eu
LAB=/tmp/ch22-author
REMOTE=/lab-scm/ch22-lab.git
rm -rf "$LAB" "$REMOTE"
mkdir -p "$(dirname "$REMOTE")"
git init --bare "$REMOTE"
git clone "$REMOTE" "$LAB"
cd "$LAB"
git config user.name 'DevOps Academy Lab'
git config user.email 'lab@example.invalid'

git switch -c main
cat > Jenkinsfile <<'EOF'
pipeline {
  agent { label 'ch22-untrusted' }
  stages {
    stage('Evidence') {
      steps {
        sh '''set -eu
          printf 'branch=%s build=%s node=%s workspace=%s\\n' "$BRANCH_NAME" "$BUILD_NUMBER" "$NODE_NAME" "$WORKSPACE"
          git rev-parse HEAD | tee source-sha.txt
          printf 'jenkinsfile_marker=main-v1\\n' | tee jenkinsfile-marker.txt
        '''
        archiveArtifacts artifacts: 'source-sha.txt,jenkinsfile-marker.txt', fingerprint: true
      }
    }
  }
}
EOF
printf 'synthetic app v1\n' > app.txt
git add Jenkinsfile app.txt
git commit -m 'main: initial synthetic pipeline'
git push -u origin main

git switch -c feature-safe
sed -i 's/main-v1/feature-safe-v1/' Jenkinsfile
printf 'feature change\n' >> app.txt
git add . && git commit -m 'feature: safe branch'
git push -u origin feature-safe

git switch main
git switch -c pr-untrusted
sed -i 's/main-v1/pr-untrusted-v1/' Jenkinsfile
printf 'untrusted contribution simulation\n' >> app.txt
git add . && git commit -m 'simulation: untrusted contribution'
git push -u origin pr-untrusted

git log --all --decorate --oneline --graph

pr-untrusted is intentionally just a branch. It gives us a reproducible candidate to discuss trust without pretending that plain Git can identify a fork author.

3. Create the Multibranch Pipeline

In Jenkins create New Item → Multibranch Pipeline named ch22-multibranch. Add a Git branch source pointing to file:///lab-scm/ch22-lab.git (or an equivalent reachable local URL). Leave credentials empty because the repository is synthetic and local. Keep the default Jenkinsfile path Jenkinsfile.

Configure an orphaned-item strategy appropriate to the lab, for example retaining a small number of old branch jobs/builds for review rather than deleting immediately. Record the exact values in your evidence packet.

4. Inspect the first branch index

Saving the project should trigger indexing. Open Scan Multibranch Pipeline Log and preserve the first log. Confirm that Jenkins discovers main, feature-safe and pr-untrusted and creates child jobs for branches containing a Jenkinsfile.

Record the parent full name and the three child names. Child names can be encoded when SCM head names contain characters that are unsafe in item paths; never derive security policy from display-name formatting.

5. Prove which source and Jenkinsfile each child runs

Run or inspect one build per branch. The archived source-sha.txt must match the Git commit for that branch at build time, and jenkinsfile-marker.txt must match the branch-specific marker. Also record the build cause and BRANCH_NAME.

cd /tmp/ch22-author
for b in main feature-safe pr-untrusted; do
  printf '%-14s ' "$b"
  git rev-parse "$b"
done

This separates “the parent indexed branch X” from “child X built commit Y using Jenkinsfile content Z.”

6. Change one branch Jenkinsfile and re-index

Modify only feature-safe:

cd /tmp/ch22-author
git switch feature-safe
sed -i 's/feature-safe-v1/feature-safe-v2/' Jenkinsfile
git add Jenkinsfile
git commit -m 'feature: update pipeline marker'
git push origin feature-safe

Trigger a branch index if your local source has no webhook/event integration. Verify the feature-safe child builds the new source revision and marker while main remains attributable to its own revision. Preserve both build numbers.

7. Simulate an untrusted contribution correctly

Treat pr-untrusted as contributor-controlled code for discussion. The lab boundary is external to the branch content: the Multibranch project has no protected credential configured or reachable, and the only eligible agent is a disposable low-privilege ch22-untrusted worker. Do not create a fake “production token” and rely on masking.

Now edit the branch Jenkinsfile so it tries to request a nonexistent credential ID such as ch22-protected-simulation. The build should fail because that credential does not exist. Preserve the failure as evidence that the lab did not silently substitute a real secret.

Important limitation: a malicious branch Jenkinsfile could also request another label if Jenkins allows it. Therefore a production fork-PR boundary requires provider trust/authorization and infrastructure controls outside contributor-editable code. This local exercise demonstrates the principle, not the provider guarantee.

8. Optional provider-specific trust path

With a provider branch-source plugin such as GitHub Branch Source, pull requests are separate SCM heads and fork trust can determine which revision supplies trusted files. Current Jenkins documentation describes strategies such as trusting nobody or approved collaborators. Use provider documentation for exact traits and never test this against an organization repository with real deployment credentials.

The production objective is simple: untrusted candidate code may be tested, but it cannot rewrite the control path that grants protected secrets or privileged agents.

9. Delete a branch and inspect orphaning

cd /tmp/ch22-author
git push origin --delete feature-safe

Run a branch index and verify how feature-safe changes according to the recorded orphaned-item strategy. Do not manually delete the child first; you want evidence of Jenkins applying policy.

10. Challenge: choose the correct layer

A new fork PR appears, Jenkins indexes it successfully, and the build then cannot access a signing credential. Is the correct fix “add the signing credential to the Multibranch parent”? No. First determine whether the PR is trusted. For an untrusted contribution, the denial is the desired boundary; move signing to a trusted post-merge/release path rather than broadening credentials.

11. Cleanup

Export the indexing log and selected build evidence, then remove only ch22-multibranch, the synthetic repository/mount and the disposable agent if they were created for this chapter. Do not touch production SCM hooks or credentials.

Next lesson

Configuration, Design Choices, and Tradeoffs

Compare Multibranch with one Pipeline job, branch/PR discovery strategies, fork trust, webhook/scan behavior, trusted libraries and retention.

Knowledge check

Answer before revealing the explanation.

1. Why does the local lab use a bare repository and plain Git branch discovery?

2. Why is the pr-untrusted branch only a simulation of a fork PR?

3. What evidence proves which Jenkinsfile revision ran?

4. Why should the lab keep protected credentials absent from all branch jobs?

5. What should happen when a test branch is deleted?

Official references and version notes

  • Jenkins LTS changelog — chapter baseline Jenkins 2.568.3 LTS, released 2026-09-02 and tested with Java 21 and 25; labs use Java 21.
  • Jenkins: Branches and Pull Requests — Multibranch discovery, branch child jobs, indexing and change-request environment variables.
  • Pipeline: Multibranch — version 841.vec5b_9e1806ec, requiring Jenkins 2.504.3.
  • Branch API — version 2.1280.v0d4e5b_b_460ef; documents Multibranch event/indexing log locations and routing.
  • SCM API — version 728.vc30dcf7a_0df5.
  • Git plugin — version 5.10.1.
  • Git Client plugin — version 6.6.1; current releases include fixes for earlier command-injection issues on agents.
  • GitHub Branch Source — provider-specific optional reference, version 1983.vfa_27ed961853, requiring Jenkins 2.541.1.
  • Pipeline: Multibranch step/reference — documents provider pull-request trust strategies and trusted-file behavior.
  • Credentials API — version 1511.v2e3cb_0008ef0; credentials remain a separate authorization boundary from SCM discovery.

Version note — 2026-09-17: executable local examples assume Jenkins 2.568.3 LTS, Java 21, Pipeline: Multibranch 841.vec5b_9e1806ec, Branch API 2.1280.v0d4e5b_b_460ef, SCM API 728.vc30dcf7a_0df5, Git 5.10.1, and Git Client 6.6.1. GitHub Branch Source 1983.vfa_27ed961853 is used only to explain a real provider fork/PR trust model; the mandatory local lab does not require an external SCM account or real SCM credential. Re-check provider plugin advisories and trust semantics before production adoption.

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
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.