Create post status notification method for all pipelines - jenkins

thanks in advance for the help.
For our project, for which we use Jenkins, I'm working on a shared library to house all methods for our different pipelines (3 different ones).
Currently I'm facing an issue, that I don't really know how to solve.
I configured the jenkins-mattermost-plugin for the project. Ideally, I'd like to create one method for the post task in Jenkins that takes currentBuild.currentResult as an argument and returns the corresponding condition block and its message.
Ex:
if success:
success {
mattermostSend(...success build notification)
}
}
if failure:
failure {
mattermostSend(...failure build notification)
}
}
etc.
The problem is not writing the method itself, but when to call it in the pipeline.
I can't call it in a stage block, not without any block wrapper.
I hope this makes sense what I'm trying to say.

You can call the function in always post-condition:
post {
always {
mattermostSend("${currentBuild.currentResult}")
}
}
Then inside mattermostSend create condition which depending on the build result will send the required message.

Related

Jenkins: Parameters disappear from pipeline job after running the job

I've been trying to construct multiple jobs from a list and everything seems to be working as expected. But as soon as I execute the first build (which works correctly) the parameters in the job disappears. This is how I've constructed the pipelineJob for the project.
import javaposse.jobdsl.dsl.DslFactory
def repositories = [
[
id : 'jenkins-test',
name : 'jenkins-test',
displayName: 'Jenkins Test',
repo : 'ssh://<JENKINS_BASE_URL>/<PROJECT_SLUG>/jenkins-test.git'
]
]
DslFactory dslFactory = this as DslFactory
repositories.each { repository ->
pipelineJob(repository.name) {
parameters {
stringParam("BRANCH", "master", "")
}
logRotator{
numToKeep(30)
}
authenticationToken('<TOKEN_MATCHES_WITH_THE_BITBUCKET_POST_RECEIVE_HOOK>')
displayName(repository.displayName)
description("Builds deploy pipelines for ${repository.displayName}")
definition {
cpsScm {
scm {
git {
branch('${BRANCH}')
remote {
url(repository.repo)
credentials('<CREDENTIAL_NAME>')
}
extensions {
localBranch('${BRANCH}')
wipeOutWorkspace()
cloneOptions {
noTags(false)
}
}
}
scriptPath('Jenkinsfile)
}
}
}
}
}
After running the above script, all the required jobs are created successfully. But then once I build any job, the parameters disappear.
After that when I run the seed job again, the job starts showing the parameter. I'm having a hard time figuring out where the problem is.
I've tried many things but nothing works. Would appreciate any help. Thanks.
This comment helped me to figure out similar issue with my .groovy file:
I called parameters property twice (one at the node start and then tried to set other parameters in if block), so the latter has overwritten the initial parameters.
BTW, as per the comments in the linked ticket, it is an issue with both scripted and declarative pipelines.
Fixed by providing all job parameters in each parameters call - for the case with ifs.
Though I don't see repeated calls in the code you've provided, please check the full groovy files for your jobs and add all parameters to all parameters {} blocks.

How to set job order for monitor view in jenkins job DSL groovy script?

I'm creating Build Monitor view with DSL Script, but there is no method in API to set the job order. I can set the order manually in configuration after view is created, but I need to do that within the script.
I'm using https://jenkinsci.github.io/job-dsl-plugin/#path/buildMonitorView as a reference. The only way I suspect it could be possible is configure(Closure) method, but I would still have the same question of how to do it.
My current code:
biuldMonitorView("name-of-the-view") {
jobs {
regex("some regex to include jobs")
recurse()
}
// I would expect something like:
view {
orderByFullName()
}
}
After some trial and error and println calls everywhere I came to this solution:
biuldMonitorView("name-of-the-view") {
jobs { // This part is as before
regex("some regex to include jobs")
recurse()
}
// The solution:
view.remove(view / order)
view / order(class: "com.smartcodeltd.jenkinsci.plugins.buildmonitor.order.ByFullName")
}
Above solution sets job order to "Full name" instead of default "Name".
I found the remove idea at Configure SVN section of job-dsl-plugin, fully qualified names of job order options can be found in the source of jenkins-build-monitor-plugin.
I had the same question today and managed to get Aivaras's proposal to work in the following way:
buildMonitorView("name-of-the-view") {
// Set properties like jobs
jobs {
regex("some regex to include jobs")
recurse()
}
// Directly manipulate the config to set the ordering
configure { view ->
view.remove(view / order)
view / order(class: "com.smartcodeltd.jenkinsci.plugins.buildmonitor.order.ByFullName")
}

How to wait for xtext service to complete before executing code

I am using the Xtext web editor framework and am having an issue with code being executed before its preconditions have been run. For instance, when I update my document It calls into the XtextServlet doService method. I have subclassed the XtextServlet class and overridden the doService method like this:
override doService(XtextServiceDispatcher.ServiceDescriptor service, HttpServletResponse response) {
super.doService(service, response)
switch (service.context.getParameter("serviceType")) {
case "update": {
// Execute other code
}
}
This other code that I am running relies on the document having been updated. But I have found that sometimes the document is not updated before my code runs. I assume these services are spun up in their own threads then. My question is, is there a way to trigger my code to run as a result of the service actually completing or do I need to completely override the update service to call my code?
EDIT: To clarify my question, where I call super.doService(service, response), this executes an edit onto the document. Where I have my comment // Execute other code I am trying to run some other side effect for the service. This other code relies on the doService method to have finished, but doService spins off an async task which is not finishing before my other code executes

How do I use `when` condition on a file's last modified time in Jenkins pipeline syntax

I am creating a Jenkins pipeline, I want certain stage to be triggered only when a particular log file's(log file is located in the server node where all the stages are going to run) last modified date is updated after the initiation of pipeline job, I understand we need to use "When" condition but not really sure how to implement it.
Tried referring some of the pipeline related portals but could not able to find an answer
Can some please help me through this?
Thanks in advance!
To get data about file is quite tricky in a Jenkins pipeline when using the Groovy sandbox since you're not allowed to do new File(...).lastModified. However there is the findFiles step, which basically returns a list of wrapped File objects with a getter for last modified time in millis, so we can use findFiles(glob: "...")[0].lastModified.
The returned array may be empty, so we should rather check on that (see full example below).
The current build start time in millis is accessible via currentBuild.currentBuild.startTimeInMillis.
Now that we git both, we can use them in an expression:
pipeline {
agent any
stages {
stage("create file") {
steps {
touch "testfile.log"
}
}
stage("when file") {
when {
expression {
def files = findFiles(glob: "testfile.log")
files && files[0].lastModified < currentBuild.startTimeInMillis
}
}
steps {
echo "i ran"
}
}
}
}

How to send an email to requester only if the build is triggered manually?

I would like to configure a project in Jenkins to send emails to the recipients group for regular scheduled builds, but only to the requester in case the build is triggered manually. Is this possible?
You should be able to accomplish this by using the "Script - After Build" trigger of the Editable Email Notification post-build action. You can run a groovy script, with the last line evaluating to a Boolean, which determines whether or not to send the email. The screenshot below shows the trigger section that checks to see if the build was initiated by a user (manually).
This script will only tell you whether or not the IMMEDIATE cause of the build was a manual user action, though. Depending on how your build pipeline is setup, one of your upstream jobs may have been initiated manually, so I'm not sure if you want an email sent in that case. If you do, you will have to iterate through all the build causes and look for a manual cause.
def boolean wasStartedManually(causes) {
boolean manuallyStarted = false
causes.each { cause ->
if (cause.class == hudson.model.Cause$UserIdCause) {
manuallyStarted = true
}
if (!manuallyStarted) {
if (cause.class == hudson.model.Cause$UpstreamCause) {
manuallyStarted = wasStartedManually(cause.upstreamCauses)
}
}
}
return manuallyStarted
}
wasStartedManually(build.getCauses())
You will need to add 2 post-build Email actions to your job, one for when the job is triggered manually, and then another if the job was not submitted manually. For the latter, you would run the same script, but just negate the results.

Resources