如何通过SEED job从同一代码库批量创建多个Jenkins作业
可行实现方案
你可以选择以下两种方案实现需求,均可直接适配你现有的Job DSL代码:
方案一:调用GitLab API 遍历远端目录(无需克隆完整仓库)
该方案通过GitLab公开的仓库文件接口直接查询目标路径下的所有Jenkinsfile,不需要拉取仓库代码,步骤如下:
- 先在GitLab中生成一个拥有
read_repository权限的个人访问令牌(PAT),用于接口鉴权 - 替换原有代码为以下实现即可:
#!/usr/bin/env groovy // 配置项 final String gitlabApiUrl = "https://gitlab.com/api/v4" final String repoFullPath = "sommerfeld.sebastian/docker-jenkins-pipelines" final String repoId = URLEncoder.encode(repoFullPath, "UTF-8") final String gitlabToken = "你的GitLab PAT" final String jobRootPath = "src/main/jobs" final String targetBranch = "main" // 调用GitLab API获取指定目录下的所有子目录 def getJobDirectories() { def get = new URL("${gitlabApiUrl}/projects/${repoId}/repository/tree?path=${jobRootPath}&ref=${targetBranch}&per_page=100").openConnection() get.setRequestProperty("PRIVATE-TOKEN", gitlabToken) def response = new groovy.json.JsonSlurper().parse(get.getInputStream()) // 过滤只保留目录,排除文件 return response.findAll { it.type == "tree" }.collect { it.name } } // 改造后的创建作业方法,支持传入作业名和Jenkinsfile路径 def createPipelineJob(final String jobName, final String scriptPath) { pipelineJob(jobName) { definition { cpsScm { scm { git { remote { url('git@gitlab.com:' + repoFullPath +'.git') } branches("*/${targetBranch}") } } scriptPath(scriptPath) } } } } // 遍历所有子目录,为每个目录下的Jenkinsfile创建作业 def jobDirs = getJobDirectories() jobDirs.each { dirName -> def scriptPath = "${jobRootPath}/${dirName}/Jenkinsfile" // 作业名直接用目录名,你也可以自定义规则,比如加前缀 createPipelineJob(dirName, scriptPath) }
方案二:Seed Job本地克隆仓库遍历(无需申请API令牌,配置更简单)
如果不想额外申请GitLab PAT,可以让你的SEED Job本身先克隆目标仓库到工作区,本地遍历匹配src/main/jobs/*/Jenkinsfile规则的文件,实现代码如下:
注意:需要先配置SEED Job的源码管理为对应的GitLab仓库,分支选择main,让Job运行时自动拉取代码到工作区
#!/usr/bin/env groovy final String repoFullPath = "sommerfeld.sebastian/docker-jenkins-pipelines" final String targetBranch = "main" final String jobRootPath = "src/main/jobs" def createPipelineJob(final String jobName, final String scriptPath) { pipelineJob(jobName) { definition { cpsScm { scm { git { remote { url('git@gitlab.com:' + repoFullPath +'.git') } branches("*/${targetBranch}") } } scriptPath(scriptPath) } } } } // 本地遍历工作区下的所有符合规则的Jenkinsfile new File(jobRootPath).eachDir { dir -> def jenkinsfile = new File(dir, "Jenkinsfile") if (jenkinsfile.exists()) { def jobName = dir.name def scriptPath = "${jobRootPath}/${dir.name}/Jenkinsfile" createPipelineJob(jobName, scriptPath) } }
注意事项
- 两种方案均支持自定义作业命名规则,你可以根据需要修改
jobName的生成逻辑,比如增加前缀、拼接目录层级等 - 可以开启Job DSL的自动删除策略,当仓库中删除某个Jenkinsfile目录后,下次运行SEED Job会自动删除Jenkins中对应的旧作业
- 如果目录数量超过100个,方案一需要处理GitLab API的分页逻辑,增加page参数遍历所有页即可
内容的提问来源于stack exchange,提问作者Sebastian Sommerfeld
相关产品推荐
相关产品推荐

