Bitbucket Jenkins plugin constructs wrong push URL - jenkins

We use Bitbucket server and want to trigger a Jenkins build whenever something is pushed to Bitbucket.
I tried to set up everything according to this page:
https://wiki.jenkins.io/display/JENKINS/BitBucket+Plugin
So I created a Post Webhook in Bitbucket, pointing at the Jenkins Bitbucket plugin's endpoint.
Bitbucket successfully notifies the plugin when a push occurs. According to the Jenkins logs, the plugin then iterates over all jobs where "Build when a change is pushed to BitBucket" is checked, and tries to match that job's repo URL to the URL of the push that occurred.
So, if the repo URL is
https://jira.mycompany.com/stash/scm/PROJ/project.git, the plugin tries to match it against
https://jira.mycompany.com/stash/PROJ/project, which obviously fails.
As per official info from Atlassian, Bitbucket cannot be prevented from inserting the "/scm/" part in the path.
The corresponding code in the Bitbucket Jenkins plugin is in class com.cloudbees.jenkins.plugins.BitbucketPayloadProcessor:
private void processWebhookPayloadBitBucketServer(JSONObject payload) {
JSONObject repo = payload.getJSONObject("repository");
String user = payload.getJSONObject("actor").getString("username");
String url = "";
if (repo.getJSONObject("links").getJSONArray("self").size() != 0) {
try {
URL pushHref = new URL(repo.getJSONObject("links").getJSONArray("self").getJSONObject(0).getString("href"));
url = pushHref.toString().replaceFirst(new String("projects.*"), new String(repo.getString("fullName").toLowerCase()));
String scm = repo.has("scmId") ? repo.getString("scmId") : "git";
probe.triggerMatchingJobs(user, url, scm, payload.toString());
} catch (MalformedURLException e) {
LOGGER.log(Level.WARNING, String.format("URL %s is malformed", url), e);
}
}
}
In the JSON payload that Bitbucket sends to the plugin, the actual checkout URL doesn't appear, only the link to the repository's Bitbucket page. The above method from the plugin appears to construct the checkout URL from that URL by removing everything after and including projects/ and adding the "full name" of the repo, resulting in the above wrong URL.
Official info from Atlassian is that Bitbucket cannot be prevented from adding the "scm" part to the checkout URL.
Is this a bug in the Jenkins plugin? If so, how can the plugin work for anyone?

I found the reason for the failure.
The issue is that the Bitbucket plugin for Jenkins does account for the /scm part in the path, but only if it's the first part after the host name.
If your Bitbucket server instance is configured not under its own domain but under a path of another service, matching the checkout URLs will fail.
Example:
https://bitbucket.foobar.com/scm/PROJ/myproject.git will work,
https://jira.foobar.com/stash/scm/PROJ/myproject.git will not work.
Someone who also had this problem has already created a fix for the plugin, the pull request for which is pending: JENKINS-49177: Now removing first occurrence of /scm

Related

Referencing Folder-level scope credentials in declarative Jenkins pipeline

Question
I have the following script as part of a declarative pipeline in Jenkins
stages {
stage('sql') {
steps {
step([
$class: 'SQLPlusRunnerBuilder',
credentialsId:"sis-database-prod-schema-test",
instance:"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=db_${ENVIRONMENT}.int.excelsior.edu)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=${ENVIRONMENT})))",
scriptType:'userDefined',
script: '',
scriptContent:"select*from dual",
customOracleHome: '/usr/lib/oracle/12.2/client64'
])
}
}
}
You will notice I am referencing the credential ID sis-database-prod-schema-test. When I scope this credential globally this script works. However, when I scope the credential at the folder level it get the following error
ERROR: Invalid credentials [sis-database-prod-schema-test]. Failed to initialize credentials or load user and password
Here is a screenshot of my folder-level scope configuration
Additional Information
When I scope the credential at the folder level I can see it in a configuration drop down element ONLY when I am in the appropriate folder. So, in my mind, the scope configuration is correct but there referencing ( in the code ) is wrong.
The entry I have highlighted is the sis-database-prod-schema-test credential ID. The one below it ( sis-test-database-prod-schema ) is a global credential unrelated to this question
Edit : This Was a Known Issue
This is a known bug that the author was unable to fix. The relevant code is here. You can issue a pull request to fix the bug.
I don't know if you still care but I just submitted a pull request for this that got accepted. Now this problem should be fixed.
Known Issue
This is a known bug that the author was unable to fix. The relevant code is here. You can issue a pull request to fix the bug.

Gitlab Webhooks (2 Webhooks on the same repo)

So heres the thing ,
We have two webhooks setup on the same repository in Gitlab ,
Webhooks number 1 is set to url : http://jenkins.local/project/job1 (build job from master branch )
Webhooks number 2 is set to url : http://jenkins.local/project/job2 (builds job from branch "1" )
The issue we're trying to overcome is , whenever there is a mergre request being opened
Both of those web hooks are being triggered .
Is there a way to "configure" the webhooks to fire only when a merge reuqest is being made into the master / 1 branch ,
i haven't found such settings in settings -> integrations
Webhook settings info
Currently, the option to restrict webhooks per branch is only available for Push events; for Merge requests events; there isn't a way to restrict/filter.
You have to filter it in your Jenkins job (which job to get fired; if that's also you looking for) as an example of GitLab plugin like this -
Job1:-
triggers {
gitlabPush {
buildOnMergeRequestEvents(true)
targetBranchRegex('master')
}
}
Job2:-
triggers {
gitlabPush {
buildOnMergeRequestEvents(true)
targetBranchRegex('branch1')
}
}

Add Parameter Value in Message of Jenkins Office 365 Connector

I use the Jenkins Office 365 Connector and it sends messages of the build status to MS Teams as expected.
Now I want to add the value of a Jenkins job parameter to the message.
My usecase: I use a single job to deploy several services. I want to know in the message which service was deployed.
Notification from Dev_Deploy
Latest status of build #43
Status
Build Success
Remarks
Started by user XXX
Service
service-abc
I've seen in the Advanced configuration that there are Macros and Fact Definitions. Unfortunately there is no documentation in the plugin docs. Perhaps this configuration could help?
There is no option to customize the message in the jenkins GUI.
But a custom message can be specified in the pipeline script:
steps {
// some instructions here
office365ConnectorSend webhookUrl: 'https://outlook.office.com/webhook/123456...',
message: 'Application has been [deployed](https://uat.green.biz)',
status: 'Success',
color: '#0000FF'
}
Hint: The status color is not automatically set. So you have to set the color depending on the status.
Official documentation
In order to get the repository data, you can follow instructions to create a checkout snippet through the Jenkins UI in the configuration.
Once you input the correct URL, browser, and so on, you may invoke the office365ConnectorSend plugin. You may adapt the card sent by passing the factDefinitions attribute an array of [name,template] objects as outlined in Jenkins Docs. You can find an example in the open-source code readme.
there are some defaulted add-ons, but this should set you on the correct path.
Here is an example of my office365ConnectorSend:
office365ConnectorSend (
webhookUrl: "${webhookURL}",
color: "${currentBuild.currentResult} == 'SUCCESS' ? '00ff00' : 'ff0000'",
factDefinitions:[
[ name: "Commit Message", template: "${commit_message}"],
[ name: "Pipeline Duration", template: "${currentBuild.durationString.minus(' and counting')}"]
]
)

Send Slack notification from Jenkins into private channel of other users

What i did:
I managed to send Notifications with Status of every Build to my private Slack Channel. So i configured my Jenkins as well as my Slack app.
What i want to do:
Sending messages to other users private Channels.
What i have tried:
I added channels to my Jenkinsfile and checked them in the Slack App of Jenkins and it wasn't successful. I think i have to create sth like a Bot, which is in the specific Channel i want to send a message to. Very sure that Jenkins can't see the channel because its a private channel of another person(obviously) and is not able to find it. Couldn't find a solution for this Problem.
Thanks a lot for your help, i think i wasted way to much time trying to find an answer for that.
I setup our build pipeline to send Slack notifications to commit authors. The biggest challenge is mapping to the Slack username. I had every developer on the team change their git user.name to match their Slack Display name. This is the most straight-forward way I know to make this work.
git config --global user.name "Mona Lisa" where "Mona Lisa" is the Slack display name of the user.
In the Jenkins pipeline, I used env.GIT_COMMIT_AUTHOR to get this value back.
Note, that the environment variable provides the commit author at the HEAD of whatever was checked out. For pull requests in a multi-branch pipeline, if the PR is not a fast forward, the commit is what the merge would produce, resulting in an author of 'Jenkins'. So, in that case, you would need the author from HEAD~1
In my experience sending Slack messages to a private channel requires OAuth. I have only succeeded sending to private channels via slackSend() when Jenkins is added to Slack as a bot and invited to the channel.
Here's an example pipeline that works:
#!/usr/bin/env groovy
pipeline {
agent {
node {
label "master"
}
}
stages {
stage('Send Notification') {
steps {
script {
def color = "${params.MESSAGE_STATUS}" == "GOOD"? "good" : "warning"
slackSend(color: "${color}", message: "${params.MESSAGE}", channel: "${params.CHANNEL}")
}
}
}
}
parameters {
string(name: 'MESSAGE', defaultValue: 'Hello')
string(name: 'CHANNEL', defaultValue: '#test_private')
choice(name: 'MESSAGE_STATUS', choices: ['GOOD', 'WARNING'], description: '')
}
}
Sending via bots etc. hasn't been successful as Slack reports the channel as non-existant.

How to get culprits or committers inside a Jenkins workflow with one or more SCMs

Is it possible to access information about committers and/or culprits of a Jenkins workflow job when checking out from one or more SCMs (either via checkout() or other SCM steps like git/svn)?
The intention is to use that information to notify committers and/or culprits about the job status, for example in a mail step.
A small example of a workflow definition:
node {
// checkout from one or more SCMs, e.g.
git url: '<URL>'
checkout([$class:...])
...
// how can we know about committers or culprits at this point?
$committers = ??
// send a mail to committers or culprits
mail to: '$committers', subject: 'JENKINS', body: '<information about the job status>'
}
How could this be adapted to get a collection of the committers after running the SCM steps?
Edit:
I am currently working with Jenkins version 1.596.2 and Workflow: Aggregator version 1.6 and it seems this is an open issue in JENKINS-24141
This is now possible using the email-ext plugin.
def to = emailextrecipients([[$class: 'CulpritsRecipientProvider'],
[$class: 'DevelopersRecipientProvider'],
[$class: 'RequesterRecipientProvider']])
if (to != null && !to.isEmpty()) {
mail to: to, subject: "JENKINS", body: "See ${env.BUILD_URL}"
}
However, if you just want to send an email on failures, you may want to use Mailer (based on the email-ext pipeline examples):
step([$class: 'Mailer',
notifyEveryUnstableBuild: true,
recipients: emailextrecipients([[$class: 'CulpritsRecipientProvider'],
[$class: 'RequesterRecipientProvider']])])
Using groovy within a pipeline script:
#NonCPS // Necessary to allow .each to work.
def changelist() {
def changes = ""
currentBuild.changeSets.each { set ->
set.each { entry ->
changes += "${entry.commitId} by ${entry.author.fullName}\n"
}
}
changes
}
similar to the answer from #szym, but without the #NonCPS required:
def authors = currentBuild.changeSets.collectMany { it.toList().collect { it.author } }.unique()
As you found, pending JENKINS-24141 this is not supported. Changes to Jenkins core are required.
You can get the xml info for a job in which you will find the name of the person who committed the change along with the commit messages.
http://<Jenkins URL>:<Port Number>/job/<Jobname>/<BuildNumber>/api/xml?
Give this a go in your browser. Search for "user".
You can dump this information in a text file to process.
It seems that this feature was implemented inside the email-ext plugin but the author forgot to document the way we are supposed to use this.
Please check https://issues.jenkins-ci.org/browse/JENKINS-34763 -- and add a comment there, asking for an example. I already did.
You can fetch committers email :
committerEmail = sh (
script: 'git --no-pager show -s --format=\'%ae\'',
returnStdout: true
).trim()
and send:
emailext body: 'text you choose', subject: 'subject you choose', recipientProviders: [[$class: 'DevelopersRecipientProvider']], to: committerEmail
taken from : https://medium.com/#dilunika/find-the-git-commit-user-jenkins-pipeline-b6790613f8b5
In the emailext plugin you can provide culprits, developers, requestor etc in the recipientProviders directly.
emailext body: '',
recipientProviders: [culprits(),
developers(),
brokenBuildSuspects(),
brokenTestsSuspects(),
requestor()],
subject: ''
Description
Culprits: Sends email to the list of users who committed a change since the last non-broken build till now. This list at least always include people who made changes in this build, but if the previous build was a failure it also includes the culprit list from there.
Developers: Sends email to all the people who caused a change in the change set.
Broken Build suspects: Sends email to the list of users suspected of causing the build to begin failing.
Broken Test suspects: Sends email to the list of users suspected of causing a unit test to begin failing. This list includes committers and requestors of the build where the test began to fail, and those for any consecutive failed builds prior to the build in which the test began to fail.
Source: Jenkins Pipeline Syntax - Snippet Generator
If you want to notify the culprits who broke the build, You do not need to any checks, Use email plugin in jenkins. This plugin gives you option to send mails to commiter between past good build and current broken build.
If you are using "Editable email notifier plugin" You get option of send mail to culprit.
If you are using email plugin then you get the option "Send separate e-mails to individuals who broke the build".

Resources