From f0991ac4bca0ddad1f9378623e2225981ed6824a Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Fri, 6 Feb 2026 10:59:58 -0500 Subject: [PATCH 1/2] fix: don't exit immediately when no concluded workflow runs to retry There is a race condition between GetCIStatus (GraphQL statusCheckRollup) and RerunFailedWorkflowsForCommit (REST ListRepositoryWorkflowRuns). The rollup reports failure as soon as any individual job fails, but the workflow run only gets a "failure" conclusion once all jobs complete. When one job fails while others are still running, the tool would find no retryable runs and exit immediately. Instead, continue polling so the next check cycle can retry once the workflow run has concluded. Co-authored-by: Cursor --- cmd/wait-for-github/pr.go | 13 +++++-- cmd/wait-for-github/pr_test.go | 55 +++++++++++++++++++++++++++--- internal/github/github.go | 22 +++++++----- internal/github/github_test.go | 62 +++++++++++++++++++++++----------- 4 files changed, 117 insertions(+), 35 deletions(-) diff --git a/cmd/wait-for-github/pr.go b/cmd/wait-for-github/pr.go index 31cea76..df3f48a 100644 --- a/cmd/wait-for-github/pr.go +++ b/cmd/wait-for-github/pr.go @@ -200,7 +200,7 @@ func (pr *prCheck) Check(ctx context.Context) error { pr.logger.InfoContext(ctx, "CI failed, attempting to retry failed GitHub Actions", "retries_done", pr.retriesDone, "retries_allowed", pr.actionRetries) - rerunCount, err := pr.githubClient.RerunFailedWorkflowsForCommit(ctx, pr.owner, pr.repo, sha) + rerunCount, hasRunsInProgress, err := pr.githubClient.RerunFailedWorkflowsForCommit(ctx, pr.owner, pr.repo, sha) if err != nil { pr.logger.WarnContext(ctx, "failed to rerun workflows, will retry", "error", err) return nil // Continue waiting and try again @@ -213,7 +213,16 @@ func (pr *prCheck) Check(ctx context.Context) error { return nil // Continue waiting } - // No workflows were rerun (maybe non-Action failures), fail immediately + if hasRunsInProgress { + // No concluded workflow runs to retry yet, but some are still running. + // This happens when a job fails but other jobs in the same workflow + // run are still in progress — the run won't have a "failure" conclusion + // until all jobs complete. Keep waiting so we can retry on the next poll. + pr.logger.InfoContext(ctx, "CI failed but workflow runs still in progress, will keep waiting") + return nil + } + + // No workflows were rerun and none are in progress — fail immediately pr.logger.InfoContext(ctx, "CI failed with no GitHub Actions to retry, exiting") return cli.Exit("CI failed", 1) } diff --git a/cmd/wait-for-github/pr_test.go b/cmd/wait-for-github/pr_test.go index 21b4ea3..84ebcbe 100644 --- a/cmd/wait-for-github/pr_test.go +++ b/cmd/wait-for-github/pr_test.go @@ -39,9 +39,10 @@ type fakeGithubClientPRCheck struct { getCIStatusError error rerunFailedWorkflowsError error - CIStatus github.CIStatus - RerunCount int - RerunCalledCount int + CIStatus github.CIStatus + RerunCount int + HasRunsInProgress bool + RerunCalledCount int } func (fg *fakeGithubClientPRCheck) IsPRMergedOrClosed(ctx context.Context, owner, repo string, pr int) (string, bool, int64, error) { @@ -56,9 +57,9 @@ func (fg *fakeGithubClientPRCheck) GetCIStatus(ctx context.Context, owner, repo return fg.CIStatus, fg.getCIStatusError } -func (fg *fakeGithubClientPRCheck) RerunFailedWorkflowsForCommit(ctx context.Context, owner, repo, commitHash string) (int, error) { +func (fg *fakeGithubClientPRCheck) RerunFailedWorkflowsForCommit(ctx context.Context, owner, repo, commitHash string) (int, bool, error) { fg.RerunCalledCount++ - return fg.RerunCount, fg.rerunFailedWorkflowsError + return fg.RerunCount, fg.HasRunsInProgress, fg.rerunFailedWorkflowsError } func TestPRCheck(t *testing.T) { @@ -176,6 +177,50 @@ func TestPRCheck(t *testing.T) { } } +// TestPRCheckRetryWithInProgressWorkflow tests the race condition where GetCIStatus +// reports failure (a job has failed) but the workflow run hasn't concluded yet because +// other jobs are still running. RerunFailedWorkflowsForCommit returns 0 on the first +// call (no concluded runs to retry), and on the next poll the workflow has completed +// and can be retried. +func TestPRCheckRetryWithInProgressWorkflow(t *testing.T) { + t.Parallel() + + fakeClient := &fakeGithubClientPRCheck{ + CIStatus: github.CIStatusFailed, + RerunCount: 0, // Workflow run hasn't concluded yet, no runs match "failure" conclusion + HasRunsInProgress: true, // Other jobs in the workflow are still running + } + + pr := &prCheck{ + prConfig: prConfig{ + owner: "owner", + repo: "repo", + pr: 1, + actionRetries: 2, + }, + githubClient: fakeClient, + logger: testLogger, + } + + // First check: CI reports failure (from a failed job), but the workflow run + // is still in progress so RerunFailedWorkflowsForCommit finds nothing to retry. + // Should continue waiting because runs are still in progress. + err := pr.Check(context.Background()) + require.NoError(t, err, "should continue waiting when workflow runs are still in progress") + require.Equal(t, 1, fakeClient.RerunCalledCount) + require.Equal(t, 0, pr.retriesDone, "retriesDone should not increment when no workflows were rerun") + + // Simulate the workflow run completing — it now has conclusion "failure" and is retryable. + fakeClient.RerunCount = 1 + fakeClient.HasRunsInProgress = false + + // Second check: CI still failed, workflow run now concluded and gets retried. + err = pr.Check(context.Background()) + require.NoError(t, err, "should continue waiting after successful rerun") + require.Equal(t, 2, fakeClient.RerunCalledCount) + require.Equal(t, 1, pr.retriesDone, "retriesDone should increment after successful rerun") +} + type fakeFileWriter struct { filename string data []byte diff --git a/internal/github/github.go b/internal/github/github.go index 6edf41d..2d6495e 100644 --- a/internal/github/github.go +++ b/internal/github/github.go @@ -66,7 +66,7 @@ type GetDetailedCIStatus interface { } type RerunFailedWorkflows interface { - RerunFailedWorkflowsForCommit(ctx context.Context, owner, repo, commitHash string) (int, error) + RerunFailedWorkflowsForCommit(ctx context.Context, owner, repo, commitHash string) (int, bool, error) } type CheckCIStatus interface { @@ -687,8 +687,8 @@ func (c GHClient) GetDetailedCIStatus(ctx context.Context, owner, repoName, ref } // RerunFailedWorkflowsForCommit finds all failed GitHub Actions workflow runs for a commit and re-runs them. -// Returns the number of workflows that were re-run. -func (c GHClient) RerunFailedWorkflowsForCommit(ctx context.Context, owner, repoName, commitHash string) (int, error) { +// Returns the number of workflows that were re-run and whether any runs are still in progress. +func (c GHClient) RerunFailedWorkflowsForCommit(ctx context.Context, owner, repoName, commitHash string) (int, bool, error) { listOptions := github.ListOptions{ PerPage: 100, } @@ -700,16 +700,17 @@ func (c GHClient) RerunFailedWorkflowsForCommit(ctx context.Context, owner, repo var failedRunIDs []int64 seenRuns := make(map[int64]bool) + hasRunsInProgress := false for { runs, resp, err := c.client.Actions.ListRepositoryWorkflowRuns(ctx, owner, repoName, opts) if err != nil { - return 0, fmt.Errorf("failed to list workflow runs: %w", err) + return 0, false, fmt.Errorf("failed to list workflow runs: %w", err) } respErr := c.handleResponseError(resp, "ListRepositoryWorkflowRuns", owner, repoName) if respErr != nil { - return 0, respErr + return 0, false, respErr } for _, run := range runs.WorkflowRuns { @@ -720,6 +721,11 @@ func (c GHClient) RerunFailedWorkflowsForCommit(ctx context.Context, owner, repo // See https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-workflow // Can be one of: completed, action_required, cancelled, failure, neutral, skipped, stale, success, timed_out, in_progress, queued, requested, waiting, pending + status := strings.ToLower(run.GetStatus()) + if status != "completed" { + hasRunsInProgress = true + } + conclusion := strings.ToLower(run.GetConclusion()) retryableConclusions := []string{"failure", "timed_out"} if slices.Contains(retryableConclusions, conclusion) { @@ -738,15 +744,15 @@ func (c GHClient) RerunFailedWorkflowsForCommit(ctx context.Context, owner, repo c.logger.InfoContext(ctx, "re-running failed workflow", "run_id", runID) resp, err := c.client.Actions.RerunFailedJobsByID(ctx, owner, repoName, runID) if err != nil { - return rerunCount, fmt.Errorf("failed to rerun workflow %d: %w", runID, err) + return rerunCount, hasRunsInProgress, fmt.Errorf("failed to rerun workflow %d: %w", runID, err) } respErr := c.handleResponseError(resp, "RerunFailedJobsByID", owner, repoName) if respErr != nil { - return rerunCount, respErr + return rerunCount, hasRunsInProgress, respErr } rerunCount++ } - return rerunCount, nil + return rerunCount, hasRunsInProgress, nil } diff --git a/internal/github/github_test.go b/internal/github/github_test.go index 21b1abb..3c92c53 100644 --- a/internal/github/github_test.go +++ b/internal/github/github_test.go @@ -1302,17 +1302,18 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { t.Parallel() tests := []struct { - name string - workflowRuns []*github.WorkflowRun - rerunShouldFail bool - expectedRerunCount int - expectedError bool - expectedRerunCalled int + name string + workflowRuns []*github.WorkflowRun + rerunShouldFail bool + expectedRerunCount int + expectedHasRunsInProgress bool + expectedError bool + expectedRerunCalled int }{ { name: "reruns failed workflow", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Conclusion: github.String("failure")}, + {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, }, expectedRerunCount: 1, expectedRerunCalled: 1, @@ -1320,7 +1321,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "reruns timed_out workflow", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Conclusion: github.String("timed_out")}, + {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("timed_out")}, }, expectedRerunCount: 1, expectedRerunCalled: 1, @@ -1328,7 +1329,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "does not rerun successful workflow", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Conclusion: github.String("success")}, + {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("success")}, }, expectedRerunCount: 0, expectedRerunCalled: 0, @@ -1336,7 +1337,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "does not rerun cancelled workflow", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Conclusion: github.String("cancelled")}, + {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("cancelled")}, }, expectedRerunCount: 0, expectedRerunCalled: 0, @@ -1344,7 +1345,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "does not rerun skipped workflow", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Conclusion: github.String("skipped")}, + {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("skipped")}, }, expectedRerunCount: 0, expectedRerunCalled: 0, @@ -1352,9 +1353,9 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "reruns multiple failed workflows", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Conclusion: github.String("failure")}, - {ID: github.Int64(2), Conclusion: github.String("timed_out")}, - {ID: github.Int64(3), Conclusion: github.String("success")}, + {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, + {ID: github.Int64(2), Status: github.String("completed"), Conclusion: github.String("timed_out")}, + {ID: github.Int64(3), Status: github.String("completed"), Conclusion: github.String("success")}, }, expectedRerunCount: 2, expectedRerunCalled: 2, @@ -1368,13 +1369,32 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "rerun API failure returns error", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Conclusion: github.String("failure")}, + {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, }, rerunShouldFail: true, expectedRerunCount: 0, expectedError: true, expectedRerunCalled: 5, // retries 5 times before failing }, + { + name: "reports in-progress runs", + workflowRuns: []*github.WorkflowRun{ + {ID: github.Int64(1), Status: github.String("in_progress"), Conclusion: github.String("")}, + }, + expectedRerunCount: 0, + expectedHasRunsInProgress: true, + expectedRerunCalled: 0, + }, + { + name: "in-progress run alongside failed run", + workflowRuns: []*github.WorkflowRun{ + {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, + {ID: github.Int64(2), Status: github.String("in_progress"), Conclusion: github.String("")}, + }, + expectedRerunCount: 1, + expectedHasRunsInProgress: true, + expectedRerunCalled: 1, + }, } for _, tt := range tests { @@ -1406,7 +1426,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { ) ghClient := newClientFromMock(t, mockedHTTPClient, "") - count, err := ghClient.RerunFailedWorkflowsForCommit(ctx, "owner", "repo", "abc123") + count, hasRunsInProgress, err := ghClient.RerunFailedWorkflowsForCommit(ctx, "owner", "repo", "abc123") if tt.expectedError { require.Error(t, err) @@ -1414,6 +1434,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { require.NoError(t, err) } require.Equal(t, tt.expectedRerunCount, count) + require.Equal(t, tt.expectedHasRunsInProgress, hasRunsInProgress) require.Equal(t, tt.expectedRerunCalled, rerunCallCount) }) } @@ -1434,7 +1455,7 @@ func TestRerunFailedWorkflowsForCommit_ListError(t *testing.T) { ) ghClient := newClientFromMock(t, mockedHTTPClient, "") - _, err := ghClient.RerunFailedWorkflowsForCommit(ctx, "owner", "repo", "abc123") + _, _, err := ghClient.RerunFailedWorkflowsForCommit(ctx, "owner", "repo", "abc123") require.Error(t, err) require.Contains(t, err.Error(), "failed to list workflow runs") @@ -1448,8 +1469,8 @@ func TestRerunFailedWorkflowsForCommit_DeduplicatesRuns(t *testing.T) { // Simulate the same run appearing twice (edge case) workflowRuns := []*github.WorkflowRun{ - {ID: github.Int64(1), Conclusion: github.String("failure")}, - {ID: github.Int64(1), Conclusion: github.String("failure")}, // duplicate + {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, + {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, // duplicate } mockedHTTPClient := mock.NewMockedHTTPClient( @@ -1470,10 +1491,11 @@ func TestRerunFailedWorkflowsForCommit_DeduplicatesRuns(t *testing.T) { ) ghClient := newClientFromMock(t, mockedHTTPClient, "") - count, err := ghClient.RerunFailedWorkflowsForCommit(ctx, "owner", "repo", "abc123") + count, hasRunsInProgress, err := ghClient.RerunFailedWorkflowsForCommit(ctx, "owner", "repo", "abc123") require.NoError(t, err) require.Equal(t, 1, count) + require.False(t, hasRunsInProgress) require.Equal(t, 1, rerunCallCount) } From 8f5282bed5463108cb0eec4ab2399d38760df20a Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Fri, 6 Feb 2026 11:19:03 -0500 Subject: [PATCH 2/2] Constants for various GH values --- internal/github/github.go | 85 ++++++++++++++++++-------- internal/github/github_test.go | 106 ++++++++++++++++----------------- 2 files changed, 112 insertions(+), 79 deletions(-) diff --git a/internal/github/github.go b/internal/github/github.go index 2d6495e..eb0fd6b 100644 --- a/internal/github/github.go +++ b/internal/github/github.go @@ -99,6 +99,41 @@ const ( CIStatusSkipped ) +// Workflow run and check run status values. +// See: https://docs.github.com/en/rest/actions/workflow-runs +const ( + RunStatusCompleted = "completed" + RunStatusActionRequired = "action_required" + RunStatusInProgress = "in_progress" + RunStatusQueued = "queued" + RunStatusRequested = "requested" + RunStatusWaiting = "waiting" + RunStatusPending = "pending" +) + +// Workflow run and check run conclusion values. +// See: https://docs.github.com/en/rest/actions/workflow-runs +const ( + RunConclusionSuccess = "success" + RunConclusionFailure = "failure" + RunConclusionCancelled = "cancelled" + RunConclusionTimedOut = "timed_out" + RunConclusionSkipped = "skipped" + RunConclusionNeutral = "neutral" + RunConclusionStale = "stale" + RunConclusionActionRequired = "action_required" + RunConclusionStartupFailure = "startup_failure" +) + +// Commit status context state values. +// See: https://docs.github.com/en/rest/commits/statuses +const ( + StatusStateSuccess = "success" + StatusStateFailure = "failure" + StatusStatePending = "pending" + StatusStateError = "error" +) + func (c CIStatus) String() string { switch c { case CIStatusPassed: @@ -160,15 +195,15 @@ func (c CheckRun) String() string { func (c CheckRun) Outcome() CIStatus { switch strings.ToLower(c.Status) { - case "completed": + case RunStatusCompleted: switch strings.ToLower(c.Conclusion) { - case "success": + case RunConclusionSuccess: return CIStatusPassed - case "startup_failure": + case RunConclusionStartupFailure: return CIStatusFailed - case "failure": + case RunConclusionFailure: return CIStatusFailed - case "skipped": + case RunConclusionSkipped: return CIStatusSkipped default: return CIStatusUnknown @@ -197,11 +232,11 @@ func (s StatusContext) String() string { func (s StatusContext) Outcome() CIStatus { switch strings.ToLower(s.State) { - case "success": + case StatusStateSuccess: return CIStatusPassed - case "failure": + case StatusStateFailure: return CIStatusFailed - case "error": + case StatusStateError: return CIStatusFailed default: return CIStatusUnknown @@ -456,9 +491,9 @@ func (c GHClient) GetCIStatus(ctx context.Context, owner, repoName, ref string, return CIStatusPassed, nil } - isSuccess := strings.ToLower(rollup.State) == "success" - isFailure := strings.ToLower(rollup.State) == "failure" - isPending := strings.ToLower(rollup.State) == "pending" + isSuccess := strings.ToLower(rollup.State) == StatusStateSuccess + isFailure := strings.ToLower(rollup.State) == StatusStateFailure + isPending := strings.ToLower(rollup.State) == StatusStatePending // return early if all checks and statuses are successful. no need to evaluate individual nodes in the response. if isSuccess { @@ -482,8 +517,8 @@ func (c GHClient) GetCIStatus(ctx context.Context, owner, repoName, ref string, } for _, node := range nodes { - isCheckFailure := strings.ToLower(node.CheckRun.Conclusion) == "failure" - isStatusFailure := strings.ToLower(node.StatusContext.State) == "failure" + isCheckFailure := strings.ToLower(node.CheckRun.Conclusion) == RunConclusionFailure + isStatusFailure := strings.ToLower(node.StatusContext.State) == StatusStateFailure checkRunName := node.CheckRun.Name statusContextName := node.StatusContext.Context @@ -558,18 +593,18 @@ func (c GHClient) getOneStatus(ctx context.Context, owner, repoName, ref, check for _, checkRun := range checkRuns { switch checkRun.GetStatus() { - case "completed": + case RunStatusCompleted: switch checkRun.GetConclusion() { - case "success": + case RunConclusionSuccess: return CIStatusPassed, nil - case "skipped": + case RunConclusionSkipped: return CIStatusPassed, nil default: return CIStatusFailed, nil } - case "queued": + case RunStatusQueued: return CIStatusPending, nil - case "in_progress": + case RunStatusInProgress: return CIStatusPending, nil } } @@ -610,13 +645,13 @@ func (c GHClient) getOneStatus(ctx context.Context, owner, repoName, ref, check } switch status.GetState() { - case "success": + case StatusStateSuccess: return CIStatusPassed, nil - case "failure": + case StatusStateFailure: return CIStatusFailed, nil - case "pending": + case StatusStatePending: return CIStatusPending, nil - case "error": + case StatusStateError: return CIStatusFailed, nil } } @@ -719,15 +754,13 @@ func (c GHClient) RerunFailedWorkflowsForCommit(ctx context.Context, owner, repo } seenRuns[run.GetID()] = true - // See https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-workflow - // Can be one of: completed, action_required, cancelled, failure, neutral, skipped, stale, success, timed_out, in_progress, queued, requested, waiting, pending status := strings.ToLower(run.GetStatus()) - if status != "completed" { + if status != RunStatusCompleted { hasRunsInProgress = true } conclusion := strings.ToLower(run.GetConclusion()) - retryableConclusions := []string{"failure", "timed_out"} + retryableConclusions := []string{RunConclusionFailure, RunConclusionTimedOut} if slices.Contains(retryableConclusions, conclusion) { failedRunIDs = append(failedRunIDs, run.GetID()) } diff --git a/internal/github/github_test.go b/internal/github/github_test.go index 3c92c53..a6ac81c 100644 --- a/internal/github/github_test.go +++ b/internal/github/github_test.go @@ -854,8 +854,8 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Name: github.String("check1"), - Status: github.String("completed"), - Conclusion: github.String("success"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionSuccess), }, }, }, @@ -869,8 +869,8 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Name: github.String("check1"), - Status: github.String("completed"), - Conclusion: github.String("failure"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionFailure), }, }, }, @@ -884,7 +884,7 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Name: github.String("check1"), - Status: github.String("queued"), + Status: github.String(RunStatusQueued), }, }, }, @@ -898,7 +898,7 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Name: github.String("check1"), - Status: github.String("in_progress"), + Status: github.String(RunStatusInProgress), }, }, }, @@ -912,8 +912,8 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Name: github.String("check1"), - Conclusion: github.String("skipped"), - Status: github.String("completed"), + Conclusion: github.String(RunConclusionSkipped), + Status: github.String(RunStatusCompleted), }, }, }, @@ -927,7 +927,7 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Context: github.String("check1"), - State: github.String("success"), + State: github.String(StatusStateSuccess), }, }, }, @@ -945,7 +945,7 @@ func TestGetCIStatusForChecks(t *testing.T) { }, { Context: github.String("check1"), - State: github.String("success"), + State: github.String(StatusStateSuccess), }, }, }, @@ -965,7 +965,7 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Context: github.String("check1"), - State: github.String("success"), + State: github.String(StatusStateSuccess), }, }, }, @@ -979,7 +979,7 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Context: github.String("check1"), - State: github.String("failure"), + State: github.String(StatusStateFailure), }, }, }, @@ -993,7 +993,7 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Context: github.String("check1"), - State: github.String("pending"), + State: github.String(StatusStatePending), }, }, }, @@ -1007,7 +1007,7 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Context: github.String("check1"), - State: github.String("error"), + State: github.String(StatusStateError), }, }, }, @@ -1021,13 +1021,13 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Name: github.String("check1"), - Status: github.String("completed"), - Conclusion: github.String("success"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionSuccess), }, { Name: github.String("check2"), - Status: github.String("completed"), - Conclusion: github.String("success"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionSuccess), }, }, }, @@ -1041,15 +1041,15 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Name: github.String("check1"), - Status: github.String("completed"), - Conclusion: github.String("success"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionSuccess), }, }, { { Name: github.String("check2"), - Status: github.String("completed"), - Conclusion: github.String("success"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionSuccess), }, }, }, @@ -1061,13 +1061,13 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Name: github.String("check1"), - Status: github.String("completed"), - Conclusion: github.String("success"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionSuccess), }, { Name: github.String("check2"), - Status: github.String("completed"), - Conclusion: github.String("failure"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionFailure), }, }, }, @@ -1081,15 +1081,15 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Name: github.String("check1"), - Status: github.String("completed"), - Conclusion: github.String("success"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionSuccess), }, }, { { Name: github.String("check2"), - Status: github.String("completed"), - Conclusion: github.String("failure"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionFailure), }, }, }, @@ -1103,12 +1103,12 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Name: github.String("check1"), - Status: github.String("completed"), - Conclusion: github.String("success"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionSuccess), }, { Name: github.String("check2"), - Status: github.String("queued"), + Status: github.String(RunStatusQueued), }, }, }, @@ -1122,13 +1122,13 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Context: github.String("check1"), - State: github.String("success"), + State: github.String(StatusStateSuccess), }, }, { { Context: github.String("check2"), - State: github.String("success"), + State: github.String(StatusStateSuccess), }, }, }, @@ -1136,15 +1136,15 @@ func TestGetCIStatusForChecks(t *testing.T) { { { Name: github.String("check3"), - Status: github.String("completed"), - Conclusion: github.String("success"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionSuccess), }, }, { { Name: github.String("check4"), - Status: github.String("completed"), - Conclusion: github.String("success"), + Status: github.String(RunStatusCompleted), + Conclusion: github.String(RunConclusionSuccess), }, }, }, @@ -1313,7 +1313,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "reruns failed workflow", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, + {ID: github.Int64(1), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionFailure)}, }, expectedRerunCount: 1, expectedRerunCalled: 1, @@ -1321,7 +1321,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "reruns timed_out workflow", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("timed_out")}, + {ID: github.Int64(1), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionTimedOut)}, }, expectedRerunCount: 1, expectedRerunCalled: 1, @@ -1329,7 +1329,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "does not rerun successful workflow", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("success")}, + {ID: github.Int64(1), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionSuccess)}, }, expectedRerunCount: 0, expectedRerunCalled: 0, @@ -1337,7 +1337,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "does not rerun cancelled workflow", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("cancelled")}, + {ID: github.Int64(1), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionCancelled)}, }, expectedRerunCount: 0, expectedRerunCalled: 0, @@ -1345,7 +1345,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "does not rerun skipped workflow", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("skipped")}, + {ID: github.Int64(1), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionSkipped)}, }, expectedRerunCount: 0, expectedRerunCalled: 0, @@ -1353,9 +1353,9 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "reruns multiple failed workflows", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, - {ID: github.Int64(2), Status: github.String("completed"), Conclusion: github.String("timed_out")}, - {ID: github.Int64(3), Status: github.String("completed"), Conclusion: github.String("success")}, + {ID: github.Int64(1), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionFailure)}, + {ID: github.Int64(2), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionTimedOut)}, + {ID: github.Int64(3), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionSuccess)}, }, expectedRerunCount: 2, expectedRerunCalled: 2, @@ -1369,7 +1369,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "rerun API failure returns error", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, + {ID: github.Int64(1), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionFailure)}, }, rerunShouldFail: true, expectedRerunCount: 0, @@ -1379,7 +1379,7 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "reports in-progress runs", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Status: github.String("in_progress"), Conclusion: github.String("")}, + {ID: github.Int64(1), Status: github.String(RunStatusInProgress), Conclusion: github.String("")}, }, expectedRerunCount: 0, expectedHasRunsInProgress: true, @@ -1388,8 +1388,8 @@ func TestRerunFailedWorkflowsForCommit(t *testing.T) { { name: "in-progress run alongside failed run", workflowRuns: []*github.WorkflowRun{ - {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, - {ID: github.Int64(2), Status: github.String("in_progress"), Conclusion: github.String("")}, + {ID: github.Int64(1), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionFailure)}, + {ID: github.Int64(2), Status: github.String(RunStatusInProgress), Conclusion: github.String("")}, }, expectedRerunCount: 1, expectedHasRunsInProgress: true, @@ -1469,8 +1469,8 @@ func TestRerunFailedWorkflowsForCommit_DeduplicatesRuns(t *testing.T) { // Simulate the same run appearing twice (edge case) workflowRuns := []*github.WorkflowRun{ - {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, - {ID: github.Int64(1), Status: github.String("completed"), Conclusion: github.String("failure")}, // duplicate + {ID: github.Int64(1), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionFailure)}, + {ID: github.Int64(1), Status: github.String(RunStatusCompleted), Conclusion: github.String(RunConclusionFailure)}, // duplicate } mockedHTTPClient := mock.NewMockedHTTPClient(