github.com/drone/go-convert@v0.0.0-20240307072510-6bd371c65e61/convert/bitbucket/extract.go (about) 1 // Copyright 2022 Harness, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package bitbucket 16 17 import ( 18 "sort" 19 20 bitbucket "github.com/drone/go-convert/convert/bitbucket/yaml" 21 ) 22 23 // 24 // this file contains helper functions that help 25 // extract data from the yaml. 26 // 27 28 // helper function that recursively returns all stage steps 29 // including parallel steps. 30 func extractSteps(stage *bitbucket.Stage) []*bitbucket.Step { 31 var steps []*bitbucket.Step 32 // iterate through steps the he stage 33 for _, step := range stage.Steps { 34 if step.Step != nil { 35 steps = append(steps, step.Step) 36 } 37 // iterate through parallel steps 38 if step.Parallel != nil { 39 for _, step2 := range step.Parallel.Steps { 40 if step2.Step != nil { 41 steps = append(steps, step2.Step) 42 } 43 } 44 } 45 } 46 return steps 47 } 48 49 // helper function that recursively returnsall stage steps, 50 // including parallel steps. 51 func extractAllSteps(stages []*bitbucket.Steps) []*bitbucket.Step { 52 var steps []*bitbucket.Step 53 for _, stage := range stages { 54 if stage.Stage != nil { 55 steps = append(steps, extractSteps(stage.Stage)...) 56 } 57 } 58 return steps 59 } 60 61 // helper function that returns a recommended machine size 62 // based on the gloal machine size, as well as any step-level 63 // overrides. 64 func extractSize(opts *bitbucket.Options, stage *bitbucket.Stage) bitbucket.Size { 65 var size bitbucket.Size 66 67 // start with the global size, if set 68 if opts != nil { 69 size = opts.Size 70 } 71 72 // loop through the steps and if a step 73 // defines a size greater than the global 74 // size, us the step size instead. 75 for _, step := range extractSteps(stage) { 76 if step.Size > size { 77 size = step.Size 78 } 79 } 80 return size 81 } 82 83 // helper function that returns runs-on tags for routing 84 // a stage to a specific set of workers. In Bitbucket, each 85 // step can be routed to a different machine, which is not 86 // compatible with Harness. We emulate this behavior by 87 // aggregating all run-on tags and applying them at the 88 // stage level in Harness. 89 func extractRunsOn(stage *bitbucket.Stage) []string { 90 set := map[string]struct{}{} 91 92 // loop through the steps and if a step 93 // defines a size greater than the global 94 // size, us the step size instead. 95 for _, step := range extractSteps(stage) { 96 for _, s := range step.RunsOn { 97 set[s] = struct{}{} 98 } 99 } 100 101 // convert the map to a slice. 102 var unique []string 103 for k := range set { 104 unique = append(unique, k) 105 } 106 107 // sort for deterministic unit testing 108 sort.Strings(unique) 109 110 return unique 111 } 112 113 // helper function that returns a list of all caches used 114 // by all steps in a given stage. 115 func extractCache(stage *bitbucket.Stage) []string { 116 set := map[string]struct{}{} 117 118 // loop through the steps and if a step 119 // defines cache directories 120 for _, step := range extractSteps(stage) { 121 for _, s := range step.Caches { 122 set[s] = struct{}{} 123 } 124 } 125 126 // convert the map to a slice. 127 var unique []string 128 for k := range set { 129 unique = append(unique, k) 130 } 131 132 // sort for deterministic unit testing 133 sort.Strings(unique) 134 135 return unique 136 } 137 138 // helper function that returns a list of all services used 139 // by all steps in a given stage. 140 func extractServices(stage *bitbucket.Stage) []string { 141 set := map[string]struct{}{} 142 143 // loop through the steps and if a step 144 // defines cache directories 145 for _, step := range extractSteps(stage) { 146 for _, s := range step.Services { 147 set[s] = struct{}{} 148 } 149 } 150 151 // convert the map to a slice. 152 var unique []string 153 for k := range set { 154 unique = append(unique, k) 155 } 156 157 // sort for deterministic unit testing 158 sort.Strings(unique) 159 160 return unique 161 }