git: accept explicit commit hash for git context (#1765)

* git: accept explicit commit hash for git context

When checking out code from non-github repositories, the typical
assumptions may not be valid, e.g. that the only interesting
non-branch commits have ref names starting with refs/pull. A specific
example is fetching an un-merged commit from a gerrit repository by
commit hash.

This change just looks at the second part of the git context path and
checks if it's a SHA commit hash, and if so, will fetch and check out
this commit after cloning the repository.

Sample context argument:

    https://github.repo/project#e1772f228e06d15facdf175e5385e265b57068c0

* ci: fix test script to recognize any non-zero exit as an error

hack/linter.sh didn't properly install golangci-lint in hack/bin as I
already have another version of golangci-lint on my PATH, but then it
failed to execute because it was looking for it specifically in
hack/bin.

When the executable is not found, the exit code is 127 instead of 1,
and so test.sh ignored the error.

Two fixes:

1. `test.sh`:
  - Use `if (script) ...` instead of assigning / checking a result
    variable to determine if each validation script passed or failed.

2. `hack/linter.sh`:
  - Instead of checking for golangci-lint on the path, just
    specifically check for an executable file (`test -x`) in the
    expected location.

Co-authored-by: Wade Carpenter <wwade@users.noreply.github.com>
This commit is contained in:
wwade
2021-10-19 19:27:15 -07:00
committed by GitHub
co-authored by Wade Carpenter
parent 3b42fe45ea
commit 82fc94d930
4 changed files with 102 additions and 32 deletions
+17 -8
View File
@@ -17,6 +17,7 @@ limitations under the License.
package buildcontext
import (
"errors"
"fmt"
"os"
"strings"
@@ -66,8 +67,14 @@ func (g *Git) UnpackTarFromBuildContext() (string, error) {
SingleBranch: g.opts.GitSingleBranch,
RecurseSubmodules: getRecurseSubmodules(g.opts.GitRecurseSubmodules),
}
var fetchRef string
if len(parts) > 1 {
if !strings.HasPrefix(parts[1], "refs/pull/") {
if plumbing.IsHash(parts[1]) || !strings.HasPrefix(parts[1], "refs/pull/") {
// Handle any non-branch refs separately. First, clone the repo HEAD, and
// then fetch and check out the fetchRef.
fetchRef = parts[1]
} else {
// Branches will be cloned directly.
options.ReferenceName = plumbing.ReferenceName(parts[1])
}
}
@@ -82,23 +89,25 @@ func (g *Git) UnpackTarFromBuildContext() (string, error) {
logrus.Debugf("Getting source from reference %s", options.ReferenceName)
r, err := git.PlainClone(directory, false, &options)
if err != nil {
return directory, err
}
if len(parts) > 1 && strings.HasPrefix(parts[1], "refs/pull/") {
if fetchRef != "" {
err = r.Fetch(&git.FetchOptions{
RemoteName: "origin",
RefSpecs: []config.RefSpec{config.RefSpec(parts[1] + ":" + parts[1])},
RefSpecs: []config.RefSpec{config.RefSpec(fetchRef + ":" + fetchRef)},
})
if err != nil {
if err != nil && !errors.Is(err, git.NoErrAlreadyUpToDate) {
return directory, err
}
}
checkoutRef := fetchRef
if len(parts) > 2 {
checkoutRef = parts[2]
}
if checkoutRef != "" {
// ... retrieving the commit being pointed by HEAD
_, err := r.Head()
if err != nil {
@@ -112,13 +121,13 @@ func (g *Git) UnpackTarFromBuildContext() (string, error) {
// ... checking out to desired commit
err = w.Checkout(&git.CheckoutOptions{
Hash: plumbing.NewHash(parts[2]),
Hash: plumbing.NewHash(checkoutRef),
})
if err != nil {
return directory, err
}
}
return directory, err
return directory, nil
}
func getGitReferenceName(directory string, url string, branch string) (plumbing.ReferenceName, error) {