What is the branch name variable for Jenkins multibranch pipelines? - jenkins

I need to know which branch is being built in my Jenkins multibranch pipeline in order for it to run steps correctly.
We are using a gitflow pattern with dev, release, and master branches that all are used to create artifacts. The dev branch auto deploys, the other two do not. Also there are feature, bugfix and hotfix branches. These branches should be built, but not produce an artifact. They should just be used to inform the developer if there is a problem with their code.
In a standard build, I have access to the $GIT_BRANCH variable to know which branch is being built, but that variable isn't set in my multibranch pipeline. I have tried env.GIT_BRANCH too, and I tried to pass $GIT_BRANCH as a parameter to the build. Nothing seems to work. I assumed that since the build knows about the branch being built (I can see the branch name at the top of the console output) that there is something that I can use - I just can't find any reference to it.

The env.BRANCH_NAME variable contains the branch name.
As of Pipeline Groovy Plugin 2.18, you can also just use BRANCH_NAME
(env isn't required but still accepted.)

There is not a dedicated variable for this purpose yet (JENKINS-30252). In the meantime you can take advantage of the fact that the subproject name is taken from the branch name, and use
env.JOB_NAME.replaceFirst('.+/', '')
This has now been resolved, see Krzysztof KrasoĊ„'s answer.

There are 2 branches to consider in a Jenkins multibranch pipeline job:
The Jenkins job branch - env.BRANCH_NAME. This may have the same name as a git branch, but might also be called PR-123 or similar
The git branch - env.GIT_BRANCH. This is the actual branch name in git.
So a job might have BRANCH_NAME=PR-123 and GIT_BRANCH=my-scm-branch-name

Jenkins documentation has a list of all the env variable for your perusal here

Another way is using the git command to obtain the branch name on the current jenkins pipeline. For example, you can add the following snippet to print the branch name in your Jenkinsfile.
...
script {
def BRANCH = sh(returnStdout: true, script: 'git rev-parse --abbrev-ref HEAD').trim()
echo ${BRANCH}
}
...

I found this stackoverflow post example useful: Git Variables in Jenkins Workflow plugin
sh '//...
git rev-parse --abbrev-ref HEAD > GIT_BRANCH'
git_branch = readFile('GIT_BRANCH').trim()
echo git_branch
//...
'

Related

GIT_COMMIT envvar incorrect for pipelines that merge master first

Context
This question relates to multibranch pipelines where the behaviour merges the PR with the target branch revision (see screenshot of settings)
In this case, the merge may cause a new merge commit. So for a trigger with a given commit from a repository:
We actually get a different value of the GIT_COMMIT envvar:
If a tool (such as a build reporting tool) needs to use the GIT_COMMIT envvar to pass information onto a service, it cannot then be linked back to the actual commit from the project (this is a screenshot from Bitbucket but this would be the same for any repo hosting service):
Question
How, in a pipeline step, can I find the commit 709502c is the actual genesis of this build, when the GIT_COMMIT is set to 6781a3d1 (which is not an actual commit in the project)?
Maybe looking at git history can help?
REAL_GIT_COMMIT = sh (
script: "git rev-parse HEAD",
returnStdout: true,
).trim()

Build Pipeline using a Branch Parameter

I seem unable to create a Jenkins Pipeline job that builds a specific branch, where that branch is a build parameter.
Here's some configuration screenshots:
(i've tried with a Git Parameter and a String Parameter, same outcome)
(I've tried $BRANCH_NAME_PARAM, ${BRANCH_NAME_PARAM} and ${env.BRANCH_NAME_PARAM}, same outcome for all variations)
And the build log:
hudson.plugins.git.GitException: Command "git fetch --tags --progress origin +refs/heads/${BRANCH_NAME_PARAM}:refs/remotes/origin/${BRANCH_NAME_PARAM} --prune" returned status code 128:
stdout:
stderr: fatal: Couldn't find remote ref refs/heads/${BRANCH_NAME_PARAM}
at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:1970)
I'm obviously doing something wrong - any ideas on what?
https://issues.jenkins-ci.org/plugins/servlet/mobile#issue/JENKINS-28447
Appears that its something to do with a lightweight checkout. if i deselect this option in my config, my parameter variables are resolved
a bit more detailed with examples combined with VonC answer
1. Configure extended choice parameter named BRANCH:
specify delimiter
specify groovy script or path to groovy file:
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\//, '')
}
return branches.join(",")
2. Set Branches to build: $BRANCH
3. Disable "Lightweight checkout" checkbox in the "Pipeline" secton of Jenkins job configuration:
Otherwise job will fail with following message:"stderr: fatal: Couldn't find remote ref refs/heads/${BRANCH"}"
4. Build with parameter executes groovy script and you will then get a dropdown list of branches
I have tried the above solution but it didn't work for me. I have chosen a slightly different approach. I am posting because it will help someone in future.
Goto configures the pipeline job.
Check the option "This project is parameterized"
Add git paramter.
Note: If it doesn't show the option, please goto manage plugins and install git parameter plugin.
My pipeline Configure looks like
Uncheck lightweight checkout and update the "branch to build" in pipeline section.
Save the configuration.
Each time I had a job based on a branch, I had to put a groovy script with EnvInject plugin in order to remove the ref/heads part of the git branch selected in parameters.
If you keep refs/heads/xxx, Jenkins will look for the branch ref/heads/ref/heads/xxx.

jenkins multibranch jenkinsfile SVN checkout

I have a Jenkinsfile located in [my svn branch]\build folder, and it checks out code to the slave node and builds.
My multi branch project finds the branch correctly, but it checks out the entire svn branch on the master just to read the jenkinsfile instead of checking out just the jenkinsfile itself of just [my svn branch]\build folder.
This is a major problem because of storage and performance, are there any solutions for that?
In your multibranch pipeline config in 'include' field type: branches/*/build (i assume that you have all svn branches in folder 'branches', and url to your build folder is something like: svn_url/branches/my_new_branch/build)
Then it will scan only build folder in each branch.
Warning - after changing that config property your multibranch pipeline will only diacover 'build', if you want to index other build folders, you can list them in that property, i.e.:
Include: trunk/build, trunk/other_build, branches/*/build, branches/*/other_build
But more clean approach is to get only one build per multibranch pipeline

Get git branch name with gradle git plugin on jenkins slave

I'm doing sonar integration and would like to pass git branch as a parameter. It will be run on Jenkins server.
Before I was using next line of code to get current git branch:
def workingBranch = """git rev-parse --abbrev-ref HEAD""".execute().text.trim()
After I replaced it with:
grgit.branch.current.fullName
But this always gives me "HEAD". How to achieve same functionality?
I am doing something very similar. As it turns out, the Git plugin in Jenkins is tuned in several ways to minimize the git clone and checkout. There are 2 ways that I've found to deal with this.
The Easy Way
Use Jenkins' built-in environment variables, as you already suggested in the comments.
def workingBranch = System.getenv("GIT_BRANCH") ?: grgit.branch.current.fullName
The Job Configuration Way
You can also set up the job to checkout the branch as a local branch, rather than a detached HEAD. This is under "Additional Behaviors", named "Check out to specific local branch". There are many other questions that detail the settings for that, and/or the Declarative Pipeline approach, depending on what your needs.
Declarative Pipeline custom checkout
Configuring local branch option

Jenkins multibranch pipeline with Jenkinsfile from different repository

I have a Git repository with code I'd like to build but I'm not "allowed" to add a Jenkinsfile in its root (it is a Debian package so I can't add files to upstream source). Is there a way to store the Jenkinsfile in one repository and have it build code from another repository? Since my code repository has several branches to build (one for each Debian release) this should be a multibranch pipeline. Commits in either the code or Jenkinsfile repositories should trigger a build.
Bonus complexity: I have several code/packaging repositories like this and I'd like to reuse the same Jenkinsfile for all of them. Thus it should somehow dynamically fetch the right Git URL to use. The branches to build have the same names across all repositories.
Short answer is : you cannot do that with a multibranch pipeline. Multibranch pipelines are only designed (at least for now) to execute a specific pipeline in Pipeline script from SCM style, with a fixed Jenkinsfile at the root of the project.
You can however use the Multi-Branch Project plugin made for multibranch freestyle projects. First, you need to define your multibranch freestyle configuration just like you would with a multibranch pipeline configuration.
Select this new item like shown below :
This type of configuration will behave exactly same as the multibranch pipeline type, i.e. it will create you a folder with the name of your configuration and a sub-project for each branch it automatically detected.
The implementation should then be a piece of cake :
Specify your SCM repository in the multibranch configuration
Call another build as part of your build/post-build as you would do in a standard freestyle project, except that you have to call a parameterized job (let's call it build-job) and give it your repository information, i.e. Git URL and current branch (you can use the pre-defined variables $GIT_URL and $GIT_BRANCH for this purpose)
In your build-job, just define either an inline pipeline or a pipeline script checked out from SCM, and inside this script do a SCM checkout and go on with the steps you need to build. Example of build-job pipeline content :
.
node() {
stage 'Checkout'
checkout scm: [$class: 'GitSCM', branches: [[name: '*/${GIT_BRANCH}']], userRemoteConfigs: [[url: '${GIT_URL}']]]
stage 'Build'
// Build steps...
}
Of course if your different multibranches projects need to be treated a bit differently, you could also use intermediate projects (let's say build-project-A, build-project-B, ...) that would in turn call the generic build-job pipeline)
The one, major drawback of this solution is that you will only have one job responsible for all of your builds, making it harder to debug. You would still have your multibranch projects going blue/red in case of success/error but you will have to go back to called build-job to find the real problem of your build.
The best way I have found is to use the Remote Jenkinsfile Provider plugin. https://plugins.jenkins.io/remote-file/
This will add an option "by Remote Jenkinsfile Provider plugin" under Build Configuration>Mode then you can point to another repo where the Jenkinsfile is. I find this to be a much better solution than the Pipeline Multibranch Defaults Plugin, which makes you store the Jenkins file in Jenkins itself, rather than in source control.
U can make use of this plugin
https://github.com/jenkinsci/pipeline-multibranch-defaults-plugin/blob/master/README.md
Where we need to configure the jenkinsfile on jenkins rather than having it on each branch of your repo
I have version 2.121 and you can do this two ways:
Way 1
In the multibranch pipeline configuration > Build Configuration > Mode > Select "Custom Script" and put in "Marker File" below the name of a file you will use to identify branches that you want to have builds for.
Then, below that in Pipeline > Definition select "Pipeline Script from SCM" and enter the "SCM" information for how to find the "Jenkinsfile" that holds the script you want to run. It can be in the same repo you are finding branches in to create the jobs (if you put in the same GitHub repo's info) but I can't find a way to indicate that you just use the same branch for the file.
Way 2
Same as above, in the multibranch pipeline configuration > Build Configuration > Mode > Select "Custom Script" and put in "Marker File" below the name of a file you will use to identify branches that you want to have builds for.
Then, below that in Pipeline > Definition select "Pipeline Script" and put a bit of Groovy in the text box to load whatever you want or to run some script that already got loaded into the workspace.
In my case, i have an escenario whith a gitlab project based on gradle who has dependencies on another gitlab preject based on gradle too (same dashboard, but differents commits, differents developers).
I have added the following lines into my Jenkinsfile (the one which depends)
stage('Build') {
steps {
git branch: 'dev', credentialsId: 'jenkins-generated-ssh-key', url: 'git#gitlab.project.com:root/coreProject.git'
sh './gradlew clean'
}
}
Note: Be awark on the order on the sentences.
If you have doubt on how to create jenkins-generated-ssh-key please ask me

Resources