github.com/jaylevin/jenkins-library@v1.230.4/documentation/bin/resolveTransitiveCalls.groovy (about) 1 import groovy.json.JsonSlurper 2 3 def cli = new CliBuilder( 4 usage: 'groovy createDocu [<options>]', 5 header: 'Options:', 6 footer: 'Copyright: SAP SE') 7 8 cli.with { 9 i longOpt: 'in', args: 1, argName: 'file', 'The file containing the mapping as created by the unit tests..' 10 o longOpt: 'out', args: 1, argName: 'file', 'The file containing the condenced mappings.' 11 h longOpt: 'help', 'Prints this help.' 12 } 13 14 def options = cli.parse(args) 15 16 if(options.h) { 17 System.err << "Printing help.\n" 18 cli.usage() 19 return 20 } 21 22 if(! options.i) { 23 System.err << "No input file" 24 cli.usage() 25 return 26 } 27 if(! options.o) { 28 System.err << "No output file" 29 cli.usage() 30 return 31 } 32 33 def steps = new JsonSlurper().parseText(new File(options.i).text) 34 35 def piperSteps = steps.piperSteps 36 def calls = steps.calls 37 38 // only temporary in order to avoid manipulating the map during 39 // iterating over it. 40 def tmpCalls = [:] 41 42 // Adjust naming 43 calls.each { c -> 44 tmpCalls.put(retrieveStepName(c.key), c.value as Set) 45 } 46 47 calls = tmpCalls 48 tmpCalls = null 49 50 // Remove selfs 51 calls.each { c -> 52 c.value.remove(c.key) 53 } 54 55 int counter=0 56 57 def alreadyHandled = [] 58 59 // 60 // in case we exceed the value we assume some cyclic call 61 // between plugin steps. 62 int MAX_LOOP = 1600 63 64 boolean done = false 65 66 while(counter < MAX_LOOP) { 67 68 def hereWeNeedToReplace = null 69 def toBeReplaced = null 70 71 if(alreadyHandled.size() == calls.size()) { 72 done = true 73 break 74 } 75 76 for (def call in calls.entrySet()) { 77 78 stepName = call.key 79 calledSteps = call.value 80 81 if(alreadyHandled.contains(stepName)) { 82 continue 83 } 84 85 for (def calledStep in calledSteps) { 86 87 if(! ( calledStep in Map)) { 88 89 // in case the calledStep is a map the map 90 // was introduced in an earlier loop. 91 // This means this entry is already handled. 92 93 if(calledStep in piperSteps) { 94 toBeReplaced = calledStep 95 hereWeNeedToReplace = calledSteps 96 break 97 } 98 } 99 } 100 if(toBeReplaced) { 101 def replacement = [:] 102 replacement[toBeReplaced] = calls[toBeReplaced] as Set 103 def removed = hereWeNeedToReplace.remove(toBeReplaced) 104 hereWeNeedToReplace.add(replacement) 105 counter++ 106 } else { 107 alreadyHandled << stepName 108 } 109 break 110 } 111 } 112 113 if(! done) { 114 throw new Exception('Unable to resolve transitive plugin calls.') 115 } 116 117 piperStepCallMappings = [:] 118 119 for(def entry : calls.entrySet()) { 120 def performedCalls = flatten(entry, (Set)[]) 121 piperStepCallMappings.put(entry.key, performedCalls) 122 } 123 124 // 125 // special handling since since changeManagement util class 126 // is separated from the steps itself 127 // 128 // should be improved in the future in order not to have 129 // that bells and whistles here. 130 131 def cm = piperStepCallMappings.get('changeManagement') 132 133 for (cmStepName in [ 134 'checkChangeInDevelopment', 135 'transportRequestCreate', 136 'transportRequestUploadFile', 137 'transportRequestRelease', 138 ]) { 139 piperStepCallMappings.get(cmStepName).addAll(cm) 140 } 141 142 // end of special handling 143 // 144 145 File performedCalls = new File(options.o) 146 if (performedCalls.exists()) performedCalls.delete() 147 performedCalls << groovy.json.JsonOutput.toJson(piperStepCallMappings) 148 149 def flatten(def entry, Set result) { 150 151 for(def e : entry.value) { 152 if(e in Map) { // the map here is expected to hold one entry always 153 for(def steps : e.entrySet().value) { 154 for(def step : steps) { 155 if (step in Map) { 156 flatten(step, result) 157 } else { 158 result << step 159 } 160 } 161 } 162 } else { 163 result << e.value.toString() 164 } 165 } 166 result 167 } 168 169 static retrieveStepName(String s) { 170 firstCharToLowerCase(removeTrailing(s, 'Test')) 171 } 172 173 static removeTrailing(String s, String trail) { 174 return s.replaceAll(trail + '$', '') 175 } 176 177 static firstCharToLowerCase(CharSequence cs) { 178 char[] c = cs.getChars() 179 c[0] = Character.toLowerCase(c[0]) 180 new String(c) 181 }