choose Jenkins post actions agent - jenkins

Is there a way to choose where the post build actions will be executed?
pipeline {
agent windows
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
post {
// agent linux
always {
echo 'I will always say Hello again!'
}
}
}
I want to run the post build actions on linux agent is there a way todo that?

This worked for me in a declarative pipeline
post {
always {
node('linux') {
echo 'I will always say Hello again!'
}
}
}

What I wanted to do could be achieved like that:
pipeline {
agent { label 'linux' }
stages {
stage('Setup Agent') {
agent { label 'windows' }
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
}
}
post {
always {
echo 'I will always say Hello again!'
}
}
}
then the post will run on the agent from the top and the inner stages will run on the inner agent.

Related

How to achive nested parallel in Jenkins declarative pipeline?

I have declarative pipeline as below and it runs 2* and 3* stages in parallel, pasted the blue ocean diagram below.
pipeline {
agent { label 'my_node' }
options {
timestamps()
parallelsAlwaysFailFast()
}
stages {
stage('1') {
steps {
script {
step([$class: 'WsCleanup'])
}
}
}
stage('2') {
parallel {
stage("2.1") {
steps {
script {
sh 'echo hi 2.1'
}
}
}
stage("2p") {
steps {
script {
sh 'echo hi 2p'
}
}
}
}
}
stage('3') {
parallel {
stage('3.1') {
steps {
script {
sh """
echo hi 3.1
"""
}
}
}
stage('3.2') {
steps {
script {
sh """
echo "hi 3.2"
"""
}
}
}
}
}
stage('4') {
steps {
script {
sh "echo end"
}
}
}
}
}
But I am looking to run 2p in parallel to 2* and 3*, like shown below, is there a way?
I tried to use paralle under parallel, to start 2p in parallel to 2 and 3, and nested parallel to run 3.1. and 3.2 underneath, but declarative pipeline is not allowing nested parallel.
You can't do this only with Declarative syntax. But you can achieve this with a combination of Scripted and Declarative syntax. One thing to note is, AFAIK there is no visualization support for nested parallel stages as of now. There is a feature request for this here.
Following is a sample pipeline you can use as a reference for your use case.
pipeline {
agent any
options {
timestamps()
parallelsAlwaysFailFast()
}
stages {
stage('1') {
steps {
script {
step([$class: 'WsCleanup'])
}
}
}
stage('2 AND 3') {
steps {
script {
parallel getWrappedStages()
}
}
}
stage('4') {
steps {
script {
sh "echo end"
}
}
}
}
}
def getWrappedStages() {
stages = [:]
stages["Step2.1"] = { stage('2.1') {
sh """
echo hi 2.1
"""
}
parallel parallel3xstages()
}
stages["Step2.p"] = { stage('2.p') {
sh """
echo hi 2.p
"""
}
}
return stages
}
def parallel3xstages() {
stages = [:]
stages["Step3.1"] = { stage('3.1') {
sh """
echo hi 3.1
"""
}
}
stages["Step3.2"] = { stage('3.2') {
sh """
echo hi 3.2
"""
}
}
return stages
}

Graph of GitLab UI showing stages in vertical way

I have an Jenkinsfile to run some stages that I want, but after each commit, I would like to see all stages info in a clean way in my Gitlab server.
Here is the Jenkinsfile:
pipeline {
agent any
options {
gitLabConnection('gitlab connection')
}
stages {
stage('Build') {
steps {
gitlabCommitStatus(name: 'Build') {
(...)
}
}
}
stage('Static Code') {
parallel {
stage('SonarQube') {
steps {
gitlabCommitStatus(name: 'SonarQube') {
(...)
}
}
}
stage('FindBugs') {
steps {
gitlabCommitStatus(name: 'FindBugs') {
(...)
}
}
}
}
}
stage('Unit Tests') {
steps {
gitlabCommitStatus(name: 'Unit Tests') {
(...)
}
}
}
}
post {
changed {
gitlabCommitStatus(name: 'Teams Notification') {
(...)
}
}
}
}
When I run that pipeline I receive the stages info in a vertical way without any type of info on which stages run in parallel or not. All my stages show in vertical mode.
Is there anything that I can do to show something like this?
Thank you so much :)

How to get failed stage name during parallel run of stages?

I've a pipeline where multiple stages run in parallel but if any of the stages fails, I want to get its name to show failed stage. With following code, even if it fails in first stage ie Checking Redmine access, it always show last stage as failed i.e. Checking Reviewers list. This is because it runs in parallel and latest assigned value is picked up.
pipeline {
agent {
label {
label "<machine-ip>"
customWorkspace "workspace/RedmineAndReviewboardProject/SVNCheckoutTest"
}
}
stages {
stage('Verify inputs') {
parallel {
stage('Checking Redmine access') {
steps {
script {
FAILED_STAGE = env.STAGE_NAME
echo "Redmine"
sh'''hello'''
}
}
}
stage('Checking SVN access') {
steps {
script {
FAILED_STAGE = env.STAGE_NAME
echo "SVN"
}
}
}
stage('Checking Reviewers list') {
steps {
script {
FAILED_STAGE = env.STAGE_NAME
echo "Reviewer"
}
}
}
}
}
}
post {
failure {
script {
echo "Failed stage is " + FAILED_STAGE
}
}
}
}
Is there any way I can get exactly failed stage of parallel running stages? or it will be also ok with me if parent stage name is returned as failed stage.
I believe you can use a post { failure { block for each stage : see https://www.jenkins.io/doc/book/pipeline/syntax/#post
pipeline {
agent {
label {
label "<machine-ip>"
customWorkspace "workspace/RedmineAndReviewboardProject/SVNCheckoutTest"
}
}
stages {
stage('Verify inputs') {
parallel {
stage('Checking Redmine access') {
steps {
script {
echo "Redmine"
sh'''hello'''
}
}
post {
failure {
script {
echo "Failed stage is ${STAGE_NAME}"
}
}
}
}
stage('Checking SVN access') {
steps {
script {
FAILED_STAGE = env.STAGE_NAME
echo "SVN"
}
}
post {
failure {
script {
echo "Failed stage is ${STAGE_NAME}"
}
}
}
}
stage('Checking Reviewers list') {
steps {
script {
FAILED_STAGE = env.STAGE_NAME
echo "Reviewer"
}
}
post {
failure {
script {
echo "Failed stage is ${STAGE_NAME}"
}
}
}
}
}
}
}
}

Run same stages in parallel on different nodes with Jenkins pipeline

There is a way to execute steps/post-actions on different nodes in parallel described in this article: https://jenkins.io/blog/2017/09/25/declarative-1/
stage('Run Tests') {
parallel {
stage('Test On Windows') {
agent {
label "windows"
}
steps {
bat "run-tests.bat"
}
post {
always {
junit "**/TEST-*.xml" // DUPLICATE CODE
}
}
}
stage('Test On Linux') {
agent {
label "linux"
}
steps {
sh "run-tests.sh"
}
post {
always {
junit "**/TEST-*.xml" // DUPLICATE CODE
}
}
}
}
}
Is there any possibility to execute same stages on multiple nodes without duplicating code?
Something like this:
stage('Run Tests') {
parallel {
stage("Test On ${NODE_NAME}") {
agents {
label "windows"
label "linux"
}
steps {
// do test steps
}
post {
always {
junit "**/TEST-*.xml"
}
}
}
}
}
You can create dynamic stages, but for your case not needed
pipeline {
agent any
stages {
stage ("Test") {
steps {
script {
testStages = ["Windows", "Linux"].collectEntries {
["${it}" : runTests(it)]
}
parallel testStages
}
}
}
}
}
def runTests(def name){
return {
node(name) {
stage("Run on ${name}") {
script {
command = "run-tests"
try {
switch(name.toLowerCase()) {
case "windows":
command += ".bat"
break;
case "linux":
command += ".sh"
break;
}
echo command
} catch (Exception ex) {
echo ex
} finally {
echo "post ${name}"
}
}
}
}
}
}
Declarative Matrix worked best for me:
pipeline {
agent none
stages {
stage('BuildAndTest') {
matrix {
agent {
label "${PLATFORM}-agent"
}
axes {
axis {
name 'PLATFORM'
values 'linux', 'windows'
}
}
stages {
stage('Test') {
steps {
echo "Do Test for ${PLATFORM}"
}
}
}
post {
always {
junit "**/TEST-*.xml"
}
}
}
}
}
}
This pipeline will execute the defined stages incl. post build actions on both platforms without any code duplication.
Quote from a Jenkins blog post about declartive matrix:
An equivalent pipeline created without matrix would easily be several
times larger, and much harder to understand and maintain.

How to define parallel stages of a Jenkinsfile in an external function?

This minimal pipeline works:
pipeline {
agent any
stages {
stage('test') {
parallel {
stage('test-1') {
steps {
sh "echo test1"
}
}
stage('test-2') {
steps {
sh "echo test2"
}
}
}
}
}
}
We have several test stages inside the parallel block and so we run into Method Code too large error that the Jenkins guys apparently aren't planning to fix.
I'd like to have my parallel stages defined in an outside function, like this:
pipeline {
agent any
stages {
stage('test') {
parallel test_func()
}
}
}
def test_func() {
return {
stage('test-1') {
steps {
sh "echo test1"
}
}
stage('test-2') {
steps {
sh "echo test2"
}
}
}
}
This however doesn't work with lots of variations of syntax that we've tried.
Thanks in advance!
Check my answer to this question.
You need to put your parallel stages in a variable, not a function. So, it could be somethink like this:
def test_func = [
"test1": {
echo "test1"
},
"test2": {
echo "test2"
}
]
pipeline {
agent any
stages {
stage('test') {
steps {
script {
parallel test_func
}
}
}
}
}
As seen in the examples here, it expects a map of an arbitrary identifier as key and a closure containing the code as value. So something (untested) like:
def test_func() {
return [
test1: {
stage('test-1') {
steps {
sh "echo test1"
}
}
},
test2: {
stage('test-2') {
steps {
sh "echo test2"
}
}
}
]
}
You could do it like this:
def createStages() {
stage_map = [:]
stage_map.put('test-1', {echo 'test1'})
stage_map.put('test-2', {echo 'test2'})
return stage_map
}
pipeline {
agent any
stages {
stage('test') {
steps{
script { parallel(createStages()) }
}
}
}
}

Resources