package run import ( "context" "os/exec" "strings" "testing" "github.com/barerepo/server/internal/gitx" ) func repoWithCommit(t *testing.T) (dir, sha string) { t.Helper() if _, err := gitx.Version(context.Background()); err != nil { t.Skip("git is not installed") } dir = t.TempDir() run := func(args ...string) string { t.Helper() cmd := exec.Command(gitx.Bin, args...) cmd.Dir = dir cmd.Env = append(cmd.Environ(), "GIT_AUTHOR_NAME=m", "GIT_AUTHOR_EMAIL=m@x", "GIT_COMMITTER_NAME=m", "GIT_COMMITTER_EMAIL=m@x") out, err := cmd.CombinedOutput() if err != nil { t.Fatalf("git %v: %v\n%s", args, err, out) } return strings.TrimSpace(string(out)) } run("init", "-q", "-b", "master") run("commit", "-q", "--allow-empty", "-m", "first") return dir, run("rev-parse", "HEAD") } func TestAppendAndRead(t *testing.T) { ctx := context.Background() dir, sha := repoWithCommit(t) rec := Record{Runner: "uproar.local", Labels: []string{"build", "test"}, Started: 1787074650, Duration: 18, Exit: 0} if err := Append(ctx, dir, sha, rec, "$ make ci\nok\n"); err != nil { t.Fatal(err) } got, err := For(ctx, dir, sha) if err != nil || len(got) != 1 { t.Fatalf("For = %v, %v", got, err) } if got[0].Runner != "uproar.local" || got[0].Exit != 0 || got[0].Duration != 18 { t.Errorf("record lost fields: %+v", got[0]) } if log, _ := Log(ctx, dir, got[0]); log != "$ make ci\nok\n" { t.Errorf("log = %q", log) } // A commit can be built more than once, and both runs survive. if err := Append(ctx, dir, sha, Record{Runner: "lisa-mbp", Started: 1787074999, Exit: 2}, "boom"); err != nil { t.Fatal(err) } got, _ = For(ctx, dir, sha) if len(got) != 2 { t.Fatalf("got %d runs, want 2", len(got)) } if got[0].Runner != "lisa-mbp" { t.Errorf("runs are not newest first: %+v", got) } if !got[0].Failed() { t.Error("exit 2 is not reported as failed") } } // Chapter 16 claims build history is readable with git alone, and this is that claim tested. func TestGitCanReadTheRuns(t *testing.T) { ctx := context.Background() dir, sha := repoWithCommit(t) if err := Append(ctx, dir, sha, Record{Runner: "uproar.local", Started: 1, Exit: 0}, "ok"); err != nil { t.Fatal(err) } out, err := gitx.Run(ctx, dir, "log", "--show-notes=runs", "--max-count=1") if err != nil { t.Fatal(err) } if !strings.Contains(out, "Notes (runs)") || !strings.Contains(out, "uproar.local") { t.Errorf("git log --show-notes=runs did not print the run:\n%s", out) } } // A long log goes to a blob so that reading the notes ref stays cheap. func TestLargeLogGoesToABlob(t *testing.T) { ctx := context.Background() dir, sha := repoWithCommit(t) big := strings.Repeat("x", inlineLimit+1) if err := Append(ctx, dir, sha, Record{Runner: "r", Started: 1}, big); err != nil { t.Fatal(err) } got, _ := For(ctx, dir, sha) if got[0].Output != "" { t.Error("a large log was inlined") } if got[0].Log == "" { t.Fatal("a large log has no blob") } log, err := Log(ctx, dir, got[0]) if err != nil || len(log) != len(big) { t.Errorf("blob log came back as %d bytes, want %d (%v)", len(log), len(big), err) } }