Dynamically Fill Jenkins Choice Parameter With Git Branches In a Specified Repo

后端 未结 13 910
离开以前
离开以前 2020-11-29 16:41

I have a parameterized Jenkins job which requires the input of a specific Git branch in a specific Git repo. Currently this parameter is a string parameter.

Is ther

相关标签:
13条回答
  • 2020-11-29 17:23

    Extended Choice Parameter plugin will allow you to read the choices from a file.

    Of course, now you have another problem: how to make sure the file is up-to-date (that can be done with a post-commit hook) and propagated to all the users (that can be done by placing it on a shared file server). But there may be better solutions.

    0 讨论(0)
  • 2020-11-29 17:27

    We can eliminate the unnecessary file read/write by using text. My complete solution is the following:

    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();
    
    0 讨论(0)
  • 2020-11-29 17:30

    expanding on @malenkiy_scot's answer. I created a new jenkins job to build up the file that is used by Extended Choice Plugin.

    you can do the following (I did it as execute shell steps in jenkins, but you could do it in a script):

    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
    

    I then use the Artifact deployer plugin to push that file to a shared location, which is in a web url, then just use 'http://localhost/branches.txt' in the Extended Choice plugin as the url. works like a charm.

    0 讨论(0)
  • 2020-11-29 17:31

    I have a new response for this case: the easy way to solve this is having you jenkinsFile from source code.

    Then you chose: this job have a git parameter

    And and the Pipeline setup, unchecked the "Lightweight checkout" checkbox, this will perform a really git checkout on job workspace.

    After, the parameter will be autopopulate by your git branch

    0 讨论(0)
  • 2020-11-29 17:31

    You can accomplish the same using the extended choice parameter plugin before mentioned by malenkiy_scot and a simple php script as follows(assuming you have somewhere a server to deploy php scripts that you can hit from the Jenkins machine)

    <?php
    chdir('/path/to/repo');
    exec('git branch -r', $output);
    print('branches='.str_replace('  origin/','',implode(',', $output)));
    ?>
    

    or

    <?php
    exec('git ls-remote -h http://user:pass@repo.git', $output);
    print('branches='.preg_replace('/[a-z0-9]*\trefs\/heads\//','',implode(',', $output)));
    ?>
    

    With the first option you would need to clone the repo. With the second one you don't, but in both cases you need git installed in the server hosting your php script. Whit any of this options it gets fully dynamic, you don't need to build a list file. Simply put the URL to your script in the extended choice parameter "property file" field.

    0 讨论(0)
  • 2020-11-29 17:37

    Yes, I wrote a little groovy script which does the trick You should add a 'Dynamic Choice Parameter' to your job and customize the following groovy script to your needs :

    #!/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()
    

    I my case the version string was in the following format X.X.X.X and could have user branches in the format X.X.X-username ,etc... So I had to write my own sort function. This was my first groovy script so if there are better ways of doing thing I would like to know.

    0 讨论(0)
提交回复
热议问题