github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/src/com/sap/piper/DebugReport.groovy (about) 1 package com.sap.piper 2 3 import com.cloudbees.groovy.cps.NonCPS 4 import groovy.text.SimpleTemplateEngine 5 6 @Singleton 7 class DebugReport implements Serializable { 8 static final long serialVersionUID = 1L 9 10 String projectIdentifier = null 11 Map environment = ['environment': 'custom'] 12 String buildTool = null 13 Map modulesMap = [:] 14 List npmModules = [] 15 Set plugins = [] 16 Map gitRepo = [:] 17 Map localExtensions = [:] 18 String globalExtensionRepository = null 19 Map globalExtensions = [:] 20 String globalExtensionConfigurationFilePath = null 21 String sharedConfigFilePath = null 22 Set additionalSharedLibraries = [] 23 Map failedBuild = [:] 24 25 /** 26 * Initialize debug report information from the environment variables. 27 * 28 * @param env The Jenkins global 'env' variable. 29 */ 30 void initFromEnvironment(def env) { 31 Set buildDetails = [] 32 buildDetails.add('Jenkins Version | ' + env.JENKINS_VERSION) 33 buildDetails.add('JAVA Version | ' + env.JAVA_VERSION) 34 environment.put('build_details', buildDetails) 35 36 if (!Boolean.valueOf(env.ON_K8S) && EnvironmentUtils.cxServerDirectoryExists()) { 37 environment.put('environment', 'cx-server') 38 39 String serverConfigContents = getServerConfigContents( 40 '/var/cx-server/server.cfg', 41 '/workspace/var/cx-server/server.cfg') 42 String dockerImage = EnvironmentUtils.getDockerFile(serverConfigContents) 43 environment.put('docker_image', dockerImage) 44 } 45 else if(Boolean.valueOf(env.ON_K8S)){ 46 DebugReport.instance.environment.put("environment", "Kubernetes") 47 } 48 } 49 50 private static String getServerConfigContents(String... possibleFileLocations) { 51 for (String location in possibleFileLocations) { 52 File file = new File(location) 53 if (file.exists()) 54 return file.getText('UTF-8') 55 } 56 return '' 57 } 58 59 /** 60 * Pulls and stores repository information from the provided Map for later inclusion in the debug report. 61 * 62 * @param scmCheckoutResult A Map including information about the checked out project, 63 * i.e. as returned by the Jenkins checkout() function. 64 */ 65 void setGitRepoInfo(Map scmCheckoutResult) { 66 if (!scmCheckoutResult.GIT_URL) 67 return 68 69 gitRepo.put('URI', scmCheckoutResult.GIT_URL) 70 if (scmCheckoutResult.GIT_LOCAL_BRANCH) { 71 gitRepo.put('branch', scmCheckoutResult.GIT_LOCAL_BRANCH) 72 } else { 73 gitRepo.put('branch', scmCheckoutResult.GIT_BRANCH) 74 } 75 } 76 77 /** 78 * Stores crash information for a failed step. Multiple calls to this method overwrite already 79 * stored information, only the information stored last will appear in the debug report. In the 80 * current use-case where this can be called multiple times, all 'unstable' steps are listed in 81 * the 'unstableSteps' entry of the commonPipelineEnvironment. 82 * 83 * @param stepName The name of the crashed step or stage 84 * @param err The Throwable that was thrown 85 * @param failedOnError Whether the failure was deemed fatal at the time of calling this method. 86 */ 87 void storeStepFailure(String stepName, Throwable err, boolean failedOnError) { 88 failedBuild.put('step', stepName) 89 failedBuild.put('reason', err) 90 failedBuild.put('stack_trace', err.getStackTrace()) 91 failedBuild.put('fatal', failedOnError ? 'true' : 'false') 92 } 93 94 Map generateReport(Script script, boolean shareConfidentialInformation) { 95 String template = script.libraryResource 'com.sap.piper/templates/debug_report.txt' 96 97 if (!projectIdentifier) { 98 projectIdentifier = 'NOT_SET' 99 } 100 101 try { 102 Jenkins.instance.getPluginManager().getPlugins().each { 103 plugins.add("${it.getShortName()} | ${it.getVersion()} | ${it.getDisplayName()}") 104 } 105 } catch (Throwable t) { 106 script.echo "Failed to retrieve Jenkins plugins for debug report (${t.getMessage()})" 107 } 108 109 Date now = new Date() 110 111 Map binding = [ 112 'projectIdentifier' : projectIdentifier, 113 'environment' : environment, 114 'buildTool': buildTool, 115 'modulesMap' : modulesMap, 116 'npmModules' : npmModules, 117 'plugins' : plugins, 118 'gitRepo' : gitRepo, 119 'localExtensions' : localExtensions, 120 'globalExtensionRepository' : globalExtensionRepository, 121 'globalExtensions' : globalExtensions, 122 'globalExtensionConfigurationFilePath' : globalExtensionConfigurationFilePath, 123 'sharedConfigFilePath' : sharedConfigFilePath, 124 'additionalSharedLibraries' : additionalSharedLibraries, 125 'failedBuild' : failedBuild, 126 'shareConfidentialInformation' : shareConfidentialInformation, 127 'utcTimestamp' : now.format('yyyy-MM-dd HH:mm', TimeZone.getTimeZone('UTC')) 128 ] 129 130 String fileNameTimestamp = now.format('yyyy-MM-dd-HH-mm', TimeZone.getTimeZone('UTC')) 131 String fileNamePrefix = shareConfidentialInformation ? 'confidential' : 'redacted' 132 133 Map result = [:] 134 result.fileName = "${fileNamePrefix}_debug_log_${fileNameTimestamp}_${projectIdentifier}.txt" 135 result.contents = fillTemplate(template, binding) 136 return result 137 } 138 139 @NonCPS 140 private String fillTemplate(String template, binding) { 141 def engine = new SimpleTemplateEngine() 142 return engine.createTemplate(template).make(binding) 143 } 144 }