I'm using Jenkins Pipeline with the declarative syntax, currently with the following stages:
For steps 1, 2, 3, and 5 I need and agent (an executor) because they do actual work on the workspace. For step 4, I don't need one, and I would like to not block my available executors while waiting for user input. This seem to be referred to as either a "flyweight" or "lightweight" executor for the classic, scripted syntax, but I cannot find any information on how to achieve this with the declarative syntax.
So far I've tried:
agent none
on the stage. This has no effect, and the pipeline runs as normalt, blocking the executor while waiting for input. It is also mentioned in the documentation that it will have no effect, but I thought I'd give it a shot anyway.agent none
in the pipeline options, and then setting an agent for each stage except #4. Unfortunately, but expectedly, this allocates a new workspace for every stage, which in turn requires me to stash and unstash. This is both messy and gives me further problems in the parallel stages (2 and 3) because I cannot have code outside the parallel
construct. I assume the parallel steps run in the same workspace, so stashing/unstashing in both would have unfortunate results.Here is an outline of my Jenkinsfile:
pipeline { agent { label 'build-slave' } stages { stage("Prepare build") { steps { // ... } } stage("Build") { steps { parallel( frontend: { // ... }, backend: { // ... } ) } } stage("Test") { steps { parallel( jslint: { // ... }, phpcs: { // ... }, ) } post { // ... } } stage("Select deploy target") { steps { script { // ... code that determines choiceParameterDefinition based on branch name ... try { timeout(time: 5, unit: 'MINUTES') { deployEnvironment = input message: 'Deploy target', parameters: [choiceParameterDefinition] } } catch(ex) { deployEnvironment = null } } } } stage("Deploy") { when { expression { return binding.variables.get("deployEnvironment") } } steps { // ... } } } post { // ... } }
Am I missing something here, or is it just not possible in the current version?
The agent directive specifies where the entire Pipeline, or a specific stage, will execute in the Jenkins environment depending on where the agent directive is placed. The directive must be defined at the top-level inside the pipeline block, but stage-level usage is optional.
The “agent” section configures on which nodes the pipeline can be run. Specifying “agent any” means that Jenkins will run the job on any of the available nodes.
Setting agent none
at the top level, then agent { label 'foo' }
on every stage, with agent none
again on the input
stage seems to work as expected for me.
i.e. Every stage that does some work runs on the same agent, while the input
stage does not consume an executor on any agent.
pipeline { agent none stages { stage("Prepare build") { agent { label 'some-agent' } steps { echo "prepare: ${pwd()}" } } stage("Build") { agent { label 'some-agent' } steps { parallel( frontend: { echo "frontend: ${pwd()}" }, backend: { echo "backend: ${pwd()}" } ) } } stage("Test") { agent { label 'some-agent' } steps { parallel( jslint: { echo "jslint: ${pwd()}" }, phpcs: { echo "phpcs: ${pwd()}" }, ) } } stage("Select deploy target") { agent none steps { input message: 'Deploy?' } } stage("Deploy") { agent { label 'some-agent' } steps { echo "deploy: ${pwd()}" } } } }
However, there are no guarantee that using the same agent label within a Pipeline will always end up using the same workspace, e.g. as another build of the same job while the first build is waiting on the input
.
You would have to use stash
after the build steps. As you note, this cannot be done normally with parallel
at the moment, so you'd have to additionally use a script
block, in order to write a snippet of Scripted Pipeline for the stashing/unstashing after/before the parallel steps.
There is a workaround to use the same build slave in the other stages. You can set a variable with the node name and use it in the others.
ie:
pipeline { agent none stages { stage('First Stage Gets Agent Dynamically') { agent { node { label "some-agent" } } steps { echo "first stage running on ${NODE_NAME}" script { BUILD_AGENT = NODE_NAME } } } stage('Second Stage Setting Node by Name') { agent { node { label "${BUILD_AGENT}" } } steps { echo "Second stage using ${NODE_NAME}" } } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With