在指定的Repo中用Git分支动态填充Jenkins Choice参数

在指定的Repo中用Git分支动态填充Jenkins Choice参数,git,parameters,branch,jenkins,choice,Git,Parameters,Branch,Jenkins,Choice,我有一个参数化的Jenkins作业,它需要在特定的Git repo中输入特定的Git分支。当前,此参数是一个字符串参数 有没有办法使这个参数成为一个选择参数,并用Git分支动态填充下拉列表?我不想要求任何人在每次创建新分支时手动配置下拉列表来维护此选项参数。将允许您从文件中读取选项 当然,现在您还有另一个问题:如何确保文件是最新的(这可以通过post-commit钩子实现)并传播给所有用户(这可以通过将其放置在共享文件服务器上实现)。但是可能有更好的解决办法。继续@malenkiy_scot的答

我有一个参数化的Jenkins作业,它需要在特定的Git repo中输入特定的Git分支。当前,此参数是一个字符串参数

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

将允许您从文件中读取选项


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

继续@malenkiy_scot的答案。 我创建了一个新的jenkins作业来构建ExtendedChoice插件使用的文件

您可以执行以下操作(我在jenkins中执行shell步骤,但您可以在脚本中执行):

git-ls-remotegit@github.com:my/repo.git | grep refs/heads/*>tmp.txt
sed-e's/*refs\/heads\//'tmp.txt>tmp2.txt
tr'\n'','tmp3.txt
sed'1i\branchs='tmp3.txt>tmp4.txt
tr-d'\n'branchs.txt

然后,我使用ArtifactDeployer插件将该文件推送到一个共享位置,即web url中,然后使用'http://localhost/branches.txt'在扩展选择插件中作为url。工作起来很有魅力。

您可以使用malenkiy_scot前面提到的extended choice parameter插件和一个简单的php脚本来完成同样的任务,如下所示(假设您有一个服务器来部署可以从Jenkins机器上点击的php脚本)



对于第一个选项,您需要克隆回购协议。对于第二个,您不需要,但在这两种情况下,您都需要在托管php脚本的服务器中安装git。 使用这些选项中的任何一个,它都是完全动态的,您不需要构建列表文件。只需将脚本的URL放在扩展选项参数“属性文件”字段中即可。

是, 我写了一个小的groovy脚本来实现这个功能 您应该向作业中添加“Dynamic Choice参数”,并根据需要自定义以下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()
#/usr/bin/groovy
def gitURL=“git回购url”
def command=“git ls remote--heads--tags${gitURL}”
def proc=command.execute()
waitFor()程序
if(proc.exitValue()!=0){
println“错误,${proc.err.text}”
系统退出(-1)
}
def text=proc.in.text
#将你的版本字符串匹配
def匹配=//
def标记=[]
text.eachMatch(match){tags.push(it[1])}
tags.unique()
tags.sort({a,b->
def a1=a.tokenize('.-'))
def b1=b.tokenize('.-'))
试一试{

对于(1中的i..我能够使用实现此结果。我使用了Dynamic Choice参数选项,对于choices脚本,我使用了以下选项:

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

我尝试了这个链接中提到的几个答案,但不知道如何告诉Jenkins关于用户选择的分支。正如我在上面的帖子中提到的,我把分支选择器字段留空了

但是,在进一步的调查中,我找到了另一种方法来做同样的事情- 我发现这个方法简单得多,而且要配置的东西更少

这是我配置的-

  • 安装了git参数插件
  • 选中“此生成已参数化”并添加了“Git参数”
  • 添加了以下值:

  • 然后,在作业的git SCM部分,我添加了与“Name”部分中提到的相同的值,就好像它是一个环境变量一样。(如果您仔细阅读此git参数插件的帮助,您会意识到这一点)


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

    如果您的作业没有直接使用“源代码管理”(同样是“Git参数插件”),下面的groovy脚本将非常有用。),但仍然可以访问本地(克隆的)git存储库:

    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()
    
    请参见此处的完整说明:

    使用

    添加“SELECT_BRANCH”这样的名称##请确保此变量在以后使用。 然后参数类型:Branch

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

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

    echo${SELECT_BRANCH}

    在此处输入图像描述


    我们可以通过使用
    文本来消除不必要的文件读/写。我的完整解决方案如下:

    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()
    
    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项目开始我的管道
  • 我使用awk命令生成一个包含所有分支列表的barnch.txt文件
  • 在stagesetps中,我读取文件并使用它生成一个输入选项params
  • 当用户启动管道时,该管道将等待他在列表选项中进行选择

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

    然后用户将与IM生成交互:


    我在这里面临着类似的问题。 我们的用户正在将他们的工作从freestyle迁移到pipeline。他们不希望Jenkinsfile存储在他们的repos中(历史原因),仍然希望使用“Git Parameter”插件

    因此,我们必须使用“管道脚本”并开发一个不同的插件,其工作原理类似于“Git参数”

    此新插件未与项目中的SCM设置集成。该插件位于


    希望它也能对您有所帮助

    对于这个案例,我有一个新的回应:解决这个问题的简单方法是让您从源代码获取一个文件

    然后选择:此作业有一个git参数

    管道设置,取消选中“轻量级签出”复选框,这将执行一个真正的git
    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()
            }
        }
    }
    
    guya@ubuntu_jenkins:~$ sudo su jenkins 
    [sudo] password for guya:
    jenkins@ubuntu_jenkins:/home/guya$ ssh-keygen
    
    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" 
               } 
          } 
       } 
    }
    
        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();
        }