Skip to content

feat: extend GoModResolver to support any valid Go *.mod file#268

Merged
kezhenxu94 merged 3 commits intoapache:mainfrom
gofogo:feat/support-go-mod-variants
Apr 5, 2026
Merged

feat: extend GoModResolver to support any valid Go *.mod file#268
kezhenxu94 merged 3 commits intoapache:mainfrom
gofogo:feat/support-go-mod-variants

Conversation

@ivankatliarchuk
Copy link
Copy Markdown
Contributor

@ivankatliarchuk ivankatliarchuk commented Apr 2, 2026

Why: Projects using Go 1.24's tool dependency pattern (e.g. go.tool.mod) were failing with unable to find a resolver because the resolver only matched the hardcoded filename go.mod.

What:

  • GoModResolver.CanResolve now matches any *.mod file
  • GoModResolver.Resolve validates file content (module + go directives) and passes -modfile to go mod download for non-default mod files
  • Makefile: fix hardcoded ARCH=amd64 - now detects host arch via go env GOARCH, overridable for cross-compilation
  • Add golang_test.go covering CanResolve, Resolve validation, and ResolvePackageLicense

Current

DEBUG Base name: go.tool.mod
DEBUG Base name: go.tool.mod
DEBUG Base name: go.tool.mod
DEBUG Base name: go.tool.mod
ERROR unable to find a resolver to resolve dependency declaration file: ../source/self/go-work/fork-external-dns/go.tool.mod
ERROR one or more errors occurred checking license compatibility

With the Change

DEBUG Base name: go.mod
DEBUG Run command: /opt/homebrew/bin/go mod download, please wait
DEBUG Module size: 200
...
...
DEBUG Base name: go.tool.mod
DEBUG Run command: /opt/homebrew/bin/go mod download -modfile go.tool.mod, please wait
DEBUG Module size: 128
DEBUG Directory of github.com/a8m/envsubst is ../go/pkg/mod/github.com/a8m/envsubst@v1.4.3
DEBUG Directory of github.com/agext/levenshtein is ../go/pkg/mod/github.com/agext/levenshtein@v1.2.1
DEBUG Director

Log example

DEBUG Directory of sigs.k8s.io/randfill is ~/go/pkg/mod/sigs.k8s.io/randfill@v1.0.0
DEBUG 	- Found license: Apache-2.0
DEBUG Directory of sigs.k8s.io/yaml is ~/go/pkg/mod/sigs.k8s.io/yaml@v1.6.0
DEBUG 	- Found license: MIT and BSD-3-Clause and Apache-2.0

Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
@ivankatliarchuk
Copy link
Copy Markdown
Contributor Author

Hi @kezhenxu94

When you have time, could you have a look pls?

@wu-sheng wu-sheng requested review from Copilot and kezhenxu94 April 5, 2026 10:10
@wu-sheng wu-sheng added this to the 0.9.0 milestone Apr 5, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Extends the Go dependency resolver to recognize and handle non-default Go module files (e.g., go.tool.mod), including passing -modfile to go mod download, and adds tests plus a Makefile arch-detection tweak.

Changes:

  • Update GoModResolver.CanResolve to match *.mod files and add module-file validation + -modfile support during resolution.
  • Add Go resolver unit tests for CanResolve, invalid module-file validation behavior, and package license resolution.
  • Makefile now derives ARCH from go env GOARCH (overridable), and renames the uname variable used for OS detection.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
pkg/deps/golang.go Broaden resolver matching to *.mod, validate modfile contents, and pass -modfile for non-go.mod files
pkg/deps/golang_test.go New tests covering Go mod resolver matching/validation and license resolution behavior
Makefile Detect host GOARCH by default rather than hardcoding amd64

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

Comment on lines +58 to +65
func validateGoModFile(file string) error {
content, err := os.ReadFile(file)
if err != nil {
return err
}
if !goModuleDirective.Match(content) || !goVersionDirective.Match(content) {
return fmt.Errorf("%v is not a valid Go module file", file)
}
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

validateGoModFile requires both module and go directives, but the go directive is optional in valid go.mod/*.mod files. This will reject legitimate modules and cause dependency resolution to fail. Consider parsing with golang.org/x/mod/modfile (and only requiring a valid module directive), or relax the validation to not require a go directive.

Copilot uses AI. Check for mistakes.
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.

relaxed

var (
goModuleDirective = regexp.MustCompile(`(?m)^\s*module\s+\S`)
goVersionDirective = regexp.MustCompile(`(?m)^\s*go\s+\d`)
possibleLicenseFileName = regexp.MustCompile(`(?i)^LICENSE|LICENCE(\.txt)?|COPYING(\.txt)?$`)
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

possibleLicenseFileName is missing grouping/anchoring, so it can match unintended names (e.g., any filename containing "LICENCE" anywhere) and ^LICENSE will also match directories like LICENSES. Since ResolvePackageLicense doesn't check info.IsDir(), this can lead to attempting to ReadFile on a directory and failing license resolution. Suggest anchoring the full pattern (e.g., ^(LICENSE|LICENCE)(\.txt)?$|^COPYING(\.txt)?$) and skipping directories before reading.

Suggested change
possibleLicenseFileName = regexp.MustCompile(`(?i)^LICENSE|LICENCE(\.txt)?|COPYING(\.txt)?$`)
possibleLicenseFileName = regexp.MustCompile(`(?i)^(LICENSE|LICENCE|COPYING)(\.txt)?$`)

Copilot uses AI. Check for mistakes.
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.

this regex pre-existed the PR (it was just moved); the PR made it visible. I could fix it, as it's valid and a real bug.

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.

resolved

Comment on lines 167 to +170
return err
}

logger.Log.Debugf("\t- Found license: %v", identifier)
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

Before os.ReadFile(licenseFilePath) earlier in this function, ensure the directory entry isn’t a directory (info.IsDir()), otherwise directories like LICENSES/ can be treated as license files and cause a hard error. (The current name regex also matches prefixes like LICENSE*.)

Copilot uses AI. Check for mistakes.
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.

resolved

Comment on lines +118 to +122
t.Fatalf("expected 1 resolved, got %d", len(report.Resolved))
}
if report.Resolved[0].LicenseSpdxID != npmLicenseApache20 {
t.Errorf("expected %v, got %v", npmLicenseApache20, report.Resolved[0].LicenseSpdxID)
}
Copy link

Copilot AI Apr 5, 2026

Choose a reason for hiding this comment

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

This test relies on npmLicenseApache20, which is declared in an unrelated NPM resolver test file. That coupling is fragile (e.g., if that file is renamed, moved, or build-tagged) and makes this test harder to understand in isolation. Prefer defining a local constant (or using a literal) in this file.

Copilot uses AI. Check for mistakes.
@kezhenxu94
Copy link
Copy Markdown
Member

@ivankatliarchuk can you please fix the CI

Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
@ivankatliarchuk
Copy link
Copy Markdown
Contributor Author

Done. I've added test-docker to Makefile directive. As running tests locally require maven installed.

Tested with

go test ./pkg/deps/ -run 'TestCanResolveGoMod|TestResolveGoModInvalidFile|TestResolvePackageLicense' -v

Green as well

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.


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

Copy link
Copy Markdown
Member

@kezhenxu94 kezhenxu94 left a comment

Choose a reason for hiding this comment

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

Thank you!

@kezhenxu94 kezhenxu94 merged commit 5f499dc into apache:main Apr 5, 2026
4 of 5 checks passed
@ivankatliarchuk ivankatliarchuk deleted the feat/support-go-mod-variants branch April 5, 2026 11:10
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.

4 participants