简体   繁体   中英

Git branch select in Jenkins with groovy script

I am trying to make a Parameterized build in Jenkins. In this way user can choose the git branch he/she wants to deploy from a cascade menu.

There are two possible ways:

  1. Writing branch names in file and configuring Jenkins to read this file ( project configuration > extend choice parameter and selecting Property file ).

    Problem : You have to make a local repository as a mirror of remote repo and keep this local repo in sync with remote repo. In the other words, you have to update the file containing the available branch name updated . This needs a scheduled job by cron and I am not allowed using this approach.

  2. Using Groovy script ( project configuration > extend choice parameter and selecting "Groovy script" ). Then you need a groovy script to retrieve the branch name as follows: branches=master,feature/Feature-1,feature/Feature-2,hotfix/Hotfix-1,release/Release-1 .

I found a groovy script in here but it doesn't work. I have installed groovy on my machine.

Can anybody help me? To make the story short: I need a groovy script which returns the available branch names of a remote repository.

The script below should be helpful. It's based on the scripts from linked question . It filters git command output with simple regular expression and creates list of branch names for specified git repository. Tested on grails-core github repo :

def gitURL = "https://github.com/grails/grails-core.git"
def command = "git ls-remote -h $gitURL"

def proc = command.execute()
proc.waitFor()              

if ( proc.exitValue() != 0 ) {
   println "Error, ${proc.err.text}"
   System.exit(-1)
}

def branches = proc.in.text.readLines().collect { 
    it.replaceAll(/[a-z0-9]*\trefs\/heads\//, '') 
}

println branches

Try Using

Use the following steps:

  1. Add an extensible choice parameter to your job

    在此处输入图片说明

  2. select System Groovy Choice parameter in Choice parameter field

    在此处输入图片说明

  3. Place the following script in Groovy script text box and replace the place holders "< >" with required values.

     import groovy.json.JsonSlurper; try{ List<String>params = new ArrayList<String>() URL apiUrl = "https://api.github.com/users/<repo-owner>/repos?access_token=<github-access-token>".toURL() List branches = new JsonSlurper().parse(apiUrl.newReader()) for (branch in branches ) { params.add(branch.name) } return params } catch(IOException ex){ print ex }
  4. Add an active choice reactive parameter to your job

    在此处输入图片说明

  5. Place Reference Parameter as repository and following script in Groovy Script text box

    import groovy.json.JsonSlurper; try{ List<String>params = new ArrayList<String>() URL apiUrl = "https://api.github.com/repos/<repo-owner>/$repository/branches?access_token=<github-access-token>".toURL() List json = new JsonSlurper().parse(apiUrl.newReader()) for (repo in json ) { params.add(repo.name) } return params } catch(IOException ex){ print ex }

    在此处输入图片说明

    Note:

    • $repository takes dynamic value from repository parameter.
    • ignore for public repository.
  6. Now try build job with parameter

    在此处输入图片说明 在此处输入图片说明

checkout github api docs for more informations. Hope this yould be helpful..!! ;-)

You don't need a Groovy Script for this. The Git Parameter Plugin lets you add git branches as a parameter.

You can use Extensible Choice Parameter plugin to retrieve Git branches of your cloned repository. To do so, add to Master-Node property an environment variable of .git directory path, eg:

在此处输入图片说明

Then add an Extensible Choice parameter with the following groovy script (and check "Use predefined variables"):

def envVars = jenkins.getNodeProperties()[0].getEnvVars() 
def NODE_PROJECT_PATH = envVars.get('NODE_PROJECT_PATH') 
def gettags = "git ls-remote -t --heads origin".execute(null, new File(NODE_PROJECT_PATH))

return gettags.text.readLines()
         .collect { it.split()[1].replaceAll('\\^\\{\\}', '').replaceAll('refs/\\w+/', '')  }
         .unique()
         .findAll { !it.startsWith('Branch_') }

That should list your branches (I filtered out all "Branch_*" from the list):

在此处输入图片说明

Notes: In case you see nothing when validating the script (with "Run the script now" button), it's probably due to required user/password prompt - so initially run "git ls-remote -t --heads origin" in .git directory. To save credential on Windows, try to run "git config --global credential.helper wincred".

This was the only technique I came up with that doesn't require you to dig git repo information out of the workspace. This uses Groovy code to inspect the job parameters for the Git URI, and then shells out to git to do the rest of the work.

It should be possible to use JGit to access the repository in native Groovy way, but I can't figure it out.

import jenkins.*
import jenkins.model.*
import hudson.*
import hudson.model.*
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;

def build = Thread.currentThread().toString()
def regexp= ".+?/job/([^/]+)/.*"
def match = build  =~ regexp
def jobName = match[0][1]
def job = Jenkins.instance.getJob(jobName)
def workspace = job.lastBuild.workspace

for(project in Hudson.instance.items) {
  scm = job.scm;
  if (scm instanceof hudson.plugins.git.GitSCM) {
    for (RemoteConfig cfg : scm.getRepositories()) {
      for (URIish uri : cfg.getURIs()) {
        gitUri = uri
      }
    }
  }
}

def branchlist = ["/bin/bash", "-c", "git ls-remote --heads ${gitUri}"].execute() | ["/bin/bash", "-c", "cut -f2"].execute()
branchlist.waitFor()

return branchlist.in.text.readLines()

Set that as the Groovy Script for your Source for Value on an Extended Choice Parameter like this:

扩展选择参数

And then you'll be able to select from a list of branches as build parameters:

分公司名单

I was following this https://stackoverflow.com/a/47880463/11951486 , and it is working perfectly fine. But the issue is, now github will disable using access_token in the url, more detail can be found here

So i changed the groovy script to use curl with username and token or password

Please find the code below for repos.

import groovy.json.JsonSlurper;

try{
def user = "<username>"
def tokenId = "<tokenid>"
def url = "https://api.github.com/user/repos?per_page=200"
def command = "curl -u $user:$tokenId $url"
   List<String>params = new ArrayList<String>()
   apiUrl = command.execute().text
   List json = new JsonSlurper().parseText(apiUrl)
   for (repo in json ) { 
    params.add(repo.name)
  }
return params
}
catch(IOException ex){
   print ex
}

Please find below code for the branches

import groovy.json.JsonSlurper;


try{
def user = "<username>"
def tokenId = "<tokenID>"
def url = "https://api.github.com/repos/<org_name>/${REPO}/branches?per_page=400"
def command = "curl -u $user:$tokenId $url"
   List<String>params = new ArrayList<String>()
   apiUrl = command.execute().text
   List json = new JsonSlurper().parseText(apiUrl)
   for (branch in json ) { 
    params.add(branch.name) 
  }
params.add(0, 'master:selected')// this is for default select master branch
return params
}
catch(IOException ex){
   print ex
}

${REPO} = This is the parameter name for listing the repos, so based on the repo you selected , the above code will list the branches.

This approach describe the settings required to compose a Jenkins pipeline that "polls" (list) dynamically all branches of a particular repository, which then lets the user run the pipeline with some specific branch when running a build of this job.

The assumptions here are:

  • The Jenkins server is 2.204.2 (hosted on Ubuntu 18.04 )
  • The repository is hosted in a BitBucket .

First thing to do is to provide Jenkins credentials to connect (and "fetch") to the private repository in BitBucket. This can be done by creating an SSH key pair to "link" between the Jenkins (!!) user on the machine that hosts the Jenkins server and the (private) BitBucket repository.

  1. First thing is to create an SSH key to the Jenkins user (which is the user that runs the Jenkins server - it is most likely created by default upon the installation):

     guya@ubuntu_jenkins:~$ sudo su jenkins [sudo] password for guya: jenkins@ubuntu_jenkins:/home/guya$ ssh-keygen

    The output should look similar to the following:

Generating public/private rsa key pair. Enter file in which to save the key
(/var/lib/jenkins/.ssh/id_rsa): Created directory '/var/lib/jenkins/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /var/lib/jenkins/.ssh/id_rsa. Your public key has been saved in /var/lib/jenkins/.ssh/id_rsa.pub. The key fingerprint is: SHA256:q6PfEthg+74QFwO+esLbOtKbwLG1dhtMLfxIVSN8fQY jenkins@ubuntu_jenkins The key's randomart image is: +---[RSA 2048]----+ | . .. oE | | . . .o... o | | . o.. o | | +.oo | | . ooX..S | |..+.Bo* . | |.++oo* o. | |..+*..*o | | .=+o==+. | +----[SHA256]-----+ jenkins@ubuntu_jenkins:/home/guya$

  1. Now the content of this SSH key needs to be set in the BitBucket repository as follows:
  • Create (add) an SSH key in the BitBucket repository by going to: Settings --> Access keys --> Add key .
  • Give the key Read permissions and copy the content of the PUBLIC key to the "body" of the key. The content of the key can be displayed by running: cat /var/lib/jenkins/.ssh/id_rsa.pub
  1. After that the SSH key was set in the BitBucket repository, we need to "tell" Jenkins to actually USE it when it tries to fetch (read in this case) the content of the repository. NOTE that by letting Jenkins know, actually means let user jenkins this "privilege".

This can be done by adding a new SSH User name with private key to the Jenkins --> Credentials --> System --> Global Credentials --> Add credentials .

  • In the ID section put any descriptive name to the key.
  • In the Username section put the user name of the Jenkins server which is jenkins .
  • Tick the Private key section and paste the content of the PRIVATE key that was generated earlier by copy-paste the content of: ~/.ssh/id_rsa . This is the private key which start with the string: -----BEGIN RSA PRIVATE KEY----- and ends with the string: -----END RSA PRIVATE KEY----- . Note that this entire "block" should be copied-paste into the above section.
  1. Install the Git Parameter plugin that can be found in its official page here

  2. The very minimum pipeline that is required to list (dynamically) all the branches of a given repository is as follows:

     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" } } } }

NOTES:

  • The defaultValue is set to master so that if no branches exist - it will be displayed in the "drop list" of the pipeline.
  • The credentialsId has the name of the credentials configured earlier.
  • In this case I used the SSH URL of the repository in the url parameter.
  • This answer assumes (and configured) that the git server is BitBucket. I assume that all the "administrative" settings done in the initial steps, have their equivalent settings in GitHub.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM