bastion 0.55.3
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
package main
|
||||
|
||||
// A git run against a repository that keeps a file in Git LFS, with the real
|
||||
// git-lfs. It runs only where git-lfs is installed; every server it talks to
|
||||
// is in this test, on loopback.
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/cgi"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func lfsPointer(body string) (oid, pointer string) {
|
||||
sum := sha256.Sum256([]byte(body))
|
||||
oid = hex.EncodeToString(sum[:])
|
||||
return oid, fmt.Sprintf("version https://git-lfs.github.com/spec/v1\noid sha256:%s\nsize %d\n", oid, len(body))
|
||||
}
|
||||
|
||||
func TestAGitRunWithTheRealGitLFS(t *testing.T) {
|
||||
if out, err := exec.Command("git-lfs", "version").Output(); err != nil || !strings.HasPrefix(string(out), "git-lfs/") {
|
||||
t.Skip("git-lfs is not installed")
|
||||
}
|
||||
f := newGitRunFixture(t)
|
||||
realGit, _ := exec.LookPath("git")
|
||||
want := "Basic " + base64.StdEncoding.EncodeToString([]byte("harness:"+gitRunToken))
|
||||
|
||||
var mu sync.Mutex
|
||||
store := map[string][]byte{}
|
||||
v1oid, v1ptr := lfsPointer("v1\n")
|
||||
store[v1oid] = []byte("v1\n")
|
||||
var srvURL string
|
||||
backend := &cgi.Handler{Path: realGit, Args: []string{"http-backend"}, Root: "/git",
|
||||
Env: []string{"GIT_PROJECT_ROOT=" + filepath.Dir(f.origin), "GIT_HTTP_EXPORT_ALL=1",
|
||||
"REMOTE_USER=harness", "GIT_CONFIG_NOSYSTEM=1", "HOME=" + t.TempDir()}}
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasPrefix(r.URL.Path, "/store/") { // the object hrefs the batch answer gives
|
||||
oid := strings.TrimPrefix(r.URL.Path, "/store/")
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if r.Method == http.MethodPut {
|
||||
b, _ := io.ReadAll(r.Body)
|
||||
store[oid] = b
|
||||
return
|
||||
}
|
||||
_, _ = w.Write(store[oid])
|
||||
return
|
||||
}
|
||||
if r.Header.Get("Authorization") != want {
|
||||
w.Header().Set("WWW-Authenticate", `Basic realm="test"`)
|
||||
http.Error(w, "auth", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
if !strings.Contains(r.URL.Path, "/info/lfs/") {
|
||||
backend.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
if !strings.HasSuffix(r.URL.Path, "/objects/batch") {
|
||||
http.NotFound(w, r) // locks: not supported here
|
||||
return
|
||||
}
|
||||
var req struct {
|
||||
Operation string `json:"operation"`
|
||||
Objects []struct {
|
||||
Oid string `json:"oid"`
|
||||
Size int64 `json:"size"`
|
||||
} `json:"objects"`
|
||||
}
|
||||
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||
var objs []map[string]any
|
||||
mu.Lock()
|
||||
for _, o := range req.Objects {
|
||||
obj := map[string]any{"oid": o.Oid, "size": o.Size, "authenticated": true}
|
||||
_, have := store[o.Oid]
|
||||
if req.Operation == "download" || !have {
|
||||
obj["actions"] = map[string]any{req.Operation: map[string]any{"href": srvURL + "/store/" + o.Oid}}
|
||||
}
|
||||
objs = append(objs, obj)
|
||||
}
|
||||
mu.Unlock()
|
||||
w.Header().Set("Content-Type", "application/vnd.git-lfs+json")
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"transfer": "basic", "objects": objs})
|
||||
}))
|
||||
t.Cleanup(srv.Close)
|
||||
srvURL = srv.URL
|
||||
var foreignHits atomic.Int64
|
||||
foreign := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
foreignHits.Add(1)
|
||||
http.Error(w, "no", http.StatusForbidden)
|
||||
}))
|
||||
t.Cleanup(foreign.Close)
|
||||
|
||||
seed := filepath.Join(t.TempDir(), "s")
|
||||
testGit(t, "", "clone", "-q", f.origin, seed)
|
||||
for name, body := range map[string]string{".gitattributes": "*.bin filter=lfs diff=lfs merge=lfs -text\n", "big.bin": v1ptr} {
|
||||
if err := os.WriteFile(filepath.Join(seed, name), []byte(body), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
testGit(t, seed, "add", "-A")
|
||||
testGit(t, seed, "commit", "-q", "-m", "an lfs file")
|
||||
testGit(t, seed, "push", "-q", "origin", "main")
|
||||
|
||||
// The agent changes the large file and names a foreign LFS server.
|
||||
f.setAgent(t, `set -e
|
||||
cd "$1"
|
||||
grep -qx v1 big.bin
|
||||
echo v2 > big.bin
|
||||
printf '[lfs]\n\turl = `+foreign.URL+`/x.git/info/lfs\n\tpushurl = `+foreign.URL+`/x.git/info/lfs\n[remote "origin"]\n\tlfsurl = `+foreign.URL+`/y\n' > .lfsconfig
|
||||
`)
|
||||
repoURL := strings.Replace(srv.URL, "http://", "http://harness:"+gitRunToken+"@", 1) + "/git/" + filepath.Base(f.origin)
|
||||
b, code := runGit(harnessSpec{Mode: "git", HarnessID: "h1", Image: "harness:test",
|
||||
RepoURL: repoURL, Branch: "agent-work", MaxMinutes: 1})
|
||||
t.Logf("result: %s", b)
|
||||
if code != 0 {
|
||||
t.Fatalf("the run failed")
|
||||
}
|
||||
v2oid, v2ptr := lfsPointer("v2\n")
|
||||
if got := testGit(t, f.origin, "show", "agent-work:big.bin"); got != v2ptr {
|
||||
t.Errorf("big.bin on the branch = %q, want the pointer to v2", got)
|
||||
}
|
||||
mu.Lock()
|
||||
got := string(store[v2oid])
|
||||
mu.Unlock()
|
||||
if got != "v2\n" {
|
||||
t.Errorf("the LFS object for v2 was not sent to the repository's own LFS server (%q)", got)
|
||||
}
|
||||
if n := foreignHits.Load(); n != 0 {
|
||||
t.Errorf("the foreign LFS server named in .lfsconfig got %d requests", n)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user