Jenkins Pipeline: Get the build url and build number and print that in post action method - jenkins

I have one pipeline job where it executes multiple jobs say job1 and job2. Once the execution is complete, i need to get the job2's build url and its build number and put that in the post section of success.
How to achieve this? Pls share your inputs.
Stages
{
Stage A
{
build 'job1'
}
stage B
{
build 'job2'
}
}
post
{
success
{
mail to: "${EMAIL_LIST}",
subject: 'Test Pipeline - SUCCESS',
body: " Get job-2's build_url and build_number"
}
}

You can try something like this if you start downstream jobs and wait for result of those:
def job1 = build job: 'myJob', wait: true
def job1Result = "${job1.getId()}"
def job1Url = "${job1.getAbsoluteUrl()}"
and use these into your post build action. I'm not using declarative pipeline but scripted pipeline. Be aware where you define the vars if you want them to be available on post build step.
Ps. I see that it's discouraged to use getAbsoluteUrl, but you can read documentation via the link below.
See for all options Run.

Related

Executing multiple jenkins jobs

Can someone please let me know how i can trigger multiple Jenkins jobs? We have 5-6 jobs that we need to trigger manually post some technical upgrades. We are having to navigate to these jobs manually and click on 'Build'. Is there anyway i can create a new job or shell script that will help me in triggering all of these jobs with a single click/run.
Simplest approach will be creating a new pipeline which will trigger other pipelines.
You can also make stages parallel to faster execution if order is not issue.
You can find detailed answer and approach here
Yes, you can do it in both ways that you mentioned. Creating a new job that will run all these other jobs as downstream jobs is the fastest and easiest.
To do this, create a new job, and if you are using declarative Jenkins, then specify the jobs to be triggered:
stage ('trigger-multiple-jobs') {
parallel {
stage ('first job') {
steps {
build([
job : 'JobName',
wait : false,
parameters: [
string(name: 'PARAM_1', value: "${PARAM_1}")
]
])
}
}
stage ('second job') {
steps {
build([
job : 'JobName2',
wait : false
])
}
}
}
}
You can alternatively create a freestyle job, navigate down to the Trigger downstream jobs section, and set the jobs you want to be triggered from the drop down.
If you want to use a shell script, then you can trigger the jobs using API calls. This is described well in this answer.

Start jenkins job immediately after creation by seed job, with parameters?

Start jenkins job immediately after creation by seed job
I can start a job from within the job dsl like this:
queue('my-job')
But how do I start a job with argument or parameters? I want to pass that job some arguments somehow.
Afaik, you can't.
But what you can do is creating it from a pipeline (jobDsl step), then run it. Something more or less like...
pipeline {
stages {
stage('jobs creation') {
steps {
jobDsl targets: 'my_job.dsl',
additionalParameters: [REQUESTED_JOB_NAME: "my_job's_name"]
build job: "my_job's_name",
parameters: [booleanParam(name: 'DRY_RUN', value: true)]
}
}
}
}
With a barebones 'my_job.dsl'...
pipelineJob(REQUESTED_JOB_NAME) {
definition {
// blah...
}
}
NOTE: As you see, I explicitly set the name of the job from the calling pipeline (the REQUESTED_JOB_NAME var) because otherwise I don't know how to make the jobDSL code to return the name of the job it creates back to the calling pipeline.
I use this "trick" to avoid the "job params go one run behind" problem. I use the DRY_RUN param of the job (I use a hidden param, in fact) to run a "do-nothing" build as its name implies, so by the time others need to use the job for "real stuff" its params section has already been properly parsed.

Select job as parameter in Jenkins (Declarative) Pipeline

I would like to set a parameter in Jenkins Declarative Pipeline enabling the user to select one of the jobs defined on Jenkins. Something like:
parameters {
choice(choices: getJenkinsJobs())
}
How can this be achieved?
Background info: I would like to implement a generic manual promotion job with the Pipeline, where the user would select a build number and the job name and the job would get promoted.
I dislike the idea of using the input step as it prevents the job from completing and I can't get e.g. the junit reports on tests.
You can iterate over all existing hudson.model.Job instances and get their names. The following should work
#NonCPS
def getJenkinsJobs() {
Jenkins.instance.getAllItems(hudson.model.Job)*.fullName.join('\n')
}
pipeline {
agent any
parameters {
choice(choices: getJenkinsJobs(), name: 'JOB')
}
//...
}
Use http://wiki.jenkins-ci.org/display/JENKINS/Extended+Choice+Parameter+plugin
and use basic groovy script as a input.
Refer the below URL for how to list the build/jobs.
https://themettlemonkey.wordpress.com/2013/01/29/jenkins-build-number-drop-down/

How to integrate Jobs in Jenkins using Pipeline

I have Four Jobs- A,B,C,D
A- Build
B- Test
C- Sonar Analysis
D- Deploy
My scenario-
1- I need to create a Pipeline
A->B->C
2- I Need to create a other Pipeline
A->B->D
My issue is--
1- If I select "Trigger Parameterized builds on other projects " and add Job B under Job A, I can't use Job A for my second scenario.
How should I use Job A for both the pipelines without effecting.
If I understand the question correctly, you are looking to create two pipelines. In the pipelines, you can define which jobs to build using stages.
For your requirement, you need to create two pipelines and define stages according to your needs. Trigger Parameterized builds on other projects is not a suitable option for you.
stage('Build A') {
build job: 'A' , parameters: <Give_your_own_parameters>
}
stage('Build B') {
build job: 'B' , parameters: <Give_your_own_parameters>
}
stage('Build C') {
build job: 'C' , parameters: <Give_your_own_parameters>
}
You can also get the syntax from Pipeline Syntax in the Pipeline Section of the pipeline you are building.
You can ease the process by creating a duplicate project of A, and B. Project can easily be duplicated during New Item> Copy details from Project A.
This is not easy feasible for a simple reason : you are not using Jenkins jobs the way they were meant to be used.
The concept of a job in Jenkins is that a job is a sequence of actions. A job does not have a single responsibility such as just building, just testing or just deploying. In your case, you should have 3 "actions" in a job, and 3 "actions" in another job.
The freestyle job approach
The common approach would be something like :
Build job
Action 1 : build
Action 2 : test
Action 3 : run Sonar analysis
Deploy job
Action 1 : build
Action 2 : test
Action 3 : deploy
Unless I'm missing something here, you don't want to separate these 3/4 actions in 4 separate jobs, as this would be highly inneficient. For example, test phase and Sonar analysis should probably be run just after a code build has been made, so you want to share the same workspace to be able to test your built code.
The pipeline approach
Another - preferred - approach would be to use actual Jenkins pipelines, i.e. Groovy scripts that will allow you to define your steps as functions and then reuse them in both your "Build job" and "Deploy job".
As an example, you could have a functions.groovy containing your build/test functions :
functions.groovy
def build() {
// Build code here...
}
def test() {
// Test code here...
}
build-job.groovy
node {
def functions = load 'functions.groovy'
stage('Build') {
functions.build()
}
stage('Test') {
functions.test()
}
stage('Sonar Analysis') {
// Sonar analysis code...
}
}
deploy-job.groovy
node {
def functions = load 'functions.groovy'
stage('Build') {
functions.build()
}
stage('Test') {
functions.test()
}
stage('Deploy') {
// Deploy code...
}
}

Aggregating results of downstream parameterised jobs in Jenkins

I have a Jenkins Build job which triggers multiple Test jobs with the test name as a parameter using the Jenkins Parameterized Trigger Plugin. This kicks off a number of test builds on multiple executors which all run correctly.
I now want to aggregate the results using 'Aggregate downstream test results->Automatically aggregate all downstream tests'. I have enabled this in the Build job and have set up fingerprinting so that these are recognised as downstream jobs. In the Build jobs lastBuild page I can see that they are recognised as downstream builds:
Downstream Builds
Test #1-#3
When I click on "Aggregated Test Results" however it only shows the latest of these (Test #3). This may be good behaviour if the job always runs the same tests but mine all run different parts of my test suite.
Is there some way I can get this to aggregate all of the relevant downstream Test builds?
Additional:
Aggregated Test Results does work if you replicate the Test job. This is not ideal as I have a large number of test suites.
I'll outline the manual solution (as mentioned in the comments), and provide more details if you need them later:
Let P be the parent job and D be a downstream job (you can easily extend the approach to multiple downstream jobs).
An instance (build) of P invokes D via Parameterized Trigger Plugin via a build step (not as a post-build step) and waits for D's to finish. Along with other parameters, P passes to D a parameter - let's call it PARENT_ID - based on P's build's BUILD_ID.
D executes the tests and archives them as artifacts (along with jUnit reports - if applicable).
P then executes an external Python (or internal Groovy) script that finds the appropriate build of D via PARENT_ID (you iterate over builds of D and examine the value of PARENT_ID parameter). The script then copies the artifacts from D to P and P publishes them.
If using Python (that's what I do) - utilize Python JenkinsAPI wrapper. If using Groovy - utilize Groovy Plugin and run your script as system script. You then can access Jenkins via its Java API.
I came up with the following solution using declarative pipelines.
It requires installation of "copy artifact" plugin.
In the downstream job, set "env" variable with the path (or pattern path) to result file:
post {
always {
steps {
script {
// Rem: Must be BEFORE execution that may fail
env.RESULT_FILE='Devices\\resultsA.xml'
}
xunit([GoogleTest(
pattern: env.RESULT_FILE,
)])
}
}
}
Note that I use xunit but the same apply with junit
In the parent job, save build variables, then in post process I aggregate results with following code:
def runs=[]
pipeline {
agent any
stages {
stage('Tests') {
parallel {
stage('test A') {
steps {
script {
runs << build(job: "test A", propagate: false)
}
}
}
stage('test B') {
steps {
script {
runs << build(job: "test B", propagate: false)
}
}
}
}
}
}
post {
always {
script {
currentBuild.result = 'SUCCESS'
def result_files = []
runs.each {
if (it.result != 'SUCCESS') {
currentBuild.result = it.result
}
copyArtifacts(
filter: it.buildVariables.RESULT_FILE,
fingerprintArtifacts: true,
projectName: it.getProjectName(),
selector: specific(it.getNumber().toString())
)
result_files << it.buildVariables.RESULT_FILE
}
env.RESULT_FILE = result_files.join(',')
println('Results aggregated from ' + env.RESULT_FILE)
}
archiveArtifacts env.RESULT_FILE
xunit([GoogleTest(
pattern: env.RESULT_FILE,
)])
}
}
}
Note that the parent job also set the "env" variable so it can itself be aggregated by a parent job.

Resources