I am trying to create a Jenkins pipeline with stages which require user input. However, during these periods where Jenkins is waiting for the user to click Proceed or Abort, the agent seems to stay online.
There is a way of pausing a stage without an agent being online/consumed:
- Set
agent none
at the top level of the Jenkinsfile. By default no stage will have an agent assigned to it. - Set an agent specifically for each stage.
- On the stage you wish to pause without consuming an agent, add a
when
clause containing anexpression
block (asking the user if they want to proceed), and then addbeforeAgent
to ensure this expression happens before an agent is brought up.
This looks like the following:
pipeline {
agent none
stages {
stage ('Stage I want to Pause') {
when {
beforeAgent true
expression {
input message: 'Do you want to continue?'
return true
}
}
agent { label MyAgent }
steps {
echo "Performing task..."
}
}
}
}
However, there is a big disadvantage with this method as far as I can see. The fact that the agent needs to be set at each stage means that after every stage the agent will go down, and a new one will come back up.
This is a problem if you have a stage that installs some packages, as the agent that comes up for the second stage will not have these packages.
Are there any other ways of achieving this, or alternatively is there a way of keeping an agent up if two consecutive stages are using the same agent label?
CodePudding user response:
SOLUTION
Answering my own question.
In my question I posted a step-by-step process for pausing a stage without consuming an agent (i.e Bringing the agent down until the pipeline is resumed/approved)
There was a big disadvantage to the process -- setting agent none
globally and specifying an agent per stage meant that a new agent was created for every stage. This is not ideal especially if you have package installs in one stage which are needed in the next stage.
The solution to this problem is Sequential Stages, introduced in Declarative Pipeline 1.3. You can wrap stages in another parent stage, which means they will all use the same agent.
So, in summary, here is how to pause a stage in Jenkinsfile without consuming an agent, while making use of sequential stages for anything you want to run on one agent.
- Set
agent none
at the top level of the pipeline. By default no stage will have an agent assigned to it. - Set an agent specifically for any 'parent' stages.
- Within this parent stage, create 'child stages' for any tasks you want to be performed on just one agent. You do not need to specify an agent on child stages. They will use the parent's agent.
- For any stage you wish to pause without consuming an agent, set an agent specifically. Then add a
when
clause containing an expression block (asking the user if they want to proceed), and addbeforeAgent true
to ensure this expression happens before the agent is brought up.
Here is an example:
pipeline {
agent none // By default, no agent will come up
stages {
stage ('Parent Stage') {
agent { label MyAgent }
stage ('Child Stage 1. Package installs for example.'){
// You don't need to specify agent here as it uses parent
steps {
// Install packages
}
}
stage ('Child Stage 2. Uses same agent as previous stage.') {
steps {
// Step operations which require above packages
}
}
}
stage ('Stage I want to pause without consuming agent') {
when {
beforeAgent true
expression {
input message: 'Do you want to continue?'
return true
}
}
agent { label MyAgent }
steps {
echo "Performing task..."
}
}
}
}