{"id":660,"date":"2019-10-21T15:09:40","date_gmt":"2019-10-21T19:09:40","guid":{"rendered":"https:\/\/crossan007.dev\/blog\/?p=660"},"modified":"2019-10-21T15:09:40","modified_gmt":"2019-10-21T19:09:40","slug":"override-jenkins-stage-function","status":"publish","type":"post","link":"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/","title":{"rendered":"Override Jenkins stage Function"},"content":{"rendered":"\n<div class=\"twitter-share\"><a href=\"https:\/\/twitter.com\/intent\/tweet?via=crossan007\" class=\"twitter-share-button\">Tweet<\/a><\/div>\n\n<p>Recently, I needed a mechanism to identify, as part of a try\/catch block, which stage in a Jenkins Groovy Scripted Pipeline was the last to execute <em>before<\/em> the catch block was called.<\/p>\n\n\n\n<p>Jenkins does not currently store details about the last stage to run <em>outside of the context of that specific stage<\/em>.  So, in other words <code>env.STAGE_NAME<\/code> is valid with a particular <code>stage(\"I'm a stage\"){ \/\/valid here} <\/code> block, but not in, say, a <code>catch(Exception e) { \/\/ where was I called from? }<\/code> block.<\/p>\n\n\n\n<p>To get around this, I found a few examples, and cobbled together something that I believe will provide future functionality.   I present to you the <code>extensibleContextStage<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/\/ Jenkins groovy stages are somewhat lacking in their ability to persist \n\/\/ context state beyond the lifespan of the stage\n\/\/ For example, to obtain the name of the last stage to run, \n\/\/ one needs to store the name in an ENV varialble (JENKINS 48315)\n\/\/ https:\/\/issues.jenkins-ci.org\/browse\/JENKINS-48315\n\n\/\/ We can create an extensible stage to provide attitional context to the pipeline\n\/\/ about the state of the currently running stage.\n\n\/\/ This also provides a capability to extend pre- and post- stage operations\n\n\/\/ Idea \/ base code borrowed from https:\/\/stackoverflow.com\/a\/51081177\/11125318\n\/\/ and from https:\/\/issues.jenkins-ci.org\/browse\/JENKINS-48315?focusedCommentId=321366&amp;page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-321366\n\ndef call(name, Closure closure) {\n    env.BUILD_LAST_STAGE_STARTED = name\n    try {\n        stage(name) {\n            def result = closure.call()\n            return result\n        }\n        env.BUILD_LAST_STAGE_SUCCEEDED = name\n    }\n    catch(Exception ex) {\n        env.BUILD_LAST_STAGE_FAILED = name\n        throw ex;\n    }\n}\n\n<\/pre><\/div>\n\n\n<p>This is a drop-in replacement for <code>stage(string name){ closure}<\/code> blocks in a Jenkins Groovy Scripted Pipeline, but with the added benefit of additional environment variables:<\/p>\n\n\n\n<ul><li>env.BUILD_LAST_STAGE_STARTED<\/li><li>env.BUILD_LAST_STAGE_SUCCEEDED<\/li><li>env.BUILD_LAST_STAGE_FAILED<\/li><\/ul>\n\n\n\n<p>So, as a full example, one can now do this (which was previously awkward):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\ntry {\n    extensibleContextStage(&quot;Do some things&quot;)\n    {\n        \/\/whatever\n    }\n    extensibleContextStage(&quot;Do some More things&quot;)\n    {\n       throw new Exception(&quot;MAYHEM!&quot;)\n    }\n    extensibleContextStage(&quot;Do some final things&quot;)\n    {\n        \/\/whatever\n    }\n}\ncatch(Exception e){\n    \/\/ at this point, with normal stage, we wouldn't know where MAYHEM came from,\n    \/\/ but with extensibleContextStage, we can look at either\n    \/\/ env.BUILD_LAST_STAGE_FAILED or  env.BUILD_LAST_STAGE_STARTED\n    \/\/ to know that &quot;Do some More things&quot; was the offendign stage.\n    \/\/ this is super handy to send &quot;helpful&quot; notifications to slack\/email\n}\n<\/pre><\/div>\n\n\n<p>I hope this helps someone (if even my future self)<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently, I needed a mechanism to identify, as part of a try\/catch block, which stage in a Jenkins Groovy Scripted Pipeline was the last to execute before the catch block was called. Jenkins does not currently store details about the last stage to run outside of the context of that specific stage. So, in other &hellip; <a href=\"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Override Jenkins stage Function<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[260,232,234,231,236],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v17.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Override Jenkins stage Function - Charles&#039; Blog\" \/>\n<meta property=\"og:description\" content=\"Recently, I needed a mechanism to identify, as part of a try\/catch block, which stage in a Jenkins Groovy Scripted Pipeline was the last to execute before the catch block was called. Jenkins does not currently store details about the last stage to run outside of the context of that specific stage. So, in other &hellip; Continue reading Override Jenkins stage Function &rarr;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/\" \/>\n<meta property=\"og:site_name\" content=\"Charles&#039; Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-10-21T19:09:40+00:00\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"crossan007\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/crossan007.dev\/blog\/#website\",\"url\":\"https:\/\/crossan007.dev\/blog\/\",\"name\":\"Charles&#039; Blog\",\"description\":\"SharePoint | PowerShell | Exchange | SCCM | Ubuntu | PHP | JavaScript | A\/V Live Production | More...\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/crossan007.dev\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/#webpage\",\"url\":\"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/\",\"name\":\"Override Jenkins stage Function - Charles&#039; Blog\",\"isPartOf\":{\"@id\":\"https:\/\/crossan007.dev\/blog\/#website\"},\"datePublished\":\"2019-10-21T19:09:40+00:00\",\"dateModified\":\"2019-10-21T19:09:40+00:00\",\"author\":{\"@id\":\"https:\/\/crossan007.dev\/blog\/#\/schema\/person\/bd99569cd81332c8fd866d023848b979\"},\"breadcrumb\":{\"@id\":\"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/crossan007.dev\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Override Jenkins stage Function\"}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/crossan007.dev\/blog\/#\/schema\/person\/bd99569cd81332c8fd866d023848b979\",\"name\":\"crossan007\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/crossan007.dev\/blog\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/fff72c74fb6a0da29accf0db83ad4b4b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/fff72c74fb6a0da29accf0db83ad4b4b?s=96&d=mm&r=g\",\"caption\":\"crossan007\"},\"url\":\"https:\/\/crossan007.dev\/blog\/author\/crossan007\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/","og_locale":"en_US","og_type":"article","og_title":"Override Jenkins stage Function - Charles&#039; Blog","og_description":"Recently, I needed a mechanism to identify, as part of a try\/catch block, which stage in a Jenkins Groovy Scripted Pipeline was the last to execute before the catch block was called. Jenkins does not currently store details about the last stage to run outside of the context of that specific stage. So, in other &hellip; Continue reading Override Jenkins stage Function &rarr;","og_url":"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/","og_site_name":"Charles&#039; Blog","article_published_time":"2019-10-21T19:09:40+00:00","twitter_misc":{"Written by":"crossan007","Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebSite","@id":"https:\/\/crossan007.dev\/blog\/#website","url":"https:\/\/crossan007.dev\/blog\/","name":"Charles&#039; Blog","description":"SharePoint | PowerShell | Exchange | SCCM | Ubuntu | PHP | JavaScript | A\/V Live Production | More...","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/crossan007.dev\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/#webpage","url":"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/","name":"Override Jenkins stage Function - Charles&#039; Blog","isPartOf":{"@id":"https:\/\/crossan007.dev\/blog\/#website"},"datePublished":"2019-10-21T19:09:40+00:00","dateModified":"2019-10-21T19:09:40+00:00","author":{"@id":"https:\/\/crossan007.dev\/blog\/#\/schema\/person\/bd99569cd81332c8fd866d023848b979"},"breadcrumb":{"@id":"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/crossan007.dev\/blog\/uncategorized\/override-jenkins-stage-function\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/crossan007.dev\/blog\/"},{"@type":"ListItem","position":2,"name":"Override Jenkins stage Function"}]},{"@type":"Person","@id":"https:\/\/crossan007.dev\/blog\/#\/schema\/person\/bd99569cd81332c8fd866d023848b979","name":"crossan007","image":{"@type":"ImageObject","@id":"https:\/\/crossan007.dev\/blog\/#personlogo","inLanguage":"en-US","url":"https:\/\/secure.gravatar.com\/avatar\/fff72c74fb6a0da29accf0db83ad4b4b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/fff72c74fb6a0da29accf0db83ad4b4b?s=96&d=mm&r=g","caption":"crossan007"},"url":"https:\/\/crossan007.dev\/blog\/author\/crossan007\/"}]}},"_links":{"self":[{"href":"https:\/\/crossan007.dev\/blog\/wp-json\/wp\/v2\/posts\/660"}],"collection":[{"href":"https:\/\/crossan007.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/crossan007.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/crossan007.dev\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/crossan007.dev\/blog\/wp-json\/wp\/v2\/comments?post=660"}],"version-history":[{"count":1,"href":"https:\/\/crossan007.dev\/blog\/wp-json\/wp\/v2\/posts\/660\/revisions"}],"predecessor-version":[{"id":661,"href":"https:\/\/crossan007.dev\/blog\/wp-json\/wp\/v2\/posts\/660\/revisions\/661"}],"wp:attachment":[{"href":"https:\/\/crossan007.dev\/blog\/wp-json\/wp\/v2\/media?parent=660"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/crossan007.dev\/blog\/wp-json\/wp\/v2\/categories?post=660"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/crossan007.dev\/blog\/wp-json\/wp\/v2\/tags?post=660"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}