{"id":2699,"date":"2018-08-02T12:07:15","date_gmt":"2018-08-02T11:07:15","guid":{"rendered":"http:\/\/www.xenonique.co.uk\/blog\/?p=2699"},"modified":"2018-08-02T12:07:15","modified_gmt":"2018-08-02T11:07:15","slug":"hot-shot-008-jenkins-pipelines","status":"publish","type":"post","link":"https:\/\/www.xenonique.co.uk\/blog\/2018\/08\/02\/hot-shot-008-jenkins-pipelines\/","title":{"rendered":"Hot shot 008 &#8211;  Jenkins Pipelines"},"content":{"rendered":"<p>This are my verbatim notes to the PEAT UK podcast:<\/p>\n<p> &nbsp; <\/p>\n<p> &nbsp; <\/p>\n<p>Hello there once again to another hot shot. My name is Peter Pilgrim, platform engineer and DevOps specialist, and Java Champion.<\/p>\n<p> &nbsp; <\/p>\n<p> &nbsp; <\/p>\n<p>As DevOps engineer, you probably already heard of Jenkins and continuous integration.<\/p>\n<p>Jenkins was originally an open source  project called Hudson, which was created by a former Sun Microsystems engineer: <a href=\"https:\/\/en.wikipedia.org\/wiki\/Kohsuke_Kawaguchi\"><strong>Kohsuke Kawaguchi<\/strong><\/a>. He started a hobby project under the name of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hudson_(software)\">Hudson<\/a>, in 2004. It was one of those pet projects that became officially sanctioned and adopted by Kawaguchi\u2019s boss and also his employer. <\/p>\n<p>When Oracle bought Sun Microsystems, and they also took stewardship of the Java brand. It was then that issue with intellectual property rights and inventions of employer\u2019s  in 2010, since started to go awry. Oracle claimed right to the name and applied for a trademark. Community in 2011 disagreed with this approach, voted decisively to rename the project <a href=\"https:\/\/en.wikipedia.org\/wiki\/Jenkins_(software)\"><strong>Jenkins<\/strong><\/a>. Hudson became a fork of Jenkins. In the meantime, Kawaguchi left Oracle and started his business.* <\/p>\n<p> &nbsp; <\/p>\n<p> &nbsp; <\/p>\n<p><iframe loading=\"lazy\" width=\"100%\" height=\"300\" scrolling=\"no\" frameborder=\"no\" allow=\"autoplay\" src=\"https:\/\/w.soundcloud.com\/player\/?url=https%3A\/\/api.soundcloud.com\/tracks\/478587909&#038;color=%23ff5500&#038;auto_play=false&#038;hide_related=false&#038;show_comments=true&#038;show_user=true&#038;show_reposts=false&#038;show_teaser=true&#038;visual=true\"><\/iframe><\/p>\n<p> &nbsp; <\/p>\n<p> &nbsp; <\/p>\n<p>Today, Jenkins is the most successfully open source continuous integration in the software developer community. It runs off JVM,  it can be launched standalone as JAR, because it embeds Apache Tomcat, when I last checked, which was sometime ago. Jenkins can also be deployed as a WAR file to an Java EE application server such as WildFly, Liberty or Payara. <\/p>\n<p>Because Jenkins has this flexible to launch as a standalone JAR, it was one of the first Uber JAR out there, DevOps people can chuck into a Docker container image. <\/p>\n<p>Jenkins can also to be deployed to AWS EC2 instance, but that is another story. <\/p>\n<p>In this episode, I am going to talk about Jenkins pipelines.<\/p>\n<p>In the field of continuous integration, when we talk about a pipeline, we define a workflow that instructs an engine how to retrieve some code from a remote source code repository, how to build and assemble this code, how to test the assembly and finally delivery it to an environment.<\/p>\n<p>In Jenkins, pipelines are essentially a Groovy DSL (domain specific language). The code looks like a scripting language. A pipeline can be attached one or more Jenkins jobs. <\/p>\n<p>A Jenkins job, therefore, can be standardised. <\/p>\n<p>All your microservices can be build against a standard Jenkins pipeline. For DevOps and Platform engineer we love this feature alot. <\/p>\n<p>There is one single source of truth &#8211; infrastructure as code<br \/>\nThe pipeline is coded and therefore it is flexible. We can program how it behaves.<br \/>\nIt is durable, pausable, versatile and extensible.<br \/>\nBest of all, Jenkins, allows a pipeline to be pulled from a Git repository. <\/p>\n<p>There are two types of pipelines within Jenkins: declarative and scripted pipeline syntax.<\/p>\n<p>Declarative pipelines are suited if your infrastructure targets particular agents. The Declarative DSL limit what you can program with Grocy. You use the pipeline keyword block in the DSL syntax to specify location the entire workflow. An agent might be a particular Docker stage. <\/p>\n<p>Scripted pipelines are build with the node DSL block, which means the workflow is scheduled to a separate Jenkins executor. Scripted pipeline You can think of this a work tasks being pushed one by one onto a queue and then another process executing the task in sequence or in parallel. The Scripted pipeline allow more flexible use of the underlying Groovy programming language, so you use if \/ then \/else and also incorporate try \/ catch \/ finally and call more standard Groovy SDK functions. <\/p>\n<p>Whether declarative or scripted pipeline, each workflow is defined into stages. Stage as individually named block that perform some task. You might have three classic stages in your pipeline such \u201cbuild\u201d, \u201ctest\u201d and \u201cdeploy\u201d. Both scripted and declarative allow DSL to invoked Shared Libraries. <\/p>\n<p>See the code examples in the accompanying blog article.<\/p>\n<p>This is code for the Declarative Pipeline<\/p>\n<pre class=\"brush: groovy; title: ; notranslate\" title=\"\">\r\npipeline { \r\n    agent any \r\n    stages {\r\n        stage('Build') { \r\n            steps { \r\n                sh '.\/gradlew clean assemble' \r\n            }\r\n        }\r\n        stage('Test'){\r\n            steps {\r\n                sh '.\/gradlew test'\r\n                junit 'reports\/**\/*.xml' \r\n            }\r\n        }\r\n        stage('Deploy') {\r\n            steps {\r\n                sh '.\/gradlew deploy'\r\n            }\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>This is code for the Scripted Pipeline<\/p>\n<pre class=\"brush: groovy; title: ; notranslate\" title=\"\">\r\nnode { \r\n    stages {\r\n        stage('Build') { \r\n            steps { \r\n                sh '.\/gradlew clean assemble' \r\n            }\r\n        }\r\n        stage('Test'){\r\n            steps {\r\n                sh '.\/gradlew test'\r\n                junit 'reports\/**\/*.xml' \r\n            }\r\n        }\r\n        stage('Deploy') {\r\n            steps {\r\n                sh '.\/gradlew deploy'\r\n            }\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>You can also have more stages for code quality. As a DevOps engineer, surely, you would throw in \u201cpmd\u201d or \u201csonarqube\u201d, \u201csmoke\u201d, \u201cdeploy artifact\u201d and \u201cdeploy environment\u201d stages.<\/p>\n<p>One nice feature of Jenkins, it is great to put the devops pipeline inside a shared library.<\/p>\n<p>That\u2019s all we have for know. I will stop here. Bye for now. <\/p>\n<p> &nbsp; <\/p>\n<p>+PP+<br \/>\nJuly 2018<\/p>\n<p> &nbsp; <\/p>\n<p> &nbsp; <\/p>\n<p>Feedback on social media with shares, comments are likes all appreciated. The more the better as they say.<\/p>\n<p> &nbsp; <\/p>\n<p> &nbsp; <\/p>\n<p>Here is an advanced example, <\/p>\n<pre class=\"brush: groovy; title: ; notranslate\" title=\"\">\r\nimport hudson.FilePath;\r\nimport jenkins.model.Jenkins;\r\n\r\ndef call(body) {\r\n    def config = [:]\r\n    body.resolveStrategy = Closure.DELEGATE_FIRST\r\n    body.delegate = config\r\n    body()\r\n\r\n    node ('GradleBuild'){\r\n        \/\/ Clean workspace before doing anything\r\n        deleteDir()\r\n\r\n        stage('Clone') {\r\n            echo &quot;checking out git repo&quot;\r\n            dir('source_dir') {\r\n                checkout scm\r\n            }\r\n        }\r\n        stage('Conditional Debug') {\r\n            if (config.pausePipeline == true) {\r\n                echo &quot;pausing the pipeline (15 minutes) in order to debug the execution inside a Kubernetes pod!&quot;\r\n                dir('source_dir') {\r\n                    sh &quot;sleep 1200&quot;\r\n                }\r\n                echo &quot;Ending pause&quot;\r\n            }\r\n        }\r\n        stage('Build') {\r\n        try {\r\n            dir('source_dir') {\r\n                sh &quot;.\/gradlew clean assemble&quot;\r\n            }\r\n           }\r\n          catch (exc) {\r\n              echo 'Build Failed.Please check the Jenkins Logs'\r\n              sendFailureNotification()\r\n            }\r\n          }          \r\n        stage ('UnitTests') {\r\n            if (config.includeUnittests == true) {\r\n                try {\r\n                    dir('source_dir') {\r\n                        sh &quot;.\/gradlew test --stacktrace --info --no-daemon --max-workers 5&quot;\r\n                    }\r\n                }\r\n                catch (exc) {\r\n                    echo 'Test Failed. Please check the Jenkins Logs'\r\n                    sendFailureNotification()\r\n                }\r\n            }\r\n        }\r\n        stage('SonarQube') {\r\n            if (config.includeSonarqube == true) {\r\n              try {\r\n                dir('source_dir') {\r\n                    sh &quot;.\/gradlew sonarqube&quot;\r\n                }\r\n              }\r\n              catch (exc) {\r\n                  echo 'Sonar Failed. Please check the Jenkins Logs'\r\n                  sendFailureNotification()\r\n                }\r\n            }\r\n        }\r\n        . . .\r\n    }\r\n}\r\n\r\n def sendFailureNotification() {\r\n    emailext (\r\n        replyTo: 'devops-lead@acme.com',\r\n        to: peter.pilgrim@acme.com',\r\n        subject: &quot;FAILED: BUILD Number : ${env.BUILD_NUMBER} - Jenkins Job : ${env.JOB_NAME}&quot;,\r\n        body: &quot;&quot;&quot;&amp;lt;p&amp;gt;FAILED: BUILD Number : ${env.BUILD_NUMBER} - Jenkins Job : ${env.JOB_NAME}&amp;lt;\/p&amp;gt;\r\n        &amp;lt;p&amp;gt; View Jenkins console output at &quot;&amp;lt;a href=&quot;${env.BUILD_URL}&quot;&amp;gt;${env.JOB_NAME} [${env.BUILD_NUMBER}]&amp;lt;\/a&amp;gt;&quot;&amp;lt;\/p&amp;gt;&quot;&quot;&quot;\r\n      )\r\n  }\r\n<\/pre>\n<p> &nbsp; <\/p>\n<p> &nbsp; <\/p>\n<p>References<\/p>\n<p><a href=\"https:\/\/jenkins.io\/doc\/book\/pipeline\/\">https:\/\/jenkins.io\/doc\/book\/pipeline\/ <\/a><\/p>\n<p><a href=\"https:\/\/jenkins.io\/doc\/book\/pipeline\/syntax\/\">https:\/\/jenkins.io\/doc\/book\/pipeline\/syntax\/ <\/a><\/p>\n<p><a href=\"https:\/\/jenkins.io\/doc\/book\/pipeline\/shared-libraries\/\">https:\/\/jenkins.io\/doc\/book\/pipeline\/shared-libraries\/ <\/a><\/p>\n<p>*I although I don\u2019t vocally state in the podcast For the record, I have never taken any side and I am not taking sides in the issue between Oracle and Kawaguchi regarding Hudson vs Jenkins<\/p>\n<p> &nbsp; <\/p>\n<p> &nbsp; <\/p>\n","protected":false},"excerpt":{"rendered":"<p>This are my verbatim notes to the PEAT UK podcast: &nbsp; &nbsp; Hello there once again to another hot shot. My name is Peter Pilgrim, platform engineer and DevOps specialist, and Java Champion. &nbsp; &nbsp; As DevOps engineer, you probably already heard of Jenkins and continuous integration. Jenkins was originally an open source project called [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[201,208,133,4,200,195],"tags":[],"_links":{"self":[{"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2699"}],"collection":[{"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=2699"}],"version-history":[{"count":5,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2699\/revisions"}],"predecessor-version":[{"id":2704,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2699\/revisions\/2704"}],"wp:attachment":[{"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=2699"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=2699"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xenonique.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=2699"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}