-
Notifications
You must be signed in to change notification settings - Fork 331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bump min go version to 1.18 && read build info from embedded binary #2548
Changes from all commits
9ff63bf
d1a74c1
041b3d8
9bd6c91
e1dbd0a
512c6b4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
Copyright 2018 The Knative Authors | ||
Copyright 2022 The Knative Authors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
|
@@ -17,113 +17,66 @@ limitations under the License. | |
package changeset | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"errors" | ||
"regexp" | ||
"strings" | ||
"runtime/debug" | ||
"strconv" | ||
"sync" | ||
) | ||
|
||
const ( | ||
commitIDFile = "HEAD" | ||
koDataPathEnvName = "KO_DATA_PATH" | ||
// packedRefsFile is a file containing a list of refs, used to compact the | ||
// list of refs instead of storing them on the filesystem directly. | ||
// See https://git-scm.com/docs/git-pack-refs | ||
packedRefsFile = "packed-refs" | ||
) | ||
const Unknown = "unknown" | ||
|
||
var ( | ||
shaRegexp = regexp.MustCompile(`^[a-f0-9]{40,64}$`) | ||
rev string | ||
err error | ||
once sync.Once | ||
|
||
var commitIDRE = regexp.MustCompile(`^[a-f0-9]{40}$`) | ||
// for testing | ||
readBuildInfo = debug.ReadBuildInfo | ||
) | ||
|
||
// Get tries to fetch the first 7 digitals of GitHub commit ID from HEAD file in | ||
// KO_DATA_PATH. If it fails, it returns the error it gets. | ||
// Get returns the 'vcs.revision' property from the embedded build information | ||
// This function will return an error if value is not a valid Git SHA | ||
// | ||
// The result will have a '-dirty' suffix if the workspace was not clean | ||
func Get() (string, error) { | ||
data, err := readFileFromKoData(commitIDFile) | ||
if err != nil { | ||
return "", err | ||
once.Do(func() { | ||
rev, err = get() | ||
}) | ||
|
||
return rev, err | ||
} | ||
|
||
func get() (string, error) { | ||
info, ok := readBuildInfo() | ||
dprotaso marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if !ok { | ||
return "", errors.New("unable to read build info") | ||
} | ||
commitID := strings.TrimSpace(string(data)) | ||
if rID := strings.TrimPrefix(commitID, "ref: "); rID != commitID { | ||
// First try to read from the direct ref file - e.g. refs/heads/main | ||
data, err := readFileFromKoData(rID) | ||
if err != nil { | ||
if !os.IsNotExist(err) { | ||
return "", err | ||
} | ||
|
||
// Ref file didn't exist - it might be contained in the packed-refs | ||
// file. | ||
var pferr error | ||
data, pferr = findPackedRef(rID) | ||
// Only return the sub-error if the packed-refs file exists, otherwise | ||
// just let the original error return (e.g. treat it as if we didn't | ||
// even attempt the operation). This is primarily to keep the error | ||
// messages clean. | ||
if pferr != nil { | ||
if os.IsNotExist(pferr) { | ||
return "", err | ||
} | ||
return "", pferr | ||
} | ||
|
||
var revision string | ||
var modified bool | ||
|
||
for _, s := range info.Settings { | ||
switch s.Key { | ||
case "vcs.revision": | ||
revision = s.Value | ||
case "vcs.modified": | ||
modified, _ = strconv.ParseBool(s.Value) | ||
} | ||
commitID = strings.TrimSpace(string(data)) | ||
} | ||
if commitIDRE.MatchString(commitID) { | ||
return commitID[:7], nil | ||
} | ||
return "", fmt.Errorf("%q is not a valid GitHub commit ID", commitID) | ||
} | ||
|
||
// readFileFromKoData tries to read data as string from the file with given name | ||
// under KO_DATA_PATH then returns the content as string. The file is expected | ||
// to be wrapped into the container from /kodata by ko. If it fails, returns | ||
// the error it gets. | ||
func readFileFromKoData(filename string) ([]byte, error) { | ||
f, err := koDataFile(filename) | ||
if err != nil { | ||
return nil, err | ||
if revision == "" { | ||
return Unknown, nil | ||
} | ||
defer f.Close() | ||
return ioutil.ReadAll(f) | ||
} | ||
|
||
// readFileFromKoData tries to open the file with given name under KO_DATA_PATH. | ||
// The file is expected to be wrapped into the container from /kodata by ko. | ||
// If it fails, returns the error it gets. | ||
func koDataFile(filename string) (*os.File, error) { | ||
koDataPath := os.Getenv(koDataPathEnvName) | ||
if koDataPath == "" { | ||
return nil, fmt.Errorf("%q does not exist or is empty", koDataPathEnvName) | ||
if shaRegexp.MatchString(revision) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Technically, we don't need this check 😎 (not necessarily advice to remove it, just a funny coincidence) Actually, I wonder if this should just be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I'd leave it as - since I don't want to assume truncating will work for different VCS - ie svn is numeric so we'd be alternating the commit id There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A further improvement could be to do this only for vcs that use SHA's for revisions -ie git, hg etc. |
||
revision = revision[:7] | ||
} | ||
return os.Open(filepath.Join(koDataPath, filename)) | ||
} | ||
|
||
// findPackedRef searches the packed-ref file for ref values. | ||
// This can happen if the # of refs in a repo grows too much - git will try | ||
// and condense them into a file. | ||
// See https://git-scm.com/docs/git-pack-refs | ||
func findPackedRef(ref string) ([]byte, error) { | ||
f, err := koDataFile(packedRefsFile) | ||
if err != nil { | ||
return nil, err | ||
if modified { | ||
revision += "-dirty" | ||
} | ||
defer f.Close() | ||
|
||
scanner := bufio.NewScanner(f) | ||
for scanner.Scan() { | ||
// We only care about lines with `<commit> <ref>` pairs. | ||
// Why this might happen: | ||
// 1. Lines starting with ^ refer to unpeeled tag SHAs | ||
// (e.g. the commits pointed to by annotated tags) | ||
s := strings.Split(scanner.Text(), " ") | ||
if len(s) != 2 { | ||
continue | ||
} | ||
if ref == s[1] { | ||
return []byte(s[0]), nil | ||
} | ||
} | ||
return nil, fmt.Errorf("%q ref not found in packed-refs", ref) | ||
|
||
return revision, nil | ||
} |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
module knative.dev/pkg | ||
|
||
go 1.17 | ||
go 1.18 | ||
|
||
require ( | ||
cloud.google.com/go v0.98.0 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have a
changeset.MustGet
that panics if it can't detect the version? I'm updating some callsites to get this once atinit
-time, and they're all justlog.Fatal
ing if this returns an error. Or should this returnUnknown
if it can't read build info, and just never return an error?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about this - let me do it in a follow up