internal/store/statuses.go
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}