From 8b8998034ceded096a761b99ff0a1f5a79f0a7b6 Mon Sep 17 00:00:00 2001 From: Hank Donnay Date: Mon, 5 Dec 2022 13:08:24 -0600 Subject: [PATCH] cmd: use git-archive for version information Signed-off-by: Hank Donnay --- .gitattributes | 2 ++ cmd/build.go | 75 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 51 insertions(+), 26 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..a2363ebf92 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +cmd/build.go export-subst +*.go diff=golang diff --git a/cmd/build.go b/cmd/build.go index da80442449..76b40e5a08 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -5,40 +5,63 @@ import ( "bytes" "context" "os/exec" + "runtime/debug" "time" ) -// This is a helper for development. In production, we shouldn't assume that the -// process is running in a git repository or that git is installed. Our build -// system does this for release builds. +// Injected via git-export(1). See that man page and gitattributes(5). +const ( + // Needs a length check because GitHub zipballs/tarballs don't do the + // describe and just strip the pattern. + describe = `$Format:%(describe:match=v4.*)$` + revision = `$Format:%h (%cI)$` +) func init() { - defer func() { - if Version == "" { - Version = `???` - } - }() - ctx, done := context.WithTimeout(context.Background(), 5*time.Second) - defer done() - if Version != "" { + switch { + case Version != "": // Had our version injected at build: do nothing. - return - } - if _, err := exec.LookPath("git"); err != nil { - // Couldn't find a git binary: do nothing. - return - } - if err := exec.CommandContext(ctx, "git", "rev-parse", "--show-toplevel").Run(); err != nil { - // Couldn't find a git repository: do nothing. - return + case len(describe) > 0 && describe[0] != '$': + Version = describe + case revision[0] == '$': + // This is a helper for development. In production, we shouldn't assume + // that the process is running in a git repository or that git is + // installed. This is quite possibly wrong if run from the wrong working + // directory. + Version = `(random source build)` + ctx, done := context.WithTimeout(context.Background(), 5*time.Second) + defer done() + if _, err := exec.LookPath("git"); err != nil { + // Couldn't find a git binary: do nothing. + break + } + if err := exec.CommandContext(ctx, "git", "rev-parse", "--show-toplevel").Run(); err != nil { + // Couldn't find a git repository: do nothing. + break + } + out, err := exec.CommandContext(ctx, "git", "describe").Output() + if err != nil { + // Couldn't describe the current commit: do nothing. + break + } + Version = string(bytes.TrimSpace(out)) + default: + Version = revision } - out, err := exec.CommandContext(ctx, "git", "describe").Output() - if err != nil { - // Couldn't describe the current commit: do nothing. - return + + // If we can read out the current binary's debug info, append the claircore + // version if there was a replacement. + if info, ok := debug.ReadBuildInfo(); ok { + for _, m := range info.Deps { + if m.Path != "github.com/quay/claircore" { + continue + } + if m.Replace != nil && m.Replace.Version != m.Version { + Version += " (claircore " + m.Replace.Version + ")" + } + } } - Version = string(bytes.TrimSpace(out)) } -// Version is a version string, injected at build time for release builds. +// Version is a version string, injected at release time for release builds. var Version string