package ci
import (
"slices"
"strings"
"testing"
)
// A PIPELINE MARKED "quarry_when": "default-branch" RUNS ON THE DEFAULT
// BRANCH AND NOWHERE ELSE, BY ANY DOOR.
//
// It is how a deploy is written: GitHub's `on: push: branches: [main]`.
// A branch tip, a proposed branch's merge and a re-run of a branch
// check-in all skip it; a trunk check-in and a re-run of one run it.
func TestADefaultBranchPipelineRunsOnTheDefaultBranchOnly(t *testing.T) {
srv, started := startedEngine(t)
e := New(srv.URL)
st := &fakeStore{mark: map[string]string{"alpha": "old"}}
repo := deployRepo()
round := func(news ...Checkin) []string {
repo.news = news
if err := Trigger(e, st, "alpha", repo, "http://x/r/alpha"); err != nil {
t.Fatal(err)
}
return started()
}
if got := round(Checkin{Hash: "b1", Branch: "feat"}); !slices.Equal(got, []string{"b1 ci/test.json"}) {
t.Errorf("FAIL: a branch push started %v; want only ci/test.json", got)
}
if got := round(Checkin{Hash: "t1", Branch: "trunk"}); !slices.Equal(got, []string{"t1 ci/deploy.json", "t1 ci/test.json"}) {
t.Errorf("FAIL: a trunk check-in started %v; want the deploy too", got)
}
repo.landings["feat"] = true
if _, err := RunPairAt(e, st, "alpha", repo, "http://x/r/alpha", "feat", "b2", "t1"); err != nil {
t.Fatal(err)
}
if got := started(); !slices.Equal(got, []string{Pair("b2", "t1") + " ci/test.json"}) {
t.Errorf("FAIL: a landing's merge started %v; want no deploy", got)
}
if err := RerunPairAt(e, st, "alpha", repo, "http://x/r/alpha", "feat", "b2", "t1"); err != nil {
t.Fatal(err)
}
if got := started(); !slices.Equal(got, []string{Pair("b2", "t1") + " ci/test.json"}) {
t.Errorf("FAIL: a Re-run of a landing's merge started %v; want no deploy", got)
}
repo.branches = map[string]string{"b1": "feat", "t1": "trunk"}
if err := RunAt(e, st, "alpha", repo, "http://x/r/alpha", "b1", ""); err != nil {
t.Fatal(err)
}
if got := started(); !slices.Equal(got, []string{"b1 ci/test.json"}) {
t.Errorf("FAIL: a re-run of a branch check-in started %v; want no deploy", got)
}
if err := RunAt(e, st, "alpha", repo, "http://x/r/alpha", "t1", ""); err != nil {
t.Fatal(err)
}
if got := started(); !slices.Equal(got, []string{"t1 ci/deploy.json", "t1 ci/test.json"}) {
t.Errorf("FAIL: a re-run of a trunk check-in started %v; want the deploy too", got)
}
if err := RunAt(e, st, "alpha", repo, "http://x/r/alpha", "unknown", ""); err != nil {
t.Fatal(err)
}
if got := started(); !slices.Equal(got, []string{"unknown ci/test.json"}) {
t.Errorf("FAIL: a re-run of a check-in on no known branch started %v; want no deploy", got)
}
t.Log("ok: the deploy runs on trunk check-ins and their re-runs, and nowhere else")
}
// An unknown quarry_when is refused in words, never run everywhere: a
// misspelt "default-branch" would otherwise deploy every branch.
func TestAnUnknownQuarryWhenIsRefused(t *testing.T) {
srv, started := startedEngine(t)
e := New(srv.URL)
repo := deployRepo()
repo.blobs["ci/deploy.json"] = []byte(`{"name":"deploy","version":"1.0","quarry_when":"default_branch","steps":[]}`)
repo.branches = map[string]string{"b1": "feat"}
err := RunAt(e, &fakeStore{mark: map[string]string{}}, "alpha", repo, "http://x/r/alpha", "b1", "")
if err == nil || !strings.Contains(err.Error(), "default_branch") {
t.Errorf("FAIL: an unknown quarry_when answered %v; want a refusal naming it", err)
}
if got := started(); !slices.Equal(got, []string{"b1 ci/test.json"}) {
t.Errorf("FAIL: beside the refused pipeline, started %v; want ci/test.json", got)
}
t.Log("ok: a misspelt quarry_when is refused alone")
}
func deployRepo() *fakeRepo {
return &fakeRepo{
files: []string{"ci/deploy.json", "ci/test.json"},
blobs: map[string][]byte{
"ci/test.json": []byte(`{"name":"test","version":"1.0","steps":[]}`),
"ci/deploy.json": []byte(`{"name":"deploy","version":"1.0","quarry_when":"default-branch","steps":[]}`),
},
landings: map[string]bool{},
}
}