internal/store/cisecrets.go
141 lines · 3922 bytes
1package store
2
3// SetBuildSecret stores or replaces one secret. The value never leaves the
4// server except inside a claimed build's environment.
5func (s *Store) SetBuildSecret(repoID int64, name, value string) error {
6 _, err := s.DB.Exec(`
7 INSERT INTO build_secrets (repo_id, name, value) VALUES (?, ?, ?)
8 ON CONFLICT (repo_id, name) DO UPDATE SET value = excluded.value`,
9 repoID, name, value)
10 return err
11}
12
13func (s *Store) RemoveBuildSecret(repoID int64, name string) error {
14 res, err := s.DB.Exec("DELETE FROM build_secrets WHERE repo_id = ? AND name = ?", repoID, name)
15 if err != nil {
16 return err
17 }
18 if n, _ := res.RowsAffected(); n == 0 {
19 return ErrNotFound
20 }
21 return nil
22}
23
24// ListBuildSecretNames returns names only; values are for builds.
25func (s *Store) ListBuildSecretNames(repoID int64) ([]string, error) {
26 rows, err := s.DB.Query("SELECT name FROM build_secrets WHERE repo_id = ? ORDER BY name", repoID)
27 if err != nil {
28 return nil, err
29 }
30 defer rows.Close()
31 var out []string
32 for rows.Next() {
33 var n string
34 if err := rows.Scan(&n); err != nil {
35 return nil, err
36 }
37 out = append(out, n)
38 }
39 return out, rows.Err()
40}
41
42// BuildSecrets returns the values, for injection into a claimed build.
43func (s *Store) BuildSecrets(repoID int64) (map[string]string, error) {
44 rows, err := s.DB.Query("SELECT name, value FROM build_secrets WHERE repo_id = ?", repoID)
45 if err != nil {
46 return nil, err
47 }
48 defer rows.Close()
49 out := map[string]string{}
50 for rows.Next() {
51 var n, v string
52 if err := rows.Scan(&n, &v); err != nil {
53 return nil, err
54 }
55 out[n] = v
56 }
57 return out, rows.Err()
58}
59
60// Schedule is one repo job's cron entry.
61type Schedule struct {
62 RepoID int64
63 Job string
64 Cron string
65 NextRun string
66}
67
68// SyncSchedules replaces a repo's schedule set with the given entries,
69// preserving next_run for entries whose cron is unchanged.
70func (s *Store) SyncSchedules(repoID int64, entries []Schedule) error {
71 tx, err := s.DB.Begin()
72 if err != nil {
73 return err
74 }
75 defer tx.Rollback()
76 keep := map[string]bool{}
77 for _, e := range entries {
78 keep[e.Job] = true
79 if _, err := tx.Exec(`
80 INSERT INTO build_schedules (repo_id, job, cron, next_run) VALUES (?, ?, ?, ?)
81 ON CONFLICT (repo_id, job) DO UPDATE SET
82 next_run = CASE WHEN cron = excluded.cron THEN next_run ELSE excluded.next_run END,
83 cron = excluded.cron`,
84 repoID, e.Job, e.Cron, e.NextRun); err != nil {
85 return err
86 }
87 }
88 rows, err := tx.Query("SELECT job FROM build_schedules WHERE repo_id = ?", repoID)
89 if err != nil {
90 return err
91 }
92 var stale []string
93 for rows.Next() {
94 var j string
95 if err := rows.Scan(&j); err != nil {
96 rows.Close()
97 return err
98 }
99 if !keep[j] {
100 stale = append(stale, j)
101 }
102 }
103 rows.Close()
104 for _, j := range stale {
105 if _, err := tx.Exec("DELETE FROM build_schedules WHERE repo_id = ? AND job = ?", repoID, j); err != nil {
106 return err
107 }
108 }
109 return tx.Commit()
110}
111
112// DueSchedules returns entries whose next_run is at or before now.
113func (s *Store) DueSchedules(nowISO string) ([]Schedule, error) {
114 rows, err := s.DB.Query(
115 "SELECT repo_id, job, cron, next_run FROM build_schedules WHERE next_run <= ? ORDER BY next_run", nowISO)
116 if err != nil {
117 return nil, err
118 }
119 defer rows.Close()
120 var out []Schedule
121 for rows.Next() {
122 var e Schedule
123 if err := rows.Scan(&e.RepoID, &e.Job, &e.Cron, &e.NextRun); err != nil {
124 return nil, err
125 }
126 out = append(out, e)
127 }
128 return out, rows.Err()
129}
130
131// SetScheduleNext advances one entry's next firing time.
132func (s *Store) SetScheduleNext(repoID int64, job, nextRun string) error {
133 _, err := s.DB.Exec(
134 "UPDATE build_schedules SET next_run = ? WHERE repo_id = ? AND job = ?", nextRun, repoID, job)
135 return err
136}
137
138func (s *Store) RemoveSchedule(repoID int64, job string) error {
139 _, err := s.DB.Exec("DELETE FROM build_schedules WHERE repo_id = ? AND job = ?", repoID, job)
140 return err
141}