我有一个参数化的 Jenkins 作业,它需要在特定的 Git 存储库中输入特定的 Git 分支。目前这个参数是一个字符串参数。
有没有办法让这个参数成为选择参数并用 Git 分支动态填充下拉列表?我不想要求有人通过在每次创建新分支时手动配置下拉菜单来维护此选择参数。
我有一个参数化的 Jenkins 作业,它需要在特定的 Git 存储库中输入特定的 Git 分支。目前这个参数是一个字符串参数。
有没有办法让这个参数成为选择参数并用 Git 分支动态填充下拉列表?我不想要求有人通过在每次创建新分支时手动配置下拉菜单来维护此选择参数。
我尝试了这个链接中提到的几个答案,但不知道如何告诉詹金斯用户选择的分支。正如我在上面线程中的先前评论中提到的,我将分支选择器字段留空。
但是,在进一步调查期间,我发现了另一种方法来做同样的事情 - https://wiki.jenkins-ci.org/display/JENKINS/Git+Parameter+Plugin 我发现这种方法要简单得多,而且东西更少配置!
这是我配置的 -
添加了以下值:
然后在作业的 git SCM 部分中,我添加了在“名称”部分中提到的相同值,就好像它是一个环境变量一样。(如果你仔细阅读这个 git 参数插件的帮助,你就会意识到这一点)
在此之后,我刚刚运行构建,选择了我的分支(Jenkins 在构建之前检查了这个分支)并且它成功地完成了构建,并且选择了我指定的分支。
扩展选择参数插件将允许您从文件中读取选择。
当然,现在您还有另一个问题:如何确保文件是最新的(可以通过 post-commit 挂钩完成)并传播给所有用户(可以通过将文件放在共享文件上来完成)文件服务器)。但可能有更好的解决方案。
我能够使用Jenkins Dynamic Parameter Plug-in实现这个结果。我使用了动态选择参数选项,对于选择脚本,我使用了以下内容:
proc1 = ['/bin/bash', '-c', "/usr/bin/git ls-remote -h ssh://user@server.com/path/to/repo.git"].execute()
proc2 = ['/bin/bash', '-c', "awk '{print \$2}'"].execute()
proc3 = ['/bin/bash', '-c', "sed s%^refs/heads%origin%"].execute()
all = proc1 | proc2 | proc3
String result = all.text
String filename = "/tmp/branches.txt"
boolean success = new File(filename).write(result)
def multiline = "cat /tmp/branches.txt".execute().text
def list = multiline.readLines()
使用“Git Parameter Plug-in”非常简单。
添加名称,例如“SELECT_BRANCH”##确保此变量,因为稍后将使用它。然后参数类型:分支
然后联系 SCM:选择:Git 和分支说明符:${SELECT_BRANCH}
要验证,请在 jenkins 的 shell 中执行以下命令:
回声 ${SELECT_BRANCH}
env.enter image description here
对于我来说,我使用输入级参数:
当用户启动一个管道时,这个管道将等待他在列表中进行选择。
pipeline{
agent any
stages{
stage('checkout scm') {
steps {
script{
git credentialsId: '8bd8-419d-8af0-30960441fcd7', url: 'ssh://jenkins@git.company.com:/usr/company/repositories/repo.git'
sh 'git branch -r | awk \'{print $1}\' ORS=\'\\n\' >>branch.txt'
}
}
}
stage('get build Params User Input') {
steps{
script{
liste = readFile 'branch.txt'
echo "please click on the link here to chose the branch to build"
env.BRANCH_SCOPE = input message: 'Please choose the branch to build ', ok: 'Validate!',
parameters: [choice(name: 'BRANCH_NAME', choices: "${liste}", description: 'Branch to build?')]
}
}
}
stage("checkout the branch"){
steps{
echo "${env.BRANCH_SCOPE}"
git credentialsId: 'ea346a50-8bd8-419d-8af0-30960441fcd7', url: 'ssh://jenkins@git.company.com/usr/company/repositories/repo.git'
sh "git checkout -b build ${env.BRANCH_NAME}"
}
}
stage(" exec maven build"){
steps{
withMaven(maven: 'M3', mavenSettingsConfig: 'mvn-setting-xml') {
sh "mvn clean install "
}
}
}
stage("clean workwpace"){
steps{
cleanWs()
}
}
}
}
然后用户将与构建进行交互:
我在这里面临类似的问题。我们的用户正在将他们的工作从自由式迁移到流水线。他们不希望将 Jenkinsfile 存储在他们的存储库中(历史原因)并且仍然想使用“Git Parameter”插件
所以我们必须使用“管道脚本”并开发一个像“Git Parameter”一样工作的不同插件。
这个新插件不与项目中的 SCM 设置集成。该插件位于https://plugins.jenkins.io/list-git-branches-parameter
希望它也能帮助你
扩展@malenkiy_scot 的答案。我创建了一个新的 jenkins 作业来构建扩展选择插件使用的文件。
您可以执行以下操作(我在 jenkins 中执行 shell 步骤,但您可以在脚本中执行此操作):
git ls-remote git@github.com:my/repo.git |grep refs/heads/* >tmp.txt
sed -e 's/.*refs\/heads\///' tmp.txt > tmp2.txt
tr '\n' ',' < tmp2.txt > tmp3.txt
sed '1i\branches=' tmp3.txt > tmp4.txt
tr -d '\n' < tmp4.txt > branches.txt
然后我使用 Artifact deployer 插件将该文件推送到共享位置,该位置位于 web url 中,然后只需使用 Extended Choice 插件中的“http://localhost/branches.txt”作为 url。奇迹般有效。
您可以使用之前由malenkiy_scot提到的扩展选择参数插件和一个简单的php脚本来完成相同的操作(假设您有一个服务器来部署您可以从Jenkins机器上访问的php脚本)
<?php
chdir('/path/to/repo');
exec('git branch -r', $output);
print('branches='.str_replace(' origin/','',implode(',', $output)));
?>
或者
<?php
exec('git ls-remote -h http://user:pass@repo.git', $output);
print('branches='.preg_replace('/[a-z0-9]*\trefs\/heads\//','',implode(',', $output)));
?>
使用第一个选项,您需要克隆 repo。对于第二个,您不需要,但在这两种情况下,您都需要在托管您的 php 脚本的服务器中安装 git。如果使用任何这些选项,它会完全动态化,您无需构建列表文件。只需将脚本的 URL 放在扩展选择参数“属性文件”字段中。
是的,我写了一个小 groovy 脚本,它可以解决问题您应该为您的工作添加一个“动态选择参数”,并根据您的需要自定义以下 groovy 脚本:
#!/usr/bin/groovy
def gitURL = "git repo url"
def command = "git ls-remote --heads --tags ${gitURL}"
def proc = command.execute()
proc.waitFor()
if ( proc.exitValue() != 0 ) {
println "Error, ${proc.err.text}"
System.exit(-1)
}
def text = proc.in.text
# put your version string match
def match = /<REGEX>/
def tags = []
text.eachMatch(match) { tags.push(it[1]) }
tags.unique()
tags.sort( { a, b ->
def a1 = a.tokenize('._-')
def b1 = b.tokenize('._-')
try {
for (i in 1..<[a1.size(), b1.size()].min()) {
if (a1[i].toInteger() != b1[i].toInteger()) return a1[i].toInteger() <=> b1[i].toInteger()
}
return 1
} catch (e) {
return -1;
}
} )
tags.reverse()
在我的情况下,版本字符串采用以下格式 XXXX 并且可以具有格式为 XXX-username 等的用户分支......所以我必须编写自己的排序函数。这是我的第一个 groovy 脚本,所以如果有更好的做事方法,我想知道。
我们可以通过使用text
. 我的完整解决方案如下:
proc1 = ['/bin/bash', '-c',
"/usr/bin/git ls-remote --heads ssh://repo_url.git"].execute()
proc2 = ['/bin/bash', '-c',
"/usr/bin/awk ' { gsub(/refs\\/heads\\//, \"\"); print \$2 }' "].execute()
all = proc1 | proc2
choices = all.text
return choices.split().toList();
如果您的工作不直接使用“源代码管理”(同样是“Git 参数插件”),但仍然可以访问本地(克隆)git 存储库,则以下 groovy 脚本将很有用:
import jenkins.model.Jenkins
def envVars = Jenkins.instance.getNodeProperties()[0].getEnvVars()
def GIT_PROJECT_PATH = envVars.get('GIT_PROJECT_PATH')
def gettags = "git ls-remote -t --heads origin".execute(null, new File(GIT_PROJECT_PATH))
return gettags.text.readLines()
.collect { it.split()[1].replaceAll('\\^\\{\\}', '').replaceAll('refs/\\w+/', '') }
.unique()
在此处查看完整说明: https ://stackoverflow.com/a/37810768/658497
我知道在最初的问题中没有提到 Jenkins 管道,但如果它仍然适用(使用它),我发现这个解决方案易于维护和方便。
这种方法描述了组成 Jenkins 管道所需的设置,该管道动态“轮询”(列出)特定存储库的所有分支,然后允许用户在运行此作业的构建时使用某些特定分支运行管道。
这里的假设是:
首先要做的是提供 Jenkins 凭据以连接(和“获取”)到 BitBucket 中的私有存储库。这可以通过创建一个 SSH 密钥对来“链接”托管 Jenkins 服务器的机器上的 Jenkins (!!) 用户和(私有)BitBucket 存储库。
首先是为 Jenkins 用户(即运行 Jenkins 服务器的用户 - 它很可能在安装时默认创建)创建一个 SSH 密钥:
guya@ubuntu_jenkins:~$ sudo su jenkins
[sudo] password for guya:
jenkins@ubuntu_jenkins:/home/guya$ ssh-keygen
输出应类似于以下内容:
生成公钥/私钥 rsa 密钥对。输入保存密钥的文件
(/var/lib/jenkins/.ssh/id_rsa):创建目录'/var/lib/jenkins/.ssh'。Enter passphrase (empty for no passphrase): Enter the same passphrase again: 您的身份已保存在 /var/lib/jenkins/.ssh/id_rsa 中。您的公钥已保存在 /var/lib/jenkins/.ssh/id_rsa.pub 中。密钥指纹为:SHA256:q6PfEthg+74QFwO+esLbOtKbwLG1dhtMLfxIVSN8fQY jenkins@ubuntu_jenkins 密钥的随机艺术图像为:+---[RSA 2048]----+ | . .. OE | | . . .o... o | | . o..o | | +.oo | | . ooX..S | |..+.Bo* . | |.++oo* o. | |..+*..*o | | .=+o==+。| +----[SHA256]-----+ jenkins@ubuntu_jenkins:/home/guya$
Settings --> Access keys --> Add key
。cat /var/lib/jenkins/.ssh/id_rsa.pub
jenkins
这个“特权”。这可以通过将带有私钥的新 SSH 用户名添加到Jenkins --> Credentials --> System --> Global Credentials --> Add credentials
.
jenkins
.~/.ssh/id_rsa
。-----BEGIN RSA PRIVATE KEY-----
这是以 string: 开头并以 string:结尾的私钥-----END RSA PRIVATE KEY-----
。请注意,应将整个“块”复制粘贴到上述部分中。列出(动态)给定存储库的所有分支所需的最小管道如下:
pipeline
{
agent any parameters
{
gitParameter branchFilter: 'origin/(.*)', defaultValue: 'master', name: 'BRANCH', type: 'PT_BRANCH'
}
stages
{
stage("list all branches")
{
steps
{
git branch: "${params.BRANCH}", credentialsId: "SSH_user_name_with_private_key", url: "ssh://git@myCompanyBitBucketSite.com:port/myRepository.git"
}
}
}
}
笔记:
defaultValue
设置为以便如果master
不存在分支 - 它将显示在管道的“下拉列表”中。credentialsId
名称。你可以试试这个,这个列表在下拉列表中输入了 Git Repo 的动态分支名称。
需要 Jenkins 插件:
选项 1:詹金斯文件:
properties([
[$class: 'JobRestrictionProperty'], parameters([validatingString(defaultValue: 'https://github.com/kubernetes/kubernetes.git', description: 'Input Git Repo (https) Url', failedValidationMessage: 'Invalid Git Url. Retry again', name: 'GIT_REPO', regex: 'https://.*'), [$class: 'CascadeChoiceParameter', choiceType: 'PT_SINGLE_SELECT', description: 'Select Git Branch Name', filterLength: 1, filterable: false, name: 'BRANCH_NAME', randomName: 'choice-parameter-8292706885056518', referencedParameters: 'GIT_REPO', script: [$class: 'GroovyScript', fallbackScript: [classpath: [], sandbox: false, script: 'return[\'Error - Unable to retrive Branch name\']'], script: [classpath: [], sandbox: false, script: ''
'def GIT_REPO_SRC = GIT_REPO.tokenize(\'/\')
GIT_REPO_FULL = GIT_REPO_SRC[-2] + \'/\' + GIT_REPO_SRC[-1]
def GET_LIST = ("git ls-remote --heads git@github.com:${GIT_REPO_FULL}").execute()
GET_LIST.waitFor()
BRANCH_LIST = GET_LIST.in.text.readLines().collect {
it.split()[1].replaceAll("refs/heads/", "").replaceAll("refs/tags/", "").replaceAll("\\\\^\\\\{\\\\}", "")
}
return BRANCH_LIST ''
']]]]), throttleJobProperty(categories: [], limitOneJobWithMatchingParams: false, maxConcurrentPerNode: 0, maxConcurrentTotal: 0, paramsToUseForLimit: '
', throttleEnabled: false, throttleOption: '
project '), [$class: '
JobLocalConfiguration ', changeReasonComment: '
']])
try {
node('master') {
stage('Print Variables') {
echo "Branch Name: ${BRANCH_NAME}"
}
}
catch (e) {
currentBuild.result = "FAILURE"
print e.getMessage();
print e.getStackTrace();
}
选项 2:詹金斯用户界面
样本输出: