From 56480db8da4aa439eaa846f4763cc0c7968ee47d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Jun 2026 05:20:21 +0000 Subject: [PATCH 1/2] Initial plan From 61be4e622ee53eb49aee58e4296402666a7bba87 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Jun 2026 05:39:24 +0000 Subject: [PATCH 2/2] Use EqualFold and enforce tolowerequalfold in CI Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/cgo.yml | 2 +- pkg/cli/add_workflow_resolution.go | 2 +- pkg/cli/codespace.go | 2 +- pkg/cli/forecast.go | 3 +-- pkg/cli/import_url_fetcher.go | 2 +- pkg/cli/outcome_eval_review.go | 2 +- pkg/parser/schema_suggestions.go | 2 +- pkg/parser/yaml_import.go | 2 +- pkg/workflow/features.go | 4 ++-- pkg/workflow/notify_comment.go | 2 +- pkg/workflow/repo_memory_validation.go | 2 +- pkg/workflow/resolve.go | 10 +++------- pkg/workflow/strings.go | 2 +- 13 files changed, 16 insertions(+), 21 deletions(-) diff --git a/.github/workflows/cgo.yml b/.github/workflows/cgo.yml index 15b507312e6..5298481fcd6 100644 --- a/.github/workflows/cgo.yml +++ b/.github/workflows/cgo.yml @@ -1075,7 +1075,7 @@ jobs: # Enforce selected production custom analyzers without blocking on unrelated # legacy custom analyzer findings in tests or other analyzer families. - name: Run custom linters - run: make golint-custom LINTER_FLAGS="-errstringmatch -panicinlibrarycode -manualmutexunlock -osexitinlibrary -rawloginlib -regexpcompileinfunction -fprintlnsprintf -strconvparseignorederror -jsonmarshalignoredeerror -uncheckedtypeassertion -fmterrorfnoverbs -test=false" + run: make golint-custom LINTER_FLAGS="-errstringmatch -panicinlibrarycode -manualmutexunlock -osexitinlibrary -rawloginlib -regexpcompileinfunction -fprintlnsprintf -strconvparseignorederror -jsonmarshalignoredeerror -uncheckedtypeassertion -fmterrorfnoverbs -tolowerequalfold -test=false" # Ensure no action shell scripts invoke python or python3 - name: Lint action shell scripts diff --git a/pkg/cli/add_workflow_resolution.go b/pkg/cli/add_workflow_resolution.go index 3770e05c433..bb2cd0ef25e 100644 --- a/pkg/cli/add_workflow_resolution.go +++ b/pkg/cli/add_workflow_resolution.go @@ -456,7 +456,7 @@ func checkWorkflowHasDispatchFromContent(content string) bool { return strings.Contains(strings.ToLower(on), "workflow_dispatch") case []any: for _, item := range on { - if str, ok := item.(string); ok && strings.ToLower(str) == "workflow_dispatch" { + if str, ok := item.(string); ok && strings.EqualFold(str, "workflow_dispatch") { return true } } diff --git a/pkg/cli/codespace.go b/pkg/cli/codespace.go index 5eb082e4bf5..a281d7d2b92 100644 --- a/pkg/cli/codespace.go +++ b/pkg/cli/codespace.go @@ -14,7 +14,7 @@ var codespaceLog = logger.New("cli:codespace") // by checking for the CODESPACES environment variable func isRunningInCodespace() bool { // GitHub Codespaces sets CODESPACES=true environment variable - isCodespace := strings.ToLower(os.Getenv("CODESPACES")) == "true" + isCodespace := strings.EqualFold(os.Getenv("CODESPACES"), "true") codespaceLog.Printf("Codespace detection: is_codespace=%v", isCodespace) return isCodespace } diff --git a/pkg/cli/forecast.go b/pkg/cli/forecast.go index 6bdf29f28e0..60c4c08bb96 100644 --- a/pkg/cli/forecast.go +++ b/pkg/cli/forecast.go @@ -457,9 +457,8 @@ func listRunsWithBackoff(ctx context.Context, opts ListWorkflowRunsOptions, work // best matches id. Matching is tried against the file-based key (e.g. "ci-doctor") and the // display name (e.g. "CI Failure Doctor"), both case-insensitively. Returns "" on no match. func matchRemoteWorkflowName(id string, workflows map[string]*GitHubWorkflow) string { - lowerID := strings.ToLower(id) for key, wf := range workflows { - if strings.ToLower(key) == lowerID || strings.ToLower(wf.Name) == lowerID { + if strings.EqualFold(key, id) || strings.EqualFold(wf.Name, id) { return wf.Name } } diff --git a/pkg/cli/import_url_fetcher.go b/pkg/cli/import_url_fetcher.go index fdbde1169dd..3ef70971cea 100644 --- a/pkg/cli/import_url_fetcher.go +++ b/pkg/cli/import_url_fetcher.go @@ -215,7 +215,7 @@ func attachImportAuthHeader(req *http.Request, rawURL string) { } // Never send credentials over plaintext HTTP — HTTPS is required. - if strings.ToLower(parsed.Scheme) != "https" { + if !strings.EqualFold(parsed.Scheme, "https") { importURLFetcherLog.Printf("Skipping auth header for non-HTTPS URL: scheme=%s", parsed.Scheme) return } diff --git a/pkg/cli/outcome_eval_review.go b/pkg/cli/outcome_eval_review.go index 7b1e134f944..59d39775b2b 100644 --- a/pkg/cli/outcome_eval_review.go +++ b/pkg/cli/outcome_eval_review.go @@ -76,7 +76,7 @@ func evalAddReviewer(item CreatedItemReport, repoOverride string) OutcomeReport var approvedReviewer string var submittedReviewer string for login, review := range latestByReviewer { - if strings.ToUpper(outcomeString(review["state"])) == "APPROVED" { + if strings.EqualFold(outcomeString(review["state"]), "APPROVED") { approvedReviewer = login break } diff --git a/pkg/parser/schema_suggestions.go b/pkg/parser/schema_suggestions.go index 336736869fc..0441e85eee3 100644 --- a/pkg/parser/schema_suggestions.go +++ b/pkg/parser/schema_suggestions.go @@ -663,7 +663,7 @@ func findFieldLocationsInSchema(schemaDoc any, targetField, currentPath string) } seen[key] = true - if strings.ToLower(loc.FieldName) == targetLower { + if strings.EqualFold(loc.FieldName, targetField) { loc.Distance = 0 exactMatches = append(exactMatches, loc) } diff --git a/pkg/parser/yaml_import.go b/pkg/parser/yaml_import.go index d79466e4627..a45bdccce38 100644 --- a/pkg/parser/yaml_import.go +++ b/pkg/parser/yaml_import.go @@ -36,7 +36,7 @@ func isYAMLWorkflowFile(filePath string) bool { func isActionDefinitionFile(filePath string, content []byte) (bool, error) { // Quick check: action.yml or action.yaml filename base := filepath.Base(filePath) - if strings.ToLower(base) == "action.yml" || strings.ToLower(base) == "action.yaml" { + if strings.EqualFold(base, "action.yml") || strings.EqualFold(base, "action.yaml") { return true, nil } diff --git a/pkg/workflow/features.go b/pkg/workflow/features.go index 26ef914f6f4..f2a5f27afcb 100644 --- a/pkg/workflow/features.go +++ b/pkg/workflow/features.go @@ -66,7 +66,7 @@ func getFeatureValueFromFrontmatter(flagLower string, workflowData *WorkflowData } for key, value := range workflowData.Features { - if strings.ToLower(key) == flagLower { + if strings.EqualFold(key, flagLower) { if enabled, found := parseFeatureValue(value); found { if logEnabled { featuresLog.Printf("Feature found in frontmatter (case-insensitive): %s=%v", flagLower, enabled) @@ -102,7 +102,7 @@ func isFeatureInEnvironment(flagLower string, logEnabled bool) bool { featuresLog.Printf("Checking GH_AW_FEATURES environment variable: %s", features) } for feature := range strings.SplitSeq(features, ",") { - if strings.ToLower(strings.TrimSpace(feature)) == flagLower { + if strings.EqualFold(strings.TrimSpace(feature), flagLower) { return true } } diff --git a/pkg/workflow/notify_comment.go b/pkg/workflow/notify_comment.go index 69f96c7f2fc..f195bd5446a 100644 --- a/pkg/workflow/notify_comment.go +++ b/pkg/workflow/notify_comment.go @@ -627,7 +627,7 @@ func isGroupConcurrencyQueueEnabled(data *WorkflowData) bool { flag := strings.ToLower(strings.TrimSpace(string(constants.GroupConcurrencyQueueFeatureFlag))) if data != nil && data.Features != nil { for key, value := range data.Features { - if strings.ToLower(key) == flag { + if strings.EqualFold(key, flag) { return parseGroupConcurrencyQueueFeatureValue(value) } } diff --git a/pkg/workflow/repo_memory_validation.go b/pkg/workflow/repo_memory_validation.go index 337e47063ca..ba5084dfd3c 100644 --- a/pkg/workflow/repo_memory_validation.go +++ b/pkg/workflow/repo_memory_validation.go @@ -49,7 +49,7 @@ func validateBranchPrefix(prefix string) error { } // Cannot be "copilot" - if strings.ToLower(prefix) == "copilot" { + if strings.EqualFold(prefix, "copilot") { return errors.New("branch-prefix cannot be 'copilot' (reserved)") } diff --git a/pkg/workflow/resolve.go b/pkg/workflow/resolve.go index 1199aa3059d..29f32668cfa 100644 --- a/pkg/workflow/resolve.go +++ b/pkg/workflow/resolve.go @@ -157,9 +157,6 @@ func FindWorkflowName(input string) (string, error) { // Normalize input for matching normalizedInput := stringutil.NormalizeWorkflowName(input) - lowerInput := strings.ToLower(input) - lowerNormalizedInput := strings.ToLower(normalizedInput) - // Strategy 2: Try exact match with workflow ID (case-sensitive) for _, wf := range workflows { if wf.WorkflowID == input || wf.WorkflowID == normalizedInput { @@ -170,7 +167,7 @@ func FindWorkflowName(input string) (string, error) { // Strategy 3: Try case-insensitive match with workflow ID for _, wf := range workflows { - if strings.ToLower(wf.WorkflowID) == lowerInput || strings.ToLower(wf.WorkflowID) == lowerNormalizedInput { + if strings.EqualFold(wf.WorkflowID, input) || strings.EqualFold(wf.WorkflowID, normalizedInput) { resolveLog.Printf("Found case-insensitive workflow ID match: %s -> %s", input, wf.DisplayName) return wf.DisplayName, nil } @@ -186,7 +183,7 @@ func FindWorkflowName(input string) (string, error) { // Strategy 5: Try case-insensitive match with display name for _, wf := range workflows { - if strings.ToLower(wf.DisplayName) == lowerInput { + if strings.EqualFold(wf.DisplayName, input) { resolveLog.Printf("Found case-insensitive display name match: %s -> %s", input, wf.DisplayName) return wf.DisplayName, nil } @@ -222,9 +219,8 @@ func GetWorkflowLockFileName(input string) (string, error) { return "", fmt.Errorf("failed to get workflows: %w", err) } - lowerInput := strings.ToLower(input) for _, wf := range workflows { - if strings.ToLower(wf.DisplayName) == lowerInput { + if strings.EqualFold(wf.DisplayName, input) { return wf.WorkflowID + ".lock.yml", nil } } diff --git a/pkg/workflow/strings.go b/pkg/workflow/strings.go index bd722ed54d1..b530538a153 100644 --- a/pkg/workflow/strings.go +++ b/pkg/workflow/strings.go @@ -240,7 +240,7 @@ func PrettifyToolName(toolName string) string { } // Handle bash specially - keep as "bash" - if strings.ToLower(toolName) == "bash" { + if strings.EqualFold(toolName, "bash") { return "bash" }