I have a website that relies on a repo of libraries which should be contained in the project root. Both repos are stored in GitHub. I am trying to set up a Jenkins Multi-branch Pipeline for this project.
What I'm trying to so is checkout the same branch on the libraries repo as the main repo, and if a matching branch does not exist, revert to 'master'.
I've found the following in the Jenkins documentation (https://jenkins.io/doc/pipeline/steps/workflow-multibranch/#code-resolvescm-code-resolves-an-scm-from-an-scm-source-and-a-list-of-candidate-target-branch-names), which seems like it would be perfect:
// checkout the main source
dir('main'){
// this will checkout the source repository that is driving the multi-branch pipeline
checkout scm
}
// now checkout the tests
dir('tests'){
// this will check if there is a branch with the same name as the current branch in
// https://example.com/example.git and use that for the checkout, but if there is no
// branch with the same name it will fall back to the master branch
checkout resolveScm(source: git('https://example.com/example.git'), targets: [BRANCH_NAME,'master']
}
// rest of pipeline
However this just throws Sytnax errors (I also noticed an unclosed bracket in the example above, so tried with a closing bracket on the end, with no joy).
Here's the Jenkinsfile I've been working on:
pipeline {
agent any
stages {
stage ('Checkout') {
steps {
dir ('Libraries') {
resolveScm source: github(credentialsId: '****', id: '_', repoOwner: '***', repository: 'Libraries', traits: [[$class: 'org.jenkinsci.plugins.github_branch_source.BranchDiscoveryTrait', strategyId: 1]]), targets: ['does_not_exist', 'master']
}
}
}
}
If the above branch name is not found, I can see that develop is, however it is not checked out. Instead whatever the last found branch was remains as the workspace (i.e. a branch that was found in a previous run).
Has anyone managed to get this successfully working?
Have you tried adding 'checkout' before the resolveScm? F.e.:
dir('Libraries') {
checkout resolveScm(source: github(credentialsId: '****',
id: '_',
repoOwner: '***',
repository: 'Libraries',
traits: [[$class: 'org.jenkinsci.plugins.github_branch_source.BranchDiscoveryTrait', strategyId: 1], [$class: 'WipeWorkspaceTrait']]),
targets: ['does_not_exist', 'master'])
}
Related
I'm creating this new Job based on pipeline on jenkins. I want my jenkinsfile to be on bitbucket reposiotry : Let's say my config file is on bitbucket.org/config.git
The job mission is to clean install a project bitbucket.org/myProject.git
How can I configure the pipeline so it will trigger if any push is made in bitbucket.org/myProject.git and following the steps defined in bitbucket.org/config.git?
I do not want to create multi-branch pipeline and I do not want my jenkins file to be on the same repository than my project to compile.
My current config is:
pipeline {
agent any
parameters {
string(defaultValue: '', description: 'URL', name: 'GIT_URL')
string(defaultValue: '', description: 'Credential', name: 'CREDENTIAL_ID')
}
stages {
stage ('Initialize') {
steps {
git branch: 'develop', credentialsId: "${params.CREDENTIAL_ID}", url: "${params.GIT_URL}"
}
}
stage ('Build') {
steps {
sh 'mvn clean install '
echo 'build'
}
}
}
You can use shared Libraries in Jenkins. you would still need a Jenkinsfile in your code, but that would not contain any logic. It would simply refer the shared library and pass any params like git repo path.
For more information on shared libraries please refer this link https://jenkins.io/doc/book/pipeline/shared-libraries/.
For triggering the build, you can define a trigger in your pipeline. Example :
triggers {
pollSCM('H/5 * * * *')
}
or use webhooks if you don't want to poll.
Actually, i managed to make it work.
In my jenkins pipeline, i activated "Build when a change is pushed to BitBucket".
node {
checkout([$class: 'GitSCM',
branches: [[name: 'feature/test-b']],
doGenerateSubmoduleConfigurations: false,
extensions: [[$class: 'SubmoduleOption', disableSubmodules: false,
parentCredentials: false, recursiveSubmodules: true, reference: '',
trackingSubmodules: false]], submoduleCfg: [],
userRemoteConfigs: [[credentialsId: 'admin',
url: 'http://localhost:7990/scm/bout/boutique-a.git']]])
}
When a change is made in boutique-a in the branch 'feature/test-b' my job is triggered which is cool.
Now i have this other issue, how can i trigger when change are made in feature/*
It looks like i cannot access to env.BRANCH_NAME when im not in a multibranch pipeline
When my pipeline polls the Mercurial repo for changes it does not detect any change, and new builds are not triggered.
Following the plugin docs, I set up a push hook to trigger the polling, which works fine, but is not able to detect changes. All I get is
Mercurial Polling Log
Started on May 19, 2018 11:58:10 PM
no polling baseline in /var/lib/jenkins/workspace/test-repo on
Done. Took 0 ms
No changes
I am working with:
- Jenkins v2.107.3
- Mercurial plugin v2.3
I just created a test mercurial repo with some files with random content to test the setup, and a jenkins pipeline 'polling-test' which checks out the repo and echoes "hello world".
pipeline {
agent any
stages {
stage('Checkout') {
steps {
checkout changelog: true,
poll: true,
scm: [
$class: 'MercurialSCM',
credentialsId: 'jenkins',
revision: 'default',
revisionType: 'BRANCH',
source: 'ssh://hg-user#hg-server/test-repo'
]
}
}
stage('Tests') {
steps {
echo "Hello World"
}
}
}
}
Also the Poll SCM option is checked out, and without any schedule.
I modify the repo doing something like:
$ echo "foo" > bar
$ hg add bar
$ hg commit -m "change"
$ hg push
And then the polling is triggered with
$ curl "https://jenkins-server/mercurial/notifyCommit?url=ssh://hg-user#hg-server/test-repo"
Scheduled polling of polling-test
The polling log shows it has triggered, but found no changes.
What am I doing wrong? How can changes be detected?
I was able to make the polling work properly by adding a Mercurial installation in the "global tools", changing the pipeline script to
pipeline {
agent any
stages {
stage('Checkout') {
steps {
checkout([$class: 'MercurialSCM', credentialsId: 'jenkins', installation: 'Mercurial', source: 'ssh://hg-user#hg-server/test-repo'])
}
}
stage('Tests') {
steps {
echo "Hello World"
}
}
}
}
while keeping the Polling option checked, and of course running the pipeline a first time manually to get a reference changeset.
I have 40-50 github repositories , each repo contain one maven job.
I want to create multibranch pipeline job for each repository.
can I use the same Jenkinsfile for all projects without add Jenkinsfile for each repository. (take it from another SCM repo) ?
I know that I can use shared library to create a full pipeline , but I prefer something cleaner.
To accomplish this, I would suggest to create a pipeline with two parameters and pass the values based on the repo to build. 1) GIT BRANCH - to build and deploy required branch
2) GIT URL - to provide the git URL to checkout the code.
Providing a reference template.
node('NODE NAME')
{
withEnv([REQUIRED ENV VARIBALES])
{ withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'CREDENTIALS ID', passwordVariable: 'PW', usernameVariable: 'USER']])
{ try
{ stage 'Build'
checkout changelog: false, poll: false, scm: [$class: 'GitSCM', branches: [[name: gitbranch]], doGenerateSubmoduleConfigurations: false,
extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'CREDENTIALS ID',
url: 'GIT URL']]]
****
MAVEN BUILD
****
stage 'Docker Image build & Push'
*****
DOCKER BUILD AND PUSH TO REPO
*****
}
catch (err) {
notify("Failed ${err}")
currentBuild.result = 'FAILURE'
}
stage 'Deploy to ENV'
*****
DEPLOYMENT TO REQUIRED ENV
*****
notify('Success -Deployed to Environment')
catch (err) {
notify("Failed ${err}")
currentBuild.result = 'FAILURE'
}
}
}
}
def notify(status)
{
****
NOTIFICATION FUCNTION
****
}
Link the Jenkinsfile in the pipeline job and provide the values- build with parameters, while building the Jenkins job.
Hope this helps.
In gradle I'd like to add both the current branch-name and commit-number as suffix to my versionName. (Why? Because when I build my app in Jenkins to release it in HockeyApp, it's useful to show what branch & commit that app was built from!)
So when I enter this in command prompt, my current branch name is returned:
git rev-parse --abbrev-ref HEAD
Same happens when I use this line in Android gradle, using the code in either this answer, or as shown in this piece of gradle code:
def getVersionNameSuffix = { ->
def branch = new ByteArrayOutputStream()
exec {
// The command line to request the current branch:
commandLine 'git', 'rev-parse', '--abbrev-ref', 'HEAD'
standardOutput = branch
}
println "My current branch: " + branch
def versionNameSuffix = "-" + branch
// ... some other suffix additions ...
return versionNameSuffix
}
buildTypes {
debug {
applicationIdSuffix ".test"
versionNameSuffix getVersionNameSuffix()
}
}
Resulting log (this is exactly what I want):
"My current branch: feature/MyFeature"
However, when I build my app in a Jenkins job, it will output a different result:
"My current branch: HEAD"
Why does this happen, and how to correctly retrieve my current branch name in Jenkins?
EDIT:
I've used a different approach, which returns the branchName correctly in most cases, also on Jenkins:
git name-rev --name-only HEAD
Example output in prompt:
"My current branch: feature/MyFeature"
Example output in Jenkins:
"My current branch: remotes/origin/feature/MyFeature"
I can remove "remotes/origin/" if i like, so that's okay!
But this approach causes different trouble (both in prompt, gradle and on Jenkins). When I have tagged the last commit, it won't output the branch-name, but this:
"My current branch: tags/MyTag^0"
EDIT 2:
A third approach can be found here.
Including the comments below the answer, I could use grep * to retrieve the branch in prompt. However, I cannot use the backslash in the gradle code. This fails:
commandLine 'git', 'branch', '|', 'grep', '\\*'
Any advice?
Try the env: BRANCH_NAME
BRANCH_NAME
For a multibranch project, this will be set to the name of the branch being built, for example in case you wish to deploy to production from master but not from feature branches.
Access it with env.BRANCH_NAME
I'm exploring Jenkins 2.0 pipelines. So far my file is pretty simple.
node {
stage "checkout"
git([url:"https://github.com/luxengine/math.git"])
stage "build"
echo "Building from pipeline"
}
I can't seem to find any way to set the directory that git will checkout to. I also can't find any kind of documentation related to that. I found https://jenkinsci.github.io/job-dsl-plugin/ but it doesn't seem to match what I see on other tutorials.
Clarification
Looks like you are trying to configure Pipeline job (formerly known as Workflow). This type of job is very distinct from Job DSL.
The purpose of Pipeline job is to:
Orchestrates long-running activities that can span multiple build slaves. Suitable for building pipelines (formerly known as workflows) and/or organizing complex activities that do not easily fit in free-style job type.
Where as Job DSL:
...allows the programmatic creation of projects using a DSL. Pushing job creation into a script allows you to automate and standardize your Jenkins installation, unlike anything possible before.
Solution
If you want to checkout your code to specific directory then replace git step with more general SCM checkout step.
Final Pipeline configuration should look like that:
node {
stage "checkout"
//git([url:"https://github.com/luxengine/math.git"])
checkout([$class: 'GitSCM',
branches: [[name: '*/master']],
doGenerateSubmoduleConfigurations: false,
extensions: [[$class: 'RelativeTargetDirectory',
relativeTargetDir: 'checkout-directory']],
submoduleCfg: [],
userRemoteConfigs: [[url: 'https://github.com/luxengine/math.git']]])
stage "build"
echo "Building from pipeline"
}
As a future reference for Jenkins 2.0 and Pipeline DSL please use built-in Snippet Generator or documentation.
This can be done by using the directive of dir:
def exists = fileExists '<your target dir>'
if (!exists){
new File('<your target dir>').mkdir()
}
dir ('<your target dir>') {
git url: '<your git repo address>'
}
First make clear that you are using Jenkins Job DSL.
You can do this like this:
scm {
git {
wipeOutWorkspace(true)
shallowClone(true);
remote {
url("xxxx....")
relativeTargetDir('checkout-folder')
}
}
}
https://jenkinsci.github.io/job-dsl-plugin/
This above address gives you the chance simply to type in upper left aread for example 'scm' and than it will show in which relationships 'scm' can be used. Than you can select 'scm-freestylejob' and afterwards click on the '***' than you can see the details.
The general start point for Jenkins Job DSL is here:
https://github.com/jenkinsci/job-dsl-plugin/wiki
You can of course ask here on SO or on Google Forum:
https://groups.google.com/forum/#!forum/job-dsl-plugin
pipeline {
agent any
stages{
stage("Checkout") {
steps {
dir('def exists = fileNotExists \'git\'') {
bat label: '', script: 'sh "mkdir.sh'
}
dir ('cm') {
git branch: 'dev',
credentialsId: '<your credential id>',
url: '<yours git url>'
}
}
} //End of Checkout stage
stage("TestShellScript") {
steps {
bat label: '', script: 'sh "PrintNumber.sh"'
}
}
}//End of stages
} // End of pipeline
Note: cat mkdir.sh
#!/bin/bash
#Create a directory
mkdir git
You are using the Pipeline Plugin, not the Job DSL Plugin. In the Pipeline Plugin, if you want to define something, where there is not yet a function available in the Pipeline syntax, you can define it yourself.