Extracting an entire Jenkins stage to a shared library?











up vote
2
down vote

favorite












Is it possible to take an entire stage('foo') {...} definition and extract it into a shared library within Jenkins? The docs are very clear on how to pull an individual step out, but I can't find any way to take an entire stage, parameterize it, and re-use it globally. I thought perhaps just return stage... would work, but it errors out as an invalid return value.










share|improve this question




























    up vote
    2
    down vote

    favorite












    Is it possible to take an entire stage('foo') {...} definition and extract it into a shared library within Jenkins? The docs are very clear on how to pull an individual step out, but I can't find any way to take an entire stage, parameterize it, and re-use it globally. I thought perhaps just return stage... would work, but it errors out as an invalid return value.










    share|improve this question


























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      Is it possible to take an entire stage('foo') {...} definition and extract it into a shared library within Jenkins? The docs are very clear on how to pull an individual step out, but I can't find any way to take an entire stage, parameterize it, and re-use it globally. I thought perhaps just return stage... would work, but it errors out as an invalid return value.










      share|improve this question















      Is it possible to take an entire stage('foo') {...} definition and extract it into a shared library within Jenkins? The docs are very clear on how to pull an individual step out, but I can't find any way to take an entire stage, parameterize it, and re-use it globally. I thought perhaps just return stage... would work, but it errors out as an invalid return value.







      jenkins groovy jenkins-pipeline






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 8 at 8:51









      Szymon Stepniak

      16.2k83061




      16.2k83061










      asked Nov 8 at 4:42









      XeroxDucati

      3,22512355




      3,22512355
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          It depends if you use scripted or declarative pipeline.



          Scripted pipeline is more flexible and it allows you e.g. create stages based on some conditions (each pipeline run can have a different number and kind of stages). In this kind of pipeline you can extract a full stage to the shared library class and it inside the node {} block. Consider following example:



          // src/ScriptedFooStage.groovy
          class ScriptedFooStage {
          private final Script script

          ScriptedFooStage(Script script) {
          this.script = script
          }

          // You can pass as many parameters as needed
          void execute(String name, boolean param1) {
          script.stage(name) {
          script.echo "Triggering ${name} stage..."
          script.sh "echo 'Execute your desired bash command here'"

          if (param1) {
          script.sh "echo 'Executing conditional command, because param1 == true'"
          }
          }
          }
          }


          Then the Jenkinsfile may look like this:



          node {
          new ScriptedFooStage(this).execute('Foo', true)
          }


          As you can see the whole stage was encapsulated in the ScriptedFooStage.execute() method. Its name is also taken from the parameter name - scripted pipeline allows you doing such thing.





          Declarative pipeline on the other hand is more strict and opinionated. It's fixed if it comes to the number of stages and their names (you can't model dynamically what stages are present per build and what are their names). You can still take advantage of shared library classes, but you are limited to execute them inside script {} block inside stage('Name') { steps {} } block. It means that you can't extract the whole stage to the separate class, but only some part that gets executed at the steps level. Consider following example:



          // src/DeclarativeFooStage.groovy
          class DeclarativeFooStage {
          private final Script script

          DeclarativeFooStage(Script script) {
          this.script = script
          }

          // You can pass as many parameters as needed
          void execute(String name, boolean param1) {
          script.echo "Triggering script with name == ${name}"
          script.sh "echo 'Execute your desired bash command here'"

          if (param1) {
          script.sh "echo 'Executing conditional command, because param1 == true'"
          }
          }
          }


          And the Jenkinsfile may look like this:



          // Jenkinsfile
          pipeline {
          agent any

          stages {
          stage('Foo') {
          steps {
          script {
          new DeclarativeFooStage(this).execute('something', false)
          }
          }
          }
          }
          }


          If we would try execute new DeclarativeFooStage(this).execute('something', false) outside script {} block in the declarative pipeline we would get compilation errors.



          Conclusion



          The choice between scripted or declarative pipeline depends on specific use case. If you want to get the best flexibility when it comes to modeling your pipeline business logic, scripted pipeline might be the good choice. However, it comes with some price. For instance, scripted pipeline does not support restarting pipeline build from specific stage - this is supported only by declarative pipeline. (Imagine you have 10 stages in the pipeline and stage 7 failed because of some silly mistake and you would like to restart the build from 7th stage - in scripted pipeline you would have to re-run from the very beginning, while declarative pipeline can restart from 7th stage by remembering the results from all 6 previous stages).






          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53201656%2fextracting-an-entire-jenkins-stage-to-a-shared-library%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote



            accepted










            It depends if you use scripted or declarative pipeline.



            Scripted pipeline is more flexible and it allows you e.g. create stages based on some conditions (each pipeline run can have a different number and kind of stages). In this kind of pipeline you can extract a full stage to the shared library class and it inside the node {} block. Consider following example:



            // src/ScriptedFooStage.groovy
            class ScriptedFooStage {
            private final Script script

            ScriptedFooStage(Script script) {
            this.script = script
            }

            // You can pass as many parameters as needed
            void execute(String name, boolean param1) {
            script.stage(name) {
            script.echo "Triggering ${name} stage..."
            script.sh "echo 'Execute your desired bash command here'"

            if (param1) {
            script.sh "echo 'Executing conditional command, because param1 == true'"
            }
            }
            }
            }


            Then the Jenkinsfile may look like this:



            node {
            new ScriptedFooStage(this).execute('Foo', true)
            }


            As you can see the whole stage was encapsulated in the ScriptedFooStage.execute() method. Its name is also taken from the parameter name - scripted pipeline allows you doing such thing.





            Declarative pipeline on the other hand is more strict and opinionated. It's fixed if it comes to the number of stages and their names (you can't model dynamically what stages are present per build and what are their names). You can still take advantage of shared library classes, but you are limited to execute them inside script {} block inside stage('Name') { steps {} } block. It means that you can't extract the whole stage to the separate class, but only some part that gets executed at the steps level. Consider following example:



            // src/DeclarativeFooStage.groovy
            class DeclarativeFooStage {
            private final Script script

            DeclarativeFooStage(Script script) {
            this.script = script
            }

            // You can pass as many parameters as needed
            void execute(String name, boolean param1) {
            script.echo "Triggering script with name == ${name}"
            script.sh "echo 'Execute your desired bash command here'"

            if (param1) {
            script.sh "echo 'Executing conditional command, because param1 == true'"
            }
            }
            }


            And the Jenkinsfile may look like this:



            // Jenkinsfile
            pipeline {
            agent any

            stages {
            stage('Foo') {
            steps {
            script {
            new DeclarativeFooStage(this).execute('something', false)
            }
            }
            }
            }
            }


            If we would try execute new DeclarativeFooStage(this).execute('something', false) outside script {} block in the declarative pipeline we would get compilation errors.



            Conclusion



            The choice between scripted or declarative pipeline depends on specific use case. If you want to get the best flexibility when it comes to modeling your pipeline business logic, scripted pipeline might be the good choice. However, it comes with some price. For instance, scripted pipeline does not support restarting pipeline build from specific stage - this is supported only by declarative pipeline. (Imagine you have 10 stages in the pipeline and stage 7 failed because of some silly mistake and you would like to restart the build from 7th stage - in scripted pipeline you would have to re-run from the very beginning, while declarative pipeline can restart from 7th stage by remembering the results from all 6 previous stages).






            share|improve this answer

























              up vote
              1
              down vote



              accepted










              It depends if you use scripted or declarative pipeline.



              Scripted pipeline is more flexible and it allows you e.g. create stages based on some conditions (each pipeline run can have a different number and kind of stages). In this kind of pipeline you can extract a full stage to the shared library class and it inside the node {} block. Consider following example:



              // src/ScriptedFooStage.groovy
              class ScriptedFooStage {
              private final Script script

              ScriptedFooStage(Script script) {
              this.script = script
              }

              // You can pass as many parameters as needed
              void execute(String name, boolean param1) {
              script.stage(name) {
              script.echo "Triggering ${name} stage..."
              script.sh "echo 'Execute your desired bash command here'"

              if (param1) {
              script.sh "echo 'Executing conditional command, because param1 == true'"
              }
              }
              }
              }


              Then the Jenkinsfile may look like this:



              node {
              new ScriptedFooStage(this).execute('Foo', true)
              }


              As you can see the whole stage was encapsulated in the ScriptedFooStage.execute() method. Its name is also taken from the parameter name - scripted pipeline allows you doing such thing.





              Declarative pipeline on the other hand is more strict and opinionated. It's fixed if it comes to the number of stages and their names (you can't model dynamically what stages are present per build and what are their names). You can still take advantage of shared library classes, but you are limited to execute them inside script {} block inside stage('Name') { steps {} } block. It means that you can't extract the whole stage to the separate class, but only some part that gets executed at the steps level. Consider following example:



              // src/DeclarativeFooStage.groovy
              class DeclarativeFooStage {
              private final Script script

              DeclarativeFooStage(Script script) {
              this.script = script
              }

              // You can pass as many parameters as needed
              void execute(String name, boolean param1) {
              script.echo "Triggering script with name == ${name}"
              script.sh "echo 'Execute your desired bash command here'"

              if (param1) {
              script.sh "echo 'Executing conditional command, because param1 == true'"
              }
              }
              }


              And the Jenkinsfile may look like this:



              // Jenkinsfile
              pipeline {
              agent any

              stages {
              stage('Foo') {
              steps {
              script {
              new DeclarativeFooStage(this).execute('something', false)
              }
              }
              }
              }
              }


              If we would try execute new DeclarativeFooStage(this).execute('something', false) outside script {} block in the declarative pipeline we would get compilation errors.



              Conclusion



              The choice between scripted or declarative pipeline depends on specific use case. If you want to get the best flexibility when it comes to modeling your pipeline business logic, scripted pipeline might be the good choice. However, it comes with some price. For instance, scripted pipeline does not support restarting pipeline build from specific stage - this is supported only by declarative pipeline. (Imagine you have 10 stages in the pipeline and stage 7 failed because of some silly mistake and you would like to restart the build from 7th stage - in scripted pipeline you would have to re-run from the very beginning, while declarative pipeline can restart from 7th stage by remembering the results from all 6 previous stages).






              share|improve this answer























                up vote
                1
                down vote



                accepted







                up vote
                1
                down vote



                accepted






                It depends if you use scripted or declarative pipeline.



                Scripted pipeline is more flexible and it allows you e.g. create stages based on some conditions (each pipeline run can have a different number and kind of stages). In this kind of pipeline you can extract a full stage to the shared library class and it inside the node {} block. Consider following example:



                // src/ScriptedFooStage.groovy
                class ScriptedFooStage {
                private final Script script

                ScriptedFooStage(Script script) {
                this.script = script
                }

                // You can pass as many parameters as needed
                void execute(String name, boolean param1) {
                script.stage(name) {
                script.echo "Triggering ${name} stage..."
                script.sh "echo 'Execute your desired bash command here'"

                if (param1) {
                script.sh "echo 'Executing conditional command, because param1 == true'"
                }
                }
                }
                }


                Then the Jenkinsfile may look like this:



                node {
                new ScriptedFooStage(this).execute('Foo', true)
                }


                As you can see the whole stage was encapsulated in the ScriptedFooStage.execute() method. Its name is also taken from the parameter name - scripted pipeline allows you doing such thing.





                Declarative pipeline on the other hand is more strict and opinionated. It's fixed if it comes to the number of stages and their names (you can't model dynamically what stages are present per build and what are their names). You can still take advantage of shared library classes, but you are limited to execute them inside script {} block inside stage('Name') { steps {} } block. It means that you can't extract the whole stage to the separate class, but only some part that gets executed at the steps level. Consider following example:



                // src/DeclarativeFooStage.groovy
                class DeclarativeFooStage {
                private final Script script

                DeclarativeFooStage(Script script) {
                this.script = script
                }

                // You can pass as many parameters as needed
                void execute(String name, boolean param1) {
                script.echo "Triggering script with name == ${name}"
                script.sh "echo 'Execute your desired bash command here'"

                if (param1) {
                script.sh "echo 'Executing conditional command, because param1 == true'"
                }
                }
                }


                And the Jenkinsfile may look like this:



                // Jenkinsfile
                pipeline {
                agent any

                stages {
                stage('Foo') {
                steps {
                script {
                new DeclarativeFooStage(this).execute('something', false)
                }
                }
                }
                }
                }


                If we would try execute new DeclarativeFooStage(this).execute('something', false) outside script {} block in the declarative pipeline we would get compilation errors.



                Conclusion



                The choice between scripted or declarative pipeline depends on specific use case. If you want to get the best flexibility when it comes to modeling your pipeline business logic, scripted pipeline might be the good choice. However, it comes with some price. For instance, scripted pipeline does not support restarting pipeline build from specific stage - this is supported only by declarative pipeline. (Imagine you have 10 stages in the pipeline and stage 7 failed because of some silly mistake and you would like to restart the build from 7th stage - in scripted pipeline you would have to re-run from the very beginning, while declarative pipeline can restart from 7th stage by remembering the results from all 6 previous stages).






                share|improve this answer












                It depends if you use scripted or declarative pipeline.



                Scripted pipeline is more flexible and it allows you e.g. create stages based on some conditions (each pipeline run can have a different number and kind of stages). In this kind of pipeline you can extract a full stage to the shared library class and it inside the node {} block. Consider following example:



                // src/ScriptedFooStage.groovy
                class ScriptedFooStage {
                private final Script script

                ScriptedFooStage(Script script) {
                this.script = script
                }

                // You can pass as many parameters as needed
                void execute(String name, boolean param1) {
                script.stage(name) {
                script.echo "Triggering ${name} stage..."
                script.sh "echo 'Execute your desired bash command here'"

                if (param1) {
                script.sh "echo 'Executing conditional command, because param1 == true'"
                }
                }
                }
                }


                Then the Jenkinsfile may look like this:



                node {
                new ScriptedFooStage(this).execute('Foo', true)
                }


                As you can see the whole stage was encapsulated in the ScriptedFooStage.execute() method. Its name is also taken from the parameter name - scripted pipeline allows you doing such thing.





                Declarative pipeline on the other hand is more strict and opinionated. It's fixed if it comes to the number of stages and their names (you can't model dynamically what stages are present per build and what are their names). You can still take advantage of shared library classes, but you are limited to execute them inside script {} block inside stage('Name') { steps {} } block. It means that you can't extract the whole stage to the separate class, but only some part that gets executed at the steps level. Consider following example:



                // src/DeclarativeFooStage.groovy
                class DeclarativeFooStage {
                private final Script script

                DeclarativeFooStage(Script script) {
                this.script = script
                }

                // You can pass as many parameters as needed
                void execute(String name, boolean param1) {
                script.echo "Triggering script with name == ${name}"
                script.sh "echo 'Execute your desired bash command here'"

                if (param1) {
                script.sh "echo 'Executing conditional command, because param1 == true'"
                }
                }
                }


                And the Jenkinsfile may look like this:



                // Jenkinsfile
                pipeline {
                agent any

                stages {
                stage('Foo') {
                steps {
                script {
                new DeclarativeFooStage(this).execute('something', false)
                }
                }
                }
                }
                }


                If we would try execute new DeclarativeFooStage(this).execute('something', false) outside script {} block in the declarative pipeline we would get compilation errors.



                Conclusion



                The choice between scripted or declarative pipeline depends on specific use case. If you want to get the best flexibility when it comes to modeling your pipeline business logic, scripted pipeline might be the good choice. However, it comes with some price. For instance, scripted pipeline does not support restarting pipeline build from specific stage - this is supported only by declarative pipeline. (Imagine you have 10 stages in the pipeline and stage 7 failed because of some silly mistake and you would like to restart the build from 7th stage - in scripted pipeline you would have to re-run from the very beginning, while declarative pipeline can restart from 7th stage by remembering the results from all 6 previous stages).







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 8 at 8:44









                Szymon Stepniak

                16.2k83061




                16.2k83061






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53201656%2fextracting-an-entire-jenkins-stage-to-a-shared-library%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    這個網誌中的熱門文章

                    Tangent Lines Diagram Along Smooth Curve

                    Yusuf al-Mu'taman ibn Hud

                    Zucchini