diff --git a/.github/workflows/arm64-build-smoke.yml b/.github/workflows/arm64-build-smoke.yml index 0f8a08c..7775a66 100644 --- a/.github/workflows/arm64-build-smoke.yml +++ b/.github/workflows/arm64-build-smoke.yml @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-24.04-arm timeout-minutes: 25 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install dependencies run: | diff --git a/.github/workflows/bpfcompat-example-hosted.yml b/.github/workflows/bpfcompat-example-hosted.yml index 51a373d..6d61220 100644 --- a/.github/workflows/bpfcompat-example-hosted.yml +++ b/.github/workflows/bpfcompat-example-hosted.yml @@ -33,7 +33,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Report KVM acceleration status shell: bash @@ -95,7 +95,7 @@ jobs: - name: Upload reports if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: bpfcompat-reports-${{ github.run_id }} if-no-files-found: warn diff --git a/.github/workflows/bpfcompat-example.yml b/.github/workflows/bpfcompat-example.yml index 1fe1de3..5ad51ff 100644 --- a/.github/workflows/bpfcompat-example.yml +++ b/.github/workflows/bpfcompat-example.yml @@ -28,7 +28,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Verify KVM availability shell: bash @@ -64,7 +64,7 @@ jobs: - name: Upload reports if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: bpfcompat-reports-${{ github.run_id }} if-no-files-found: warn diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21f2c0e..3e5f821 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,10 +41,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: ${{ env.GO_VERSION }} cache: true @@ -62,7 +62,7 @@ jobs: - name: Coverage summary run: go tool cover -func=coverage.out | tail -20 - name: Upload coverage artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 if: always() with: name: coverage-${{ github.run_id }} @@ -74,16 +74,16 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: ${{ env.GO_VERSION }} cache: true - name: golangci-lint (pull request diff) if: github.event_name == 'pull_request' - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v9 with: version: latest args: --timeout=5m --new-from-rev=origin/main @@ -99,7 +99,7 @@ jobs: fi - name: golangci-lint (push diff) if: github.event_name != 'pull_request' && steps.push-diff-base.outputs.has_parent == 'true' - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v9 with: version: latest args: --timeout=5m --new-from-rev=HEAD~1 @@ -112,8 +112,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 + - uses: actions/checkout@v6 + - uses: actions/setup-go@v6 with: go-version: ${{ env.GO_VERSION }} cache: true @@ -127,8 +127,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 + - uses: actions/checkout@v6 + - uses: actions/setup-go@v6 with: go-version: ${{ env.GO_VERSION }} cache: true diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 279d6ec..b4496cd 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -34,16 +34,16 @@ jobs: security-events: write steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: "1.25.11" cache: true - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: go # Go does not support build-mode: none; autobuild runs `go build`, @@ -53,6 +53,6 @@ jobs: queries: security-and-quality - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 with: category: "/language:go" diff --git a/.github/workflows/compatibility-matrix-publish.yml b/.github/workflows/compatibility-matrix-publish.yml index 3c11897..4ff3f31 100644 --- a/.github/workflows/compatibility-matrix-publish.yml +++ b/.github/workflows/compatibility-matrix-publish.yml @@ -27,7 +27,7 @@ jobs: timeout-minutes: 60 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Verify KVM availability shell: bash @@ -75,7 +75,7 @@ jobs: - name: Upload compatibility evidence if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: bpfcompat-compatibility-matrix-${{ github.run_id }} if-no-files-found: warn @@ -113,14 +113,14 @@ jobs: - name: Configure Pages if: github.event_name == 'workflow_dispatch' && inputs.deploy_pages == 'true' - uses: actions/configure-pages@v5 + uses: actions/configure-pages@v6 - name: Upload Pages artifact if: github.event_name == 'workflow_dispatch' && inputs.deploy_pages == 'true' - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v5 with: path: public/compatibility - name: Deploy Pages if: github.event_name == 'workflow_dispatch' && inputs.deploy_pages == 'true' - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@v5 diff --git a/.github/workflows/firecracker-preflight.yml b/.github/workflows/firecracker-preflight.yml index c78431e..a33949a 100644 --- a/.github/workflows/firecracker-preflight.yml +++ b/.github/workflows/firecracker-preflight.yml @@ -16,7 +16,7 @@ jobs: runs-on: [self-hosted, linux, x64, kvm] timeout-minutes: 20 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Verify KVM run: | diff --git a/.github/workflows/kernel-freshness.yml b/.github/workflows/kernel-freshness.yml index e877699..f537357 100644 --- a/.github/workflows/kernel-freshness.yml +++ b/.github/workflows/kernel-freshness.yml @@ -29,8 +29,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 + - uses: actions/checkout@v6 + - uses: actions/setup-go@v6 with: go-version: "1.25.11" cache: true @@ -55,7 +55,7 @@ jobs: - name: Upload freshness report if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: kernel-freshness-${{ github.run_id }} if-no-files-found: warn diff --git a/.github/workflows/latest-kernel-compatibility.yml b/.github/workflows/latest-kernel-compatibility.yml index d933dd2..7748100 100644 --- a/.github/workflows/latest-kernel-compatibility.yml +++ b/.github/workflows/latest-kernel-compatibility.yml @@ -40,7 +40,7 @@ jobs: VM_CONCURRENCY: ${{ github.event.inputs.concurrency || '2' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Verify KVM availability shell: bash @@ -93,7 +93,7 @@ jobs: - name: Upload latest-kernel evidence if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: bpfcompat-latest-kernel-${{ github.run_id }} if-no-files-found: warn diff --git a/.github/workflows/multiarch-compatibility.yml b/.github/workflows/multiarch-compatibility.yml index 98674c6..a799dcc 100644 --- a/.github/workflows/multiarch-compatibility.yml +++ b/.github/workflows/multiarch-compatibility.yml @@ -42,7 +42,7 @@ jobs: timeout-minutes: 75 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Verify runner virtualization shell: bash @@ -79,7 +79,7 @@ jobs: - name: Upload multiarch evidence if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: bpfcompat-${{ matrix.arch }}-${{ github.run_id }} if-no-files-found: warn diff --git a/.github/workflows/profile-catalog-maintenance.yml b/.github/workflows/profile-catalog-maintenance.yml index a04ae65..7c681eb 100644 --- a/.github/workflows/profile-catalog-maintenance.yml +++ b/.github/workflows/profile-catalog-maintenance.yml @@ -17,8 +17,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 20 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 + - uses: actions/checkout@v6 + - uses: actions/setup-go@v6 with: go-version: "1.25.11" cache: true @@ -40,7 +40,7 @@ jobs: - name: Upload catalog evidence if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: bpfcompat-profile-catalog-${{ github.run_id }} if-no-files-found: warn diff --git a/.github/workflows/release-artifacts.yml b/.github/workflows/release-artifacts.yml index bf6d93c..45889ce 100644 --- a/.github/workflows/release-artifacts.yml +++ b/.github/workflows/release-artifacts.yml @@ -42,10 +42,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 20 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: ${{ env.GO_VERSION }} cache: true @@ -110,7 +110,7 @@ jobs: cosign sign-blob --yes dist/SHA256SUMS --output-signature dist/SHA256SUMS.sig --output-certificate dist/SHA256SUMS.crt cosign sign-blob --yes dist/bpfcompat.sbom.cdx.json --output-signature dist/bpfcompat.sbom.cdx.sig --output-certificate dist/bpfcompat.sbom.cdx.crt - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: bpfcompat-release-${{ steps.meta.outputs.version }} path: | @@ -132,7 +132,7 @@ jobs: # The action consumes these assets at run time to skip building from # source: bpfcompat-linux-amd64, bpfcompat-validator-static-linux-amd64, # and SHA256SUMS for verification. - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v3 with: files: | dist/bpfcompat-linux-amd64 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index f724b19..9b67afa 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -34,7 +34,7 @@ jobs: contents: read steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: persist-credentials: false @@ -46,13 +46,13 @@ jobs: publish_results: true - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: scorecard-results path: results.sarif retention-days: 5 - name: Upload to code scanning - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@v4 with: sarif_file: results.sarif diff --git a/.github/workflows/upstream-kernel-compatibility.yml b/.github/workflows/upstream-kernel-compatibility.yml index 5b6547a..df5dedd 100644 --- a/.github/workflows/upstream-kernel-compatibility.yml +++ b/.github/workflows/upstream-kernel-compatibility.yml @@ -24,7 +24,7 @@ jobs: env: VM_CONCURRENCY: ${{ github.event.inputs.concurrency || '1' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Verify virtme-ng/KVM prerequisites run: | @@ -55,7 +55,7 @@ jobs: --concurrency "${VM_CONCURRENCY}" - name: Upload upstream-kernel evidence - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 if: always() with: name: upstream-kernel-compatibility diff --git a/.golangci.yml b/.golangci.yml index e656dcd..783ea78 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,130 +5,148 @@ # default posture against shell/path/network footguns. # # How to run locally: -# golangci-lint run --timeout=5m +# golangci-lint run # # CI runs this with --new-from-rev=origin/main so it doesn't fail on # pre-existing issues outside the PR. Cleanups are tracked separately. +# +# Schema: golangci-lint v2 (migrated from v1 with `golangci-lint migrate`). +version: "2" run: - timeout: 5m tests: true modules-download-mode: vendor linters: - disable-all: true + # v2: `default: none` replaces v1 `disable-all: true`. gofmt/goimports moved + # to the `formatters` block below; gosimple is now folded into staticcheck. + default: none enable: - # Stdlib / language correctness + - bodyclose # http.Response.Body must be Closed + - contextcheck # missing context propagation + - copyloopvar # Go 1.22+ for-loop variable capture + - dupword - errcheck # unchecked errors are bugs in flight - - gosimple # idioms + - errorlint # %w usage, errors.Is/As correctness + - exhaustive # switch on enums + - gocritic + - gosec # security-focused static analysis - govet - ineffassign - - staticcheck # the big one — catches many real bugs - - typecheck - - unused - - unconvert - - unparam # unused params hint at incomplete refactors - # Style + readability - - gocritic - - gofmt - - goimports - - revive - misspell - - whitespace - # Security-adjacent - - errorlint # %w usage, errors.Is/As correctness - - gosec # security-focused static analysis - - bodyclose # http.Response.Body must be Closed - - contextcheck # missing context propagation - nilerr # returning nil after non-nil err - noctx # http requests without context - - rowserrcheck # sql.Rows.Err() check (cheap to keep) - # Concurrency - - copyloopvar # Go 1.22+ for-loop variable capture - # Misc - prealloc # slice preallocation hints - - dupword - - exhaustive # switch on enums - -linters-settings: - govet: - enable-all: true - disable: - - fieldalignment # cosmetic; not worth the churn - - shadow # too noisy on idiomatic err shadowing - gocritic: - enabled-tags: - - diagnostic - - style - - performance - disabled-checks: - - hugeParam # noisy on small request structs - - unnamedResult # we prefer terse signatures - - whyNoLint - gosec: - excludes: - # G107 (variable URL): we audit each call site explicitly (e.g. JWKS - # HTTPS check, SSRF guard) and the linter's heuristic flags every one. - - G107 - # G304 (file inclusion via variable): we guard paths via - # report_paths.go and filepath.Clean. The linter can't see that and - # flags every os.Open. - - G304 - # G115 (integer overflow): mostly noisy on size_t conversions where - # the value is already bounded by caller. Re-enable if we add untrusted - # numeric inputs. - - G115 - revive: + - revive + - rowserrcheck # sql.Rows.Err() check (cheap to keep) + - staticcheck # the big one — catches many real bugs (includes gosimple) + - unconvert + - unparam # unused params hint at incomplete refactors + - unused + - whitespace + settings: + exhaustive: + default-signifies-exhaustive: true + gocritic: + disabled-checks: + - hugeParam # noisy on small request structs + - unnamedResult # we prefer terse signatures + - whyNoLint + enabled-tags: + - diagnostic + - style + - performance + gosec: + excludes: + # G107 (variable URL): we audit each call site explicitly (e.g. JWKS + # HTTPS check, SSRF guard) and the linter's heuristic flags every one. + - G107 + # G304 (file inclusion via variable): we guard paths via + # report_paths.go and filepath.Clean. The linter can't see that. + - G304 + # G115 (integer overflow): mostly noisy on size_t conversions where + # the value is already bounded by caller. + - G115 + govet: + enable-all: true + disable: + - fieldalignment # cosmetic; not worth the churn + - shadow # too noisy on idiomatic err shadowing + revive: + rules: + - name: var-naming + - name: package-comments + disabled: true # too noisy; we'll do this in a follow-up pass + - name: exported + disabled: true # ditto — package-level docstring sweep is separate + - name: error-naming + - name: error-return + - name: blank-imports + - name: context-as-argument + - name: context-keys-type + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling rules: - - name: var-naming - - name: package-comments - disabled: true # too noisy; we'll do this in a follow-up pass - - name: exported - disabled: true # ditto — package-level docstring sweep is separate - - name: error-naming - - name: error-return - - name: blank-imports - - name: context-as-argument - - name: context-keys-type - exhaustive: - default-signifies-exhaustive: true + # Tests routinely shadow err and call panic-paths; relax there. + - path: _test\.go + linters: + - contextcheck + - errcheck + - gosec + - noctx + - unparam + # Vendored code is not ours. + - path: ^vendor/ + linters: + - errcheck + - gocritic + - gosec + - revive + - staticcheck + # Generated/embedded UI lives in one big string literal; gocritic's + # commentFormatting trips on the inline JS inside the heredoc. + - path: internal/api/ui\.go + linters: + - dupword + - gocritic + - misspell + paths: + - .*\.pb\.go + - vendor + - .bpfcompat + - .bpfcompat-api + - evidence + - reports + - vm/cache + - third_party$ + - builtin$ + - examples$ issues: # Don't fail the build on pre-existing issues outside the PR diff; CI # passes --new-from-rev to enforce that. Locally, devs still see warnings. max-issues-per-linter: 0 max-same-issues: 0 - exclude-rules: - # Tests routinely shadow err and call panic-paths; relax there. - - path: _test\.go - linters: - - errcheck - - gosec - - unparam - - contextcheck - - noctx - # Vendored code is not ours. - - path: ^vendor/ - linters: - - typecheck - - staticcheck - - errcheck - - gosec - - revive - - gocritic - # Generated/embedded UI lives in one big string literal; gocritic's - # commentFormatting trips on the inline JS inside the heredoc. - - path: internal/api/ui\.go - linters: - - gocritic - - misspell - - dupword - exclude-dirs: - - vendor - - .bpfcompat - - .bpfcompat-api - - evidence - - reports - - vm/cache - exclude-files: - - ".*\\.pb\\.go" + +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - .*\.pb\.go + - vendor + - .bpfcompat + - .bpfcompat-api + - evidence + - reports + - vm/cache + - third_party$ + - builtin$ + - examples$