diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..eff95b7 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: weekly + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: weekly diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..e3e18d0 --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,95 @@ +name: Security + +on: + push: + branches: [main] + schedule: + - cron: "17 3 * * 1" + workflow_dispatch: + pull_request: + +permissions: + contents: read + +jobs: + dependency-review: + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Review dependencies + uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 + + vulnerabilities-and-sbom: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Set up Go + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 + with: + go-version: stable + - name: Check every Go module for vulnerabilities + shell: bash + run: | + while IFS= read -r -d '' module; do + module_dir=${module%/go.mod} + package_list=$( + ( + cd -- "$module_dir" + GOWORK=off go list ./... + ) + ) + if [ -n "$package_list" ]; then + ( + cd -- "$module_dir" + GOWORK=off go run golang.org/x/vuln/cmd/govulncheck@v1.7.0 -test ./... + ) + fi + done < <(find . -name go.mod -type f -not -path './.git/*' -not -path './node_modules/*' -not -path './vendor/*' -print0) + - name: Generate an SBOM for every Go module + shell: bash + run: | + mkdir -p sbom + module_count=0 + while IFS= read -r -d '' module; do + module_dir=${module%/go.mod} + package_list=$( + ( + cd -- "$module_dir" + GOWORK=off go list ./... + ) + ) + if [ -n "$package_list" ]; then + module_count=$((module_count + 1)) + ( + cd -- "$module_dir" + GOWORK=off go run github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@v1.9.0 mod -json -type library -test -output "$GITHUB_WORKSPACE/sbom/go-${module_count}.cdx.json" + ) + fi + done < <(find . -name go.mod -type f -not -path './.git/*' -not -path './node_modules/*' -not -path './vendor/*' -print0) + test "$module_count" -gt 0 + for artifact in sbom/*.cdx.json; do + jq -e '.bomFormat == "CycloneDX" and .metadata.component.type == "library" and all(.components[]?; .name != "..")' "$artifact" >/dev/null + done + artifact_count=$(find sbom -type f -name '*.cdx.json' -size +0c | wc -l | tr -d ' ') + test "$module_count" -eq "$artifact_count" + - name: Upload SBOMs + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: cyclonedx-sboms + path: sbom + if-no-files-found: error + + secret-scan: + runs-on: ubuntu-latest + steps: + - name: Checkout complete history + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + - name: Install Gitleaks + run: | + GOBIN="$RUNNER_TEMP/gitleaks" go install github.com/zricethezav/gitleaks/v8@v8.30.1 + - name: Scan Git history for secrets + run: | + "$RUNNER_TEMP/gitleaks/gitleaks" git . --redact --no-banner diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2c47637..4a45dd1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,6 +14,9 @@ name: Wire Tests on: [push, pull_request] + +permissions: + contents: read jobs: build: strategy: @@ -26,26 +29,40 @@ jobs: WIRE_CACHE_MODE: ${{ matrix.cache-mode }} steps: - name: Install Go - uses: actions/setup-go@v2 + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: ${{ matrix.go-version }} - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 2 # required for codecov - name: Run Tests shell: bash run: 'internal/runtests.sh' + minimum-go: + name: Go 1.25 on Linux + runs-on: ubuntu-latest + steps: + - name: Install Go + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 + with: + go-version: "1.25.x" + - name: Checkout code + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Run Tests + shell: bash + run: 'internal/runtests.sh' + codecov: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: "stable" @@ -56,6 +73,6 @@ jobs: run: go test ./internal/... -coverprofile=coverage.txt - name: Upload results to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@e53489f4d376d79066609109e7a95a29eb3740b1 # v7.0.0 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/README.md b/README.md index c094dbc..2a414d3 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Go Reference License Go Test - Go version + Go version Latest tag

diff --git a/go.mod b/go.mod index 5db8855..61baf4d 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,17 @@ module github.com/goforj/wire -go 1.19 +go 1.25.0 require ( github.com/fsnotify/fsnotify v1.7.0 github.com/google/go-cmp v0.6.0 github.com/google/subcommands v1.2.0 github.com/pmezard/go-difflib v1.0.0 - golang.org/x/tools v0.24.1 + golang.org/x/tools v0.49.0 ) require ( - golang.org/x/mod v0.20.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.23.0 // indirect + golang.org/x/mod v0.40.0 // indirect + golang.org/x/sync v0.22.0 // indirect + golang.org/x/sys v0.47.0 // indirect ) diff --git a/go.sum b/go.sum index 6fba262..2b0c19d 100644 --- a/go.sum +++ b/go.sum @@ -6,11 +6,11 @@ github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/tools v0.24.1 h1:vxuHLTNS3Np5zrYoPRpcheASHX/7KiGo+8Y4ZM1J2O8= -golang.org/x/tools v0.24.1/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= +golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE= +golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= +golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI= +golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo= diff --git a/internal/loader/loader_test.go b/internal/loader/loader_test.go index 328fe6a..12c949d 100644 --- a/internal/loader/loader_test.go +++ b/internal/loader/loader_test.go @@ -3281,12 +3281,21 @@ func comparableErrors(errs []packages.Error) []string { continue } pos := normalizeErrorPos(err.Pos) - add(pos + "|" + err.Msg) + add(pos + "|" + normalizeCompilerDiagnostic(err.Msg)) } sort.Strings(out) return out } +// normalizeCompilerDiagnostic makes package-loader comparisons independent of Go's equivalent diagnostic wording. +func normalizeCompilerDiagnostic(msg string) string { + const legacy = "undefined: " + if strings.HasPrefix(msg, legacy) { + return "undeclared name: " + strings.TrimPrefix(msg, legacy) + } + return msg +} + func hasPrefixLabel(labels []string, prefix string) bool { for _, label := range labels { if strings.HasPrefix(label, prefix) { @@ -3336,7 +3345,7 @@ func expandSummaryDiagnostics(msg string) []string { } if parts := strings.SplitN(line, ": ", 2); len(parts) == 2 { pos := normalizeErrorPos(parts[0]) - out = append(out, pos+"|"+parts[1]) + out = append(out, pos+"|"+normalizeCompilerDiagnostic(parts[1])) continue } out = append(out, line) diff --git a/internal/wire/wire_test.go b/internal/wire/wire_test.go index 23db303..3ea856f 100644 --- a/internal/wire/wire_test.go +++ b/internal/wire/wire_test.go @@ -542,7 +542,7 @@ func isIdent(s string) bool { // "C:\GOPATH" and running on Windows, the string // "C:\GOPATH\src\foo\bar.go:15:4" would be rewritten to "foo/bar.go:x:y". func scrubError(gopath string, s string) string { - s = normalizeHeaderRelativeError(s) + s = normalizeLegacyUnexportedName(normalizeHeaderRelativeError(s)) sb := new(strings.Builder) query := gopath + string(os.PathSeparator) + "src" + string(os.PathSeparator) for { @@ -582,6 +582,26 @@ func scrubError(gopath string, s string) string { return strings.TrimRight(sb.String(), "\n") } +// normalizeLegacyUnexportedName aligns the Go 1.19 compiler diagnostic with newer Go releases. +func normalizeLegacyUnexportedName(s string) string { + const marker = ": " + const suffix = " not exported by package " + idx := strings.Index(s, marker) + if idx == -1 { + return s + } + rest := s[idx+len(marker):] + end := strings.Index(rest, suffix) + if end == -1 { + return s + } + name := rest[:end] + if !isLowerIdent(name) { + return s + } + return s[:idx] + ": name " + rest +} + func normalizeHeaderRelativeError(s string) string { const headerPrefix = "-: # " if !strings.HasPrefix(s, headerPrefix) {