diff --git a/.github/workflows/govulncheck.yaml b/.github/workflows/govulncheck.yaml new file mode 100644 index 000000000..405e8dec9 --- /dev/null +++ b/.github/workflows/govulncheck.yaml @@ -0,0 +1,28 @@ +# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. +# Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/go/base/.github/workflows/govulncheck.yaml instead. + +# Run govulncheck at midnight every night on the main branch, +# to alert us to recent vulnerabilities which affect the Go code in this +# project. +name: govulncheck +on: + workflow_dispatch: {} + schedule: + - cron: '0 0 * * *' + +jobs: + govulncheck: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@v5 + with: + go-version: ${{ steps.go-version.outputs.result }} + + - run: make verify-govulncheck diff --git a/.golangci.ci.yaml b/.golangci.ci.yaml deleted file mode 100644 index 9342f2b0c..000000000 --- a/.golangci.ci.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# This golangci-lint configuration is for use in CI. -# It has a non-standard filename so that maintainers can still easily run the -# full `golangci-lint` suite locally on their laptops. -# This configuration limits golangci-lint to check only for those issues that -# have already been fixed. to allow us to incrementally fix the remaining -# issues. -# Please contribute small PRs where a new linter is added or a particular -# exclude is removed in the first commit, wait for golangci-lint-action to -# report the issues and then fix those issues in a subsequent commit. -linters: - disable-all: true - enable: - - gosec - - staticcheck -issues: - # When we enable a new linter or a new issue check, we want to show **all** - # instances of each issue in the GitHub UI or in the CLI report. This allows - # the all the issues to be addressed in a single commit or addressed in a - # series of followup commits grouped per-package or per-module. - # By default golangci-lint only shows 50 issues per linter and only shows the - # first three instances of any particular issue. Why? We do not know, but - # perhaps it's to avoid overwhelming the user when there are a large number of - # issues. - # The value 0 below means show all. - max-issues-per-linter: 0 - max-same-issues: 0 - # Ignore some of the gosec warnings until we have time to address them. - exclude-rules: - - linters: - - gosec - text: "G(101|107|204|306|402)" - - linters: - - staticcheck - text: "SA(1002|1006|4000|4006)" - - linters: - - staticcheck - text: "(NewCertManagerBasicCertificateRequest|DeprecatedCertificateTemplateFromCertificateRequestAndAllowInsecureCSRUsageDefinition)" diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 000000000..7c830b1f0 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,119 @@ +issues: + exclude-rules: + - linters: + - dogsled + - errcheck + - misspell + - contextcheck + - unparam + - promlinter + - errname + - tenv + - exhaustive + - gocritic + - gci + - nilerr + - tagalign + - dupword + - bodyclose + - loggercheck + - forbidigo + - interfacebloat + - predeclared + - unused + - unconvert + - usestdlibvars + - noctx + - nilnil + - gosimple + - nakedret + - asasalint + - ginkgolinter + - goprintffuncname + - ineffassign + - musttag + - wastedassign + - nosprintfhostport + - exportloopref + - gomoddirectives + text: ".*" + - linters: + - gosec + text: "G(101|107|204|306|402)" + - linters: + - staticcheck + text: "SA(1002|1006|4000|4006)" + - linters: + - staticcheck + text: "(NewCertManagerBasicCertificateRequest|DeprecatedCertificateTemplateFromCertificateRequestAndAllowInsecureCSRUsageDefinition)" +linters: + # Explicitly define all enabled linters + disable-all: true + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - contextcheck + - decorder + - dogsled + - dupword + - durationcheck + - errcheck + - errchkjson + - errname + - execinquery + - exhaustive + - exportloopref + - forbidigo + - gci + - ginkgolinter + - gocheckcompilerdirectives + - gochecksumtype + - gocritic + - gofmt + - goheader + - gomoddirectives + - gomodguard + - goprintffuncname + - gosec + - gosimple + - gosmopolitan + - govet + - grouper + - importas + - ineffassign + - interfacebloat + - loggercheck + - makezero + - mirror + - misspell + - musttag + - nakedret + - nilerr + - nilnil + - noctx + - nosprintfhostport + - predeclared + - promlinter + - protogetter + - reassign + - sloglint + - staticcheck + - tagalign + - tenv + - testableexamples + - typecheck + - unconvert + - unparam + - unused + - usestdlibvars + - wastedassign +linters-settings: + gci: + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix(github.com/cert-manager/cert-manager) # Custom section: groups all imports with the specified Prefix. + - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. + - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. diff --git a/hack/verify-goimports.sh b/hack/verify-goimports.sh deleted file mode 100755 index ffc150814..000000000 --- a/hack/verify-goimports.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2022 The cert-manager Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -o errexit -set -o nounset -set -o pipefail - -if [[ -z "${1:-}" ]]; then - echo "usage: $0 [go dirs ...]" >&2 - exit 1 -fi - -goimports=$(realpath "$1") - -shift 1 - -godirs=("$@") -if [ ${#godirs[@]} -eq 0 ]; then - echo "No go dirs specified" >&2 - exit 1 -fi - -# passing "-local" would be ideal, but it'll conflict with auto generated files ATM -# and cause churn when we want to update those files -#common_flags="-local github.com/cert-manager/cert-manager" - -common_flags="" - -echo "+++ running goimports on [${godirs[@]}]" >&2 - -output=$($goimports $common_flags -l $godirs) - -if [ ! -z "${output}" ]; then - echo "${output}" | sed "s/^/goimports: broken file: /" - echo "+++ goimports failed; the following command may fix:" >&2 - echo "+++ $goimports $common_flags -w $godirs" >&2 - exit 1 -fi diff --git a/klone.yaml b/klone.yaml index a63fbbf20..badaa9de9 100644 --- a/klone.yaml +++ b/klone.yaml @@ -17,6 +17,11 @@ targets: repo_ref: main repo_hash: 04f424fa90aa8ca570278cf0c07b18dea607b542 repo_path: modules/generate-verify + - folder_name: go + repo_url: https://github.com/cert-manager/makefile-modules.git + repo_ref: main + repo_hash: fa9c9274d1d852de501461b9442f7206aaf74007 + repo_path: modules/go - folder_name: help repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main diff --git a/make/00_mod.mk b/make/00_mod.mk index 529610bf8..b5f380ef7 100644 --- a/make/00_mod.mk +++ b/make/00_mod.mk @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +repo_name := github.com/cert-manager/cert-manager + include make/util.mk # SOURCES contains all go files except those in $(bin_dir), the old bindir `bin`, or in @@ -52,3 +54,5 @@ GOFLAGS := -trimpath GOLDFLAGS := -w -s \ -X github.com/cert-manager/cert-manager/pkg/util.AppVersion=$(VERSION) \ -X github.com/cert-manager/cert-manager/pkg/util.AppGitCommit=$(GITCOMMIT) + +golangci_lint_config := .golangci.yaml diff --git a/make/_shared/go/.golangci.override.yaml b/make/_shared/go/.golangci.override.yaml new file mode 100644 index 000000000..e569eff72 --- /dev/null +++ b/make/_shared/go/.golangci.override.yaml @@ -0,0 +1,71 @@ +linters: + # Explicitly define all enabled linters + disable-all: true + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - contextcheck + - decorder + - dogsled + - dupword + - durationcheck + - errcheck + - errchkjson + - errname + - execinquery + - exhaustive + - exportloopref + - forbidigo + - gci + - ginkgolinter + - gocheckcompilerdirectives + - gochecksumtype + - gocritic + - gofmt + - goheader + - gomoddirectives + - gomodguard + - goprintffuncname + - gosec + - gosimple + - gosmopolitan + - govet + - grouper + - importas + - ineffassign + - interfacebloat + - loggercheck + - makezero + - mirror + - misspell + - musttag + - nakedret + - nilerr + - nilnil + - noctx + - nosprintfhostport + - predeclared + - promlinter + - protogetter + - reassign + - sloglint + - staticcheck + - tagalign + - tenv + - testableexamples + - typecheck + - unconvert + - unparam + - unused + - usestdlibvars + - wastedassign +linters-settings: + gci: + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix({{REPO-NAME}}) # Custom section: groups all imports with the specified Prefix. + - blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled. + - dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled. diff --git a/make/_shared/go/01_mod.mk b/make/_shared/go/01_mod.mk new file mode 100644 index 000000000..e12d51e82 --- /dev/null +++ b/make/_shared/go/01_mod.mk @@ -0,0 +1,107 @@ +# Copyright 2023 The cert-manager Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ifndef bin_dir +$(error bin_dir is not set) +endif + +ifndef repo_name +$(error repo_name is not set) +endif + +go_base_dir := $(dir $(lastword $(MAKEFILE_LIST)))/base/ +golangci_lint_override := $(dir $(lastword $(MAKEFILE_LIST)))/.golangci.override.yaml + +.PHONY: generate-govulncheck +## Generate base files in the repository +## @category [shared] Generate/ Verify +generate-govulncheck: + cp -r $(go_base_dir)/. ./ + +shared_generate_targets += generate-govulncheck + +.PHONY: verify-govulncheck +## Verify all Go modules for vulnerabilities using govulncheck +## @category [shared] Generate/ Verify +# +# Runs `govulncheck` on all Go modules related to the project. +# Ignores Go modules among the temporary build artifacts in _bin, to avoid +# scanning the code of the vendored Go, after running make vendor-go. +# Ignores Go modules in make/_shared, because those will be checked in centrally +# in the makefile_modules repository. +# +# `verify-govulncheck` not added to the `shared_verify_targets` variable and is +# not run by `make verify`, because `make verify` is run for each PR, and we do +# not want new vulnerabilities in existing code to block the merging of PRs. +# Instead `make verify-govulnecheck` is intended to be run periodically by a CI job. +verify-govulncheck: | $(NEEDS_GOVULNCHECK) + @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) -printf '%h\n' \ + | while read d; do \ + echo "Running 'GOTOOLCHAIN=go$(VENDORED_GO_VERSION) $(bin_dir)/tools/govulncheck ./...' in directory '$${d}'"; \ + pushd "$${d}" >/dev/null; \ + GOTOOLCHAIN=go$(VENDORED_GO_VERSION) $(GOVULNCHECK) ./... || exit; \ + popd >/dev/null; \ + echo ""; \ + done + +ifdef golangci_lint_config + +.PHONY: generate-golangci-lint-config +## Generate a golangci-lint configuration file +## @category [shared] Generate/ Verify +generate-golangci-lint-config: | $(NEEDS_YQ) $(bin_dir)/scratch + cp $(golangci_lint_config) $(bin_dir)/scratch/golangci-lint.yaml.tmp + $(YQ) -i 'del(.linters.enable)' $(bin_dir)/scratch/golangci-lint.yaml.tmp + $(YQ) eval-all -i '. as $$item ireduce ({}; . * $$item)' $(bin_dir)/scratch/golangci-lint.yaml.tmp $(golangci_lint_override) + $(YQ) -i '(.. | select(tag == "!!str")) |= sub("{{REPO-NAME}}", "$(repo_name)")' $(bin_dir)/scratch/golangci-lint.yaml.tmp + mv $(bin_dir)/scratch/golangci-lint.yaml.tmp $(golangci_lint_config) + +shared_generate_targets += generate-golangci-lint-config + +.PHONY: verify-golangci-lint +## Verify all Go modules using golangci-lint +## @category [shared] Generate/ Verify +verify-golangci-lint: | $(NEEDS_GOLANGCI-LINT) $(NEEDS_YQ) $(bin_dir)/scratch + @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) -printf '%h\n' \ + | while read d; do \ + echo "Running '$(bin_dir)/tools/golangci-lint run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config)' in directory '$${d}'"; \ + pushd "$${d}" >/dev/null; \ + $(GOLANGCI-LINT) run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config) --timeout 4m || exit; \ + popd >/dev/null; \ + echo ""; \ + done + +shared_verify_targets_dirty += verify-golangci-lint + +.PHONY: fix-golangci-lint +## Fix all Go modules using golangci-lint +## @category [shared] Generate/ Verify +fix-golangci-lint: | $(NEEDS_GOLANGCI-LINT) $(NEEDS_YQ) $(bin_dir)/scratch + gci write \ + -s "standard" \ + -s "default" \ + -s "prefix($(repo_name))" \ + -s "blank" \ + -s "dot" . + + @find . -name go.mod -not \( -path "./$(bin_dir)/*" -or -path "./make/_shared/*" \) -printf '%h\n' \ + | while read d; do \ + echo "Running '$(bin_dir)/tools/golangci-lint run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config) --fix' in directory '$${d}'"; \ + pushd "$${d}" >/dev/null; \ + $(GOLANGCI-LINT) run --go $(VENDORED_GO_VERSION) -c $(CURDIR)/$(golangci_lint_config) --fix || exit; \ + popd >/dev/null; \ + echo ""; \ + done + +endif diff --git a/make/_shared/go/README.md b/make/_shared/go/README.md new file mode 100644 index 000000000..ad1962ba1 --- /dev/null +++ b/make/_shared/go/README.md @@ -0,0 +1,3 @@ +# README + +A module for various Go static checks. diff --git a/make/_shared/go/base/.github/workflows/govulncheck.yaml b/make/_shared/go/base/.github/workflows/govulncheck.yaml new file mode 100644 index 000000000..405e8dec9 --- /dev/null +++ b/make/_shared/go/base/.github/workflows/govulncheck.yaml @@ -0,0 +1,28 @@ +# THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. +# Edit https://github.com/cert-manager/makefile-modules/blob/main/modules/go/base/.github/workflows/govulncheck.yaml instead. + +# Run govulncheck at midnight every night on the main branch, +# to alert us to recent vulnerabilities which affect the Go code in this +# project. +name: govulncheck +on: + workflow_dispatch: {} + schedule: + - cron: '0 0 * * *' + +jobs: + govulncheck: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - id: go-version + run: | + make print-go-version >> "$GITHUB_OUTPUT" + + - uses: actions/setup-go@v5 + with: + go-version: ${{ steps.go-version.outputs.result }} + + - run: make verify-govulncheck diff --git a/make/ci.mk b/make/ci.mk index e24e5b7d4..d329f6d15 100644 --- a/make/ci.mk +++ b/make/ci.mk @@ -12,24 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -.PHONY: verify-golangci-lint -verify-golangci-lint: | $(NEEDS_GOLANGCI-LINT) - find . -name go.mod -not \( -path "./$(bin_dir)/*" -prune \) -execdir $(GOLANGCI-LINT) run --timeout=30m --config=$(CURDIR)/.golangci.ci.yaml \; - -shared_verify_targets += verify-golangci-lint - .PHONY: verify-modules verify-modules: | $(NEEDS_CMREL) $(CMREL) validate-gomod --path $(shell pwd) --no-dummy-modules github.com/cert-manager/cert-manager/integration-tests shared_verify_targets += verify-modules -.PHONY: verify-imports -verify-imports: | $(NEEDS_GOIMPORTS) - ./hack/verify-goimports.sh $(GOIMPORTS) $(SOURCE_DIRS) - -shared_verify_targets += verify-imports - .PHONY: verify-chart verify-chart: $(bin_dir)/cert-manager-$(VERSION).tgz DOCKER=$(CTR) ./hack/verify-chart-version.sh $< diff --git a/test/e2e/suite/certificates/duplicatesecretname.go b/test/e2e/suite/certificates/duplicatesecretname.go index b97b1cb27..fee2e5318 100644 --- a/test/e2e/suite/certificates/duplicatesecretname.go +++ b/test/e2e/suite/certificates/duplicatesecretname.go @@ -129,8 +129,7 @@ var _ = framework.CertManagerDescribe("Certificate Duplicate Secret Name", func( Expect(err).NotTo(HaveOccurred()) var ownedReqs int for _, req := range reqs.Items { - // #nosec G601 -- False positive. See https://github.com/golang/go/discussions/56010 - if predicate.ResourceOwnedBy(crt)(&req) { + if predicate.ResourceOwnedBy(crt)(&req) /* #nosec G601 -- False positive. See https://github.com/golang/go/discussions/56010 */ { ownedReqs++ } }