github.com/drone/runner-go@v1.12.0/environ/calver.go (about)

     1  // Copyright 2019 Drone.IO Inc. All rights reserved.
     2  // Use of this source code is governed by the Polyform License
     3  // that can be found in the LICENSE file.
     4  
     5  package environ
     6  
     7  import (
     8  	"bytes"
     9  	"strconv"
    10  	"strings"
    11  )
    12  
    13  func calversions(s string) map[string]string {
    14  	env := map[string]string{}
    15  
    16  	version := parseCalver(s)
    17  	if version == nil {
    18  		return nil
    19  	}
    20  
    21  	// we try to determine if the major and minor
    22  	// versions are valid years.
    23  	if !isYear(version.Major) {
    24  		return env
    25  	}
    26  
    27  	env["DRONE_CALVER"] = version.String()
    28  	env["DRONE_CALVER_MAJOR_MINOR"] = version.Major + "." + version.Minor
    29  	env["DRONE_CALVER_MAJOR"] = version.Major
    30  	env["DRONE_CALVER_MINOR"] = version.Minor
    31  	env["DRONE_CALVER_MICRO"] = version.Micro
    32  	if version.Modifier != "" {
    33  		env["DRONE_CALVER_MODIFIER"] = version.Modifier
    34  	}
    35  
    36  	version.Modifier = ""
    37  	env["DRONE_CALVER_SHORT"] = version.String()
    38  	return env
    39  }
    40  
    41  type calver struct {
    42  	Major    string
    43  	Minor    string
    44  	Micro    string
    45  	Modifier string
    46  }
    47  
    48  // helper function that parses tags in the calendar version
    49  // format. note this is not a robust parser implementation
    50  // and mat fail to properly parse all strings.
    51  func parseCalver(s string) *calver {
    52  	s = strings.TrimPrefix(s, "v")
    53  	p := strings.SplitN(s, ".", 3)
    54  	if len(p) < 2 {
    55  		return nil
    56  	}
    57  
    58  	c := new(calver)
    59  	c.Major = p[0]
    60  	c.Minor = p[1]
    61  	if len(p) > 2 {
    62  		c.Micro = p[2]
    63  	}
    64  
    65  	switch {
    66  	case strings.Contains(c.Micro, "-"):
    67  		p := strings.SplitN(c.Micro, "-", 2)
    68  		c.Micro = p[0]
    69  		c.Modifier = p[1]
    70  	}
    71  
    72  	// the major and minor segments must be numbers to
    73  	// conform to the calendar version spec.
    74  	if !isNumber(c.Major) ||
    75  		!isNumber(c.Minor) {
    76  		return nil
    77  	}
    78  
    79  	return c
    80  }
    81  
    82  // String returns the calendar version string.
    83  func (c *calver) String() string {
    84  	var buf bytes.Buffer
    85  	buf.WriteString(c.Major)
    86  	buf.WriteString(".")
    87  	buf.WriteString(c.Minor)
    88  	if c.Micro != "" {
    89  		buf.WriteString(".")
    90  		buf.WriteString(c.Micro)
    91  	}
    92  	if c.Modifier != "" {
    93  		buf.WriteString("-")
    94  		buf.WriteString(c.Modifier)
    95  	}
    96  	return buf.String()
    97  }
    98  
    99  // helper function returns true if the string is a
   100  // valid number.
   101  func isNumber(s string) bool {
   102  	_, err := strconv.Atoi(s)
   103  	return err == nil
   104  }
   105  
   106  // helper function returns true if the string is a
   107  // valid year. This assumes a minimum year of 2019
   108  // for YYYY format and a minimum year of 19 for YY
   109  // format.
   110  //
   111  // TODO(bradrydzewski) if people are still using this
   112  // code in 2099 we need to adjust the minimum YY value.
   113  func isYear(s string) bool {
   114  	i, _ := strconv.Atoi(s)
   115  	return (i > 18 && i < 100) || (i > 2018 && i < 9999)
   116  }