Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

180 lines
4.8 KiB
Go

package forge
import (
"context"
"os"
"os/exec"
"path/filepath"
"testing"
)
// Recorded GitHub REST responses (trimmed to the fields forge reads).
const prListJSON = `[
{
"number": 7,
"title": "Add forge",
"state": "open",
"draft": false,
"html_url": "https://github.com/octo/gortex/pull/7",
"mergeable_state": "clean",
"updated_at": "2026-06-01T10:00:00Z",
"user": {"login": "alice"},
"base": {"ref": "main"},
"head": {"ref": "feature", "sha": "headsha"}
}
]`
const prGetJSON = `{
"number": 7,
"title": "Add forge",
"state": "open",
"draft": false,
"html_url": "https://github.com/octo/gortex/pull/7",
"mergeable_state": "clean",
"updated_at": "2026-06-01T10:00:00Z",
"user": {"login": "alice"},
"base": {"ref": "main"},
"head": {"ref": "feature", "sha": "headsha"}
}`
const prFilesJSON = `[
{
"filename": "internal/forge/forge.go",
"status": "added",
"patch": "@@ -0,0 +1,3 @@\n+package forge\n+\n+// new\n"
},
{
"filename": "internal/forge/ghrest.go",
"previous_filename": "internal/forge/old.go",
"status": "renamed",
"patch": "@@ -1,2 +1,2 @@\n-old\n+new\n line2\n"
}
]`
const prReviewsJSON = `[
{"state": "APPROVED", "user": {"login": "bob"}, "submitted_at": "2026-06-01T09:00:00Z"},
{"state": "COMMENTED", "user": {"login": "carol"}, "submitted_at": "2026-06-01T09:30:00Z"},
{"state": "CHANGES_REQUESTED", "user": {"login": "carol"}, "submitted_at": "2026-06-01T09:40:00Z"}
]`
const checkRunsJSON = `{
"total_count": 2,
"check_runs": [
{"name": "build", "status": "completed", "conclusion": "success"},
{"name": "test", "status": "completed", "conclusion": "failure"}
]
}`
const combinedStatusJSON = `{
"state": "failure",
"sha": "headsha",
"total_count": 1,
"statuses": [
{"state": "success", "context": "lint"}
]
}`
func TestReviewDecision_LatestPerReviewer(t *testing.T) {
srv := fixtureServer(t)
c := newTestClient(t, srv.URL)
got, err := c.reviewDecision(context.Background(), 7)
if err != nil {
t.Fatalf("reviewDecision: %v", err)
}
// carol's latest non-comment state is CHANGES_REQUESTED → wins.
if got != "CHANGES_REQUESTED" {
t.Errorf("reviewDecision = %q, want CHANGES_REQUESTED", got)
}
}
func TestCIRollup(t *testing.T) {
srv := fixtureServer(t)
c := newTestClient(t, srv.URL)
got, err := c.ciRollup(context.Background(), "headsha")
if err != nil {
t.Fatalf("ciRollup: %v", err)
}
if got != "FAILURE" {
t.Errorf("ciRollup = %q, want FAILURE", got)
}
}
func TestCIRollup_NoRef(t *testing.T) {
c := &ghClient{owner: "octo", repo: "gortex"}
got, err := c.ciRollup(context.Background(), "")
if err != nil {
t.Fatalf("ciRollup: %v", err)
}
if got != "NONE" {
t.Errorf("ciRollup(empty ref) = %q, want NONE", got)
}
}
func TestParsePorcelainWorktrees(t *testing.T) {
out := "worktree /repo/main\nHEAD abcd1234\nbranch refs/heads/main\n\n" +
"worktree /repo/wt-feature\nHEAD ef567890\nbranch refs/heads/feature\n\n" +
"worktree /repo/detached\nHEAD 99999999\ndetached\n"
got := parsePorcelainWorktrees(out)
if len(got) != 3 {
t.Fatalf("got %d entries, want 3: %+v", len(got), got)
}
if got[0].Path != "/repo/main" || got[0].Branch != "main" || got[0].Head != "abcd1234" {
t.Errorf("entry[0] = %+v", got[0])
}
if got[1].Branch != "feature" {
t.Errorf("entry[1].Branch = %q, want feature", got[1].Branch)
}
if got[2].Branch != "" {
t.Errorf("detached entry must have empty Branch, got %q", got[2].Branch)
}
}
func TestLocalWorktrees(t *testing.T) {
if _, err := exec.LookPath("git"); err != nil {
t.Skip("git not on PATH")
}
dir := t.TempDir()
main := filepath.Join(dir, "main")
if err := os.MkdirAll(main, 0o755); err != nil {
t.Fatal(err)
}
runGit := func(wd string, args ...string) {
t.Helper()
cmd := exec.Command("git", args...)
cmd.Dir = wd
cmd.Env = append(os.Environ(),
"GIT_AUTHOR_NAME=t", "GIT_AUTHOR_EMAIL=t@t",
"GIT_COMMITTER_NAME=t", "GIT_COMMITTER_EMAIL=t@t")
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("git %v: %v\n%s", args, err, out)
}
}
runGit(main, "init", "-q", "-b", "main")
if err := os.WriteFile(filepath.Join(main, "f.txt"), []byte("x"), 0o644); err != nil {
t.Fatal(err)
}
runGit(main, "add", ".")
runGit(main, "commit", "-q", "-m", "init")
wt := filepath.Join(dir, "wt")
runGit(main, "worktree", "add", "-q", "-b", "feature", wt)
entries, err := LocalWorktrees(context.Background(), main)
if err != nil {
t.Fatalf("LocalWorktrees: %v", err)
}
if len(entries) != 2 {
t.Fatalf("got %d worktrees, want 2: %+v", len(entries), entries)
}
branches := map[string]bool{}
for _, e := range entries {
branches[e.Branch] = true
if e.Path == "" || e.Head == "" {
t.Errorf("entry missing path/head: %+v", e)
}
}
if !branches["main"] || !branches["feature"] {
t.Errorf("branches = %v, want main+feature", branches)
}
}