File: provenance.go

package info (click to toggle)
golang-k8s-sigs-kustomize-api 0.20.1%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,768 kB
  • sloc: makefile: 206; sh: 67
file content (141 lines) | stat: -rw-r--r-- 3,819 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package provenance

import (
	"fmt"
	"runtime"
	"runtime/debug"
	"strings"

	"github.com/blang/semver/v4"
)

// These variables are set at build time using ldflags.
//
//nolint:gochecknoglobals
var (
	// During a release, this will be set to the release tag, e.g. "kustomize/v4.5.7"
	version = developmentVersion
	// build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ')
	buildDate = unknown
)

const (
	// This default value, (devel), matches
	// the value debug.BuildInfo uses for an unset main module version.
	developmentVersion = "(devel)"

	// ModulePath is kustomize module path, defined in kustomize/go.mod
	ModulePath = "sigs.k8s.io/kustomize/kustomize/v5"

	// This is default value, unknown, substituted when
	// the value can't be determined from debug.BuildInfo.
	unknown = "unknown"
)

// Provenance holds information about the build of an executable.
type Provenance struct {
	// Version of the kustomize binary.
	Version string `json:"version,omitempty" yaml:"version,omitempty"`
	// GitCommit is a git commit
	GitCommit string `json:"gitCommit,omitempty" yaml:"gitCommit,omitempty"`
	// BuildDate is date of the build.
	BuildDate string `json:"buildDate,omitempty" yaml:"buildDate,omitempty"`
	// GoOs holds OS name.
	GoOs string `json:"goOs,omitempty" yaml:"goOs,omitempty"`
	// GoArch holds architecture name.
	GoArch string `json:"goArch,omitempty" yaml:"goArch,omitempty"`
	// GoVersion holds Go version.
	GoVersion string `json:"goVersion,omitempty" yaml:"goVersion,omitempty"`
}

// GetProvenance returns an instance of Provenance.
func GetProvenance() Provenance {
	p := Provenance{
		BuildDate: buildDate,
		Version:   version,
		GitCommit: unknown,
		GoOs:      runtime.GOOS,
		GoArch:    runtime.GOARCH,
		GoVersion: runtime.Version(),
	}
	info, ok := debug.ReadBuildInfo()
	if !ok {
		return p
	}

	for _, setting := range info.Settings {
		// For now, the git commit is the only information of interest.
		// We could consider adding other info such as the commit date in the future.
		if setting.Key == "vcs.revision" {
			p.GitCommit = setting.Value
			break
		}
	}
	p.Version = FindVersion(info, p.Version)

	return p
}

// FindVersion searches for a version in the depth of dependencies including replacements,
// otherwise, it tries to get version from debug.BuildInfo Main.
func FindVersion(info *debug.BuildInfo, version string) string {
	for _, dep := range info.Deps {
		if dep != nil && dep.Path == ModulePath {
			if dep.Version == developmentVersion {
				continue
			}
			v, err := GetMostRecentTag(*dep)
			if err != nil {
				fmt.Printf("failed to get most recent tag for %s: %v\n", dep.Path, err)
				continue
			}

			return v
		}
	}

	if version == developmentVersion && info.Main.Version != "" {
		return info.Main.Version
	}

	return version
}

func GetMostRecentTag(m debug.Module) (string, error) {
	for m.Replace != nil {
		m = *m.Replace
	}

	split := strings.Split(m.Version, "-")
	sv, err := semver.Parse(strings.TrimPrefix(split[0], "v"))

	if err != nil {
		return "", fmt.Errorf("failed to parse version %s: %w", m.Version, err)
	}

	if len(split) > 1 && sv.Patch > 0 {
		sv.Patch -= 1
	}
	return fmt.Sprintf("v%s", sv.FinalizeVersion()), nil
}

// Short returns the shortened provenance stamp.
func (v Provenance) Short() string {
	return fmt.Sprintf(
		"%v",
		Provenance{
			Version:   v.Version,
			BuildDate: v.BuildDate,
		})
}

// Semver returns the semantic version of kustomize.
// kustomize version is set in format "kustomize/vX.X.X" in every release.
// X.X.X is a semver. If the version string is not in this format,
// return the original version string
func (v Provenance) Semver() string {
	return strings.TrimPrefix(v.Version, "kustomize/")
}