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  }