Chapter 23Lesson 02~190 minutes

Organization Folders, GitHub/GitLab/Bitbucket Discovery, Repository Onboarding, and Platform Automation: Guided Hands-On Workflow and Core Operations

Build a free local simulation of provider discovery, filter a synthetic organization inventory, create the matching Jenkins child items, preserve scan evidence, simulate repository addition/removal, and compare the simulation with an optional real GitHub/GitLab/Bitbucket Organization Folder path.

Hands-onMock providerRepository filtersChild itemsScan logsOrphans

Learning objectives

  • Create a disposable organization inventory with active, archived, private and ineligible repositories.
  • Run a deterministic discovery/filter pass and preserve its evidence.
  • Map eligible repositories to disposable Jenkins Multibranch children.
  • Simulate repository addition/removal and deterministic orphan handling.
  • Understand what a real GitHub/GitLab/Bitbucket Organization Folder adds beyond the simulation.

1. Lab topology and preflight

Use Jenkins 2.568.3 LTS on Java 21 and the disposable low-privilege agent used by the previous chapters. The mandatory path does not require a provider account, provider token, webhook or organization-admin permission. We will model the provider API as versioned local JSON and use local bare Git repositories.

Simulation boundary: a local mock cannot reproduce provider-side fork identity, app installation permissions, webhook delivery or real API quotas. Those remain optional provider-specific exercises.

2. Create a synthetic organization inventory

set -eu
LAB=/tmp/ch23-platform
rm -rf "$LAB"
mkdir -p "$LAB/provider" "$LAB/repos"
cat > "$LAB/provider/repos.json" <<'EOF'
[
 {"id":101,"name":"payments-api","visibility":"public","archived":false,"jenkins":true,"owner":"team-payments"},
 {"id":102,"name":"catalog-api","visibility":"public","archived":false,"jenkins":true,"owner":"team-catalog"},
 {"id":103,"name":"legacy-archived","visibility":"public","archived":true,"jenkins":true,"owner":"team-legacy"},
 {"id":104,"name":"private-sim","visibility":"private","archived":false,"jenkins":true,"owner":"team-security"},
 {"id":105,"name":"docs-only","visibility":"public","archived":false,"jenkins":false,"owner":"docs"}
]
EOF
python3 -m json.tool "$LAB/provider/repos.json"

This JSON is provider state. Do not edit it to force Jenkins to match your expectation; save the original as evidence.

3. Apply the discovery policy

The lab policy is intentionally explicit: repository must be active, public in this fake environment, Jenkins-enabled and owned by an allowed engineering team.

# /tmp/ch23-platform/discover.py
import json
from pathlib import Path
repos=json.loads(Path('/tmp/ch23-platform/provider/repos.json').read_text())
allowed={'team-payments','team-catalog'}
selected=[r for r in repos if not r['archived'] and r['visibility']=='public'
          and r['jenkins'] and r['owner'] in allowed]
for r in selected:
    print(f"{r['id']}\t{r['name']}\t{r['owner']}")
python3 /tmp/ch23-platform/discover.py | tee /tmp/ch23-platform/discovered.tsv

Expected children are only payments-api and catalog-api. Preserve both the input JSON and output TSV.

4. Create local synthetic repositories

set -eu
LAB=/tmp/ch23-platform
for name in payments-api catalog-api; do
  git init --bare "$LAB/repos/${name}.git"
  work=$(mktemp -d)
  git clone "$LAB/repos/${name}.git" "$work/$name"
  cd "$work/$name"
  git config user.name 'DevOps Academy Lab'
  git config user.email 'lab@example.invalid'
  git switch -c main
  cat > Jenkinsfile < app.txt
  git add . && git commit -m 'initial synthetic service'
  git push -u origin main
  rm -rf "$work"
done

5. Map discovery to Jenkins child items

Create a disposable ordinary Folder named ch23-org-sim. Inside it create two Multibranch Pipeline items named exactly payments-api and catalog-api, each pointing to its local bare repository. This manual mapping intentionally separates discovery evidence from Jenkins item mutation. Record the folder full name and each child full name.

Do not add protected credentials. Route all builds only to the disposable ch23-lowtrust agent. Run one branch index/build per child and capture the exact source SHA.

6. Simulate repository addition

Add a new eligible repository orders-api to repos.json with a stable ID and allowed owner, rerun discover.py, and save the before/after diff. Only after the discovery output proves eligibility should you create the matching disposable Multibranch child. This models the Organization Folder transition “provider inventory changed → computation creates a child.”

7. Simulate removal without destructive cleanup

Remove catalog-api from the provider inventory and rerun discovery. Mark the Jenkins child as orphan candidate in your evidence notes. Do not delete it yet. Record its latest build/source SHA and your intended retention window, then disable or retain it according to the lab policy. This models deterministic orphan handling without losing proof.

8. Optional real Organization Folder path

If you own a disposable GitHub/GitLab/Bitbucket organization or group, install the exact reviewed branch-source plugin and create an Organization Folder using the narrowest provider identity that can list the intended repositories. Record the credential type/scope, organization identifier, traits, webhook registration behavior, provider rate-limit headers and generated children. Never use an employer/customer organization for this lab.

9. Challenge: choose the right layer

A repository is visible to the provider identity but should not be onboarded. Do you remove provider access? Not necessarily. First ask whether a discovery filter/topic/team rule should exclude it while keeping the identity scoped to the smallest practical provider boundary. Provider visibility and Jenkins eligibility are different states.

10. Cleanup

Export the inventory, discovery outputs, child/source evidence and orphan notes. Remove only ch23-org-sim, the lab repositories and the low-trust agent if created for this chapter. Do not touch real provider hooks, credentials or unrelated Jenkins folders.

Next lesson

Configuration, Design Choices, and Tradeoffs

Compare organization-wide onboarding models, provider identities, self-service, scan/webhook strategies and retention tradeoffs.

Knowledge check

Answer before revealing the explanation.

1. Why does the mandatory lab use a mock provider inventory?

2. What proves that a repository is eligible in the simulation?

3. Why create child Multibranch items only after saving the discovery result?

4. How should a removed repository be handled?

5. What is different in a real provider path?

Official references and version notes

Version note — 2026-09-17: mandatory exercises are a local faithful simulation and require no external SCM account. The optional real-provider path must re-check the exact provider plugin version, security advisories, API permissions, webhook behavior, rate-limit headers and provider-plan limits before use. Never substitute a broad personal/admin token merely to make discovery easier.

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.