bastion 0.55.3
ci / personal-data (push) Successful in 5s
ci / test (push) Successful in 3m51s
ci / fuzz (push) Successful in 2m55s

This commit is contained in:
Privatae
2026-10-25 23:16:45 +00:00
parent 77b7853ae1
commit 8822d5df85
136 changed files with 8638 additions and 1641 deletions
@@ -0,0 +1,360 @@
package main
// What a git run hands the agent, how it ends when its commit cannot be made,
// and the git-lfs filter it supplies itself.
import (
"bufio"
"bytes"
"fmt"
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"testing"
)
const gitRunToken = "tok3n0f7hisrun5a1e"
// The agent's clone names the repository without the run's token, and the
// token is in no file of the tree it is handed; the run still pushes.
func TestAGitRunHandsTheAgentNoToken(t *testing.T) {
f := newGitRunFixture(t)
snap := filepath.Join(t.TempDir(), "agent-saw")
f.setAgent(t, "cp -a \"$1\" "+snap+" && cd \"$1\" && echo new > edit.txt\n")
b, code := runGit(harnessSpec{Mode: "git", HarnessID: "h1", Image: "harness:test",
RepoURL: "file://harness:" + gitRunToken + "@" + f.origin, Branch: "agent-work", MaxMinutes: 1})
if code != 0 {
t.Fatalf("the run failed: %s", b)
}
if bytes.Contains(b, []byte(gitRunToken)) {
t.Errorf("the result carries the token: %s", b)
}
n := 0
err := filepath.WalkDir(snap, func(p string, d fs.DirEntry, err error) error {
if err != nil || !d.Type().IsRegular() {
return err
}
n++
body, err := os.ReadFile(p)
if err == nil && bytes.Contains(body, []byte(gitRunToken)) {
t.Errorf("the token is in the agent's tree, in %s", p[len(snap):])
}
return err
})
if err != nil || n == 0 {
t.Fatalf("the agent's tree was not read (%d files): %v", n, err)
}
if got := testGit(t, f.origin, "show", "agent-work:edit.txt"); got != "new\n" {
t.Errorf("edit.txt = %q", got)
}
}
func TestRepoURLPartsAndLFSPins(t *testing.T) {
bare, secret, err := repoURLParts("https://host-user:" + gitRunToken + "@git.example.invalid/o/r.git")
if err != nil || bare != "https://git.example.invalid/o/r.git" || secret != gitRunToken {
t.Errorf("parts = %q, %q, %v", bare, secret, err)
}
if bare, secret, err := repoURLParts("/srv/x/origin.git"); err != nil || bare != "/srv/x/origin.git" || secret != "" {
t.Errorf("a path = %q, %q, %v", bare, secret, err)
}
pins := strings.Join(lfsEndpointPins("https://u:"+gitRunToken+"@git.example.invalid/o/r"), " ")
for _, k := range []string{"lfs.url", "lfs.pushurl", "remote.origin.lfsurl", "remote.origin.lfspushurl"} {
if !strings.Contains(pins, k+"=https://u:"+gitRunToken+"@git.example.invalid/o/r.git/info/lfs") {
t.Errorf("%s is not pinned to the repository's own LFS address: %s", k, pins)
}
}
if p := lfsEndpointPins("/srv/x/origin.git"); p != nil {
t.Errorf("a path got pins: %v", p)
}
}
// standInGit puts a git on PATH that fails on the subcommand fail and is the
// real git otherwise.
func standInGit(t *testing.T, fail string) {
t.Helper()
real, err := exec.LookPath("git")
if err != nil {
t.Skip("no git")
}
bin := t.TempDir()
script := "#!/bin/sh\nfor a; do [ \"$a\" = " + fail + " ] && { echo 'stand-in: " + fail + " failed' >&2; exit 128; }; done\nexec " + real + " \"$@\"\n"
if err := os.WriteFile(filepath.Join(bin, "git"), []byte(script), 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("PATH", bin+string(os.PathListSeparator)+os.Getenv("PATH"))
}
func branchPushed(f gitRunFixture) bool {
return exec.Command("git", "--git-dir", f.origin, "rev-parse", "--verify", "-q", "agent-work").Run() == nil
}
// A commit that fails is the run failing: nothing is pushed.
func TestAGitRunWhoseCommitFailsPushesNothing(t *testing.T) {
f := newGitRunFixture(t)
f.setAgent(t, "cd \"$1\" && echo new > edit.txt\n")
standInGit(t, "commit")
res, code := f.run(t)
if code == 0 || res["ok"] != false {
t.Errorf("a run whose commit failed reads ok: code %d, %v", code, res)
}
if e, _ := res["error"].(string); !strings.Contains(e, "commit") || !strings.Contains(e, "nothing was pushed") {
t.Errorf("the error does not say the commit failed: %q", e)
}
if branchPushed(f) {
t.Error("the branch was pushed")
}
}
// A run that changed nothing is ok, says so, and pushes no branch.
func TestAGitRunThatChangesNothingPushesNothing(t *testing.T) {
f := newGitRunFixture(t)
f.setAgent(t, "true\n")
res, code := f.run(t)
if code != 0 || res["ok"] != true || res["changed"] != false {
t.Errorf("want ok with changed false: code %d, %v", code, res)
}
if _, ok := res["branch"]; ok {
t.Errorf("the result names a branch: %v", res["branch"])
}
if branchPushed(f) {
t.Error("a branch was pushed for a run that changed nothing")
}
}
// Names a file system may open as .git are left out of the copy, and the
// rest of the run goes on.
func TestAGitRunLeavesOutEveryNameThatOpensAsDotGit(t *testing.T) {
f := newGitRunFixture(t)
names := []string{".git.", ".GIT ", "git~1", "GIT~1. ", ".g\u200cit", ".git::$INDEX_ALLOCATION"}
script := "cd \"$1\" && echo new > edit.txt\n"
for _, n := range names {
script += "mkdir '" + n + "' && echo '[core]' > '" + n + "/config'\n"
}
f.setAgent(t, script)
res, code := f.run(t)
if code != 0 || res["ok"] != true {
t.Fatalf("the run failed: code %d, %v", code, res)
}
files := testGit(t, f.origin, "ls-tree", "-r", "--name-only", "-z", "agent-work")
for _, n := range names {
if strings.Contains(files, n+"/") {
t.Errorf("%q is in the commit", n)
}
}
skipped, _ := res["worktree_skipped"].([]any)
listed := map[string]bool{}
for _, s := range skipped {
listed[fmt.Sprint(s)] = true
}
for _, n := range names {
if !listed[n] {
t.Errorf("%q is not listed as left out: %v", n, skipped)
}
}
for _, n := range []string{".git", ".Git", ".git.", ".git . .", "GiT~1", ".gi\ufefft", ".git:x"} {
if !dotGitName(n) {
t.Errorf("dotGitName(%q) = false", n)
}
}
for _, n := range []string{".gitignore", ".gitattributes", "git", ".github", "git~2", "x.git"} {
if dotGitName(n) {
t.Errorf("dotGitName(%q) = true", n)
}
}
}
// With git-lfs installed, the bastion's own git calls clean and smudge
// through it and push its objects; the agent's .git cannot replace it, and a
// filter of another name the agent's .gitattributes names runs nothing.
func TestAGitRunUsesTheLFSFilterOnlyFromThisProcess(t *testing.T) {
f := newGitRunFixture(t)
seed := filepath.Join(t.TempDir(), "s")
testGit(t, "", "clone", "-q", f.origin, seed)
if err := os.WriteFile(filepath.Join(seed, ".gitattributes"), []byte("*.bin filter=lfs -text\n"), 0o644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(seed, "big.bin"), []byte("v1\n"), 0o644); err != nil {
t.Fatal(err)
}
testGit(t, seed, "add", "-A")
testGit(t, seed, "commit", "-q", "-m", "lfs")
testGit(t, seed, "push", "-q", "origin", "main")
bin := t.TempDir()
lfsLog := filepath.Join(t.TempDir(), "lfs.log")
wrapper := "#!/bin/sh\nGO_HELPER_GITLFS=1 GO_HELPER_GITLFS_LOG=" + lfsLog + " exec " + os.Args[0] +
" -test.run='^TestHelperGitLFS$' -- \"$@\"\n"
if err := os.WriteFile(filepath.Join(bin, "git-lfs"), []byte(wrapper), 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("PATH", bin+string(os.PathListSeparator)+os.Getenv("PATH"))
mark := func(name string) string { return "touch " + filepath.Join(f.marks, name) }
f.setAgent(t, `set -e
cd "$1"
git config filter.lfs.process '`+mark("agent-lfs-process")+`; exit 1'
git config filter.lfs.clean '`+mark("agent-lfs-clean")+`; cat'
git config filter.evil.clean '`+mark("evil")+`; cat'
printf '*.bin filter=lfs -text\n*.txt filter=evil\n' > .gitattributes
echo v2 > big.bin
echo new > edit.txt
`)
res, code := f.run(t)
if code != 0 || res["ok"] != true {
t.Fatalf("the run failed: code %d, %v", code, res)
}
ents, _ := os.ReadDir(f.marks)
for _, e := range ents {
t.Errorf("the agent's %s ran as this process", e.Name())
}
logged, _ := os.ReadFile(lfsLog)
for _, want := range []string{"smudge big.bin", "clean big.bin", "push origin agent-work"} {
if !strings.Contains(string(logged), want+"\n") {
t.Errorf("git-lfs did not %s; it logged:\n%s", want, logged)
}
}
for _, line := range strings.Split(string(logged), "\n") {
if strings.HasSuffix(line, ".txt") {
t.Errorf("git-lfs ran for a file of another filter: %s", line)
}
}
if got := testGit(t, f.origin, "show", "agent-work:big.bin"); got != "v2\n" {
t.Errorf("big.bin = %q", got)
}
}
// TestHelperGitLFS is the stand-in git-lfs: run by the wrapper above, it is
// an identity filter that logs what it was asked to do.
func TestHelperGitLFS(t *testing.T) {
if os.Getenv("GO_HELPER_GITLFS") != "1" {
return
}
args := os.Args
for i, a := range args {
if a == "--" {
args = args[i+1:]
break
}
}
logf, err := os.OpenFile(os.Getenv("GO_HELPER_GITLFS_LOG"), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o644)
if err != nil {
os.Exit(2)
}
switch {
case len(args) > 0 && args[0] == "filter-process":
if err := helperFilterProcess(logf); err != nil {
fmt.Fprintln(os.Stderr, "stand-in git-lfs:", err)
os.Exit(1)
}
case len(args) > 0 && (args[0] == "clean" || args[0] == "smudge"):
fmt.Fprintf(logf, "%s %s\n", args[0], args[len(args)-1])
_, _ = io.Copy(os.Stdout, os.Stdin)
default:
fmt.Fprintln(logf, strings.Join(args, " "))
}
logf.Close()
os.Exit(0)
}
func pktRead(r *bufio.Reader) ([]byte, bool, error) {
var h [4]byte
if _, err := io.ReadFull(r, h[:]); err != nil {
return nil, false, err
}
n, err := strconv.ParseUint(string(h[:]), 16, 16)
if err != nil {
return nil, false, err
}
if n == 0 {
return nil, true, nil
}
b := make([]byte, n-4)
_, err = io.ReadFull(r, b)
return b, false, err
}
func pktList(r *bufio.Reader) ([]string, error) {
var out []string
for {
b, flush, err := pktRead(r)
if err != nil || flush {
return out, err
}
out = append(out, strings.TrimSuffix(string(b), "\n"))
}
}
func pktWrite(w io.Writer, lines ...string) {
for _, l := range lines {
fmt.Fprintf(w, "%04x%s", len(l)+4, l)
}
_, _ = w.Write([]byte("0000"))
}
// helperFilterProcess speaks git's long-running filter protocol, version 2,
// returning every file as it came.
func helperFilterProcess(logf io.Writer) error {
r, w := bufio.NewReader(os.Stdin), bufio.NewWriter(os.Stdout)
if _, err := pktList(r); err != nil {
return err
}
pktWrite(w, "git-filter-server\n", "version=2\n")
if err := w.Flush(); err != nil {
return err
}
if _, err := pktList(r); err != nil {
return err
}
pktWrite(w, "capability=clean\n", "capability=smudge\n")
if err := w.Flush(); err != nil {
return err
}
for {
head, err := pktList(r)
if err == io.EOF {
return nil
}
if err != nil {
return err
}
cmd, path := "", ""
for _, kv := range head {
k, v, _ := strings.Cut(kv, "=")
switch k {
case "command":
cmd = v
case "pathname":
path = v
}
}
var body bytes.Buffer
for {
b, flush, err := pktRead(r)
if err != nil {
return err
}
if flush {
break
}
body.Write(b)
}
fmt.Fprintf(logf, "%s %s\n", cmd, path)
pktWrite(w, "status=success\n")
data := body.Bytes()
for len(data) > 0 {
n := min(len(data), 65516)
fmt.Fprintf(w, "%04x", n+4)
_, _ = w.Write(data[:n])
data = data[n:]
}
_, _ = w.Write([]byte("0000"))
pktWrite(w)
if err := w.Flush(); err != nil {
return err
}
}
}