@@ -7,16 +7,13 @@ package lifecycle |
| 7 | import ( | 7 | import ( |
| 8 | "context" | 8 | "context" |
| 9 | "errors" | 9 | "errors" |
| 10 | - "fmt" | | |
| 11 | "strings" | 10 | "strings" |
| 12 | - "time" | | |
| 13 | | 11 | |
| 14 | "github.com/jackc/pgx/v5" | 12 | "github.com/jackc/pgx/v5" |
| 15 | - "github.com/jackc/pgx/v5/pgtype" | | |
| 16 | | 13 | |
| | 14 | + "github.com/tenseleyFlow/shithub/internal/actions/checksync" |
| | 15 | + "github.com/tenseleyFlow/shithub/internal/actions/runstate" |
| 17 | actionsdb "github.com/tenseleyFlow/shithub/internal/actions/sqlc" | 16 | actionsdb "github.com/tenseleyFlow/shithub/internal/actions/sqlc" |
| 18 | - "github.com/tenseleyFlow/shithub/internal/checks" | | |
| 19 | - checksdb "github.com/tenseleyFlow/shithub/internal/checks/sqlc" | | |
| 20 | "github.com/tenseleyFlow/shithub/internal/infra/metrics" | 17 | "github.com/tenseleyFlow/shithub/internal/infra/metrics" |
| 21 | ) | 18 | ) |
| 22 | | 19 | |
@@ -72,7 +69,7 @@ func CancelRun(ctx context.Context, deps Deps, runID int64, reason string) (Canc |
| 72 | runConclusion actionsdb.CheckConclusion | 69 | runConclusion actionsdb.CheckConclusion |
| 73 | ) | 70 | ) |
| 74 | if len(changed) > 0 { | 71 | if len(changed) > 0 { |
| 75 | - runCompleted, runConclusion, err = rollupRunAfterCancel(ctx, q, tx, runID) | 72 | + runCompleted, runConclusion, err = runstate.RollupAfterCancel(ctx, q, tx, runID) |
| 76 | if err != nil { | 73 | if err != nil { |
| 77 | return CancelResult{}, err | 74 | return CancelResult{}, err |
| 78 | } | 75 | } |
@@ -137,7 +134,7 @@ func CancelJob(ctx context.Context, deps Deps, jobID int64, reason string) (Canc |
| 137 | runConclusion actionsdb.CheckConclusion | 134 | runConclusion actionsdb.CheckConclusion |
| 138 | ) | 135 | ) |
| 139 | if len(changed) > 0 { | 136 | if len(changed) > 0 { |
| 140 | - runCompleted, runConclusion, err = rollupRunAfterCancel(ctx, q, tx, runID) | 137 | + runCompleted, runConclusion, err = runstate.RollupAfterCancel(ctx, q, tx, runID) |
| 141 | if err != nil { | 138 | if err != nil { |
| 142 | return CancelResult{}, err | 139 | return CancelResult{}, err |
| 143 | } | 140 | } |
@@ -157,63 +154,6 @@ func CancelJob(ctx context.Context, deps Deps, jobID int64, reason string) (Canc |
| 157 | }, nil | 154 | }, nil |
| 158 | } | 155 | } |
| 159 | | 156 | |
| 160 | -func rollupRunAfterCancel( | | |
| 161 | - ctx context.Context, | | |
| 162 | - q *actionsdb.Queries, | | |
| 163 | - tx pgx.Tx, | | |
| 164 | - runID int64, | | |
| 165 | -) (bool, actionsdb.CheckConclusion, error) { | | |
| 166 | - jobs, err := q.ListJobsForRun(ctx, tx, runID) | | |
| 167 | - if err != nil { | | |
| 168 | - return false, "", err | | |
| 169 | - } | | |
| 170 | - runConclusion, complete := deriveWorkflowRunConclusion(jobs) | | |
| 171 | - if complete { | | |
| 172 | - if _, err := q.CompleteWorkflowRun(ctx, tx, actionsdb.CompleteWorkflowRunParams{ | | |
| 173 | - ID: runID, | | |
| 174 | - Conclusion: runConclusion, | | |
| 175 | - }); err != nil { | | |
| 176 | - return false, "", err | | |
| 177 | - } | | |
| 178 | - return true, runConclusion, nil | | |
| 179 | - } | | |
| 180 | - if err := q.MarkWorkflowRunRunning(ctx, tx, runID); err != nil { | | |
| 181 | - return false, "", err | | |
| 182 | - } | | |
| 183 | - return false, "", nil | | |
| 184 | -} | | |
| 185 | - | | |
| 186 | -func deriveWorkflowRunConclusion(jobs []actionsdb.ListJobsForRunRow) (actionsdb.CheckConclusion, bool) { | | |
| 187 | - if len(jobs) == 0 { | | |
| 188 | - return actionsdb.CheckConclusionFailure, true | | |
| 189 | - } | | |
| 190 | - worst := actionsdb.CheckConclusionSuccess | | |
| 191 | - for _, job := range jobs { | | |
| 192 | - switch job.Status { | | |
| 193 | - case actionsdb.WorkflowJobStatusCompleted, actionsdb.WorkflowJobStatusCancelled, actionsdb.WorkflowJobStatusSkipped: | | |
| 194 | - default: | | |
| 195 | - return "", false | | |
| 196 | - } | | |
| 197 | - if job.Status == actionsdb.WorkflowJobStatusCancelled { | | |
| 198 | - worst = actionsdb.CheckConclusionCancelled | | |
| 199 | - continue | | |
| 200 | - } | | |
| 201 | - if !job.Conclusion.Valid { | | |
| 202 | - return actionsdb.CheckConclusionFailure, true | | |
| 203 | - } | | |
| 204 | - c := job.Conclusion.CheckConclusion | | |
| 205 | - if c == actionsdb.CheckConclusionFailure || | | |
| 206 | - c == actionsdb.CheckConclusionTimedOut || | | |
| 207 | - c == actionsdb.CheckConclusionActionRequired { | | |
| 208 | - return c, true | | |
| 209 | - } | | |
| 210 | - if c == actionsdb.CheckConclusionCancelled { | | |
| 211 | - worst = actionsdb.CheckConclusionCancelled | | |
| 212 | - } | | |
| 213 | - } | | |
| 214 | - return worst, true | | |
| 215 | -} | | |
| 216 | - | | |
| 217 | func recordCancelledJobs(jobs []actionsdb.WorkflowJob, reason string) { | 157 | func recordCancelledJobs(jobs []actionsdb.WorkflowJob, reason string) { |
| 218 | if len(jobs) == 0 { | 158 | if len(jobs) == 0 { |
| 219 | return | 159 | return |
@@ -235,74 +175,12 @@ func cancelReason(reason string) string { |
| 235 | } | 175 | } |
| 236 | | 176 | |
| 237 | func syncChangedJobChecks(ctx context.Context, deps Deps, jobs []actionsdb.WorkflowJob) { | 177 | func syncChangedJobChecks(ctx context.Context, deps Deps, jobs []actionsdb.WorkflowJob) { |
| 238 | - for _, job := range jobs { | 178 | + checksync.ChangedJobs(ctx, checksync.Deps{Pool: deps.Pool, Logger: deps.Logger}, jobs) |
| 239 | - if job.Status != actionsdb.WorkflowJobStatusRunning && | | |
| 240 | - job.Status != actionsdb.WorkflowJobStatusCompleted && | | |
| 241 | - job.Status != actionsdb.WorkflowJobStatusCancelled { | | |
| 242 | - continue | | |
| 243 | - } | | |
| 244 | - if err := SyncCheckRunForJob(ctx, deps, job); err != nil && deps.Logger != nil { | | |
| 245 | - deps.Logger.WarnContext(ctx, "actions lifecycle: sync check_run", "job_id", job.ID, "error", err) | | |
| 246 | - } | | |
| 247 | - } | | |
| 248 | } | 179 | } |
| 249 | | 180 | |
| 250 | // SyncCheckRunForJob mirrors an Actions workflow_job row into its check_run | 181 | // SyncCheckRunForJob mirrors an Actions workflow_job row into its check_run |
| 251 | // row. Missing check rows are non-fatal because check creation is already | 182 | // row. Missing check rows are non-fatal because check creation is already |
| 252 | // best-effort in the trigger path and can be reconciled independently. | 183 | // best-effort in the trigger path and can be reconciled independently. |
| 253 | func SyncCheckRunForJob(ctx context.Context, deps Deps, job actionsdb.WorkflowJob) error { | 184 | func SyncCheckRunForJob(ctx context.Context, deps Deps, job actionsdb.WorkflowJob) error { |
| 254 | - if deps.Pool == nil { | 185 | + return checksync.Job(ctx, checksync.Deps{Pool: deps.Pool, Logger: deps.Logger}, job) |
| 255 | - return errors.New("actions lifecycle: nil Pool") | | |
| 256 | - } | | |
| 257 | - run, err := actionsdb.New().GetWorkflowRunByID(ctx, deps.Pool, job.RunID) | | |
| 258 | - if err != nil { | | |
| 259 | - return err | | |
| 260 | - } | | |
| 261 | - name := strings.TrimSpace(job.JobName) | | |
| 262 | - if name == "" { | | |
| 263 | - name = job.JobKey | | |
| 264 | - } | | |
| 265 | - checkRun, err := checksdb.New().GetCheckRunByExternalID(ctx, deps.Pool, checksdb.GetCheckRunByExternalIDParams{ | | |
| 266 | - RepoID: run.RepoID, | | |
| 267 | - HeadSha: run.HeadSha, | | |
| 268 | - Name: name, | | |
| 269 | - ExternalID: pgtype.Text{String: fmt.Sprintf("workflow_run:%d:job:%s", job.RunID, job.JobKey), Valid: true}, | | |
| 270 | - }) | | |
| 271 | - if err != nil { | | |
| 272 | - if errors.Is(err, pgx.ErrNoRows) { | | |
| 273 | - return nil | | |
| 274 | - } | | |
| 275 | - return err | | |
| 276 | - } | | |
| 277 | - params := checks.UpdateParams{ | | |
| 278 | - RunID: checkRun.ID, | | |
| 279 | - HasStatus: true, | | |
| 280 | - HasStartedAt: true, | | |
| 281 | - StartedAt: timeFromPg(job.StartedAt), | | |
| 282 | - } | | |
| 283 | - switch job.Status { | | |
| 284 | - case actionsdb.WorkflowJobStatusRunning: | | |
| 285 | - params.Status = "in_progress" | | |
| 286 | - case actionsdb.WorkflowJobStatusCompleted, actionsdb.WorkflowJobStatusCancelled: | | |
| 287 | - params.Status = "completed" | | |
| 288 | - params.HasConclusion = true | | |
| 289 | - if job.Conclusion.Valid { | | |
| 290 | - params.Conclusion = string(job.Conclusion.CheckConclusion) | | |
| 291 | - } else if job.Status == actionsdb.WorkflowJobStatusCancelled { | | |
| 292 | - params.Conclusion = string(actionsdb.CheckConclusionCancelled) | | |
| 293 | - } | | |
| 294 | - params.HasCompletedAt = true | | |
| 295 | - params.CompletedAt = timeFromPg(job.CompletedAt) | | |
| 296 | - default: | | |
| 297 | - return nil | | |
| 298 | - } | | |
| 299 | - _, err = checks.Update(ctx, checks.Deps{Pool: deps.Pool, Logger: deps.Logger}, params) | | |
| 300 | - return err | | |
| 301 | -} | | |
| 302 | - | | |
| 303 | -func timeFromPg(ts pgtype.Timestamptz) time.Time { | | |
| 304 | - if !ts.Valid { | | |
| 305 | - return time.Time{} | | |
| 306 | - } | | |
| 307 | - return ts.Time | | |
| 308 | } | 186 | } |