Jenkins will not continue pipeline after updating via Mercurial plugin - jenkins

I'm trying to setup a CI process using Jenkins with the source code being held in Mercurial, so I have the Jenkins Mercurial Plugin installed.
It's a simple pipeline script just now which polls my repository every 10 minutes. Using the checkout command below and hitting Build Now on my job it successfully clones my repository and continues with the pipeline as expected. It also successfully sets up polling and I can see from the polling log that it is checking the repository for changes every 10 minutes.
checkout changelog: true, poll: true, scm: [$class: 'MercurialSCM', credentialsId: 'xxx', installation: 'TortoiseHg', source: 'C:\\Path\\to\\repo']
However, when I push to my repository, Jenkins on next running the job spots these changes, pulls them down but then reports back 'No changes' and so the job stops. I expected that at this point the job would continue because there are changes. Of course if there were no changes I would expect it to stop the job at this point.
The Mercurial Polling Log shows the changes have been pulled but hg update has not been run. This is confirmed by looking at the Jenkins-created-repo in the Tortoise Workbench. However, even putting a hook in Mercurial configuration in Jenkins such that it does update after pulling does not fix the issue. Jenkins still reports 'No changes' after the checkout step.
So after the initial build, which works fine, Jenkins never runs the job all the way through again. It always bails out after the checkout step because despite pulling down any changes it reports there are none.
I have checked the permissions and everything seems fine, the fact that it completely runs on demand and can subsequently pull also suggests there is nothing wrong with the pipeline or elsewhere.
Any suggestions as to how to get the job to continue after the checkout stage would be much appreciated.
Below is an example pipeline script:
pipeline {
agent any
triggers {
pollSCM '*/10 * * * *'
}
stages {
stage('Checkout') {
steps {
checkout changelog: true, poll: true, scm: [$class: 'MercurialSCM', credentialsId: 'xxx', installation: 'TortoiseHg', source: 'C:\\Path\\to\\repo']
}
}
stage('Build') {
steps {
echo Continuing with build...
}
}
}
UPDATE I have noticed that if I manually build after the poll has pulled down but not updated the local repository the job then updates the repository and the build continues as normal.

It looks like you have omitted to specify a branch in your scm checkout. Are you using the default branch in HG?
This Jenlins issue and the source code show that if you are not using the deault branch, you'll likely not see your changes pulled down even if the references are there.
If you are trying to build a non default branch give this a try
checkout changelog: true, poll: true, scm: [$class: 'MercurialSCM', branches: [[name: '*/yourbranch']], credentialsId: 'xxx', installation: 'TortoiseHg', source: 'C:\\Path\\to\\repo']

Related

Make Jenkins with declarative pipeline work with SVN trunk as well as branches

I want to set up a Jenkins job with a declarative pipeline from a Jenkinsfile, using Subversion as the SCM, which should
do a scheduled SCM poll to detect changes in the trunk
be manually startable to build the trunk or any branch of choice
So I've set up the Jenkins job with the List Subversion tags (and more) parameter that collects existing SVN branches from an SVN url and lets the user select one. The selected value is stored in a variable, for instance $svnBranch, and I defined 'trunk' as its default value.
Then this variable is used to build the resulting SCM url, for example
svn+ssh://svn.mydomain.org/Reponame/projectname/$svnBranch/componentname
Now here's the problem:
This setup does work as long as the job ist started manually. But if it is started by the cron schedule, Jenkins keeps detecting SCM changes each and every time and always starts a new build. The SCN polling log shows
Workspace doesn't contain Reponame/projectname/$svnBranch/componentname. Need a new build.
So the problem is obviously caused by Jenkins not resolving the variable when polling the SCM for changes. To verify this assumption, I changed the job to use a fixed string variable, and the same happened again.
I was wondering if it possible to solve the problem by moving the polling and checkout logic to the Jenkinsfile. The idea would be to always poll the trunk, but checkout and build based on $svnBranch, but I'm unsure how to do this. Is it possible to define different SCM urls for polling and checkouts? According to my research, all checkout urls in a Jenkinsfile would automatically be used for polling, so how to accomplish that?
Any other working solution would be welcome, too.
Note that there's a similar question Jenkins Pipeline - SVN polling that stumbled upon the same issue, but no solution that would fit my scenario.
Also note that there is an issue reported at JENKINS-10628: SCM build trigger not working correctly with variables in SVN URL that describes my problem, but it's said to be resolved with a new version of the Subversion plugin since 2015. I've updated to the latest version 2.16.0, yet it did not resolve the problem.
This is the solution I've found (I'm open to better ones - for example, I'm not happy with configuring the same SCM url in two different places):
First, in the Jenkins job, under Pipeline from SCM, I configured the trunk url that contains no variable. This url will be used to poll for changes in trunk.
svn+ssh://svn.mydomain.org/Reponame/projectname/trunk/componentname
Second, I created thid function to replace the "trunk" part by the branch name:
def call(Map param = [ : ]) {
if ( param.branch == null ) {
return param.trunkUrl
}
url = param.trunkUrl.replaceAll('/trunk(?=/|$)', '/'+param.branch) // replaces /trunk if followed by / or if at end of url
return url
}
I have moved this function to a shared library, so I can use it from any pipeline.
This is then used to derive the checkout url with the svnBranch being selected in the user interface:
environment {
// Set actual checkout url, because SVN_URL_1 will always contain the fixed url of the trunk used for polling
checkoutUrl = composeSvnUrl(trunkUrl: env.SVN_URL_1, branch: env.svnBranch)
}
Finally, I added a checkout stage (as the first stage) to my Jenkinsfile:
stage('Checkout') {
steps {
/* Checkout for actual build (may be different if started manually) */
checkout(
poll: false, changelog: false, // = do not use this for polling
scm: [
$class: 'SubversionSCM',
quietOperation: false,
additionalCredentials: [],
excludedCommitMessages: '',
excludedRegions: '',
excludedRevprop: '',
excludedUsers: '',
filterChangelog: false,
ignoreDirPropChanges: false,
includedRegions: '',
locations: [[
credentialsId: 'id.from.jenkins.credentials',
depthOption: 'infinity',
ignoreExternalsOption: true,
local: '.',
remote: checkoutUrl,
workspaceUpdater: [$class: 'CheckoutUpdater']
]
)
}
}
The important parts are:
poll: false, changelog: false means that Jenkins should not use these checkout information for polling. As mentioned on Pipeline: SCM Step - checkout: Check out from version control at the very bottom of the page:
If 'Include in polling' is disabled and 'Include in changelog' is disabled, then when polling occurs, changes that are detected from this repository will be ignored.
workspaceUpdater: [$class: 'CheckoutUpdater'] is probably important, too, as this will wipe the workspace before checking out again.

How to trigger a Jenkins Pipeline on Git commit

I'm setting up Jenkins pipeline for my .Net Core application.
Jenkins multibranch pipeline build gets trigger on Git commit if I am configuring the checkout SCM in multibranch Pipeline configuration. But multibranch Pipeline build is not getting trigger on git commit if I checkout SCM explicitly inside Jenkins Declarative Pipeline script.
Is there any way to resolve this issue?
Below is the checkout command which I am using inside the script:
checkout([$class: 'GitSCM', branches: [], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'CleanCheckout'], [$class: 'PruneStaleBranch']], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'credential-id', url: 'my/git/ssh/url']]])
To get the build triggered on new git commit you should first enable SCM polling in your pipeline script by adding proper triggers directive to your Jenkinsfile:
triggers {
pollSCM 'H/2 * * * *'
}
This will poll your SCM for any changes every two minutes. If a change is detected since the last build your job will be triggered to build the changes.
Polling is the easiest way to get what you want. However, you should consider using post-commit hook instead of polling. Using polling Jenkins has to periodically check SCM for the changes. In case of post-commit hook, Jenkins will be notified about the changes by SCM if necessary. It's prefered over polling because it will relieve the number of required requests and the traffic from Jenkins towards SCM repository.
After configuring post-commit hook, the triggers directive should be modified by providing an empty string as cron parameter to pollSCM trigger.
triggers {
pollSCM ''
}
It can be confusing but this empty string is required to enable post-commit hooks requests to be handled by the job. It's also not very well documented by Jenkins docs.

Jenkins pipeline not polling mercurial branch

Jenkins version 2.89.4
I have a pipeline that should checkout my code and test it everytime a commit is pushed.
stage('Code checkout') {
dir("${env.HG_NODE_DIRECTORY}") {
checkout([$class: 'MercurialSCM',
credentialsId: '...',
clean: true,
disableChangeLog: true,
installation: '(Default)',
source: 'ssh://hg#bitbucket.org/team/project'])
}
}
I have a webhook on my Bitbucket project that should trigger this builds, but they are not triggering.
The only job that triggers is one I created as a test, where I have my checkout configured the old way, directly into the job configuration, with no pipeline.
Is this a bug? Can I somehow trigger this kind of pipeline by SCM polling?
EDIT: I had to create a job with "normal" SCM configuration to then trigger the other jobs.

Trigger on only one of multiple polled SCMs in a Jenkinsfile

My Jenkinsfile has two SCM checkouts, primary, and secondary. I only want to have the build triggered when commits are made in primary. I've set the poll argument in the obvious way, but it does not seem to be honored; the build gets triggered when commits are made to either repository.
node {
stage("checkout") {
checkout scm: [$class: "MercurialSCM", source: "/var/jenkins_home/hg/primary", subdir: "hg/primary", clean: true], poll: true
checkout scm: [$class: "MercurialSCM", source: "/var/jenkins_home/hg/secondary", subdir: "hg/secondary", clean: true], poll: false
}
stage("do something") {
echo 'Hello World'
sh 'sleep 30s'
echo 'Done'
}
}
I could not figure out how to do this from within Jenkinsfile only.
To solve this problem for myself, I ended up creating a separate Jenkins job (Free Style project, not pipeline) which was setup to Poll SCM on the primary repo. This job does nothing except in the Post-build Actions it triggers my actual Jenkins Pipeline job which loads the Jenkinsfile like you showed.
The trigger passes a Predefined parameter set to the change ID that the poller found. In my case it was Git so I set change=${GIT_COMMIT}.
In my Pipeline job, I created a String parameter called change.
In my Jenkinsfile, I used env.change in the checkout line to checkout the specific commit.

Trigger workflow on Github push - Pipeline plugin - Multibranch configuration

We are using the pipeline plugin with multibranch configuration for our CD.
We have checked in the Jenkinsfile which works off git.
git url: "$url",credentialsId:'$credentials'
The job works fine, but does not auto trigger when a change is pushed to github.
I have set up the GIT web hooks correctly.
Interestingly, when I go into a branch of the multibranch job and I click "View Configuration", I see that the "Build when a change is pushed to Github" is unchecked. There is no way to check it since I can not modify the configuration of the job (since it takes from parent) and the same option is not there in parent.
Any ideas how to fix this?
For declarative pipelines try:
pipeline {
...
triggers {
githubPush()
}
...
}
For me this enables the checkbox "GitHub hook trigger for GITScm polling", but polling is not actually required. This requires the GitHub plugin.
I found a way to check the checkbox "Build when a change is pushed to Github".
This line did the trick:
properties([pipelineTriggers([[$class: 'GitHubPushTrigger'], pollSCM('H/15 * * * *')])])
I think the polling is needed to make it work. Would be nice if no polling is needed.
Here's a Jenkinsfile example with this implemented:
#!/usr/bin/env groovy
node ('master'){
stage('Build and Test') {
properties([pipelineTriggers([[$class: 'GitHubPushTrigger'], pollSCM('H/15 * * * *')])])
checkout scm
env.PATH = "${tool 'Maven 3'}/bin:${env.PATH}"
sh 'mvn clean package'
}
}
For declarative pipelines, try this:
pipeline {
agent any
triggers {
pollSCM('') //Empty quotes tells it to build on a push
}
}
If you use Stash for example you can register a Post-Receive WebHook where you have to insert your URL form Jenkins like : http://jenkinsHost:9090/git/notifyCommit?url=ssh://git#gitHost:1234/test.git
In your jenkins Job you have to set at least the Build trigger "Poll SCM".
And set a polling time of e.g 5 mins.
This enables also the automatic branch indexing for your multibranch project configuration.
Resorting to polling adds latency - time that it takes for a build to start and hence finish giving back a result.
It seemed to me that the basic plugins have a low level of abstraction, so I switched to the Github Organization Folder plugin, which depends on all of them and sets up an organization hook for triggering builds branches and/or pull requests.
Before I start, I would like to emphasize that I had no previous experience with Jenkins so far, so there might be a bunch of better solutions out there.
What I wanted to achieve in a nutshell:
After every push made to a Bitbucket repo(test2), on every branch,
pull and build another Bitbucket repo(test1), from an identical
branch name and right after that, build test2 using test1 as a
dependency.
How I managed to achieve that?
I started a new job with type 'Multibranch Pipeline'
I added the following Jenkinsfile to test2:
pipeline {
agent any
stages {
stage('build') {
steps {
dir('test1') {
git branch: BRANCH_NAME, url: 'git#bitbucket.org:user/test1.git', credentialsId: 'credentials_id'
}
sh('build_process')
}
}
}
}
I come across the issue that you can't set up a Bitbucket hook for pipelines
I added Bitbucket Branch Source Plugin to Jenkins
I selected Bitbucket at 'Branch Sources' when setting up the job
I added credentials and put a checkmark to Auto-register webhook
Under 'Scan Multibranch Pipeline Triggers' I put a checkmark to Periodically if not otherwise run, with an interval of 1 min
I added a webhook to my Bitbucket repo
I updated all my plugins, restarted Jenkins and it's ready to go
Other plugins I have installed: Bitbucket Plugin, Pipeline plugin. Hope this helps for somebody, I did manage to solve it this way after hours of struggling without the Bitbucket Branch Source Plugin.
node{
stage('Build and Test') {
properties([pipelineTriggers([[$class: 'GitHubPushTrigger'], pollSCM('* * * * *')])])
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'xxx-xxx-xxxx[your credentails Id]', url: 'https://github.com/git']]])
echo 'Build and Test has been done'
}
}

Resources