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.
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.
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.
Knowledge check
Answer before revealing the explanation.
1. Why does the mandatory lab use a mock provider inventory?
A real Organization Folder requires an external SCM provider account and organization-level API semantics. The mock preserves the discovery/filter/lifecycle model while keeping the lab free, local and disposable.
2. What proves that a repository is eligible in the simulation?
A deterministic rule over provider metadata: active/not archived, permitted visibility, required Jenkinsfile signal/topic, allowed ownership, and an explicit repository identifier. The rule and input inventory are both preserved.
3. Why create child Multibranch items only after saving the discovery result?
It separates provider discovery evidence from Jenkins item mutation. If later behavior is wrong, you can prove whether the error came from filtering or child configuration.
4. How should a removed repository be handled?
First mark it absent/orphaned and preserve scan evidence. Apply the configured retention policy deterministically; do not immediately delete the child and erase history.
5. What is different in a real provider path?
The provider plugin performs authenticated API discovery and may manage webhooks/traits. You must verify actual provider permissions, rate limits, trust semantics and webhook ownership instead of assuming the mock reproduces them.
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. - Branch API — version
2.1280.v0d4e5b_b_460ef; defines organizational folders, Multibranch children and event/computation logging. - Folders — version
6.1106.v3a_d9a_6d2465e. - Credentials — version
1511.v2e3cb_0008ef0. - GitHub Branch Source — version
1983.vfa_27ed961853, requiring Jenkins 2.541.1. - GitLab Branch Source — version
743.ve0c8154a_8da_b_, requiring Jenkins 2.504.3. - Bitbucket Branch Source — version
937.3.10, requiring Jenkins 2.541.3. - GitHub REST API rate limits — authenticated users normally receive 5,000 requests/hour; GitHub App installation limits vary and include higher Enterprise Cloud allowances.
- GitLab.com rate limits — authenticated limits are plan-dependent; self-managed limits can differ.
- Bitbucket Cloud API request limits — authenticated and anonymous requests have separate rolling limits.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.