github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/src/com/sap/piper/JenkinsUtils.groovy (about) 1 package com.sap.piper 2 3 import com.cloudbees.groovy.cps.NonCPS 4 import hudson.Functions 5 import hudson.tasks.junit.TestResultAction 6 7 import jenkins.model.Jenkins 8 9 import org.apache.commons.io.IOUtils 10 import org.jenkinsci.plugins.workflow.libs.LibrariesAction 11 import org.jenkinsci.plugins.workflow.steps.MissingContextVariableException 12 13 @NonCPS 14 def getActiveJenkinsInstance() { 15 return Jenkins.getActiveInstance() 16 } 17 18 @API 19 @NonCPS 20 static def isPluginActive(pluginId) { 21 return Jenkins.instance.pluginManager.plugins.find { p -> p.isActive() && p.getShortName() == pluginId } 22 } 23 24 static boolean hasTestFailures(build){ 25 //build: https://javadoc.jenkins.io/plugin/workflow-support/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapper.html 26 //getRawBuild: https://javadoc.jenkins.io/plugin/workflow-job/org/jenkinsci/plugins/workflow/job/WorkflowRun.html 27 //getAction: http://www.hudson-ci.org/javadoc/hudson/tasks/junit/TestResultAction.html 28 def action = build?.getRawBuild()?.getAction(TestResultAction.class) 29 return action && action.getFailCount() != 0 30 } 31 32 boolean addWarningsNGParser(String id, String name, String regex, String script, String example = ''){ 33 def classLoader = this.getClass().getClassLoader() 34 // usage of class loader to avoid plugin dependency for other use cases of JenkinsUtils class 35 def parserConfig = classLoader.loadClass('io.jenkins.plugins.analysis.warnings.groovy.ParserConfiguration', true)?.getInstance() 36 37 if(parserConfig.contains(id)){ 38 return false 39 }else{ 40 parserConfig.setParsers( 41 parserConfig.getParsers().plus( 42 classLoader.loadClass('io.jenkins.plugins.analysis.warnings.groovy.GroovyParser', true)?.newInstance(id, name, regex, script, example) 43 ) 44 ) 45 return true 46 } 47 } 48 49 @NonCPS 50 static String getFullBuildLog(currentBuild) { 51 Reader reader = currentBuild.getRawBuild().getLogReader() 52 String logContent = IOUtils.toString(reader); 53 reader.close(); 54 reader = null 55 return logContent 56 } 57 58 def nodeAvailable() { 59 try { 60 sh "echo 'Node is available!'" 61 } catch (MissingContextVariableException e) { 62 echo "No node context available." 63 return false 64 } 65 return true 66 } 67 68 69 @NonCPS 70 def getCurrentBuildInstance() { 71 return currentBuild 72 } 73 74 @NonCPS 75 def getParentJob() { 76 return getRawBuild().getParent() 77 } 78 79 @NonCPS 80 def getRawBuild() { 81 return getCurrentBuildInstance().rawBuild 82 } 83 84 def isJobStartedByTimer() { 85 return isJobStartedByCause(hudson.triggers.TimerTrigger.TimerTriggerCause.class) 86 } 87 88 def isJobStartedByUser() { 89 return isJobStartedByCause(hudson.model.Cause.UserIdCause.class) 90 } 91 92 @NonCPS 93 def isJobStartedByCause(Class cause) { 94 def startedByGivenCause = false 95 def detectedCause = getRawBuild().getCause(cause) 96 if (null != detectedCause) { 97 startedByGivenCause = true 98 echo "Found build cause ${detectedCause}" 99 } 100 return startedByGivenCause 101 } 102 103 @NonCPS 104 String getIssueCommentTriggerAction() { 105 try { 106 def triggerCause = getRawBuild().getCause(org.jenkinsci.plugins.pipeline.github.trigger.IssueCommentCause) 107 if (triggerCause) { 108 //triggerPattern e.g. like '.* /piper ([a-z]*) .*' 109 def matcher = triggerCause.comment =~ triggerCause.triggerPattern 110 if (matcher) { 111 return matcher[0][1] 112 } 113 } 114 return null 115 } catch (err) { 116 return null 117 } 118 } 119 120 def getJobStartedByUserId() { 121 return getRawBuild().getCause(hudson.model.Cause.UserIdCause.class)?.getUserId() 122 } 123 124 @NonCPS 125 def getLibrariesInfo() { 126 def libraries = [] 127 def build = getRawBuild() 128 def libs = build.getAction(LibrariesAction.class).getLibraries() 129 130 for (def i = 0; i < libs.size(); i++) { 131 Map lib = [:] 132 133 lib['name'] = libs[i].name 134 lib['version'] = libs[i].version 135 lib['trusted'] = libs[i].trusted 136 libraries.add(lib) 137 } 138 139 return libraries 140 } 141 142 @NonCPS 143 void addRunSideBarLink(String relativeUrl, String displayName, String relativeIconPath) { 144 try { 145 def linkActionClass = this.class.classLoader.loadClass("hudson.plugins.sidebar_link.LinkAction") 146 if (relativeUrl != null && displayName != null) { 147 def run = getRawBuild() 148 def iconPath = (null != relativeIconPath) ? "${Functions.getResourcePath()}/${relativeIconPath}" : null 149 def action = linkActionClass.newInstance(relativeUrl, displayName, iconPath) 150 echo "Added run level sidebar link to '${action.getUrlName()}' with name '${action.getDisplayName()}' and icon '${action.getIconFileName()}'" 151 run.getActions().add(action) 152 } 153 } catch (e) { 154 e.printStackTrace() 155 } 156 } 157 158 @NonCPS 159 def getPlugin(name){ 160 for (plugin in getActiveJenkinsInstance().pluginManager.plugins) { 161 if (name == plugin.getShortName()) { 162 return plugin 163 } 164 } 165 return null 166 } 167 168 @NonCPS 169 String getPluginVersion(name) { 170 return getPlugin(name)?.getVersion() 171 } 172 173 @NonCPS 174 void addJobSideBarLink(String relativeUrl, String displayName, String relativeIconPath) { 175 try { 176 def linkActionClass = this.class.classLoader.loadClass("hudson.plugins.sidebar_link.LinkAction") 177 if (relativeUrl != null && displayName != null) { 178 def parentJob = getParentJob() 179 def buildNumber = getCurrentBuildInstance().number 180 def iconPath = (null != relativeIconPath) ? "${Functions.getResourcePath()}/${relativeIconPath}" : null 181 def action = linkActionClass.newInstance("${buildNumber}/${relativeUrl}", displayName, iconPath) 182 echo "Added job level sidebar link to '${action.getUrlName()}' with name '${action.getDisplayName()}' and icon '${action.getIconFileName()}'" 183 parentJob.getActions().add(action) 184 } 185 } catch (e) { 186 e.printStackTrace() 187 } 188 } 189 190 @NonCPS 191 void removeJobSideBarLinks(String relativeUrl = null) { 192 try { 193 def linkActionClass = this.class.classLoader.loadClass("hudson.plugins.sidebar_link.LinkAction") 194 def parentJob = getParentJob() 195 def listToRemove = new ArrayList() 196 for (def action : parentJob.getActions()) { 197 if (linkActionClass.isAssignableFrom(action.getClass()) && (null == relativeUrl || action.getUrlName().endsWith(relativeUrl))) { 198 echo "Removing job level sidebar link to '${action.getUrlName()}' with name '${action.getDisplayName()}' and icon '${action.getIconFileName()}'" 199 listToRemove.add(action) 200 } 201 } 202 parentJob.getActions().removeAll(listToRemove) 203 echo "Removed Jenkins global sidebar links ${listToRemove}" 204 } catch (e) { 205 e.printStackTrace() 206 } 207 } 208 209 void handleStepResults(String stepName, boolean failOnMissingReports, boolean failOnMissingLinks) { 210 def reportsFileName = "${stepName}_reports.json" 211 def reportsFileExists = fileExists(file: reportsFileName) 212 if (failOnMissingReports && !reportsFileExists) { 213 error "Expected to find ${reportsFileName} in workspace but it is not there" 214 } else if (reportsFileExists) { 215 def reports = readJSON(file: reportsFileName) 216 for (report in reports) { 217 String target = report['target'] as String 218 if (target != null && target.startsWith("./")) { 219 // archiveArtifacts does not match any files when they start with "./", 220 // even though that is a correct relative path. 221 target = target.substring(2) 222 } 223 archiveArtifacts artifacts: target, allowEmptyArchive: !report['mandatory'] 224 } 225 } 226 227 def linksFileName = "${stepName}_links.json" 228 def linksFileExists = fileExists(file: linksFileName) 229 if (failOnMissingLinks && !linksFileExists) { 230 error "Expected to find ${linksFileName} in workspace but it is not there" 231 } else if (linksFileExists) { 232 def links = readJSON(file: linksFileName) 233 for (link in links) { 234 if(link['scope'] == 'job') { 235 removeJobSideBarLinks(link['target']) 236 addJobSideBarLink(link['target'], link['name'], "images/24x24/graph.png") 237 } 238 addRunSideBarLink(link['target'], link['name'], "images/24x24/graph.png") 239 } 240 } 241 } 242 243 def getInstance() { 244 Jenkins.get() 245 }