Last active
January 17, 2025 13:03
-
-
Save jimklimov/46e3f78379cb5ddd0c8202a5e4b7b9fa to your computer and use it in GitHub Desktop.
Quick and dirty Mother Seed Job for Jenkins pipelines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Quick and dirty Mother Seed Job for Jenkins pipelines | |
// when many Jenkinsfiles live in same CI repository. | |
// Creates (if absent) a folder populated by multi-branch | |
// pipelines, each relying on its Git repo and pipeline | |
// filename (should be unique by naming construct below). | |
// | |
// NOTE: Needs "Job DSL plugin" installed | |
// | |
// NOTE: You will need to approve a number of method signatures | |
// at $JENKINS_URL/scriptApproval/ before it completes successfully. | |
// | |
// NOTE: For Jenkins instances that are used to test pipelines | |
// (so security is not a great concern), hopefully, setting | |
// org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.ADMIN_AUTO_APPROVAL_ENABLED=true | |
// and org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval.ALLOW_ADMIN_APPROVAL_ENABLED=true | |
// as java properties during startup of Jenkins will disable | |
// the need to approve scripts as an admin. | |
// | |
// (C) 2025 by Jim Klimov, docs and blogs I inspired from | |
import com.cloudbees.hudson.plugins.folder.AbstractFolder | |
// Local repo can be used, e.g.: | |
def GIT_REPO = 'file:///c/continuous-integration' | |
def JENKINS_FOLDER = 'WIP' | |
def JF_REGEX = /^Jenkinsfile.*$/ | |
//def BRANCH_REGEX_STR = 'master' | |
def BRANCH_REGEX_STR = '.*' | |
Map tips = [:] | |
Set branch_hashes = [] | |
Set filenames = [] | |
pipeline { | |
agent any | |
stages { | |
stage("list git tips and Jenkinsfiles") { | |
steps { | |
script { | |
dir ('tmp-ci') { | |
deleteDir() | |
} | |
dir ('tmp-ci') { | |
sh "git clone --bare '${GIT_REPO}' ." | |
sh (script: "git ls-remote .", returnStdout: true).split(/[\r\n]/).each{ | |
if (!it) | |
return // continue | |
def l = it.split(/\s+/) | |
// 1a1d3d5bda2773b82dd9ddf0485110309639eba6 HEAD | |
// 853ac842014019a62f6ca01ae37f6f230a9586dc refs/heads/master | |
// fde2ccebe0cbd3fb7c20dcc9526a7f63a8e22930 refs/remotes/origin/HEAD | |
// 853ac842014019a62f6ca01ae37f6f230a9586dc refs/remotes/origin/master | |
tips[l[1]] = l[0] | |
if (l[1] ==~ /^refs\/heads\/${BRANCH_REGEX_STR}/) | |
branch_hashes << l[0] | |
} | |
echo "GIT TIPS: ${tips}" | |
branch_hashes.each { | |
sh (script: "git ls-tree '${it}'", returnStdout: true).split(/[\r\n]/).each{ | |
if (!it) | |
return // continue | |
def l = it.split(/\s+/) | |
// 100644 blob 4d414593cd4c0888c3cdb688eab8ffb6cfe93546 Jenkinsfile-sbomgen | |
if (l[3] ==~ JF_REGEX) | |
filenames << l[3] | |
} | |
} | |
echo "JENKINSFILES: ${filenames}" | |
} | |
} | |
} | |
} | |
stage("Use JobDSL to create stuff") { | |
steps { | |
script { | |
// https://opstree.com/blog/2023/06/06/jenkins-job-creation-using-multibranch-job-dsl/ | |
// https://github.com/jenkinsci/job-dsl-plugin/wiki/User-Power-Moves#use-job-dsl-in-pipeline-scripts | |
// https://github.com/cloudbees/jenkins-scripts/blob/master/FindAllGroupsInFolders.groovy | |
AbstractFolder folderItem = Jenkins.instance.getAllItems(AbstractFolder.class).find{ (it.name == JENKINS_FOLDER) } | |
if (folderItem) { | |
echo "SKIP: ${folderItem} already exists" | |
} else { | |
jobDsl scriptText: ''' | |
folder("${JENKINS_FOLDER}") { | |
displayName("${JENKINS_FOLDER}") | |
description('Folder for CI job MBPs') | |
} | |
''', additionalParameters: [JENKINS_FOLDER: JENKINS_FOLDER] | |
} | |
filenames.each { String filename -> | |
// Check if job exists | |
def mbpItem = Jenkins.instance.getAllItems().find{ (it.name == "${JENKINS_FOLDER}/${filename}") } | |
if (mbpItem) { | |
echo "SKIP: ${mbpItem} already exists" | |
return // continue | |
} | |
jobDsl scriptText: ''' | |
multibranchPipelineJob("${JENKINS_FOLDER}/${filename}") { | |
branchSources { | |
branchSource { | |
source { | |
git { | |
id('CI') | |
remote(GIT_REPO) | |
} | |
} | |
strategy { | |
defaultBranchPropertyStrategy { | |
props { | |
noTriggerBranchProperty() | |
} | |
} | |
} | |
} | |
} | |
configure { | |
def traits = it / sources / data / 'jenkins.branch.BranchSource' / source / traits | |
traits << 'jenkins.plugins.git.traits.BranchDiscoveryTrait' {} | |
} | |
factory { | |
workflowBranchProjectFactory { | |
scriptPath(filename) | |
} | |
} | |
orphanedItemStrategy { | |
discardOldItems { | |
numToKeep(20) | |
} | |
} | |
} | |
''', additionalParameters: [JENKINS_FOLDER: JENKINS_FOLDER, filename: filename, GIT_REPO: GIT_REPO] | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment