67

我有一个参数化的 Jenkins 作业,它需要在特定的 Git 存储库中输入特定的 Git 分支。目前这个参数是一个字符串参数。

有没有办法让这个参数成为选择参数并用 Git 分支动态填充下拉列表?我不想要求有人通过在每次创建新分支时手动配置下拉菜单来维护此选择参数。

4

14 回答 14

87

我尝试了这个链接中提到的几个答案,但不知道如何告诉詹金斯用户选择的分支。正如我在上面线程中的先前评论中提到的,我将分支选择器字段留空。

但是,在进一步调查期间,我发现了另一种方法来做同样的事情 - https://wiki.jenkins-ci.org/display/JENKINS/Git+Parameter+Plugin 我发现这种方法要简单得多,而且东西更少配置!

这是我配置的 -

  1. 安装了git参数插件
  2. 检查“此构建已参数化”并添加了“Git 参数”
  3. 添加了以下值:作业中的 Git Parameter 插件配置

  4. 然后在作业的 git SCM 部分中,我添加了在“名称”部分中提到的相同值,就好像它是一个环境变量一样。(如果你仔细阅读这个 git 参数插件的帮助,你就会意识到这一点) 分支选择器

在此之后,我刚刚运行构建,选择了我的分支(Jenkins 在构建之前检查了这个分支)并且它成功地完成了构建,并且选择了我指定的分支。

于 2015-03-23T16:16:25.770 回答
22

扩展选择参数插件将允许您从文件中读取选择。

当然,现在您还有另一个问题:如何确保文件是最新的(可以通过 post-commit 挂钩完成)并传播给所有用户(可以通过将文件放在共享文件上来完成)文件服务器)。但可能有更好的解决方案。

于 2012-05-03T15:44:29.167 回答
15

我能够使用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()
于 2014-09-02T16:42:42.883 回答
12

使用“Git Parameter Plug-in”非常简单。

添加名称,例如“SELECT_BRANCH”##确保此变量,因为稍后将使用它。然后参数类型:分支

然后联系 SCM:选择:Git 和分支说明符:${SELECT_BRANCH}

要验证,请在 jenkins 的 shell 中执行以下命令:

回声 ${SELECT_BRANCH}

env.enter image description here

在此处输入图像描述

于 2016-10-15T15:54:42.387 回答
7

对于我来说,我使用输入级参数:

  1. 我通过检查 git 项目开始我的管道。
  2. 我使用 awk commade 生成包含所有分支列表的 barnch.txt 文件
  3. 在阶段 setps 中,我读取文件并使用它来生成输入选择参数

当用户启动一个管道时,这个管道将等待他在列表中进行选择。

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()
        }
    }
}

}

然后用户将与构建进行交互:

在此处输入图像描述

在此处输入图像描述

于 2018-06-06T14:19:46.517 回答
5

我在这里面临类似的问题。我们的用户正在将他们的工作从自由式迁移到流水线。他们不希望将 Jenkinsfile 存储在他们的存储库中(历史原因)并且仍然想使用“Git Parameter”插件

所以我们必须使用“管道脚本”并开发一个像“Git Parameter”一样工作的不同插件。

这个新插件不与项目中的 SCM 设置集成。该插件位于https://plugins.jenkins.io/list-git-branches-parameter

希望它也能帮助你

于 2018-12-25T09:28:00.193 回答
4

我对这种情况有一个新的回应:解决这个问题的简单方法是让你从源代码中获取 jenkinsFile。

然后你选择了:这个工作有一个 git 参数

在此处输入图像描述

并且管道设置,取消选中“轻量级结帐”复选框,这将在作业工作区执行真正的 git 结帐。

在此处输入图像描述

之后,参数将由您的 git 分支自动填充

于 2019-04-18T11:17:51.177 回答
2

扩展@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。奇迹般有效。

于 2013-01-12T09:18:27.823 回答
2

您可以使用之前由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 放在扩展选择参数“属性文件”字段中。

于 2013-03-06T09:25:47.267 回答
2

是的,我写了一个小 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 脚本,所以如果有更好的做事方法,我想知道。

于 2014-03-16T17:36:51.803 回答
1

我们可以通过使用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();
于 2017-12-12T10:33:55.333 回答
0

如果您的工作不直接使用“源代码管理”(同样是“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

于 2016-06-15T21:19:44.040 回答
0

我知道在最初的问题中没有提到 Jenkins 管道,但如果它仍然适用(使用它),我发现这个解决方案易于维护和方便。

这种方法描述了组成 Jenkins 管道所需的设置,该管道动态“轮询”(列出)特定存储库的所有分支,然后允许用户在运行此作业的构建时使用某些特定分支运行管道。

这里的假设是:

  • Jenkins 服务器是2.204.2(托管在Ubuntu 18.04上)
  • 存储库托管在BitBucket中。

首先要做的是提供 Jenkins 凭据以连接(和“获取”)到 BitBucket 中的私有存储库。这可以通过创建一个 SSH 密钥对来“链接”托管 Jenkins 服务器的机器上的 Jenkins (!!) 用户和(私有)BitBucket 存储库。

  1. 首先是为 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$

  1. 现在需要在 BitBucket 存储库中设置这个 SSH 密钥的内容,如下所示:
  • 在 BitBucket 存储库中创建(添加)一个 SSH 密钥,方法是:Settings --> Access keys --> Add key
  • 授予密钥读取权限并将 PUBLIC 密钥的内容复制到密钥的“正文”。可以通过运行显示密钥的内容:cat /var/lib/jenkins/.ssh/id_rsa.pub
  1. 在 BitBucket 存储库中设置 SSH 密钥之后,我们需要“告诉”Jenkins 在尝试获取(在本例中为读取)存储库的内容时实际使用它。请注意,通过让 Jenkins 知道,实际上意味着让用户拥有jenkins这个“特权”。

这可以通过将带有私钥的新 SSH 用户名添加到Jenkins --> Credentials --> System --> Global Credentials --> Add credentials.

  • 在 ID 部分中,将任何描述性名称放入键中。
  • 在用户名部分输入 Jenkins 服务器的用户名,即jenkins.
  • 勾选 Private key 部分并粘贴之前通过复制粘贴以下内容生成的 PRIVATE key 的内容:~/.ssh/id_rsa-----BEGIN RSA PRIVATE KEY-----这是以 string: 开头并以 string:结尾的私钥-----END RSA PRIVATE KEY-----。请注意,应将整个“块”复制粘贴到上述部分中。
  1. 安装可以在其官方页面中找到的 Git Parameter 插件

  2. 列出(动态)给定存储库的所有分支所需的最小管道如下:

    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名称。
  • 在这种情况下,我在 url 参数中使用了存储库的 SSH URL。
  • 此答案假定(并已配置)git 服务器是 BitBucket。我假设在初始步骤中完成的所有“管理”设置在 GitHub 中都有其等效设置。
于 2020-10-03T09:43:23.167 回答
0

你可以试试这个,这个列表在下拉列表中输入了 Git Repo 的动态分支名称。

需要 Jenkins 插件:

  1. 验证字符串参数
  2. 主动选择

选项 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:詹金斯用户界面

在此处输入图像描述

在此处输入图像描述



样本输出:

在此处输入图像描述

于 2020-12-05T08:00:02.620 回答