Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-47179

Can't use milestone with parallel stages in Declarative

      Hello,

      thanks for this  feature - https://jenkins.io/blog/2017/09/25/declarative-1/

      Parallel stages with declarative pipeline.

      We wanted to try parallel, node, milestone together in the particular stage.

      And we tried the below :

      pipeline {
        agent none
        stage('Tests') {
          when { branch 'declarative-pipeline' }
          parallel {
            stage('One') {
              agent any
              steps {
                lock(resource: "${env.JOB_NAME}/10", inversePrecedence: true) {
                  milestone  10
                  node() {
                    deleteDir()
                    execute tests
                  }
                }
              }
            }
          }
        }
      }
      

      but it does not execute this stage and there will be no syntax errors. could you please let me know what is missing in the above example?

      Regards,
      Ashwin

       

       

          [JENKINS-47179] Can't use milestone with parallel stages in Declarative

          Hi Andrew, I replaced the emptyNode. We set the agent on parallel stage level to have an own workspace for each parallel execution. Thus we omitted the top level agent.

          Christopher Fenner added a comment - Hi Andrew, I replaced the emptyNode . We set the agent on parallel stage level to have an own workspace for each parallel execution. Thus we omitted the top level agent.

          The issue here is Using a milestone step inside parallel is not allowed.

          Basically we want to achieve the following behaviour:

          • enter stage
          • wait for lock (LIFO)
          • only proceed if no newer stage has been completed, abort otherwise

          This we do with the lock - milestone combination.

          Christopher Fenner added a comment - The issue here is Using a milestone step inside parallel is not allowed . Basically we want to achieve the following behaviour: enter stage wait for lock (LIFO) only proceed if no newer stage has been completed, abort otherwise This we do with the lock - milestone combination.

          Andrew Bayer added a comment -

          Ah, so the problem is that milestone doesn't work inside parallel - yeah, then it wouldn't work in parallel stages in Declarative either.

          Andrew Bayer added a comment - Ah, so the problem is that milestone doesn't work inside parallel - yeah, then it wouldn't work in parallel stages in Declarative either.

          Before we used it like this in scripted pipelines:

          stage('add. Unit Tests') {
            lock(resource: "${env.JOB_NAME}/20", inversePrecedence: true) {
              milestone 20
              parallel(
                'Test1': {
                  node {
                    deleteDir()
                    execute test
                  }
                }, 'Test2': {
                  node {
                    deleteDir()
                    execute test
                  }
                }, failFast: false
              )
            }
          }
          

          But with declarative this is no longer possible, right?

          Christopher Fenner added a comment - Before we used it like this in scripted pipelines: stage( 'add. Unit Tests' ) { lock(resource: "${env.JOB_NAME}/20" , inversePrecedence: true ) { milestone 20 parallel( 'Test1' : { node { deleteDir() execute test } }, 'Test2' : { node { deleteDir() execute test } }, failFast: false ) } } But with declarative this is no longer possible, right?

          Andrew Bayer added a comment -

          Not using parallel stages, no. Let me think on this.

          Andrew Bayer added a comment - Not using parallel stages, no. Let me think on this.

          Andrew Bayer added a comment -

          Ok, what would be needed here is a way to make the parent stage call milestone and lock before entering the parallel. That's not going to be trivial, so no promises it'll happen. A workaround for you for now would be to have another stage before the one containing parallel that has the milestone, though yeah, that won't work with lock.

          Andrew Bayer added a comment - Ok, what would be needed here is a way to make the parent stage call milestone and lock before entering the parallel . That's not going to be trivial, so no promises it'll happen. A workaround for you for now would be to have another stage before the one containing parallel that has the milestone , though yeah, that won't work with lock .

          Sean MacKay added a comment - - edited

          I'm just bumping up against this as well. I'm trying to set up deployments in a Declarative Pipeline. Really I just need some logic to go "If `develop`, then `DevServer`, if `release/*` then `stagingServer`. Multiple `when` calls don't work in a stage, so I switch to a `parallel` block where each path has a `when` and only one should ever execute. Putting the `milestone` before `parallel` could work (as long as different branches don't cancel each other), but a milestone in each deployment branch would be more ideal. 

          Is there some other way I could structure my "If this branch deploy here" logic to avoid `parallel` altogether?

          edit: Just using a `script` step might be the easiest way to do what I need.

          Sean MacKay added a comment - - edited I'm just bumping up against this as well. I'm trying to set up deployments in a Declarative Pipeline. Really I just need some logic to go "If `develop`, then `DevServer`, if `release/*` then `stagingServer`. Multiple `when` calls don't work in a stage, so I switch to a `parallel` block where each path has a `when` and only one should ever execute. Putting the `milestone` before `parallel` could work (as long as different branches don't cancel each other), but a milestone in each deployment branch would be more ideal.  Is there some other way I could structure my "If this branch deploy here" logic to avoid `parallel` altogether? edit: Just using a `script` step might be the easiest way to do what I need.

          Jonathan Kuleff added a comment - - edited

          Any chance we could do something similar to locks? i.e.

          stage('Parent') {
            options {
              milestone()
            }
            stages {
              stage('first child') {
                options { 
                    milestone() 
                }
                ...
              }
              stage('second child') { {
                options { 
                    milestone() 
                }
                ...
              }
            }
          }
          

          Jonathan Kuleff added a comment - - edited Any chance we could do something similar to locks? i.e. stage( 'Parent' ) { options { milestone() } stages { stage( 'first child' ) { options { milestone() } ... } stage( 'second child' ) { { options { milestone() } ... } } }

          Ashu Goel added a comment - - edited

          Any updates on this one? We have a parallel stage in which we deploy multiple services in their own stages. In each stage, we first prompt the user for input and then proceed to deploy. I'd like to be able to stick a milestone between each input and subsequent deploy:

           

           

          stage("Deploy") {
            parallel {
               stage("Deploy Service 1") {
                steps {
                  waitUntil {
                    script
          {              input "Want to deploy service 1?"              milestone()              echo "Deploying service 1"           }
                 }
               }
              stage("Deploy Service 2") {
                steps {
                  waitUntil {
                    script
          {              input "Want to deploy service 2?"              milestone()              echo "Deploying service 2"           }
                 }
               }
            }
          

           

           

           

          But am receiving the same "Using a milestone step inside parallel is not allowed" error.

           

          Ashu Goel added a comment - - edited Any updates on this one? We have a parallel stage in which we deploy multiple services in their own stages. In each stage, we first prompt the user for input and then proceed to deploy. I'd like to be able to stick a milestone between each input and subsequent deploy:     stage( "Deploy" ) {   parallel {     stage( "Deploy Service 1" ) {       steps {         waitUntil {           script {              input "Want to deploy service 1?"              milestone()              echo "Deploying service 1"           }        }      }     stage( "Deploy Service 2" ) {       steps {         waitUntil {           script {              input "Want to deploy service 2?"              milestone()              echo "Deploying service 2"           }        }      }   }       But am receiving the same "Using a milestone step inside parallel is not allowed" error.  

          +1

          Michael Kroell added a comment - +1

            Unassigned Unassigned
            ashsy_009 Ashwin Y
            Votes:
            11 Vote for this issue
            Watchers:
            17 Start watching this issue

              Created:
              Updated: