Skip to content
quarry Artifact [c68b3ab4cc]
Login

Artifact [c68b3ab4cc]

Artifact c68b3ab4cc5a8c4d06d72cc486dabc1e2e40fc3b4a3207271e49416b31eb0591:


package ci

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"regexp"
	"strings"
	"sync"
	"testing"
)

// permissionsKey is a permissions: key at any level; the file's comments
// may name it.
var permissionsKey = regexp.MustCompile(`(?m)^\s*permissions:`)

// QUARRY'S OWN RELEASE WORKFLOW, ci/release.yml (RFC 0020 §releases, RFC
// 0021 §runs): a version tag starts it, its one job names the release
// environment and is recorded as asking for y (uv: write) and the read
// letters, and the engine is handed the file with permissions: stripped.
func TestQuarryReleaseWorkflowRecordsItsLetters(t *testing.T) {
	spec, err := os.ReadFile("../../ci/release.yml")
	if err != nil {
		t.Fatal(err)
	}
	var mu sync.Mutex
	var compiled []string
	n := 0
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		mu.Lock()
		defer mu.Unlock()
		switch {
		case r.URL.Path == "/v1/ci/compile":
			var body struct{ Name, Spec string }
			json.NewDecoder(r.Body).Decode(&body)
			compiled = append(compiled, body.Spec)
			fmt.Fprintf(w, `{"workflow":{"name":%q},"registered":true,"on":{"tag":{"tags":["version-*"]}}}`, body.Name)
		case r.URL.Path == "/runs" && r.Method == http.MethodPost:
			n++
			w.WriteHeader(http.StatusCreated)
			fmt.Fprintf(w, `{"run_id":"r%d"}`, n)
		case r.URL.Path == "/runs":
			fmt.Fprint(w, `[]`)
		}
	}))
	defer srv.Close()
	e := New(srv.URL)
	st := &fakeStore{mark: map[string]string{"quarry": "t1"}, pushedBy: map[string]string{"s0": "tagger"}}
	repo := &fakeRepo{
		files: []string{"ci/release.yml"},
		blobs: map[string][]byte{"ci/release.yml": spec},
		news:  []Checkin{{Hash: "t1", Branch: "trunk", User: "author"}},
	}
	if err := TriggerTags(e, st, "quarry", repo, "u"); err != nil { // first sight
		t.Fatal(err)
	}
	repo.tags = []Tagged{{TagKey: TagKey{Src: "s0", Target: "t1", Name: "version-0.2.0"}, At: Checkin{Hash: "t1", Branch: "trunk", User: "author"}}}
	if err := TriggerTags(e, st, "quarry", repo, "u"); err != nil {
		t.Fatal(err)
	}
	got, ok := st.starts["r1"]
	if !ok {
		t.Fatalf("FAIL: the tag version-0.2.0 started no run; starts %+v", st.starts)
	}
	want := JobGrant{Environment: "release", Letters: "goy", Timeout: 60}
	if got.Event != "tag" || got.Starter != "tagger" || len(got.Jobs) != 1 || got.Jobs["release"] != want {
		t.Errorf("FAIL: the release run recorded %+v; want event tag, starter tagger, release: %+v", got, want)
	}
	if len(compiled) == 0 {
		t.Fatal("FAIL: the engine compiled nothing")
	}
	for _, s := range compiled {
		if permissionsKey.MatchString(s) {
			t.Errorf("FAIL: the engine was handed permissions:\n%s", s)
		}
		if !strings.Contains(s, "environment: release") || !strings.Contains(s, "scripts/release.sh") {
			t.Errorf("FAIL: the engine was not handed the release job:\n%s", s)
		}
	}
	t.Log("ok: ci/release.yml starts on version-*, records release/goy/60m, and the engine never sees permissions:")
}