Skip to content

Add globwalkignorederror linter: flag discarded errors from filepath.Glob/os.ReadDir - #51185

Merged
pelikhan merged 3 commits into
mainfrom
copilot/add-globwalkignorederror-linter
Aug 7, 2026
Merged

Add globwalkignorederror linter: flag discarded errors from filepath.Glob/os.ReadDir#51185
pelikhan merged 3 commits into
mainfrom
copilot/add-globwalkignorederror-linter

Conversation

Copilot AI commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

filepath.Glob and os.ReadDir errors are sometimes discarded via the blank identifier, silently masking malformed patterns or unreadable directories and letting callers proceed as if an empty result were success (observed in pkg/cli/enable.go, pkg/cli/compile_pipeline.go, pkg/cli/audit_job.go).

New linter

  • pkg/linters/globwalkignorederror/globwalkignorederror.gogo/analysis pass flagging x, _ := filepath.Glob(...) and x, _ := os.ReadDir(...) assignments, following the strconvparseignorederror conventions (nolint suppression + generated-file skip support).
  • globwalkignorederror_test.go + testdata/analysistest fixtures covering bad, good (error checked), suppressed (//nolint), and generated-file cases.

Wiring & docs

  • pkg/linters/registry.go — registers globwalkignorederror.Analyzer in All().
  • pkg/linters/doc.go, pkg/linters/README.md, pkg/linters/spec_test.go — updated analyzer count (63 → 64) and documentation entries.
// flagged
files, _ := filepath.Glob("*.go")

// preferred
files, err := filepath.Glob("*.go")
if err != nil {
    return err
}

Copilot AI and others added 2 commits August 7, 2026 20:33
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] Add globwalkignorederror linter to catch discarded errors Add globwalkignorederror linter: flag discarded errors from filepath.Glob/os.ReadDir Aug 7, 2026
Copilot AI requested a review from pelikhan August 7, 2026 20:35
@pelikhan
pelikhan marked this pull request as ready for review August 7, 2026 20:36
Copilot AI balanced review requested due to automatic review settings August 7, 2026 20:36

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

Adds a custom analyzer detecting discarded errors from filepath.Glob and os.ReadDir.

Changes:

  • Implements and registers globwalkignorederror.
  • Adds analyzer fixtures and tests.
  • Updates linter documentation and registry specifications.
Show a summary per file
File Description
pkg/linters/globwalkignorederror/globwalkignorederror.go Implements the analyzer.
pkg/linters/globwalkignorederror/globwalkignorederror_test.go Runs analyzer tests.
pkg/linters/globwalkignorederror/testdata/src/globwalkignorederror/globwalkignorederror.go Covers detected, valid, and suppressed cases.
pkg/linters/globwalkignorederror/testdata/src/globwalkignorederror/generated.go Verifies generated-file exclusion.
pkg/linters/registry.go Registers the analyzer.
pkg/linters/spec_test.go Adds specification coverage.
pkg/linters/doc.go Documents the analyzer.
pkg/linters/README.md Adds public documentation entries.

Review details

Tip

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

Files not reviewed (1)
  • pkg/linters/globwalkignorederror/testdata/src/globwalkignorederror/generated.go: Generated file
  • Files reviewed: 7/8 changed files
  • Comments generated: 1
  • Review effort level: Balanced

if nolint.HasDirectiveForLinter(position, nolintIndex, "globwalkignorederror") {
return
}
pass.ReportRangef(call, "error return from %s.%s is discarded; malformed patterns or unreadable directories silently produce an empty result", pkgName.Imported().Name(), sel.Sel.Name)
@pelikhan
pelikhan merged commit 2ca1e5e into main Aug 7, 2026
8 checks passed
@pelikhan
pelikhan deleted the copilot/add-globwalkignorederror-linter branch August 7, 2026 20:55
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security scanning failed for Test Quality Sentinel. Review the logs for details.

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • api.individual.githubcopilot.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "api.individual.githubcopilot.com"

See Network Configuration for more information.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ failed during design decision gate check.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security scanning failed for Matt Pocock Skills Reviewer. Review the logs for details.

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

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel Report 🧪

PR: #51185 — Add globwalkignorederror linter
Test Quality Score: ✅ 100/100 (Excellent)

Test Coverage Summary

Metric Result
New/Modified Test Functions 1
Design Tests 1 (100%)
Tests with Edge Cases 1 (100%)
Test Inflation Ratio 0.19:1 (16 test lines / 86 prod lines)
Build Tags ✓ Present
Mock Libraries ✓ None (proper)

Analyzed Tests

Test Details (1 test)
Test File Classification Value Notes
TestAnalyzer globwalkignorederror_test.go behavioral_contract high_value Uses golang.org/x/tools/go/analysis standard testing pattern; verifies linter correctly flags discarded error returns from filepath.Glob and os.ReadDir; validates error handling, nolint directive suppression, and generated file exclusion.

Design Invariants Verified ✓

  • Discarded error returns from filepath.Glob are flagged
  • Discarded error returns from os.ReadDir are flagged
  • Proper error handling is not flagged
  • (nolint/redacted):globwalkignorederror suppresses warnings
  • Generated files are correctly excluded from analysis

Spec Compliance

  • spec_test.go updated to add globwalkignorederror to documented analyzers list
  • Registry consistency check in TestRegistryMatchesDocumentation validates proper export

Quality Signals ✓

  • Standard analysis framework: Uses analysistest.Run() from golang.org/x/tools — tested, proven pattern
  • Comprehensive testdata: Covers positive, negative, and suppression scenarios plus generated-file edge case
  • Low inflation: Test adds 16 lines to cover 86 lines of production logic
  • No violations: Proper build tags, no forbidden mocks, clean architecture

🧪 Test quality analysis by Test Quality Sentinel · haiku45 · 24.8 AIC · ⊞ 7.7K ·
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.

✅ Test Quality Sentinel: 100/100. 100% design tests (threshold: 30% implementation). This PR demonstrates excellent test quality with a single behavioral test that comprehensively validates the new globwalkignorederror linter. The test uses the standard golang.org/x/tools/go/analysis framework and covers positive, negative, suppression, and generated-file edge cases with minimal test inflation (0.19:1 ratio).

@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: globwalkignorederror linter

The linter structure, AST traversal, nolint support, and test coverage are solid. One blocking correctness issue with the diagnostic message (see inline comment).

Non-blocking note: spec_test.go bumps the documented analyzer count comment from 62 → 64, but only one analyzer is added here. The pre-existing count of 62 appears stale — worth correcting in the same commit.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 34.9 AIC · ⊞ 5.5K

if nolint.HasDirectiveForLinter(position, nolintIndex, "globwalkignorederror") {
return
}
pass.ReportRangef(call, "error return from %s.%s is discarded; malformed patterns or unreadable directories silently produce an empty result", pkgName.Imported().Name(), sel.Sel.Name)

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.

The diagnostic message conflates the two different failure modes of filepath.Glob and os.ReadDir:

  • filepath.Glob returns ErrBadPattern for malformed glob patterns; filesystem read errors are silently suppressed by design.
  • os.ReadDir returns filesystem errors but has no pattern concept.

The current message "malformed patterns or unreadable directories silently produce an empty result" is inaccurate for both. Consider per-function messages:

var msgs = map[string]map[string]string{
    "path/filepath": {"Glob": "error return from filepath.Glob is discarded; ErrBadPattern is silently ignored"},
    "os":            {"ReadDir": "error return from os.ReadDir is discarded; filesystem errors are silently ignored"},
}

@copilot please address this.

@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 /tdd and /grill-with-docs — requesting changes on two test coverage gaps and one inaccurate diagnostic message.

📋 Key Themes & Highlights

Issues

  • Inaccurate diagnostic message (line 85): the message mentions "malformed patterns" for both APIs, but os.ReadDir has no concept of patterns — only filepath.Glob does. An existing Copilot comment already flagged this.
  • spec_test comment count (spec_test.go:93): the comment jumped from 62 to 64, implying two analyzers were added. It should read 63.
  • Test coverage gaps: the generated-file fixture covers only filepath.Glob; os.ReadDir is untested there. The suppressed() fixture omits the preceding-line (nolint/redacted) case for os.ReadDir.

Positive Highlights

  • ✅ Clean, idiomatic go/analysis implementation following the established strconvparseignorederror conventions
  • nolint suppression and generated-file skip both wired correctly
  • ✅ Registry, doc.go, README, and spec_test all updated consistently
  • ✅ Motivated by concrete real-world occurrences in the codebase

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 40.6 AIC · ⊞ 7.1K
Comment /matt to run again

Comment thread pkg/linters/spec_test.go

// documentedAnalyzers returns the analyzer subpackages documented in the README
// "Public API > Subpackages" table. The README documents 62 analyzers
// "Public API > Subpackages" table. The README documents 64 analyzers

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] Off-by-one in the count comment: it jumped from 62 to 64 (adds 2), but this PR adds exactly one analyzer.

💡 Fix

The comment on line 93 should read:

// "Public API > Subpackages" table. The README documents 63 analyzers

The doc.go bump (63 → 64) is correct. The spec_test comment that previously said 62 should become 63 after this PR.

@copilot please address this.

if nolint.HasDirectiveForLinter(position, nolintIndex, "globwalkignorederror") {
return
}
pass.ReportRangef(call, "error return from %s.%s is discarded; malformed patterns or unreadable directories silently produce an empty result", pkgName.Imported().Name(), sel.Sel.Name)

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.

[/grill-with-docs] The diagnostic message conflates the two APIs — os.ReadDir does not involve patterns at all, so "malformed patterns" does not apply to it.

💡 Suggested fix

An existing review comment already flags this (id 3738627680). The message should distinguish the two cases, e.g.:

// filepath.Glob path
pass.ReportRangef(call, "error return from filepath.Glob is discarded; a malformed pattern silently produces an empty result")

// os.ReadDir path
pass.ReportRangef(call, "error return from os.ReadDir is discarded; an unreadable directory silently produces an empty result")

Or keep one message but drop the inaccurate half: "error return from %s.%s is discarded and will silently produce an empty result".

@copilot please address this.

_ = files
entries, _ := os.ReadDir(".") //nolint:globwalkignorederror
_ = entries
}

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] Missing test case: os.ReadDir with a preceding-line (nolint/redacted) comment is not covered.

💡 Suggested addition

The suppressed() function covers filepath.Glob with a preceding-line nolint and os.ReadDir with a trailing-line nolint, but not os.ReadDir with a preceding-line nolint:

func suppressed() {
    (nolint/redacted):globwalkignorederror
    files, _ := filepath.Glob("*.go")
    _ = files

    entries, _ := os.ReadDir(".") (nolint/redacted):globwalkignorederror
    _ = entries

    // Missing: preceding-line nolint for os.ReadDir
    (nolint/redacted):globwalkignorederror
    entries2, _ := os.ReadDir(".")
    _ = entries2
}

This confirms the nolint index handles both placement styles for both APIs.

@copilot please address this.

func generatedBad() {
files, _ := filepath.Glob("*.go")
_ = files
}

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] The generated-file fixture only tests filepath.Glob — add an os.ReadDir call to confirm both functions are suppressed in generated files.

💡 Suggested addition
func generatedBad() {
    files, _ := filepath.Glob("*.go")
    _ = files
    entries, _ := os.ReadDir(".")
    _ = entries
}

Without this, a regression where only one function is skipped in generated files would go undetected.

@copilot please address this.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.86.1

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.

[linter-miner] Add globwalkignorederror linter: flag discarded errors from filepath.Glob/os.ReadDir

3 participants