Skip to content
quarry Artifact [dfbef07ae6]
Login

Artifact [dfbef07ae6]

Artifact dfbef07ae69d13de0df448c3e2fd1841f012cd4a5cb11e6372bfc4040d74cea0:


package api

// NotifyRedTrunk tells a repository's owners that a pipeline failed on
// a check-in of its default branch. The caller (the CI poller, on the
// lease holder) decides the run failed and was not cancelled; this
// decides whether the check-in is on the default branch and who hears.
//
// The owners are the deed holder and whoever owns the default branch,
// once each. It rides the landing family because a red trunk is the
// same question a landing asks — may work merge here — and so the one
// preference a person already has for "trunk wants my attention"
// answers for it too, with no fifth family in the matrix.
//
// The idempotency key is the check-in and the pipeline, not the run: a
// re-run of the same pipeline on the same check-in that fails again is
// the same news.
func (d Deps) NotifyRedTrunk(repo, checkin, pipeline, runID string) {
	if d.Repos == nil {
		return
	}
	r, ok := d.Repos.Get(repo)
	if !ok || r.Index == nil {
		return
	}
	branch := r.Index.DefaultBranch()
	on, err := r.Index.BranchOf([]string{checkin})
	if err != nil || on[checkin] != branch {
		return
	}
	var owners []string
	if d.Owners != nil {
		if o, err := d.Owners.OwnerOf(repo); err == nil {
			owners = append(owners, o)
		}
	}
	_, branchOwners := d.protectionOf(repo, branch)
	told := map[string]bool{"": true}
	short := checkin
	if len(short) > 12 {
		short = short[:12]
	}
	for _, who := range append(owners, branchOwners...) {
		if told[who] {
			continue
		}
		told[who] = true
		d.fireNotify(NotifyEvent{
			Workflow: "quarry-landing", To: who,
			Payload: map[string]any{
				"repo": repo, "from": "ci", "surface": "ci",
				"summary": pipeline + " failed on " + branch + " at " + short,
				"link":    d.link("/r/" + repo + "/ci/run/" + runID),
			},
			TxnID: "ci:red:" + repo + ":" + checkin + ":" + pipeline + ":" + who,
		})
	}
}