37

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: "test@test.com", 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?

Daniel Steinmann
  • 2,119
  • 2
  • 15
  • 25

2 Answers2

48

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

post {
  always {
    node('awesome_node_label') {
      step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: "test@test.com", sendToIndividuals: true])
    }
  }
}
burnettk
  • 13,557
  • 4
  • 51
  • 52
  • 2
    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? – Daniel Steinmann Jun 14 '17 at 05:59
  • 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. – Daniel Steinmann Jun 14 '17 at 09:33
  • 8
    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? – red888 Aug 16 '17 at 14:21
  • 6
    @red888 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. https://jenkins.io/doc/book/pipeline/syntax/#agent – Nick Petrovic Jan 09 '19 at 15:48
  • 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. – Martin May 21 '19 at 14:56
  • 2
    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. – sanya Jun 14 '21 at 10:15
13

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: "test@test.com", 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.

Heatmanofurioso
  • 968
  • 7
  • 19
skeletor
  • 131
  • 1
  • 2