Skip to content

fix(parser): wrap upstream errors with %w in import pipeline#46414

Closed
pelikhan with Copilot wants to merge 6 commits into
mainfrom
copilot/deep-report-audit-yaml-errors
Closed

fix(parser): wrap upstream errors with %w in import pipeline#46414
pelikhan with Copilot wants to merge 6 commits into
mainfrom
copilot/deep-report-audit-yaml-errors

Conversation

Copilot AI commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

A repository-quality audit found 93 non-wrapping fmt.Errorf calls in pkg/parser. In the import pipeline, several cases had an accessible upstream error that was silently discarded rather than wrapped, breaking errors.Is/errors.As traversal.

Changes

  • remote_resolve_path.go / remote_fetch_wasm.go: Split the combined filepath.Rel check into two if blocks so that a filepath.Rel failure (Windows cross-drive paths) wraps the upstream error, while the path-escape check (relativePath == "..") continues to produce a fresh error as before.

  • github_urls.go: Wrap strconv.ParseInt errors in parseNumberedURL and parseRunURL, enabling callers to inspect *strconv.NumError via errors.As.

  • schedule_parser.go: Split parseLongIntervalParts to separate the strconv.Atoi parse-failure path (now wraps *strconv.NumError) from the interval < 1 value-range check (no upstream error; message unchanged).

Intentionally not changed

os.Stat errors in the "file not found" path are not wrapped. TestUserFacingErrorsDontLeakInternals explicitly enforces that *os.PathError must not appear in the user-facing FormattedParserError chain. Wrapping os.Stat with %w would propagate the path error through ImportError.Cause → FormattedParserError.Unwrap(), breaking that invariant.

// Before — upstream strconv error swallowed
if err != nil || interval < 1 {
    return 0, "", fmt.Errorf("invalid interval '%s', must be a positive integer", intervalStr)
}

// After — parse failure preserves NumError; range failure is a new error (no upstream cause)
if err != nil {
    return 0, "", fmt.Errorf("invalid interval '%s', must be a positive integer: %w", intervalStr, err)
}
if interval < 1 {
    return 0, "", fmt.Errorf("invalid interval '%s', must be a positive integer", intervalStr)
}

Copilot AI and others added 2 commits July 18, 2026 10:57
…eline

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Audit the parser import pipeline for non-wrapping fmt.Errorf calls where a
genuine upstream error exists but was being discarded (swallowed), preventing
errors.Is/errors.As from inspecting the real cause.

Changes:
- remote_resolve_path.go: split filepath.Rel condition so that when
  filepath.Rel itself errors (rare, Windows-only), the error is wrapped with
  %w. The path-escape case (relativePath == "..") has no error to wrap so it
  keeps its original format.
- remote_fetch_wasm.go: same split for the WASM build variant.
- github_urls.go: wrap strconv.ParseInt errors in parseNumberedURL and
  parseRunURL, enabling errors.As(&strconv.NumError{}) by callers.
- schedule_parser.go: split the strconv.Atoi+interval<1 condition in
  parseLongIntervalParts so that parse failures (non-integer input) wrap the
  underlying NumError, while the value-range check (interval < 1) keeps its
  original message.

os.Stat errors are intentionally NOT wrapped to prevent *os.PathError from
leaking into the user-facing error chain (enforced by TestUserFacingErrorsDontLeakInternals).

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Audit and wrap upstream YAML errors in parser import pipeline fix(parser): wrap upstream errors with %w in import pipeline Jul 18, 2026
Copilot AI requested a review from pelikhan July 18, 2026 11:23
@pelikhan
pelikhan marked this pull request as ready for review July 18, 2026 11:45
Copilot AI review requested due to automatic review settings July 18, 2026 11:45

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

Preserves upstream parser errors for errors.Is/errors.As traversal.

Changes:

  • Wraps numeric parsing and path-resolution errors.
  • Separates parsing failures from validation failures.
  • Reschedules the generated auto-upgrade workflow.
Show a summary per file
File Description
pkg/parser/schedule_parser.go Wraps interval parsing errors.
pkg/parser/remote_resolve_path.go Wraps native path-resolution errors.
pkg/parser/remote_fetch_wasm.go Mirrors path handling for WASM.
pkg/parser/github_urls.go Wraps invalid GitHub numeric IDs.
.github/workflows/agentic-auto-upgrade.yml Changes the weekly schedule.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 5/5 changed files
  • Comments generated: 4
  • Review effort level: Medium

Comment thread pkg/parser/remote_resolve_path.go Outdated
if relErr != nil {
allowedFolder := filepath.Base(normalizedSecurityBase)
remoteLog.Printf("Security: Path escapes allowed folder: %s (rel error: %v)", filePath, relErr)
return "", fmt.Errorf("security: path %s must be within %s folder: %w", filePath, allowedFolder, relErr)

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.

Addressed in c9a688e. Replaced the bare %w wrapping with a pathRelError type (pkg/parser/path_rel_error.go). Its Error() returns only the sanitised message (no internal absolute paths exposed), while Unwrap() returns the underlying relErr for errors.Is/errors.As traversal. Both remote_resolve_path.go and remote_fetch_wasm.go now use &pathRelError{…}.

Comment thread pkg/parser/github_urls.go
number, err := strconv.ParseInt(numberText, 10, 32)
if err != nil {
return nil, fmt.Errorf("invalid %s number: %s", label, numberText)
return nil, fmt.Errorf("invalid %s number %s: %w", label, numberText, err)

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.

Addressed in c9a688e. Added TestParseGitHubURL_NumErrorWrapping in pkg/parser/github_urls_test.go with four table-driven cases covering numbered URLs (PR, issue), run URL, and job URL, each asserting errors.As(err, &(*strconv.NumError)(nil)) is reachable.

Comment on lines +225 to 229
if err != nil {
return 0, "", fmt.Errorf("invalid interval '%s', must be a positive integer: %w", intervalStr, err)
}
if interval < 1 {
return 0, "", fmt.Errorf("invalid interval '%s', must be a positive integer", intervalStr)

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.

Addressed in c9a688e. Added TestParseLongIntervalParts_NumErrorWrapping in pkg/parser/schedule_parser_test.go with three subtests: non-numeric interval asserts errors.As reaches *strconv.NumError; zero and negative intervals (value-range branch, no upstream error) assert it does not. Uses assert.ErrorAs/assert.NotErrorAs per testifylint convention.

on:
schedule:
- cron: "21 3 * * 5" # Weekly (auto-upgrade)
- cron: "11 4 * * 6" # Weekly (auto-upgrade)

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.

Addressed in c9a688e. The cron schedule has been reverted to "21 3 * * 5" — the deterministic value generated by make recompile --schedule-seed github/gh-aw.

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

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

No ADR enforcement needed: PR #46414 does not have the 'implementation' label and has ≤100 new lines of code in business logic directories (20 additions detected).

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

No test files were added or modified in this PR. PR #46414 only modified production code files (pkg/parser/*.go) and workflow configuration. Test Quality Sentinel skipped.

@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 /diagnosing-bugs and /tdd — requesting changes on two themes: missing regression tests for the new %w contracts, and an unexplained cron schedule change bundled into a parser fix.

📋 Key Themes & Highlights

Key Themes

  • Missing regression tests — the three wrapping sites (github_urls.go, schedule_parser.go, remote_resolve_path.go) each introduce a new errors.As-reachable cause, but no test asserts that the cause is actually reachable. Without these, the contract can silently regress.
  • Out-of-scope change — the cron reschedule in agentic-auto-upgrade.yml is unrelated to parser error wrapping and should be in a separate PR or explained in the description.
  • Error message content shift — wrapping filepath.Rel failures now embeds OS-level path diagnostics (e.g. Windows cross-drive paths) in user-facing import errors. This is probably intentional but worth a short note in the PR description.

Positive Highlights

  • ✅ Surgical and well-scoped — only wraps errors where an upstream cause exists; fresh errors for validation-only paths are correctly left as-is.
  • ✅ PR description explains the os.Stat intentional non-wrap and TestUserFacingErrorsDontLeakInternals invariant clearly.
  • ✅ Consistent pattern applied uniformly across all three files in the import pipeline.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 22.3 AIC · ⌖ 6.79 AIC · ⊞ 6.7K
Comment /matt 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.

Review Summary

The error-wrapping changes in the import pipeline are correct and well-reasoned. The PR description explains the deliberate non-wrapping of os.Stat errors to preserve the TestUserFacingErrorsDontLeakInternals invariant — this is a good call.

Existing review comments (from prior Copilot pass) cover the main gaps:

  • remote_resolve_path.go line 183 — wrapping filepath.Rel error may expose internal paths in user-facing messages on Windows; confirm FormatImportError strips internal path data.
  • github_urls.go line 135 — no tests verify errors.As reaches *strconv.NumError for the new wrapped errors.
  • schedule_parser.go line 229 — no regression test verifies the strconv.Atoi cause is actually wrapped.
  • agentic-auto-upgrade.yml line 37 — unrelated cron schedule change (Friday → Saturday) with no explanation in the PR description.

No new blocking issues found beyond those already raised.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 14.6 AIC · ⌖ 4.54 AIC · ⊞ 5K

@github-actions github-actions Bot mentioned this pull request Jul 18, 2026

@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.

Review: minor concerns only — existing comments cover the key issues

The mechanical changes are correct: filepath.Rel error path split, strconv.Parse* wrapping, and schedule-parser split all preserve original semantics while properly chaining upstream errors. No logic regressions introduced.

All blocking concerns (missing errors.As regression tests, potential internal-path exposure in wrapped relErr messages, and the out-of-scope cron reschedule) are already surfaced in the existing review thread. No new comments needed from this pass.

🔎 Code quality review by PR Code Quality Reviewer · 20.6 AIC · ⌖ 4.25 AIC · ⊞ 5.6K
Comment /review to run again

@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Triage

Field Value
Category bug
Risk medium
Score 42/100 (impact:20 urgency:12 quality:10)
Action defer
Batch pr-batch:parser-errors

Rationale: CHANGES_REQUESTED; reviewer found issues. Defer until agent addresses feedback. Related to #46421.

Generated by 🔧 PR Triage Agent · 26.9 AIC · ⌖ 7.24 AIC · ⊞ 5.6K ·

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill on #46414, address the outstanding review feedback before requesting maintainer attention, and report the next concrete step once the branch is ready.

Generated by 👨‍🍳 PR Sous Chef · 14.9 AIC · ⌖ 6.23 AIC · ⊞ 6K ·
Comment /souschef to run again

…or tests, revert cron

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

Copilot AI commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill on #46414, address the outstanding review feedback before requesting maintainer attention, and report the next concrete step once the branch is ready.

...

All four review threads have been addressed in commit fix(parser): address review feedback - redacting path wrapper, NumError tests, revert cron:

  1. remote_resolve_path.go / remote_fetch_wasm.go — redacting wrapper: replaced the bare %w wrapping of filepath.Rel errors with a new pathRelError type (pkg/parser/path_rel_error.go). Its Error() returns only the sanitised message (no internal absolute paths); Unwrap() returns the upstream relErr for errors.Is/errors.As traversal.

  2. github_urls.go — regression tests: added TestParseGitHubURL_NumErrorWrapping in github_urls_test.go with four cases covering the numbered-URL (PR, issue), run-URL, and job-URL paths, each asserting errors.As(err, &strconv.NumError{}) is reachable.

  3. schedule_parser.go — regression tests: added TestParseLongIntervalParts_NumErrorWrapping in schedule_parser_test.go asserting that a non-numeric interval wraps *strconv.NumError while zero and negative intervals (value-range branch, no upstream error) do not.

  4. .github/workflows/agentic-auto-upgrade.yml — schedule revert: reverted the unrelated cron change back to "21 3 * * 5" (the deterministic value generated by make recompile --schedule-seed github/gh-aw).

Local validation: make fmt, make lint, make test-unit all pass. CI needs a human re-trigger to confirm.

Copilot AI requested a review from gh-aw-bot July 18, 2026 13:28
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill on #46414, address the unresolved review feedback listed below, confirm the branch is up to date, and hand back the next concrete maintainer action.

Unresolved review feedback:

Generated by 👨‍🍳 PR Sous Chef · 3.87 AIC · ⌖ 6.21 AIC · ⊞ 7.5K ·
Comment /souschef to run again

Copilot AI commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill on #46414, address the unresolved review feedback listed below, confirm the branch is up to date, and hand back the next concrete maintainer action.

Unreso...

All four threads have been replied to (commit c9a688e). The code changes were already in place from the previous push; this pass adds the per-thread replies so they can be resolved. Local validation (make fmt, make lint, make test-unit) continues to pass. Ready for human CI re-trigger and maintainer approval.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

\n@copilot please run the skill, address any unresolved review feedback, and rerun checks once the branch is up to date.

Generated by 👨‍🍳 PR Sous Chef · 2.37 AIC · ⌖ 5.94 AIC · ⊞ 7.5K ·
Comment /souschef to run again

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address any unresolved review feedback, and rerun checks once the branch is up to date.

Generated by 👨‍🍳 PR Sous Chef · 3.64 AIC · ⌖ 7.92 AIC · ⊞ 7.5K ·
Comment /souschef to run again

Copilot AI commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

\n@copilot please run the skill, address any unresolved review feedback, and rerun checks once the branch is up to date.

...

All review feedback was addressed in commit c9a688e. Local validation passes. See the follow-up comment below for the full pr-finisher summary.

@copilot please run the pr-finisher skill, address any unresolved review feedback, and rerun checks once the branch is up to date.

...

All four review threads from commit cf5a132 were addressed in c9a688e and have replies. No new in-scope feedback requires code changes. Local validation (make fmt, make lint, make test-unit, make agent-report-progress) all pass.

Thread resolution status: All threads have been replied to. Two are already marked outdated (the remote_resolve_path.go and agentic-auto-upgrade.yml threads became stale when c9a688e superseded the commented lines). Resolution via the agent's tooling is not available for review threads; a maintainer can resolve them on merge or manually.

CI: A run was in progress at triage time (29652709348); the prior completed run (29646879784) succeeded. The branch needs a human to re-trigger CI (close/reopen or workflow_dispatch) before merge since agent pushes do not trigger workflows.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address any unresolved review feedback, and rerun checks once the branch is up to date.

Generated by PR Sous Chef: https://github.com/github/gh-aw/actions/runs/29654427038

Generated by 👨‍🍳 PR Sous Chef · 6.34 AIC · ⌖ 5.58 AIC · ⊞ 7.5K ·
Comment /souschef to run again

Copilot AI commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill, address any unresolved review feedback, and rerun checks once the branch is up to date.

Generated by PR Sous Chef: https://github.com/github/gh-aw/actio...

No new actionable items since the last pass. Status:

  • Reviews — All four copilot-pull-request-reviewer threads have replies (commit c9a688e). Two are already marked outdated; the other two are fully addressed with code changes and per-thread replies.
  • Checks (local)make fmt, make lint, make test-unit, and make agent-report-progress pass cleanly.
  • Checks (CI) — Prior completed runs 29646879784 and 29652709348 both succeeded. Run 29654724614 is currently in progress.
  • Mergeable — PR is open, not draft. Blocked pending maintainer approval.

No code changes required. Ready for maintainer review and CI confirmation.

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

Copy link
Copy Markdown
Collaborator

@copilot resolve the merge conflicts on this branch.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts on this branch.

Resolved in commit df63989. Two conflicts:

  1. .github/workflows/agentic-auto-upgrade.yml — took main's cron value ("41 23 * * 1") from dc63b6bdaf.
  2. pkg/parser/schedule_parser_test.go — kept both our TestParseLongIntervalParts_NumErrorWrapping and main's TestErrUnsupportedSyntaxIs; both pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[deep-report] Audit and wrap upstream YAML errors in the parser import pipeline (%w)

4 participants