github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/cmd/build/version.go (about)

     1  // Package build contains information about the build that injected at build-time.
     2  //
     3  // To use this package, simply import it in your program, then add build
     4  // arguments like the following:
     5  //
     6  //	go build -ldflags "-X github.com/onflow/flow-go/cmd/build.semver=v1.0.0"
     7  package build
     8  
     9  import (
    10  	"fmt"
    11  	"strings"
    12  
    13  	smv "github.com/coreos/go-semver/semver"
    14  )
    15  
    16  // Default value for build-time-injected version strings.
    17  const undefined = "undefined"
    18  
    19  // The following variables are injected at build-time using ldflags.
    20  var (
    21  	semver string
    22  	commit string
    23  )
    24  
    25  // Version returns the raw version string of this build.
    26  func Version() string {
    27  	return semver
    28  }
    29  
    30  // Commit returns the commit at which this build was created.
    31  func Commit() string {
    32  	return commit
    33  }
    34  
    35  // IsDefined determines whether a version string is defined. Inputs should
    36  // have been produced from this package.
    37  func IsDefined(v string) bool {
    38  	return v != undefined
    39  }
    40  
    41  // If any of the build-time-injected variables are empty at initialization,
    42  // mark them as undefined.
    43  func init() {
    44  	if len(semver) == 0 {
    45  		semver = undefined
    46  	}
    47  	if len(commit) == 0 {
    48  		commit = undefined
    49  	}
    50  }
    51  
    52  var UndefinedVersionError = fmt.Errorf("version is undefined")
    53  
    54  // Semver returns the semantic version of this build as a semver.Version
    55  // if it is defined, or UndefinedVersionError otherwise.
    56  // The version string is converted to a semver compliant one if it isn't already
    57  // but this might fail if the version string is still not semver compliant. In that
    58  // case, an error is returned.
    59  func Semver() (*smv.Version, error) {
    60  	if !IsDefined(semver) {
    61  		return nil, UndefinedVersionError
    62  	}
    63  	ver, err := smv.NewVersion(makeSemverCompliant(semver))
    64  	return ver, err
    65  }
    66  
    67  // makeSemverCompliant converts a non-semver version string to a semver compliant one.
    68  // This removes the leading 'v'.
    69  // In the past we sometimes omitted the patch version, e.g. v1.0.0 became v1.0 so this
    70  // also adds a 0 patch version if there's no patch version.
    71  func makeSemverCompliant(version string) string {
    72  	if !IsDefined(version) {
    73  		return version
    74  	}
    75  
    76  	// Remove the leading 'v'
    77  	version = strings.TrimPrefix(version, "v")
    78  
    79  	// If there's no patch version, add .0
    80  	parts := strings.SplitN(version, "-", 2)
    81  	if strings.Count(parts[0], ".") == 1 {
    82  		parts[0] = parts[0] + ".0"
    83  	}
    84  
    85  	version = strings.Join(parts, "-")
    86  	return version
    87  }