From 184e7c765452cb10c162adffd5723971d2d112a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20=C5=A0tibran=C3=BD?= Date: Fri, 6 Mar 2026 11:20:51 +0100 Subject: [PATCH] fix: handle error-state status contexts in --exclude flag --- cmd/wait-for-github/pr.go | 12 ++++++- internal/github/github.go | 3 +- internal/github/github_test.go | 65 ++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/cmd/wait-for-github/pr.go b/cmd/wait-for-github/pr.go index e9ad914..3b92851 100644 --- a/cmd/wait-for-github/pr.go +++ b/cmd/wait-for-github/pr.go @@ -117,12 +117,22 @@ func parsePRArguments(ctx context.Context, cmd *cli.Command, logger *slog.Logger } logger.InfoContext(ctx, "waiting for PR to be merged/closed", "owner", owner, "repo", repo, "pr", n) + // Filter out empty strings from excludes. When GITHUB_CI_EXCLUDE is set to + // an empty string, urfave/cli splits it into a slice containing one empty + // string. Remove these so that an empty env var is treated the same as unset. + var excludes []string + for _, e := range cmd.StringSlice("exclude") { + if e != "" { + excludes = append(excludes, e) + } + } + return prConfig{ owner: owner, repo: repo, pr: n, commitInfoFile: cmd.String("commit-info-file"), - excludes: cmd.StringSlice("exclude"), + excludes: excludes, actionRetries: int(cmd.Int("action-retries")), writer: osFileWriter{}, }, nil diff --git a/internal/github/github.go b/internal/github/github.go index 75fe70f..4154246 100644 --- a/internal/github/github.go +++ b/internal/github/github.go @@ -518,7 +518,8 @@ func (c GHClient) GetCIStatus(ctx context.Context, owner, repoName, ref string, for _, node := range nodes { isCheckFailure := strings.ToLower(node.CheckRun.Conclusion) == RunConclusionFailure - isStatusFailure := strings.ToLower(node.StatusContext.State) == StatusStateFailure + isStatusFailure := strings.ToLower(node.StatusContext.State) == StatusStateFailure || + strings.ToLower(node.StatusContext.State) == StatusStateError checkRunName := node.CheckRun.Name statusContextName := node.StatusContext.Context diff --git a/internal/github/github_test.go b/internal/github/github_test.go index 2aa17bb..fd933e8 100644 --- a/internal/github/github_test.go +++ b/internal/github/github_test.go @@ -793,6 +793,71 @@ func TestGetCIStatus(t *testing.T) { excludedChecks: []string{"deployment", "workflow"}, expectedStatus: CIStatusFailed, }, + { + name: "status context with error state treated as failure", + mockGraphQL: ` + { + "data": { + "repository": { + "object": { + "statusCheckRollup": { + "state": "FAILURE", + "contexts": { + "checkRunCount": 0, + "statusContextCount": 1, + "nodes": [ + { + "__typename": "StatusContext", + "context": "dev-policy-bot: master", + "state": "ERROR" + } + ], + "pageInfo": { + "hasNextPage": false, + "endCursor": null + } + } + } + } + } + } + } + `, + expectedStatus: CIStatusFailed, + }, + { + name: "excluded status context with error state", + mockGraphQL: ` + { + "data": { + "repository": { + "object": { + "statusCheckRollup": { + "state": "FAILURE", + "contexts": { + "checkRunCount": 0, + "statusContextCount": 1, + "nodes": [ + { + "__typename": "StatusContext", + "context": "dev-policy-bot: master", + "state": "ERROR" + } + ], + "pageInfo": { + "hasNextPage": false, + "endCursor": null + } + } + } + } + } + } + } + `, + excludedChecks: []string{"dev-policy-bot: master"}, + expectedStatus: CIStatusPassed, + }, } for _, tt := range tests {