internal/store/statuses.go

v0.3.0
gitbay/internal/store/statuses.go history · blame · raw

67 lines · 2193 bytes

 1package store
 2
 3type CommitStatus struct {
 4	Context     string
 5	State       string // pending | success | failure | error
 6	Description string
 7	TargetURL   string
 8	Creator     string
 9	UpdatedAt   string
10}
11
12// SetCommitStatus upserts the latest state for one context on one commit.
13// A zero creatorID records no creator (system actions like the scheduler).
14func (s *Store) SetCommitStatus(repoID int64, sha, context, state, description, targetURL string, creatorID int64) error {
15	var creator any
16	if creatorID != 0 {
17		creator = creatorID
18	}
19	_, err := s.DB.Exec(`
20		INSERT INTO commit_statuses (repo_id, commit_sha, context, state, description, target_url, creator_id)
21		VALUES (?, ?, ?, ?, ?, ?, ?)
22		ON CONFLICT (repo_id, commit_sha, context) DO UPDATE SET
23			state = excluded.state, description = excluded.description,
24			target_url = excluded.target_url, creator_id = excluded.creator_id,
25			updated_at = strftime('%Y-%m-%dT%H:%M:%fZ','now')`,
26		repoID, sha, context, state, description, targetURL, creator)
27	return err
28}
29
30// ListCommitStatuses returns the latest status per context for a commit.
31func (s *Store) ListCommitStatuses(repoID int64, sha string) ([]CommitStatus, error) {
32	rows, err := s.DB.Query(`
33		SELECT cs.context, cs.state, cs.description, cs.target_url, COALESCE(u.username, ''), cs.updated_at
34		FROM commit_statuses cs LEFT JOIN users u ON u.id = cs.creator_id
35		WHERE cs.repo_id = ? AND cs.commit_sha = ? ORDER BY cs.context`, repoID, sha)
36	if err != nil {
37		return nil, err
38	}
39	defer rows.Close()
40	var out []CommitStatus
41	for rows.Next() {
42		var c CommitStatus
43		if err := rows.Scan(&c.Context, &c.State, &c.Description, &c.TargetURL, &c.Creator, &c.UpdatedAt); err != nil {
44			return nil, err
45		}
46		out = append(out, c)
47	}
48	return out, rows.Err()
49}
50
51// CombinedStatus reduces per-context states to one: error/failure dominate,
52// then pending, then success; "" when no statuses exist.
53func CombinedStatus(statuses []CommitStatus) string {
54	if len(statuses) == 0 {
55		return ""
56	}
57	combined := "success"
58	for _, s := range statuses {
59		switch s.State {
60		case "error", "failure":
61			return "failure"
62		case "pending":
63			combined = "pending"
64		}
65	}
66	return combined
67}