github.com/xgoffin/jenkins-library@v1.154.0/vars/checksPublishResults.groovy (about) 1 import static com.sap.piper.Prerequisites.checkScript 2 3 import com.cloudbees.groovy.cps.NonCPS 4 5 import com.sap.piper.GenerateDocumentation 6 import com.sap.piper.ConfigurationHelper 7 import com.sap.piper.MapUtils 8 import com.sap.piper.Utils 9 10 import groovy.transform.Field 11 12 @Field def STEP_NAME = getClass().getName() 13 14 @Field Set TOOLS = [ 15 /** 16 * Allows to publish the check results. 17 * @possibleValues `true`, `false`, `Map` 18 */ 19 'aggregation', 20 /** 21 * Searches and publishes TODOs in files with the [Task Scanner Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Task+Scanner+Plugin). 22 * @possibleValues `true`, `false`, `Map` 23 */ 24 'tasks', 25 /** 26 * Publishes PMD findings with the [PMD plugin](https://plugins.jenkins.io/pmd). 27 * @possibleValues `true`, `false`, `Map` 28 */ 29 'pmd', 30 /** 31 * Publishes CPD findings with the [DRY plugin](https://plugins.jenkins.io/dry). 32 * @possibleValues `true`, `false`, `Map` 33 */ 34 'cpd', 35 /** 36 * Publishes Findbugs findings with the [Findbugs plugin](https://plugins.jenkins.io/findbugs). 37 * @possibleValues `true`, `false`, `Map` 38 */ 39 'findbugs', 40 /** 41 * Publishes Checkstyle findings with the [Checkstyle plugin](https://plugins.jenkins.io/checkstyle). 42 * @possibleValues `true`, `false`, `Map` 43 */ 44 'checkstyle', 45 /** 46 * Publishes ESLint findings (in [JSLint format](https://eslint.org/docs/user-guide/formatters/)) with the [Warnings plugin](https://plugins.jenkins.io/warnings). 47 * @possibleValues `true`, `false`, `Map` 48 */ 49 'eslint', 50 /** 51 * Publishes PyLint findings with the [Warnings plugin](https://plugins.jenkins.io/warnings), pylint needs to run with `--output-format=parseable` option. 52 * @possibleValues `true`, `false`, `Map` 53 */ 54 'pylint' 55 ] 56 57 @Field Set GENERAL_CONFIG_KEYS = [] 58 @Field Set STEP_CONFIG_KEYS = TOOLS.plus([ 59 /** 60 * If it is set to `true` the step will archive reports matching the tool specific pattern. 61 * @possibleValues `true`, `false` 62 */ 63 'archive', 64 /** 65 * If it is set to `true` the step will fail the build if JUnit detected any failing tests. 66 * @possibleValues `true`, `false` 67 */ 68 'failOnError' 69 ]) 70 @Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS 71 72 /** 73 * This step can publish static check results from various sources. 74 */ 75 @GenerateDocumentation 76 void call(Map parameters = [:]) { 77 handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters) { 78 79 def script = checkScript(this, parameters) ?: this 80 81 prepare(parameters) 82 String stageName = parameters.stageName ?: env.STAGE_NAME 83 // load default & individual configuration 84 Map configuration = ConfigurationHelper.newInstance(this) 85 .loadStepDefaults([:], stageName) 86 .mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS) 87 .mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS) 88 .mixinStageConfig(script.commonPipelineEnvironment, stageName, STEP_CONFIG_KEYS) 89 .mixin(parameters, PARAMETER_KEYS) 90 .use() 91 92 if (configuration.aggregation && configuration.aggregation.active != false){ 93 error "[ERROR] Configuration of the aggregation view is no longer possible. Migrate any thresholds defined here to tool specific quality gates. (piper-lib/${STEP_NAME})" 94 } 95 96 new Utils().pushToSWA([ 97 step: STEP_NAME, 98 stepParamKey1: 'scriptMissing', 99 stepParam1: parameters?.script == null 100 ], configuration) 101 102 // JAVA 103 if(configuration.pmd.active) { 104 report(pmdParser(createToolOptions(configuration.pmd)), configuration.pmd, configuration.archive) 105 } 106 if(configuration.cpd.active) { 107 report(cpd(createToolOptions(configuration.cpd)), configuration.cpd, configuration.archive) 108 } 109 if(configuration.findbugs.active) { 110 report(findBugs(createToolOptions(configuration.findbugs, [useRankAsPriority: true])), configuration.findbugs, configuration.archive) 111 } 112 if(configuration.checkstyle.active) { 113 report(checkStyle(createToolOptions(configuration.checkstyle)), configuration.checkstyle, configuration.archive) 114 } 115 // JAVA SCRIPT 116 if(configuration.eslint.active) { 117 report(esLint(createToolOptions(configuration.eslint)), configuration.eslint, configuration.archive) 118 } 119 // PYTHON 120 if(configuration.pylint.active) { 121 report(pyLint(createToolOptions(configuration.pylint)), configuration.pylint, configuration.archive) 122 } 123 // GENERAL 124 if(configuration.tasks.active) { 125 report(taskScanner(createToolOptions(configuration.tasks, [ 126 includePattern: configuration.tasks.get('pattern'), 127 highTags: configuration.tasks.get('high'), 128 normalTags: configuration.tasks.get('normal'), 129 lowTags: configuration.tasks.get('low'), 130 ]).minus([pattern: configuration.tasks.get('pattern')])), configuration.tasks, configuration.archive) 131 } 132 if (configuration.failOnError && 'FAILURE' == script.currentBuild?.result){ 133 script.currentBuild.result = 'FAILURE' 134 error "[${STEP_NAME}] Some checks failed!" 135 } 136 } 137 } 138 139 def report(tool, settings, doArchive){ 140 def options = createOptions(settings).plus([tools: [tool]]) 141 echo "recordIssues OPTIONS: ${options}" 142 // publish 143 recordIssues(options) 144 // archive check results 145 archiveResults(doArchive && settings.get('archive'), settings.get('pattern'), true) 146 } 147 148 def archiveResults(archive, pattern, allowEmpty){ 149 if(archive){ 150 echo "[${STEP_NAME}] archive ${pattern}" 151 archiveArtifacts artifacts: pattern, allowEmptyArchive: allowEmpty 152 } 153 } 154 155 @NonCPS 156 def createOptions(settings){ 157 Map result = [:] 158 result.put('blameDisabled', true) 159 result.put('enabledForFailure', true) 160 result.put('aggregatingResults', false) 161 162 def qualityGates = [] 163 if (settings.qualityGates) 164 qualityGates = qualityGates.plus(settings.qualityGates) 165 166 // handle legacy thresholds 167 // https://github.com/jenkinsci/warnings-ng-plugin/blob/6602c3a999b971405adda15be03979ce21cb3cbf/plugin/src/main/java/io/jenkins/plugins/analysis/core/util/QualityGate.java#L186 168 def thresholdsList = settings.get('thresholds', [:]) 169 if (thresholdsList) { 170 for (String status : ['fail', 'unstable']) { 171 def thresholdsListPerStatus = thresholdsList.get(status, [:]) 172 if (thresholdsListPerStatus) { 173 for (String severity : ['all', 'high', 'normal', 'low']) { 174 def threshold = thresholdsListPerStatus.get(severity) 175 if (threshold == null) 176 continue 177 threshold = threshold.toInteger() + 1 178 def type = "TOTAL" 179 if(severity != 'all') 180 type += "_" + severity.toUpperCase() 181 def gate = [threshold: threshold, type: type, unstable: status == 'unstable'] 182 echo "[WARNING] legacy threshold found, please migrate to quality gate (piper-lib/checksPublishResults)" 183 echo "legacy threshold transformed to quality gate: ${gate}" 184 qualityGates = qualityGates.plus([gate]) 185 } 186 } 187 } 188 } 189 190 result.put('qualityGates', qualityGates) 191 // filter empty values 192 result = result.findAll { 193 return it.value != null && it.value != '' 194 } 195 return result 196 } 197 198 @NonCPS 199 def createToolOptions(settings, additionalOptions = [:]){ 200 Map result = [pattern: settings.get('pattern')] 201 if (settings.id) 202 result.put('id', settings.id) 203 if (settings.name) 204 result.put('name', settings.name) 205 result = result.plus(additionalOptions) 206 // filter empty values 207 result = result.findAll { 208 return it.value != null && it.value != '' 209 } 210 return result 211 } 212 213 def prepare(parameters){ 214 // ensure tool maps are initialized correctly 215 for(String tool : TOOLS){ 216 parameters[tool] = toMap(parameters[tool]) 217 } 218 return parameters 219 } 220 221 def toMap(parameter){ 222 if(MapUtils.isMap(parameter)) 223 parameter.put('active', parameter.active == null?true:parameter.active) 224 else if(Boolean.TRUE.equals(parameter)) 225 parameter = [active: true] 226 else if(Boolean.FALSE.equals(parameter)) 227 parameter = [active: false] 228 else 229 parameter = [:] 230 return parameter 231 }