Skip to content

Refactor shared value formatting and unify GitHub error/SHA classification paths - #53018

Merged
pelikhan merged 8 commits into
mainfrom
copilot/refactor-duplicate-value-formatting-logic
Aug 16, 2026
Merged

Refactor shared value formatting and unify GitHub error/SHA classification paths#53018
pelikhan merged 8 commits into
mainfrom
copilot/refactor-duplicate-value-formatting-logic

Conversation

Copilot AI commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

This refactor removes duplicated value-formatting logic and resolves split-brain GitHub error classification between gitutil, cli, and parser. It also standardizes full-SHA validation by replacing hand-inlined predicates with gitutil.IsValidFullSHA.

  • Value formatting deduplication (workflowimportinpututil)

    • Replaced marshalEnvValue’s inlined JSON/reflect normalization with delegation to importinpututil.FormatResolvedValue.
    • Preserved scalar behavior via fmt.Sprint fallback and nil"".
  • Error classifier consolidation (gitutilerrorutil)

    • Moved auth/rate-limit string classifiers into pkg/errorutil as shared APIs:
      • IsAuthError(output string)
      • IsRateLimitError(output string)
    • Updated callers across pkg/cli and pkg/parser to use errorutil.
    • Removed obsolete classifier exports from pkg/gitutil.
  • Audit permission classifier alignment

    • Updated isPermissionErrorStr to delegate to shared auth classification and keep audit-only markers (exit status 4, gh auth login, workflow-specific guidance, generic permission).
  • Full SHA predicate normalization

    • Replaced inline len(x)==40 && IsHexString(x) checks with gitutil.IsValidFullSHA in resolver/download/action paths.
  • Spec/docs updates

    • Updated errorutil and gitutil READMEs and tests to reflect ownership changes and public API contracts.
func marshalEnvValue(v any) string {
	if s, ok := importinpututil.FormatResolvedValue(v); ok {
		return s
	}
	if v == nil {
		return ""
	}
	return fmt.Sprint(v)
}

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 17.8 AIC · ⌖ 7.58 AIC · ⊞ 6.3K ·
Comment /souschef to run again


Run: https://github.com/github/gh-aw/actions/runs/31928605740> Generated by 👨‍🍳 PR Sous Chef · gpt54 · 5.23 AIC · ⌖ 5.69 AIC · ⊞ 6.3K ·

Comment /souschef to run again

Copilot AI and others added 2 commits August 16, 2026 03:21
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor duplicate value-formatting logic and error classifiers Refactor shared value formatting and unify GitHub error/SHA classification paths Aug 16, 2026
Copilot AI requested a review from pelikhan August 16, 2026 03:42
@pelikhan
pelikhan marked this pull request as ready for review August 16, 2026 03:54
Copilot AI balanced review requested due to automatic review settings August 16, 2026 03:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors shared formatting, error classification, and SHA validation to use centralized utilities.

Changes:

  • Delegates environment-value formatting to importinpututil.
  • Moves GitHub error classifiers into errorutil and updates callers.
  • Standardizes full-SHA checks and updates related tests/docs.
Show a summary per file
File Description
pkg/workflow/step_types.go Reuses shared value formatting.
pkg/workflow/action_resolver.go Uses canonical SHA validation.
pkg/parser/remote_resolve_sha.go Centralizes error and SHA checks.
pkg/parser/remote_list_files.go Uses shared auth classification.
pkg/parser/remote_download_file.go Updates auth and SHA checks.
pkg/gitutil/spec_test.go Removes relocated classifier specs.
pkg/gitutil/README.md Updates package responsibilities.
pkg/gitutil/gitutil.go Removes error classifiers.
pkg/gitutil/gitutil_test.go Removes relocated classifier tests.
pkg/errorutil/spec_test.go Adds classifier contract tests.
pkg/errorutil/README.md Documents new classifier APIs.
pkg/errorutil/errors.go Adds shared classifiers.
pkg/errorutil/errors_test.go Tests classifier behavior.
pkg/cli/update_workflows.go Migrates classifier calls.
pkg/cli/update_display.go Migrates failure grouping.
pkg/cli/update_actions_release.go Migrates auth fallback detection.
pkg/cli/health_command.go Migrates rate-limit detection.
pkg/cli/forecast_resolution.go Migrates retry classification.
pkg/cli/forecast_compute.go Migrates rate-limit handling.
pkg/cli/download_workflow.go Centralizes auth and SHA checks.
pkg/cli/audit.go Aligns permission classification.

Review details

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 21/21 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread pkg/errorutil/errors.go

// IsRateLimitError reports whether output indicates a GitHub API rate-limit error.
// The check is case-insensitive and matches known API phrases.
func IsRateLimitError(output string) bool {
Comment thread pkg/workflow/action_resolver.go Outdated
Comment on lines 187 to 189
if !gitutil.IsValidFullSHA(sha) {
return "", "", fmt.Errorf("invalid SHA format: expected 40 hex characters, got %d (%s)", len(sha), sha)
}
@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Ponytail Reviewer completed successfully!

Lean already. Ship. This PR is a net simplification (-369/+199 lines): it deduplicates value-formatting logic into importinpututil.FormatResolvedValue and consolidates error classifiers into errorutil, deleting redundant code from gitutil/workflow. No new abstractions, dependencies, or speculative flexibility were introduced. Existing review comments already cover the two correctness concerns (removed public API, error message wording), which are out of scope for this over-engineering-only pass.

Generated by Ponytail Reviewer for #53018

@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

reviewed_at: 2026-08-16T00:00:00Z
review_event: REQUEST_CHANGES
top_themes:
  - uppercase full-SHA regression from IsValidFullSHA substitution
  - generic 403/forbidden now misclassified as auth failure
files_reviewed:
  - pkg/cli/audit.go
  - pkg/cli/download_workflow.go
  - pkg/cli/forecast_compute.go
  - pkg/cli/forecast_resolution.go
  - pkg/cli/health_command.go
  - pkg/cli/update_actions_release.go
  - pkg/cli/update_display.go
  - pkg/cli/update_workflows.go
  - pkg/errorutil/errors.go
  - pkg/errorutil/errors_test.go
  - pkg/errorutil/spec_test.go
  - pkg/gitutil/gitutil.go
  - pkg/gitutil/gitutil_test.go
  - pkg/gitutil/spec_test.go
  - pkg/parser/remote_download_file.go
  - pkg/parser/remote_list_files.go
  - pkg/parser/remote_resolve_sha.go
  - pkg/workflow/action_resolver.go
  - pkg/workflow/step_types.go
comment_count: 2

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · gpt54 · 11.3 AIC · ⌖ 6.6 AIC · ⊞ 6.9K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes

This cleanup is not behavior-preserving: it narrows accepted SHA inputs and broadens auth-error detection enough to send unrelated 403s down the wrong fallback paths.

Blocking themes
  • Replacing len(x) == 40 && IsHexString(x) with IsValidFullSHA changes user-visible behavior by rejecting uppercase full SHAs that previously worked.
  • The new shared IsAuthError classifier treats generic forbidden responses as auth failures, which changes control flow in parser/CLI fallback code and can mask the real error.

🔎 Code quality review by PR Code Quality Reviewer · gpt54 · 11.3 AIC · ⌖ 6.6 AIC · ⊞ 6.9K
Comment /review to run again

Comment thread pkg/parser/remote_resolve_sha.go Outdated
func resolveRefToSHA(ctx context.Context, owner, repo, ref, host string) (string, error) {
// If ref is already a full SHA (40 hex characters), return it as-is
if len(ref) == 40 && gitutil.IsHexString(ref) {
if gitutil.IsValidFullSHA(ref) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This refactor silently changes the accepted meaning of a “full SHA”: the old code accepted any 40-character hex string, but IsValidFullSHA only accepts lowercase, so callers like resolveRefToSHA now reject uppercase commit IDs that previously worked.

💡 Why this blocks merge

Several changed paths (download_workflow, remote_download_file, remote_resolve_sha, action_resolver) used to gate on len(x) == 40 && gitutil.IsHexString(x), and IsHexString explicitly accepts both uppercase and lowercase hex. Replacing those checks with gitutil.IsValidFullSHA is not a mechanical cleanup — it narrows behavior.

That means an input like ABCDEF... now stops being treated as a SHA and falls into branch/tag/API resolution paths, which can produce wrong lookups or hard failures for a value that previously succeeded.

A safe fix is to preserve the old predicate for user-supplied refs, or normalize with strings.ToLower before validating only in places where lowercase-only storage is actually required.

Comment thread pkg/errorutil/errors.go

// IsAuthError reports whether output indicates an authentication or
// authorization issue from the GitHub API or gh CLI.
func IsAuthError(output string) bool {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsAuthError now treats every 403 Forbidden as an authentication problem, which will misroute ordinary authorization failures into auth/git-fallback paths and hide the real cause from users.

💡 Why this blocks merge

The old audit helper had extra command-specific heuristics, but the shared classifier is now used in parser and CLI fallback logic to decide whether to retry with git or unauthenticated API calls. Broadening that shared predicate to match bare forbidden means any non-auth 403 — for example repo policy restrictions, disabled endpoints, or feature gating — gets mislabeled as an auth failure.

That changes control flow, not just messaging: callers will take fallback branches intended only for missing/invalid credentials, and the final error becomes misleading when the fallback also fails.

Please tighten the classifier so it only matches credential-specific markers, or require stronger context than a generic forbidden substring before triggering auth recovery.

Add draft Architecture Decision Record for the refactor that moves
IsAuthError and IsRateLimitError from pkg/gitutil to pkg/errorutil
and delegates marshalEnvValue serialization to importinpututil.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (199 new lines across pkg/errorutil, pkg/cli, pkg/parser, and pkg/workflow) but did not have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/53018-centralize-error-classifiers-and-value-formatting.md — review and complete it before merging.

🔒 This PR cannot merge until an ADR is linked in the PR body.

📋 What to do next
  1. Review the draft ADR committed to your branch — it was generated from the PR diff
  2. Complete the missing sections — add context the AI couldn't infer, refine the decision rationale, and list real alternatives you considered
  3. Commit the finalized ADR to docs/adr/ on your branch
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-53018: Centralize GitHub Error Classifiers and Value Formatting

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

❓ Why ADRs Matter

"AI made me procrastinate on key design decisions. Because refactoring was cheap, I could always say 'I'll deal with this later.' Deferring decisions corroded my ability to think clearly."

ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you.

📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 0042-use-postgresql.md for PR #42).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · sonnet46 · 100.1 AIC · ⌖ 24.3 AIC · ⊞ 9K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This PR refactors error/SHA classification to shared packages, reducing duplication across the codebase. The intent is good, but two issues need attention:

  1. Breaking API change (pkg/gitutil): IsRateLimitError and IsAuthError are deleted from gitutil and moved to errorutil. This breaks any external consumers of the gitutil public API without a deprecation shim or compatibility wrapper. The existing review comment on pkg/errorutil/errors.go:65 captures this.

  2. Stale error message (pkg/workflow/action_resolver.go:189): After switching to gitutil.IsValidFullSHA (which uses ^[0-9a-f]{40}$ — lowercase only), the error message still says "40 hex characters" without clarifying the lowercase constraint, making the message misleading for uppercase SHA input. The existing review comment on pkg/workflow/action_resolver.go:189 captures this.

The marshalEnvValue delegation to importinpututil.FormatResolvedValue is a clean unification, and the isPermissionErrorStr refactor in audit.go correctly preserves the original matching behaviour through the shared classifier.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 52.9 AIC · ⌖ 7.93 AIC · ⊞ 5.6K

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /codebase-design, /improve-codebase-architecture, and /tdd to this refactor. Requesting changes on two correctness issues (misleading error message, sensitive debug logs) and flagging a dead-code structure and a coverage gap.

📋 Key Themes & Findings

Key Findings

  1. Sensitive content in debug logs (pkg/errorutil/errors.go lines 71 & 90): IsRateLimitError and IsAuthError log the full output string on a positive match. Unlike the old gitutil.IsAuthError (which logged only "Detected authentication error"), these logs may echo credential error messages verbatim into debug output. Should be bounded to len(output) or a redacted marker.

  2. Misleading error message (pkg/workflow/action_resolver.go line 188): IsValidFullSHA requires lowercase hex, but the error message says "expected 40 hex characters" — an uppercase valid-looking SHA will produce a confusing diagnostic.

  3. Dead-code structure (pkg/workflow/step_types.go line 243): The if v == nil guard is logically unreachable after FormatResolvedValue returns ("", false) for nil. The guard works correctly now but will silently misbehave if FormatResolvedValue ever returns false for non-nil values, since the fallback then skips nil-checking and calls fmt.Sprint(v) on a non-nil value.

  4. Removed marker without a regression test (pkg/cli/audit.go line 302): "GitHub CLI authentication" was removed as a literal and is now covered by the "authentication" substring match inside errorutil.IsAuthError. This is correct, but there's no test in audit_test.go asserting the legacy phrase still triggers isPermissionErrorStr.

  5. Redundant rate-limit pattern (pkg/errorutil/errors.go line 63): "api rate limit exceeded" is a superstring of "rate limit exceeded", making the former pattern unreachable. Minor, but the README documents both as independent phrases.

Positive Highlights

  • ✅ Clean elimination of split-brain IsAuthError/IsRateLimitError duplication between gitutil and parser/cli
  • ✅ Full spec tests and unit tests added for the new errorutil public API
  • IsValidFullSHA consolidation is thorough — all five call sites replaced consistently
  • marshalEnvValue delegation to importinpututil.FormatResolvedValue keeps serialization logic in one place

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 90.6 AIC · ⌖ 9.13 AIC · ⊞ 7.7K
Comment /matt to run again

Comment thread pkg/errorutil/errors.go Outdated
"secondary rate limit",
)
if matched {
errorutilLog.Printf("Classified output as rate-limit related: %s", output)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] Debug log may leak sensitive content: the full output string is written to the log on a positive match, but that string can contain credential fragments from CLI error messages. The original gitutil.IsAuthError logged only a fixed sentinel — not the payload.

💡 Suggested fix

Log a bounded indicator instead of the raw value:

errorutilLog.Printf("Classified output as rate-limit related (len=%d)", len(output))

This is consistent with how gitutil.IsAuthError handled it and avoids echoing potentially sensitive error payloads into debug logs.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated both shared classifiers to log only the output length in aaec1b1.

Comment thread pkg/errorutil/errors.go Outdated
"saml enforcement",
)
if matched {
errorutilLog.Printf("Classified output as auth-related: %s", output)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] Same sensitive-log concern applies to IsAuthError: the full output (which often contains the exact credential error message) is logged verbatim when the function returns true. Consider logging only len(output) or a fixed marker here too.

💡 Suggested fix
if matched {
    errorutilLog.Printf("Classified output as auth-related (len=%d)", len(output))
}

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated both shared classifiers to log only the output length in aaec1b1.

objType = parts[1]
if len(sha) != 40 || !gitutil.IsHexString(sha) {
if !gitutil.IsValidFullSHA(sha) {
return "", "", fmt.Errorf("invalid SHA format: expected 40 hex characters, got %d (%s)", len(sha), sha)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] The error message at line 188 says "expected 40 hex characters" but IsValidFullSHA now requires lowercase hex (^[0-9a-f]{40}$). An uppercase 40-character SHA like ABCDEF... would produce a misleading message reporting it got 40 characters yet was still rejected.

💡 Suggested fix

Update the error to reflect the actual constraint:

return "", "", fmt.Errorf("invalid SHA format: expected 40 lowercase hex characters, got %q", sha)

Alternatively, accept uppercase and call strings.ToLower before matching, but that changes the semantics so the error message fix is safer.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uppercase 40-character SHA values are now accepted in the affected ref-resolution paths via gitutil.IsValidFullSHACaseInsensitive, with regression coverage in aaec1b1.

// importinpututil.FormatResolvedValue so import substitutions and env
// serialization stay aligned. Scalar values (int, bool, float64, etc.)
// fall back to fmt.Sprint.
func marshalEnvValue(v any) string {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] marshalEnvValue now silently returns "" when FormatResolvedValue returns (_, false) and v == nil is false — i.e. it falls through to fmt.Sprint(v). But FormatResolvedValue returns false only for nil; all other types return true. The double-nil guard (if s, ok := ...; ok then if v == nil) therefore creates a dead-code branch: the second if v == nil is unreachable because FormatResolvedValue(nil) returns ("", false) so the first branch doesn't return, but then v == nil is true.

This means nil returns "" correctly, but the structure is confusing — a future FormatResolvedValue change that returns false for non-nil values (e.g. a marshalling error) would silently fall into fmt.Sprint.

💡 Suggested fix

Either log/surface the marshalling failure, or be explicit:

func marshalEnvValue(v any) string {
    if v == nil {
        return ""
    }
    if s, ok := importinpututil.FormatResolvedValue(v); ok {
        return s
    }
    return fmt.Sprint(v)
}

This makes the nil guard first-class and the fallback readable.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the nil guard before FormatResolvedValue in aaec1b1.

Comment thread pkg/cli/audit.go
strings.Contains(s, "To use GitHub CLI in a GitHub Actions workflow") ||
strings.Contains(s, "gh auth login")
if errorutil.IsAuthError(s) {
return true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] isPermissionErrorStr in audit.go now lowercases the input before matching, but the existing errorutil.IsAuthError (which it delegates to first) also lowercases internally. This is correct and harmless, but the audit-specific branch that follows uses strings.ToLower(s) on a different variable (lower). One subtle gap: the original "GitHub CLI authentication" marker is no longer present — it was removed and not mapped to any matching pattern in errorutil.IsAuthError ("authentication" would match it, but "GitHub CLI authentication" is a distinct phrase). A targeted test for this removed literal would confirm it's still covered.

💡 Suggested test
// In pkg/cli/audit_test.go
assert.True(t, isPermissionErrorStr("GitHub CLI authentication token is missing"), "legacy marker should still match via 'authentication'")

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added coverage for the legacy GitHub CLI authentication marker in aaec1b1.

Comment thread pkg/errorutil/errors.go
return matched
}

// IsRateLimitError reports whether output indicates a GitHub API rate-limit error.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/improve-codebase-architecture] IsRateLimitError is documented as matching "api rate limit exceeded", "rate limit exceeded", or "secondary rate limit". The implementation uses containsSubstring which matches "rate limit exceeded" — this is a substring of "api rate limit exceeded", so the two patterns collapse into one. The "api rate limit exceeded" entry in errors_test.go passes because "rate limit exceeded" matches it too.

This redundancy isn't harmful, but it means the first documented phrase has no independent coverage. Consider either removing the redundant literal or documenting that "rate limit exceeded" is the canonical form.

💡 Why this matters

If someone later adds a string-specific exclusion or a more restrictive matcher, the documented phrases should be independently testable. A deduplication comment in errors.go would make the intent explicit:

// "rate limit exceeded" is a suffix of "api rate limit exceeded" — one pattern covers both.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The redundant API-specific phrase remains covered by the canonical rate limit exceeded substring; the documentation now lists that canonical matcher in aaec1b1.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the unresolved review feedback below, refresh the branch if GitHub does not do it automatically, and run the pr-finisher skill before handing back.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 17.8 AIC · ⌖ 7.58 AIC · ⊞ 6.3K ·
Comment /souschef to run again

@github-actions

Copy link
Copy Markdown
Contributor

Great work on this refactor! 🎯 This PR successfully consolidates duplicated value-formatting logic, unifies error classification across errorutil, and normalizes SHA validation patterns — exactly addressing the findings from issue #53011.

Highlights:

  • Consolidates marshalEnvValue to delegate to importinpututil.FormatResolvedValue (eliminates ~35 lines of duplication)
  • Moves IsAuthError and IsRateLimitError to the semantically correct home in pkg/errorutil
  • Replaces 7 hand-inlined SHA checks with gitutil.IsValidFullSHA for consistency
  • Includes comprehensive test coverage for the relocated error classifiers
  • Adds an ADR documenting the refactoring decisions

Tests look good — both errors_test.go and spec_test.go are updated to verify the new behavior across all changed paths.

The diff is well-scoped for a cross-package refactor touching 22 files. Ready for review!

Generated by ✅ Contribution Check · auto · 65.6 AIC · ⌖ 3.96 AIC · ⊞ 9.1K ·

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the unresolved review feedback below, refresh the branch if GitHub does not do it automatically, and run the pr-finisher skill before handing back.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 5.23 AIC · ⌖ 5.69 AIC · ⊞ 6.3K ·
Comment /souschef to run again

Copilot AI commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please address the unresolved review feedback below, refresh the branch if GitHub does not do it automatically, and run the pr-finisher skill before handing back.

  • Unresolved feedback: [P...

Addressed the SHA and auth-classification feedback in aaec1b1, then refreshed the branch with the latest main in b6c0a5a. Uppercase SHAs retain prior handling, and generic forbidden responses no longer trigger auth recovery.

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Copilot AI requested a review from gh-aw-bot August 16, 2026 05:25
@pelikhan
pelikhan merged commit 53175a1 into main Aug 16, 2026
3 of 4 checks passed
@pelikhan
pelikhan deleted the copilot/refactor-duplicate-value-formatting-logic branch August 16, 2026 05:31
Copilot stopped work on behalf of gh-aw-bot due to an error August 16, 2026 05:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[refactor] Duplicate value-formatting logic and split-brain error classifiers around pkg/gitutil and pkg/importinpututil

4 participants