How to use post steps with Jenkins pipeline on multiple agents?
Asked Answered
F

2

39

When using the Jenkins pipeline where each stage runs on a different agent, it is good practice to use agent none at the beginning:

pipeline {
  agent none
  stages {
    stage('Checkout') {
      agent { label 'master' }
      steps { script { currentBuild.result = 'SUCCESS' } }
    }
    stage('Build') {
      agent { label 'someagent' }
      steps { bat "exit 1" }
    }
  }
  post {
    always {
      step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: "[email protected]", sendToIndividuals: true])
    }
  }
}

But doing this leads to Required context class hudson.FilePath is missing error message when the email should go out:

[Pipeline] { (Declarative: Post Actions)
[Pipeline] step
Required context class hudson.FilePath is missing
Perhaps you forgot to surround the code with a step that provides this, such as: node
[Pipeline] error
[Pipeline] }

When I change from agent none to agent any, it works fine.

How can I get the post step to work without using agent any?

Footle answered 13/6, 2017 at 20:32 Comment(0)
H
49

wrap the step that does the mailing in a node step:

post {
  always {
    node('awesome_node_label') {
      step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: "[email protected]", sendToIndividuals: true])
    }
  }
}
Horseweed answered 13/6, 2017 at 23:24 Comment(6)
I used node('master') and now it works. Thank you. If I omit the label, I get the error WorkflowScript: 15: Missing required parameter: "label". Can you adjust your answer?Footle
Before I asked this question I tried to use node right after post, which is not allowed, but it never occurred to me to wrap only the step. Thanks for your help.Footle
Can someone please explain this? node is a scripted Pipeline right? Why must this action be scripted and what is Jenkins doing behind the scenes?Pantalets
@Pantalets When the agent is set to none, no nodes are allocated. In OP's configuration, the agent is set to none at the top level, therefore you must set the agent in every stage. Unfortunately, you cannot set an agent in the post block which is why node() is required. Here's the docs on how you can configure the agent. jenkins.io/doc/book/pipeline/syntax/#agentAeschylus
Thanks, that worked fine. Haven't found a way to run the node on any executor without needing to specify a label. But it is fine that way.Floristic
Be aware this will allocate an extra executor at the end of the build which can lead to a deadlock. Say you have 2 executors and a multibranch pipeline. Fist executor is allocated and it starts the build on branch A. During this build a second executor is allocated and starts a build on branch B. Branch A gets to the post phase and tries to allocate another executor which it cannot since branch B is building on it. So it start waiting. Branch B gets to the post build phase and tries to allocate another executor which it cannot since branch A is waiting on a free executor. You're screwed.Dissection
G
15

I know this is old but I stumbled on this looking for something related. If you want to run the post step on any node, you can use

    post {
      always {
        node(null) {
          step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: "[email protected]", sendToIndividuals: true])
        }
      }
    }

https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#node-allocate-node Says that the label may be left blank. Many times in a declarative pipeline if something is left blank this results in an error. To work around this, setting it to null will often work.

Guiscard answered 4/11, 2019 at 16:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.