github.com/jenkins-x/jx/v2@v2.1.155/pkg/builds/build_number.go (about)

     1  package builds
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"regexp"
     7  	"strings"
     8  
     9  	"github.com/jenkins-x/jx-logging/pkg/log"
    10  	"github.com/jenkins-x/jx/v2/pkg/util"
    11  )
    12  
    13  var (
    14  	numericStringRegex = regexp.MustCompile("[0-9]+")
    15  )
    16  
    17  // GetBuildNumber returns the build number using environment variables and/or pod Downward API files
    18  func GetBuildNumber() string {
    19  	buildNumber := os.Getenv("JX_BUILD_NUMBER")
    20  	if buildNumber != "" {
    21  		return buildNumber
    22  	}
    23  	buildNumber = os.Getenv("BUILD_NUMBER")
    24  	if buildNumber != "" {
    25  		return buildNumber
    26  	}
    27  	buildID := os.Getenv("BUILD_ID")
    28  	if buildID != "" {
    29  		return buildID
    30  	}
    31  
    32  	m := getDownwardAPILabelsMap()
    33  	if m != nil {
    34  		return GetBuildNumberFromLabels(m)
    35  	}
    36  	return ""
    37  }
    38  
    39  // GetBuildNumberFromLabels returns the
    40  func GetBuildNumberFromLabels(m map[string]string) string {
    41  	return GetBuildNumberFromLabelsWithKeys(m, LabelBuildName, "build-number", LabelOldBuildName, LabelPipelineRunName)
    42  }
    43  
    44  // getDownwardAPILabels returns the downward API labels from inside a pod or an empty string if they could not be found
    45  func getDownwardAPILabelsMap() map[string]string {
    46  	// if we are in a knative build pod we can discover it via the Downward API if the `/etc/podinfo/labels` file exists
    47  	const podInfoLabelsFile = "/etc/podinfo/labels"
    48  	exists, err := util.FileExists(podInfoLabelsFile)
    49  	if err != nil {
    50  		log.Logger().Warnf("failed to detect if the file %s exists: %s", podInfoLabelsFile, err)
    51  	} else if exists {
    52  		data, err := ioutil.ReadFile(podInfoLabelsFile)
    53  		if err != nil {
    54  			log.Logger().Warnf("failed to load downward API pod labels from %s due to: %s", podInfoLabelsFile, err)
    55  		} else {
    56  			text := strings.TrimSpace(string(data))
    57  			if text != "" {
    58  				return LoadDownwardAPILabels(text)
    59  			}
    60  		}
    61  	}
    62  	return nil
    63  }
    64  
    65  // GetBranchName returns the branch name using environment variables and/or pod Downward API
    66  func GetBranchName() string {
    67  	branch := os.Getenv(util.EnvVarBranchName)
    68  	if branch == "" {
    69  		m := getDownwardAPILabelsMap()
    70  		if m != nil {
    71  			branch = GetBranchNameFromLabels(m)
    72  		}
    73  	}
    74  	return branch
    75  }
    76  
    77  // GetBranchNameFromLabels returns the branch name from the given pod labels
    78  func GetBranchNameFromLabels(m map[string]string) string {
    79  	return GetValueFromLabels(m, "branch")
    80  }
    81  
    82  // GetBuildNumberFromLabelsWithKeys returns the build number from the given Pod labels
    83  func GetBuildNumberFromLabelsWithKeys(m map[string]string, keys ...string) string {
    84  	if m == nil {
    85  		return ""
    86  	}
    87  
    88  	answer := ""
    89  	for _, key := range keys {
    90  		answer = m[key]
    91  		if answer != "" {
    92  			break
    93  		}
    94  	}
    95  	if answer != "" {
    96  		return lastNumberFrom(answer)
    97  	}
    98  	return ""
    99  }
   100  
   101  // GetValueFromLabels returns the first label with the given key
   102  func GetValueFromLabels(m map[string]string, keys ...string) string {
   103  	if m == nil {
   104  		return ""
   105  	}
   106  	answer := ""
   107  	for _, key := range keys {
   108  		answer = m[key]
   109  		if answer != "" {
   110  			break
   111  		}
   112  	}
   113  	return answer
   114  }
   115  
   116  // lastNumberFrom splits a string such as "jstrachan-mynodething-master-1-build" via "-" and returns the last
   117  // numeric string
   118  func lastNumberFrom(text string) string {
   119  	// lets remove any whilespace or double quotes
   120  	paths := strings.Split(text, "-")
   121  	for i := len(paths) - 1; i >= 0; i-- {
   122  		path := paths[i]
   123  		if numericStringRegex.MatchString(path) {
   124  			return path
   125  		}
   126  	}
   127  	return ""
   128  }
   129  
   130  func trimValue(text string) string {
   131  	text = strings.TrimSpace(text)
   132  	text = strings.TrimPrefix(text, "\"")
   133  	text = strings.TrimSuffix(text, "\"")
   134  	return text
   135  }
   136  
   137  // LoadDownwardAPILabels parses the /etc/podinfo/labels text into a map of label values
   138  func LoadDownwardAPILabels(text string) map[string]string {
   139  	m := map[string]string{}
   140  	if text != "" {
   141  		lines := strings.Split(text, "\n")
   142  		for _, line := range lines {
   143  			l := strings.TrimSpace(line)
   144  			paths := strings.SplitN(l, "=", 2)
   145  			if len(paths) == 2 {
   146  				m[paths[0]] = trimValue(paths[1])
   147  			}
   148  		}
   149  	}
   150  	return m
   151  }