From 2c0a95088669101478ed95957bd6c519e62768fb Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Mon, 2 Mar 2026 00:04:42 +0200 Subject: [PATCH 01/20] Change to use custom golangci-lint To enable adding `tfproviderlint` as a plugin Signed-off-by: Timo Sand --- .custom-gcl.yml | 5 ++ .golangci.yml | 26 +++++++++++ GNUmakefile | 23 +++++---- tools/tfproviderlint/go.mod | 11 +++++ tools/tfproviderlint/go.sum | 23 +++++++++ tools/tfproviderlint/tfproviderlint.go | 65 ++++++++++++++++++++++++++ 6 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 .custom-gcl.yml create mode 100644 tools/tfproviderlint/go.mod create mode 100644 tools/tfproviderlint/go.sum create mode 100644 tools/tfproviderlint/tfproviderlint.go diff --git a/.custom-gcl.yml b/.custom-gcl.yml new file mode 100644 index 0000000000..55256e0e8b --- /dev/null +++ b/.custom-gcl.yml @@ -0,0 +1,5 @@ +version: v2.10.1 # should be in sync with GNUmakefile + +plugins: + - module: "github.com/integrations/terraform-provider-github/tools/tfproviderlint" + path: ./tools/tfproviderlint diff --git a/.golangci.yml b/.golangci.yml index 900dce093b..a30952f2f2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -27,6 +27,32 @@ linters: - unparam - unused - usetesting + - tfproviderlint + + settings: + custom: + tfproviderlint: + type: module + description: Reports Terraform provider linting issues. + original-url: github.com/bflad/tfproviderlint/cmd/tfproviderlintx + settings: + # https://github.com/bflad/tfproviderlint/tree/main?tab=readme-ov-file#standard-acceptance-test-checks + enabled-checks: + - AT005 # https://github.com/bflad/tfproviderlint/tree/main/passes/AT005 + - AT008 # https://github.com/bflad/tfproviderlint/tree/main/passes/AT008 + # - AT009 # https://github.com/bflad/tfproviderlint/tree/main/passes/AT009 + # - R002 # https://github.com/bflad/tfproviderlint/tree/main/passes/R002 + # - R004 # https://github.com/bflad/tfproviderlint/tree/main/passes/R004 + - R005 # https://github.com/bflad/tfproviderlint/tree/main/passes/R005 + - R006 # https://github.com/bflad/tfproviderlint/tree/main/passes/R006 + # - R009 # https://github.com/bflad/tfproviderlint/tree/main/passes/R009 + # - R010 # https://github.com/bflad/tfproviderlint/tree/main/passes/R010 + - R011 # https://github.com/bflad/tfproviderlint/tree/main/passes/R011 + - R012 # https://github.com/bflad/tfproviderlint/tree/main/passes/R012 + - R013 # https://github.com/bflad/tfproviderlint/tree/main/passes/R013 + - R015 # https://github.com/bflad/tfproviderlint/tree/main/passes/R015 + - R016 # https://github.com/bflad/tfproviderlint/tree/main/passes/R016 + - R017 # https://github.com/bflad/tfproviderlint/tree/main/passes/R017 exclusions: generated: lax diff --git a/GNUmakefile b/GNUmakefile index 0409d0b9ed..57a8f94454 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -4,6 +4,7 @@ TEST?=./$(PKG_NAME)/... WEBSITE_REPO=github.com/hashicorp/terraform-website COVERAGEARGS?=-race -coverprofile=coverage.txt -covermode=atomic +BIN="$$(pwd -P)"/bin # VARIABLE REFERENCE: # @@ -27,23 +28,29 @@ endif default: build -tools: - go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.10.1 +bin/golangci-lint: + mkdir -p $(BIN) + GOBIN=$(BIN) go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.10.1 + +bin/custom-gcl: bin/golangci-lint tools/tfproviderlint/tfproviderlint.go + $(BIN)/golangci-lint custom --name custom-gcl --destination $(BIN) + +tools: bin/custom-gcl build: lintcheck CGO_ENABLED=0 go build -ldflags="-s -w" ./... -fmt: +fmt: tools @echo "==> Fixing source code formatting..." - golangci-lint fmt ./... + $(BIN)/custom-gcl fmt ./... -lint: +lint: tools @echo "==> Checking source code against linters and fixing..." - golangci-lint run --fix ./... + $(BIN)/custom-gcl run --fix ./... -lintcheck: +lintcheck: tools @echo "==> Checking source code against linters..." - golangci-lint run ./... + $(BIN)/custom-gcl run ./... test: @branch=$$(git rev-parse --abbrev-ref HEAD); \ diff --git a/tools/tfproviderlint/go.mod b/tools/tfproviderlint/go.mod new file mode 100644 index 0000000000..3eb1b0728d --- /dev/null +++ b/tools/tfproviderlint/go.mod @@ -0,0 +1,11 @@ +module tools/tfproviderlint + +go 1.24.4 + +require ( + github.com/bflad/tfproviderlint v0.31.0 + github.com/golangci/plugin-module-register v0.1.2 + golang.org/x/tools v0.42.0 +) + +require github.com/bflad/gopaniccheck v0.1.0 // indirect diff --git a/tools/tfproviderlint/go.sum b/tools/tfproviderlint/go.sum new file mode 100644 index 0000000000..88275e483b --- /dev/null +++ b/tools/tfproviderlint/go.sum @@ -0,0 +1,23 @@ +github.com/bflad/gopaniccheck v0.1.0 h1:tJftp+bv42ouERmUMWLoUn/5bi/iQZjHPznM00cP/bU= +github.com/bflad/gopaniccheck v0.1.0/go.mod h1:ZCj2vSr7EqVeDaqVsWN4n2MwdROx1YL+LFo47TSWtsA= +github.com/bflad/tfproviderlint v0.31.0 h1:9N/dUzFARsTpAQOjdZzIWnHKMzQc7UDDEYrSNV2xnrw= +github.com/bflad/tfproviderlint v0.31.0/go.mod h1:yZQdJs4uobBIgVHt1Tv5OpHhgM8fwh29OgxL/La5BFs= +github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= +github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20200214201135-548b770e2dfa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/tools/tfproviderlint/tfproviderlint.go b/tools/tfproviderlint/tfproviderlint.go new file mode 100644 index 0000000000..a1fda6d3f8 --- /dev/null +++ b/tools/tfproviderlint/tfproviderlint.go @@ -0,0 +1,65 @@ +// Package tfproviderlint is a custom linter to be used by +// golangci-lint to find instances of `%d` or `%s` in +// format strings when `%v` would be more consistent. +package tfproviderlint + +import ( + "github.com/bflad/tfproviderlint/passes" + "github.com/bflad/tfproviderlint/xpasses" + "github.com/golangci/plugin-module-register/register" + "golang.org/x/tools/go/analysis" +) + +func init() { + register.Plugin("tfproviderlint", New) +} + +// TfProviderLintPlugin is a custom linter plugin for golangci-lint. +type TfProviderLintPlugin struct { + enabledChecks map[string]bool +} + +type Settings struct { + EnabledChecks []string `json:"enabled-checks" yaml:"enabled-checks"` +} + +// New returns an analysis.Analyzer to use with golangci-lint. +func New(settings any) (register.LinterPlugin, error) { + enabledChecks := map[string]bool{} + + if settings != nil { + if settingsMap, ok := settings.(map[string]any); ok { + if enabledChecksRaw, ok := settingsMap["enabled-checks"]; ok { + if enabledChecksList, ok := enabledChecksRaw.([]any); ok { + for _, check := range enabledChecksList { + if check, ok := check.(string); ok { + enabledChecks[check] = true + } + } + } + } + } + } + return &TfProviderLintPlugin{enabledChecks: enabledChecks}, nil +} + +// BuildAnalyzers builds the analyzers for the TfProviderLintPlugin. +func (t *TfProviderLintPlugin) BuildAnalyzers() ([]*analysis.Analyzer, error) { + var analyzers []*analysis.Analyzer + for _, check := range passes.AllChecks { + if t.enabledChecks[check.Name] { + analyzers = append(analyzers, check) + } + } + for _, check := range xpasses.AllChecks { + if t.enabledChecks[check.Name] { + analyzers = append(analyzers, check) + } + } + + return analyzers, nil +} + +func (t *TfProviderLintPlugin) GetLoadMode() string { + return register.LoadModeSyntax +} From 460f4e3d6c61729a8dcd6d5fce3ffa0aa1dcd307 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Mon, 2 Mar 2026 21:44:47 +0200 Subject: [PATCH 02/20] Enable all no-op reasonable Schema rules of tfproviderlint Signed-off-by: Timo Sand --- .golangci.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index a30952f2f2..5c34eee73d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -53,6 +53,43 @@ linters: - R015 # https://github.com/bflad/tfproviderlint/tree/main/passes/R015 - R016 # https://github.com/bflad/tfproviderlint/tree/main/passes/R016 - R017 # https://github.com/bflad/tfproviderlint/tree/main/passes/R017 + # - R018 # https://github.com/bflad/tfproviderlint/tree/main/passes/R018 + - S001 # https://github.com/bflad/tfproviderlint/tree/main/passes/S001 + - S002 # https://github.com/bflad/tfproviderlint/tree/main/passes/S002 + - S003 # https://github.com/bflad/tfproviderlint/tree/main/passes/S003 + - S004 # https://github.com/bflad/tfproviderlint/tree/main/passes/S004 + - S005 # https://github.com/bflad/tfproviderlint/tree/main/passes/S005 + # - S006 # https://github.com/bflad/tfproviderlint/tree/main/passes/S006 + - S007 # https://github.com/bflad/tfproviderlint/tree/main/passes/S007 + - S008 # https://github.com/bflad/tfproviderlint/tree/main/passes/S008 + - S009 # https://github.com/bflad/tfproviderlint/tree/main/passes/S009 + - S010 # https://github.com/bflad/tfproviderlint/tree/main/passes/S010 + - S011 # https://github.com/bflad/tfproviderlint/tree/main/passes/S011 + - S012 # https://github.com/bflad/tfproviderlint/tree/main/passes/S012 + # - S013 # https://github.com/bflad/tfproviderlint/tree/main/passes/S013 + - S014 # https://github.com/bflad/tfproviderlint/tree/main/passes/S014 + - S015 # https://github.com/bflad/tfproviderlint/tree/main/passes/S015 + - S016 # https://github.com/bflad/tfproviderlint/tree/main/passes/S016 + - S017 # https://github.com/bflad/tfproviderlint/tree/main/passes/S017 + - S018 # https://github.com/bflad/tfproviderlint/tree/main/passes/S018 + # - S019 # https://github.com/bflad/tfproviderlint/tree/main/passes/S019 + # - S020 # https://github.com/bflad/tfproviderlint/tree/main/passes/S020 + - S021 # https://github.com/bflad/tfproviderlint/tree/main/passes/S021 + - S022 # https://github.com/bflad/tfproviderlint/tree/main/passes/S022 + - S023 # https://github.com/bflad/tfproviderlint/tree/main/passes/S023 + - S024 # https://github.com/bflad/tfproviderlint/tree/main/passes/S024 + - S025 # https://github.com/bflad/tfproviderlint/tree/main/passes/S025 + - S026 # https://github.com/bflad/tfproviderlint/tree/main/passes/S026 + - S027 # https://github.com/bflad/tfproviderlint/tree/main/passes/S027 + - S028 # https://github.com/bflad/tfproviderlint/tree/main/passes/S028 + - S029 # https://github.com/bflad/tfproviderlint/tree/main/passes/S029 + - S030 # https://github.com/bflad/tfproviderlint/tree/main/passes/S030 + - S031 # https://github.com/bflad/tfproviderlint/tree/main/passes/S031 + - S032 # https://github.com/bflad/tfproviderlint/tree/main/passes/S032 + - S033 # https://github.com/bflad/tfproviderlint/tree/main/passes/S033 + - S035 # https://github.com/bflad/tfproviderlint/tree/main/passes/S035 + - S036 # https://github.com/bflad/tfproviderlint/tree/main/passes/S036 + - S037 # https://github.com/bflad/tfproviderlint/tree/main/passes/S037 exclusions: generated: lax From dc3bb9f52da8630389506056c8bda3bcf9ee15eb Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Mon, 2 Mar 2026 21:46:08 +0200 Subject: [PATCH 03/20] Update makefile to recomple `custom-gcl` when `tools/*.go` files change Signed-off-by: Timo Sand --- GNUmakefile | 10 +++++++--- tools/tfproviderlint/go.mod | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 57a8f94454..c1bc5398e1 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -32,10 +32,13 @@ bin/golangci-lint: mkdir -p $(BIN) GOBIN=$(BIN) go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.10.1 -bin/custom-gcl: bin/golangci-lint tools/tfproviderlint/tfproviderlint.go +bin/custom-gcl: bin/golangci-lint $(shell find tools -name '*.go' -or -name '*.mod' -or -name '*.sum') $(BIN)/golangci-lint custom --name custom-gcl --destination $(BIN) -tools: bin/custom-gcl +tools: bin/custom-gcl go.sum + +go.sum: go.mod $(shell find github -name '*.go') + go mod tidy build: lintcheck CGO_ENABLED=0 go build -ldflags="-s -w" ./... @@ -49,7 +52,8 @@ lint: tools $(BIN)/custom-gcl run --fix ./... lintcheck: tools - @echo "==> Checking source code against linters..." + @branch=$$(git rev-parse --abbrev-ref HEAD); \ + printf "==> Checking source code against linters on branch: \033[1m%s\033[0m...\n" "🌿 $$branch 🌿" $(BIN)/custom-gcl run ./... test: diff --git a/tools/tfproviderlint/go.mod b/tools/tfproviderlint/go.mod index 3eb1b0728d..80c41ca141 100644 --- a/tools/tfproviderlint/go.mod +++ b/tools/tfproviderlint/go.mod @@ -1,4 +1,4 @@ -module tools/tfproviderlint +module github.com/integrations/terraform-provider-github/tools/tfproviderlint go 1.24.4 From c66c004627fb6da62e929d01301bc70787196fc6 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Mon, 2 Mar 2026 22:04:02 +0200 Subject: [PATCH 04/20] Enable all the rest of reasonable `tfproviderlint` rules Signed-off-by: Timo Sand --- .golangci.yml | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 5c34eee73d..9d09efbb2a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -40,40 +40,40 @@ linters: enabled-checks: - AT005 # https://github.com/bflad/tfproviderlint/tree/main/passes/AT005 - AT008 # https://github.com/bflad/tfproviderlint/tree/main/passes/AT008 - # - AT009 # https://github.com/bflad/tfproviderlint/tree/main/passes/AT009 + # - AT009 # https://github.com/bflad/tfproviderlint/tree/main/passes/AT009 # TODO: Enable when we can fix the issues # - R002 # https://github.com/bflad/tfproviderlint/tree/main/passes/R002 # - R004 # https://github.com/bflad/tfproviderlint/tree/main/passes/R004 - R005 # https://github.com/bflad/tfproviderlint/tree/main/passes/R005 - R006 # https://github.com/bflad/tfproviderlint/tree/main/passes/R006 - # - R009 # https://github.com/bflad/tfproviderlint/tree/main/passes/R009 - # - R010 # https://github.com/bflad/tfproviderlint/tree/main/passes/R010 + # - R009 # https://github.com/bflad/tfproviderlint/tree/main/passes/R009 # TODO: Enable when we can fix the issues + # - R010 # https://github.com/bflad/tfproviderlint/tree/main/passes/R010 # TODO: Enable when we can fix the issues - R011 # https://github.com/bflad/tfproviderlint/tree/main/passes/R011 - R012 # https://github.com/bflad/tfproviderlint/tree/main/passes/R012 - R013 # https://github.com/bflad/tfproviderlint/tree/main/passes/R013 - R015 # https://github.com/bflad/tfproviderlint/tree/main/passes/R015 - R016 # https://github.com/bflad/tfproviderlint/tree/main/passes/R016 - R017 # https://github.com/bflad/tfproviderlint/tree/main/passes/R017 - # - R018 # https://github.com/bflad/tfproviderlint/tree/main/passes/R018 + # - R018 # https://github.com/bflad/tfproviderlint/tree/main/passes/R018 # TODO: Enable when we can fix the issues - S001 # https://github.com/bflad/tfproviderlint/tree/main/passes/S001 - S002 # https://github.com/bflad/tfproviderlint/tree/main/passes/S002 - S003 # https://github.com/bflad/tfproviderlint/tree/main/passes/S003 - S004 # https://github.com/bflad/tfproviderlint/tree/main/passes/S004 - S005 # https://github.com/bflad/tfproviderlint/tree/main/passes/S005 - # - S006 # https://github.com/bflad/tfproviderlint/tree/main/passes/S006 + # - S006 # https://github.com/bflad/tfproviderlint/tree/main/passes/S006 # TODO: Enable when we can fix the issues - S007 # https://github.com/bflad/tfproviderlint/tree/main/passes/S007 - S008 # https://github.com/bflad/tfproviderlint/tree/main/passes/S008 - S009 # https://github.com/bflad/tfproviderlint/tree/main/passes/S009 - S010 # https://github.com/bflad/tfproviderlint/tree/main/passes/S010 - S011 # https://github.com/bflad/tfproviderlint/tree/main/passes/S011 - S012 # https://github.com/bflad/tfproviderlint/tree/main/passes/S012 - # - S013 # https://github.com/bflad/tfproviderlint/tree/main/passes/S013 + # - S013 # https://github.com/bflad/tfproviderlint/tree/main/passes/S013 # TODO: Enable when we can fix the issues - S014 # https://github.com/bflad/tfproviderlint/tree/main/passes/S014 - S015 # https://github.com/bflad/tfproviderlint/tree/main/passes/S015 - S016 # https://github.com/bflad/tfproviderlint/tree/main/passes/S016 - S017 # https://github.com/bflad/tfproviderlint/tree/main/passes/S017 - S018 # https://github.com/bflad/tfproviderlint/tree/main/passes/S018 - # - S019 # https://github.com/bflad/tfproviderlint/tree/main/passes/S019 - # - S020 # https://github.com/bflad/tfproviderlint/tree/main/passes/S020 + # - S019 # https://github.com/bflad/tfproviderlint/tree/main/passes/S019 # TODO: Enable when we can fix the issues + # - S020 # https://github.com/bflad/tfproviderlint/tree/main/passes/S020 # TODO: Enable when we can fix the issues - S021 # https://github.com/bflad/tfproviderlint/tree/main/passes/S021 - S022 # https://github.com/bflad/tfproviderlint/tree/main/passes/S022 - S023 # https://github.com/bflad/tfproviderlint/tree/main/passes/S023 @@ -90,6 +90,14 @@ linters: - S035 # https://github.com/bflad/tfproviderlint/tree/main/passes/S035 - S036 # https://github.com/bflad/tfproviderlint/tree/main/passes/S036 - S037 # https://github.com/bflad/tfproviderlint/tree/main/passes/S037 + # - XR002 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR002 # TODO: Enable when we can fix the issues + # - XR003 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR003 # TODO: Enable when we can fix the issues + - XR004 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR004 + # - XR005 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR005 # TODO: Enable when we can fix the issues + - XR006 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR006 + # - XR007 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR007 # TODO: Enable when we can fix the issues + - XR008 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR008 + # - XS001 # https://github.com/bflad/tfproviderlint/tree/main/passes/XS001 # TODO: Enable when we can fix the issues exclusions: generated: lax From 48b410e69639cb64e65c38dffcc876f18ed81cd0 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 3 Mar 2026 00:09:58 +0200 Subject: [PATCH 05/20] Add functionality to create own tfproviderlint checks Signed-off-by: Timo Sand --- .gitignore | 1 + .golangci.yml | 1 + GNUmakefile | 8 +- tools/tfproviderlint/GNUmakefile | 13 ++ tools/tfproviderlint/checks/L001/L001.go | 52 +++++++ tools/tfproviderlint/checks/L001/L001_test.go | 14 ++ .../checks/L001/testdata/go.mod | 39 +++++ .../checks/L001/testdata/go.sum | 143 ++++++++++++++++++ .../L001/testdata/src/a/comment_ignore.go | 25 +++ .../checks/L001/testdata/src/a/main.go | 33 ++++ tools/tfproviderlint/checks/checks.go | 11 ++ tools/tfproviderlint/go.mod | 6 +- tools/tfproviderlint/go.sum | 2 + tools/tfproviderlint/tfproviderlint.go | 10 +- 14 files changed, 353 insertions(+), 5 deletions(-) create mode 100644 tools/tfproviderlint/GNUmakefile create mode 100644 tools/tfproviderlint/checks/L001/L001.go create mode 100644 tools/tfproviderlint/checks/L001/L001_test.go create mode 100644 tools/tfproviderlint/checks/L001/testdata/go.mod create mode 100644 tools/tfproviderlint/checks/L001/testdata/go.sum create mode 100644 tools/tfproviderlint/checks/L001/testdata/src/a/comment_ignore.go create mode 100644 tools/tfproviderlint/checks/L001/testdata/src/a/main.go create mode 100644 tools/tfproviderlint/checks/checks.go diff --git a/.gitignore b/.gitignore index f5d638ac85..bba9859027 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ website/node_modules *.tfvars .vscode/ testdata/ +!tools/tfproviderlint/**/testdata/ website/vendor terraform-provider-github diff --git a/.golangci.yml b/.golangci.yml index 9d09efbb2a..3c80d19eb9 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -98,6 +98,7 @@ linters: # - XR007 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR007 # TODO: Enable when we can fix the issues - XR008 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR008 # - XS001 # https://github.com/bflad/tfproviderlint/tree/main/passes/XS001 # TODO: Enable when we can fix the issues + - L001 # file:///./tools/tfproviderlint/checks/L001/README.md exclusions: generated: lax diff --git a/GNUmakefile b/GNUmakefile index c1bc5398e1..fa84555972 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -32,7 +32,7 @@ bin/golangci-lint: mkdir -p $(BIN) GOBIN=$(BIN) go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.10.1 -bin/custom-gcl: bin/golangci-lint $(shell find tools -name '*.go' -or -name '*.mod' -or -name '*.sum') +bin/custom-gcl: bin/golangci-lint $(shell find tools \( -name '*.go' -or -name '*.mod' -or -name '*.sum' \) -and -not -name '*_test.go' -maxdepth 4) $(BIN)/golangci-lint custom --name custom-gcl --destination $(BIN) tools: bin/custom-gcl go.sum @@ -67,6 +67,10 @@ test: $(RUNARGS) $(TESTARGS) \ -count 1; +test-tools: + @echo "==> Running tools tests..." + $(MAKE) test -C tools/tfproviderlint + testacc: @branch=$$(git rev-parse --abbrev-ref HEAD); \ printf "==> Running acceptance tests on branch: \033[1m%s\033[0m...\n" "🌿 $$branch 🌿" @@ -90,4 +94,4 @@ ifeq (,$(wildcard $(GOPATH)/src/$(WEBSITE_REPO))) endif @$(MAKE) -C $(GOPATH)/src/$(WEBSITE_REPO) website-provider-test PROVIDER_PATH=$(shell pwd) PROVIDER_NAME=$(PKG_NAME) -.PHONY: build test testacc fmt lint lintcheck tools website website-test sweep +.PHONY: build test testacc fmt lint lintcheck tools test-tools website website-test sweep diff --git a/tools/tfproviderlint/GNUmakefile b/tools/tfproviderlint/GNUmakefile new file mode 100644 index 0000000000..281752b67c --- /dev/null +++ b/tools/tfproviderlint/GNUmakefile @@ -0,0 +1,13 @@ +test_go_sums = $(patsubst %/go.mod,%/go.sum,$(wildcard checks/*/testdata/go.mod)) + +.SECONDEXPANSION: +checks/%/testdata/go.sum: checks/%/testdata/go.mod $$(wildcard checks/$$*/*.go) + cd $(dir $@) && go mod tidy + +go.sum: go.mod $(shell find checks -name '*.go' -maxdepth 2) + go mod tidy + +test: go.sum $(test_go_sums) + CGO_ENABLED=0 go test ./... -v -count=1 -timeout=30s -parallel=4 + +.PHONY: test \ No newline at end of file diff --git a/tools/tfproviderlint/checks/L001/L001.go b/tools/tfproviderlint/checks/L001/L001.go new file mode 100644 index 0000000000..c54054f388 --- /dev/null +++ b/tools/tfproviderlint/checks/L001/L001.go @@ -0,0 +1,52 @@ +// Package L001 defines an Analyzer that checks for +// Schema with ValidateFunc configured +package L001 + +import ( + "log" + + "github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema" + "github.com/bflad/tfproviderlint/passes/commentignore" + "github.com/bflad/tfproviderlint/passes/helper/schema/schemainfo" + "golang.org/x/tools/go/analysis" +) + +const Doc = `check for Schema with ValidateFunc configured + +The L001 analyzer reports cases of schemas which configures ValidateFunc instead of ValidateDiagFunc +, which will fail provider schema validation. + +This is because ValidateFunc is deprecated.` + +const analyzerName = "L001" + +var Analyzer = &analysis.Analyzer{ + Name: analyzerName, + Doc: Doc, + Requires: []*analysis.Analyzer{ + commentignore.Analyzer, + schemainfo.Analyzer, + }, + Run: run, +} + +func run(pass *analysis.Pass) (any, error) { + log.Println("$$$ L001: running") + defer log.Println("$$$ L001: done") + ignorer := pass.ResultOf[commentignore.Analyzer].(*commentignore.Ignorer) + schemaInfos := pass.ResultOf[schemainfo.Analyzer].([]*schema.SchemaInfo) + for _, schemaInfo := range schemaInfos { + if ignorer.ShouldIgnore(analyzerName, schemaInfo.AstCompositeLit) { + continue + } + + if !schemaInfo.DeclaresField("ValidateFunc") { + continue + } + + log.Printf("$$$ L001: reporting: %d", schemaInfo.AstCompositeLit.Pos()) + pass.Reportf(schemaInfo.AstCompositeLit.Pos(), "%s: schema should not configure ValidateFunc, replace it with ValidateDiagFunc", analyzerName) + } + log.Println("$$$ L001: returning nil") + return nil, nil +} diff --git a/tools/tfproviderlint/checks/L001/L001_test.go b/tools/tfproviderlint/checks/L001/L001_test.go new file mode 100644 index 0000000000..32564ae24b --- /dev/null +++ b/tools/tfproviderlint/checks/L001/L001_test.go @@ -0,0 +1,14 @@ +package L001_test + +import ( + "testing" + + "github.com/integrations/terraform-provider-github/tools/tfproviderlint/checks/L001" + + "golang.org/x/tools/go/analysis/analysistest" +) + +func TestL001(t *testing.T) { + testdata := analysistest.TestData() + analysistest.Run(t, testdata, L001.Analyzer, "testdata/src/a") +} diff --git a/tools/tfproviderlint/checks/L001/testdata/go.mod b/tools/tfproviderlint/checks/L001/testdata/go.mod new file mode 100644 index 0000000000..8db7104371 --- /dev/null +++ b/tools/tfproviderlint/checks/L001/testdata/go.mod @@ -0,0 +1,39 @@ +module testdata + +go 1.24.4 + +require github.com/hashicorp/terraform-plugin-sdk/v2 v2.39.0 + +require ( + github.com/agext/levenshtein v1.2.2 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/hashicorp/go-cty v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect + github.com/hashicorp/hcl/v2 v2.24.0 // indirect + github.com/hashicorp/logutils v1.0.0 // indirect + github.com/hashicorp/terraform-plugin-go v0.30.0 // indirect + github.com/hashicorp/terraform-plugin-log v0.10.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/zclconf/go-cty v1.17.0 // indirect + golang.org/x/mod v0.33.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.34.0 // indirect + golang.org/x/tools v0.41.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.36.11 // indirect +) diff --git a/tools/tfproviderlint/checks/L001/testdata/go.sum b/tools/tfproviderlint/checks/L001/testdata/go.sum new file mode 100644 index 0000000000..c681e2cf1f --- /dev/null +++ b/tools/tfproviderlint/checks/L001/testdata/go.sum @@ -0,0 +1,143 @@ +github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= +github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/hashicorp/go-cty v1.5.0 h1:EkQ/v+dDNUqnuVpmS5fPqyY71NXVgT5gf32+57xY8g0= +github.com/hashicorp/go-cty v1.5.0/go.mod h1:lFUCG5kd8exDobgSfyj4ONE/dc822kiYMguVKdHGMLM= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE= +github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= +github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/terraform-plugin-go v0.30.0 h1:VmEiD0n/ewxbvV5VI/bYwNtlSEAXtHaZlSnyUUuQK6k= +github.com/hashicorp/terraform-plugin-go v0.30.0/go.mod h1:8d523ORAW8OHgA9e8JKg0ezL3XUO84H0A25o4NY/jRo= +github.com/hashicorp/terraform-plugin-log v0.10.0 h1:eu2kW6/QBVdN4P3Ju2WiB2W3ObjkAsyfBsL3Wh1fj3g= +github.com/hashicorp/terraform-plugin-log v0.10.0/go.mod h1:/9RR5Cv2aAbrqcTSdNmY1NRHP4E3ekrXRGjqORpXyB0= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.39.0 h1:ltFG/dSs4mMHNpBqHptCtJqYM4FekUDJbUcWj+6HGlg= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.39.0/go.mod h1:xJk7ap8vRI/B2U6TrVs7bu/gTihyor8XBTLSs5Y6z2w= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= +github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0= +github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/tfproviderlint/checks/L001/testdata/src/a/comment_ignore.go b/tools/tfproviderlint/checks/L001/testdata/src/a/comment_ignore.go new file mode 100644 index 0000000000..93d1e4c2ba --- /dev/null +++ b/tools/tfproviderlint/checks/L001/testdata/src/a/comment_ignore.go @@ -0,0 +1,25 @@ +package a + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func fcommentignore() { + // lintignore:L001 + _ = schema.Schema{ + Type: schema.TypeMap, + ValidateFunc: func(v any, k string) (ws []string, es []error) { + return nil, nil + }, + } + + // lintignore:L001 + _ = map[string]*schema.Schema{ + "name": { + Type: schema.TypeMap, + ValidateFunc: func(v any, k string) (ws []string, es []error) { + return nil, nil + }, + }, + } +} diff --git a/tools/tfproviderlint/checks/L001/testdata/src/a/main.go b/tools/tfproviderlint/checks/L001/testdata/src/a/main.go new file mode 100644 index 0000000000..9c747e1389 --- /dev/null +++ b/tools/tfproviderlint/checks/L001/testdata/src/a/main.go @@ -0,0 +1,33 @@ +package a + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func f() { + _ = schema.Schema{ // want "L001: schema should not configure ValidateFunc, replace it with ValidateDiagFunc" + Type: schema.TypeMap, + ValidateFunc: func(v any, k string) (ws []string, es []error) { + return nil, nil + }, + } + + _ = schema.Schema{ + Type: schema.TypeMap, + } + + _ = map[string]*schema.Schema{ + "name": { // want "L001: schema should not configure ValidateFunc, replace it with ValidateDiagFunc" + Type: schema.TypeMap, + ValidateFunc: func(v any, k string) (ws []string, es []error) { + return nil, nil + }, + }, + } + + _ = map[string]*schema.Schema{ + "name": { + Type: schema.TypeMap, + }, + } +} diff --git a/tools/tfproviderlint/checks/checks.go b/tools/tfproviderlint/checks/checks.go new file mode 100644 index 0000000000..7a1470a7dd --- /dev/null +++ b/tools/tfproviderlint/checks/checks.go @@ -0,0 +1,11 @@ +package checks + +import ( + "golang.org/x/tools/go/analysis" + + L001 "github.com/integrations/terraform-provider-github/tools/tfproviderlint/checks/L001" +) + +var AllChecks = []*analysis.Analyzer{ + L001.Analyzer, +} diff --git a/tools/tfproviderlint/go.mod b/tools/tfproviderlint/go.mod index 80c41ca141..35dc58d30e 100644 --- a/tools/tfproviderlint/go.mod +++ b/tools/tfproviderlint/go.mod @@ -8,4 +8,8 @@ require ( golang.org/x/tools v0.42.0 ) -require github.com/bflad/gopaniccheck v0.1.0 // indirect +require ( + github.com/bflad/gopaniccheck v0.1.0 // indirect + golang.org/x/mod v0.33.0 // indirect + golang.org/x/sync v0.19.0 // indirect +) diff --git a/tools/tfproviderlint/go.sum b/tools/tfproviderlint/go.sum index 88275e483b..cc28b45161 100644 --- a/tools/tfproviderlint/go.sum +++ b/tools/tfproviderlint/go.sum @@ -4,6 +4,8 @@ github.com/bflad/tfproviderlint v0.31.0 h1:9N/dUzFARsTpAQOjdZzIWnHKMzQc7UDDEYrSN github.com/bflad/tfproviderlint v0.31.0/go.mod h1:yZQdJs4uobBIgVHt1Tv5OpHhgM8fwh29OgxL/La5BFs= github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= diff --git a/tools/tfproviderlint/tfproviderlint.go b/tools/tfproviderlint/tfproviderlint.go index a1fda6d3f8..a9d5f2ec77 100644 --- a/tools/tfproviderlint/tfproviderlint.go +++ b/tools/tfproviderlint/tfproviderlint.go @@ -1,9 +1,10 @@ // Package tfproviderlint is a custom linter to be used by -// golangci-lint to find instances of `%d` or `%s` in -// format strings when `%v` would be more consistent. +// golangci-lint to integrate bflad/tfproviderlint. package tfproviderlint import ( + "github.com/integrations/terraform-provider-github/tools/tfproviderlint/checks" + "github.com/bflad/tfproviderlint/passes" "github.com/bflad/tfproviderlint/xpasses" "github.com/golangci/plugin-module-register/register" @@ -46,6 +47,11 @@ func New(settings any) (register.LinterPlugin, error) { // BuildAnalyzers builds the analyzers for the TfProviderLintPlugin. func (t *TfProviderLintPlugin) BuildAnalyzers() ([]*analysis.Analyzer, error) { var analyzers []*analysis.Analyzer + for _, check := range checks.AllChecks { + if t.enabledChecks[check.Name] { + analyzers = append(analyzers, check) + } + } for _, check := range passes.AllChecks { if t.enabledChecks[check.Name] { analyzers = append(analyzers, check) From d90066daf26fbb8b07f6896eb1e93901c3c9a7b9 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Wed, 4 Mar 2026 21:51:28 +0200 Subject: [PATCH 06/20] Add capability to run stricter linting against new changes Signed-off-by: Timo Sand --- .github/workflows/ci.yaml | 44 ++++++++++++++++++++++++++++++++++++--- .gitignore | 1 + .golangci.strict.yml | 30 ++++++++++++++++++++++++++ .golangci.yml | 1 - GNUmakefile | 15 ++++++++++++- 5 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 .golangci.strict.yml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0bdd194767..a1fbc54fac 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,8 +16,11 @@ concurrency: permissions: read-all +env: + GOLANGCI_LINT_VERSION: v2.10 + jobs: - ci: + test: name: Continuous Integration runs-on: ubuntu-latest permissions: @@ -33,6 +36,41 @@ jobs: with: go-version-file: go.mod cache: true - - run: make tools - - run: make build + - run: make build -o lintcheck - run: make test + golangci: + name: lint + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set-up Go + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version-file: go.mod + cache: true + - name: golangci-lint + uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 + with: + version: ${{ env.GOLANGCI_LINT_VERSION }} + golangci-new: + name: lint-new + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set-up Go + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version-file: go.mod + cache: true + - run: make .golangci.new.yml + - name: golangci-lint + uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 + with: + version: ${{ env.GOLANGCI_LINT_VERSION }} + args: --new-from-merge-base=main --config=.golangci.new.yml diff --git a/.gitignore b/.gitignore index bba9859027..6b79779330 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ testdata/ !tools/tfproviderlint/**/testdata/ website/vendor terraform-provider-github +.golangci.new.yml # Test exclusions !command/test-fixtures/**/*.tfstate diff --git a/.golangci.strict.yml b/.golangci.strict.yml new file mode 100644 index 0000000000..727b740e5f --- /dev/null +++ b/.golangci.strict.yml @@ -0,0 +1,30 @@ +# This file is for linting rules we want to start enforcing, but can't enable for the whole codebase yet. +# Always try adding new rules to .golangci.yml first. If they cause too many issues to fix, add them here. +# Once a rule in here has been fixed across the codebase, remove it from here and add it to .golangci.yml. +version: "2" + +linters: + enable: + - forcetypeassert + + settings: + custom: + tfproviderlint: + settings: + # https://github.com/bflad/tfproviderlint/tree/main?tab=readme-ov-file#standard-acceptance-test-checks + enabled-checks: + - AT009 # https://github.com/bflad/tfproviderlint/tree/main/passes/AT009 + - R002 # https://github.com/bflad/tfproviderlint/tree/main/passes/R002 + - R004 # https://github.com/bflad/tfproviderlint/tree/main/passes/R004 + - R009 # https://github.com/bflad/tfproviderlint/tree/main/passes/R009 + - R010 # https://github.com/bflad/tfproviderlint/tree/main/passes/R010 + - R018 # https://github.com/bflad/tfproviderlint/tree/main/passes/R018 + - S006 # https://github.com/bflad/tfproviderlint/tree/main/passes/S006 + - S013 # https://github.com/bflad/tfproviderlint/tree/main/passes/S013 + - S019 # https://github.com/bflad/tfproviderlint/tree/main/passes/S019 + - S020 # https://github.com/bflad/tfproviderlint/tree/main/passes/S020 + - XR002 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR002 + - XR003 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR003 + - XR005 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR005 + - XR007 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR007 + - XS001 # https://github.com/bflad/tfproviderlint/tree/main/passes/XS001 diff --git a/.golangci.yml b/.golangci.yml index 3c80d19eb9..8ae0ae3f16 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -12,7 +12,6 @@ linters: - errcheck - errname - errorlint - # - forcetypeassert TODO: Re-enable when we can fix the issues - godot - govet - ineffassign diff --git a/GNUmakefile b/GNUmakefile index fa84555972..0a98ef4dab 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -56,6 +56,19 @@ lintcheck: tools printf "==> Checking source code against linters on branch: \033[1m%s\033[0m...\n" "🌿 $$branch 🌿" $(BIN)/custom-gcl run ./... +.golangci.new.yml: .golangci.yml .golangci.strict.yml + yq eval-all 'select(fileIndex == 0) *+ select(fileIndex == 1)' .golangci{,.strict}.yml > .golangci.new.yml + +lintcheck-new: tools .golangci.new.yml + @branch=$$(git rev-parse --abbrev-ref HEAD); \ + printf "==> Checking source code against linters on branch: \033[1m%s\033[0m...\n" "🌿 $$branch 🌿" + $(BIN)/custom-gcl run ./... --new-from-merge-base main --config .golangci.new.yml + +lintcheck-strict: tools .golangci.new.yml + @branch=$$(git rev-parse --abbrev-ref HEAD); \ + printf "==> Checking source code against linters on branch: \033[1m%s\033[0m...\n" "🌿 $$branch 🌿" + $(BIN)/custom-gcl run ./... --config .golangci.new.yml + test: @branch=$$(git rev-parse --abbrev-ref HEAD); \ printf "==> Running unit tests on branch: \033[1m%s\033[0m...\n" "🌿 $$branch 🌿" @@ -94,4 +107,4 @@ ifeq (,$(wildcard $(GOPATH)/src/$(WEBSITE_REPO))) endif @$(MAKE) -C $(GOPATH)/src/$(WEBSITE_REPO) website-provider-test PROVIDER_PATH=$(shell pwd) PROVIDER_NAME=$(PKG_NAME) -.PHONY: build test testacc fmt lint lintcheck tools test-tools website website-test sweep +.PHONY: build test testacc fmt lint lintcheck lintcheck-new lintcheck-strict tools test-tools website website-test sweep From de0b817dfb921267c34d2bc8ca2d6fe673efed25 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Wed, 4 Mar 2026 22:37:33 +0200 Subject: [PATCH 07/20] Improve portability Signed-off-by: Timo Sand --- .github/workflows/ci.yaml | 7 ++++--- GNUmakefile | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a1fbc54fac..28b9683b4f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,15 +19,16 @@ permissions: read-all env: GOLANGCI_LINT_VERSION: v2.10 +defaults: + run: + shell: bash + jobs: test: name: Continuous Integration runs-on: ubuntu-latest permissions: contents: read - defaults: - run: - shell: bash steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/GNUmakefile b/GNUmakefile index 0a98ef4dab..81e6fee090 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -57,7 +57,7 @@ lintcheck: tools $(BIN)/custom-gcl run ./... .golangci.new.yml: .golangci.yml .golangci.strict.yml - yq eval-all 'select(fileIndex == 0) *+ select(fileIndex == 1)' .golangci{,.strict}.yml > .golangci.new.yml + yq eval-all 'select(fileIndex == 0) *+ select(fileIndex == 1)' .golangci.yml .golangci.strict.yml > .golangci.new.yml lintcheck-new: tools .golangci.new.yml @branch=$$(git rev-parse --abbrev-ref HEAD); \ From ba2c19be5776ee8debf6212438745a6574391372 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Wed, 4 Mar 2026 23:14:24 +0200 Subject: [PATCH 08/20] There is no easy way to fetch all PR commits until merge base... Signed-off-by: Timo Sand --- .github/workflows/ci.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 28b9683b4f..98d583a2f8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -74,4 +74,6 @@ jobs: uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 with: version: ${{ env.GOLANGCI_LINT_VERSION }} - args: --new-from-merge-base=main --config=.golangci.new.yml + github-token: ${{ secrets.GITHUB_TOKEN }} + only-new-issues: true + args: --config=.golangci.new.yml From 30c1216f8a3c9313c400aa9f378d4f3a189447c4 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Sun, 8 Mar 2026 18:18:49 +0200 Subject: [PATCH 09/20] Remove logging from L001 Signed-off-by: Timo Sand --- tools/tfproviderlint/checks/L001/L001.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tools/tfproviderlint/checks/L001/L001.go b/tools/tfproviderlint/checks/L001/L001.go index c54054f388..a95b33a94e 100644 --- a/tools/tfproviderlint/checks/L001/L001.go +++ b/tools/tfproviderlint/checks/L001/L001.go @@ -3,8 +3,6 @@ package L001 import ( - "log" - "github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema" "github.com/bflad/tfproviderlint/passes/commentignore" "github.com/bflad/tfproviderlint/passes/helper/schema/schemainfo" @@ -31,8 +29,6 @@ var Analyzer = &analysis.Analyzer{ } func run(pass *analysis.Pass) (any, error) { - log.Println("$$$ L001: running") - defer log.Println("$$$ L001: done") ignorer := pass.ResultOf[commentignore.Analyzer].(*commentignore.Ignorer) schemaInfos := pass.ResultOf[schemainfo.Analyzer].([]*schema.SchemaInfo) for _, schemaInfo := range schemaInfos { @@ -44,9 +40,7 @@ func run(pass *analysis.Pass) (any, error) { continue } - log.Printf("$$$ L001: reporting: %d", schemaInfo.AstCompositeLit.Pos()) pass.Reportf(schemaInfo.AstCompositeLit.Pos(), "%s: schema should not configure ValidateFunc, replace it with ValidateDiagFunc", analyzerName) } - log.Println("$$$ L001: returning nil") return nil, nil } From efac96f900d4dbf7cd253a6b2a366c9269efd6c7 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Sun, 8 Mar 2026 18:34:27 +0200 Subject: [PATCH 10/20] Add `L002` check to ensure all new resources use Context-aware functions Signed-off-by: Timo Sand --- .golangci.strict.yml | 1 + tools/tfproviderlint/checks/L002/L002.go | 69 +++++++++ tools/tfproviderlint/checks/L002/L002_test.go | 14 ++ .../checks/L002/testdata/go.mod | 39 +++++ .../checks/L002/testdata/go.sum | 143 ++++++++++++++++++ .../L002/testdata/src/a/comment_ignore.go | 42 +++++ .../checks/L002/testdata/src/a/main.go | 69 +++++++++ tools/tfproviderlint/checks/checks.go | 4 +- .../helper/schema/type_resourceimporter.go | 23 +++ 9 files changed, 403 insertions(+), 1 deletion(-) create mode 100644 tools/tfproviderlint/checks/L002/L002.go create mode 100644 tools/tfproviderlint/checks/L002/L002_test.go create mode 100644 tools/tfproviderlint/checks/L002/testdata/go.mod create mode 100644 tools/tfproviderlint/checks/L002/testdata/go.sum create mode 100644 tools/tfproviderlint/checks/L002/testdata/src/a/comment_ignore.go create mode 100644 tools/tfproviderlint/checks/L002/testdata/src/a/main.go create mode 100644 tools/tfproviderlint/helper/schema/type_resourceimporter.go diff --git a/.golangci.strict.yml b/.golangci.strict.yml index 727b740e5f..9511453912 100644 --- a/.golangci.strict.yml +++ b/.golangci.strict.yml @@ -28,3 +28,4 @@ linters: - XR005 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR005 - XR007 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR007 - XS001 # https://github.com/bflad/tfproviderlint/tree/main/passes/XS001 + - L002 # file:///./tools/tfproviderlint/checks/L002/README.md diff --git a/tools/tfproviderlint/checks/L002/L002.go b/tools/tfproviderlint/checks/L002/L002.go new file mode 100644 index 0000000000..e27da6d1d0 --- /dev/null +++ b/tools/tfproviderlint/checks/L002/L002.go @@ -0,0 +1,69 @@ +package L002 + +import ( + "go/ast" + "go/token" + + tfplsh "github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema" + "github.com/bflad/tfproviderlint/passes/commentignore" + "github.com/bflad/tfproviderlint/passes/helper/schema/resourceinfo" + "github.com/bflad/tfproviderlint/passes/helper/schema/schemainfo" + "golang.org/x/tools/go/analysis" + + "github.com/integrations/terraform-provider-github/tools/tfproviderlint/helper/schema" +) + +const Doc = `check for resources which configure Create, Update, Delete, or Importer.State instead of CreateContext, UpdateContext, DeleteContext, or Importer.StateContext + +The L002 analyzer reports cases of resources which configure Create, Update, Delete, or Importer.State instead of CreateContext, UpdateContext, DeleteContext, or Importer.StateContext` + +const analyzerName = "L002" + +var Analyzer = &analysis.Analyzer{ + Name: analyzerName, + Doc: Doc, + Requires: []*analysis.Analyzer{ + commentignore.Analyzer, + resourceinfo.Analyzer, + schemainfo.Analyzer, + }, + Run: run, +} + +func run(pass *analysis.Pass) (any, error) { + ignorer := pass.ResultOf[commentignore.Analyzer].(*commentignore.Ignorer) + resources := pass.ResultOf[resourceinfo.Analyzer].([]*tfplsh.ResourceInfo) + for _, resource := range resources { + + fields := []string{tfplsh.ResourceFieldCreate, tfplsh.ResourceFieldRead, tfplsh.ResourceFieldUpdate, tfplsh.ResourceFieldDelete} + + for _, field := range fields { + if resource.DeclaresField(field) { + if ignorer.ShouldIgnore(analyzerName, resource.Fields[field].Key) { + continue + } + pass.Reportf(resource.Fields[field].Pos(), "%s: resource should not configure %s, replace it with %s", analyzerName, field, field+"Context") + } + } + + if resource.DeclaresField(tfplsh.ResourceFieldImporter) { + var resourceImporterSchema *tfplsh.SchemaInfo + switch value := resource.Fields[tfplsh.ResourceFieldImporter].Value.(type) { + case *ast.UnaryExpr: + if value.Op != token.AND || !schema.IsTypeResourceImporter(pass.TypesInfo.TypeOf(value.X)) { + continue + } + resourceImporterSchema = tfplsh.NewSchemaInfo(value.X.(*ast.CompositeLit), pass.TypesInfo) + } + if resourceImporterSchema != nil && resourceImporterSchema.DeclaresField("State") { + if ignorer.ShouldIgnore(analyzerName, resourceImporterSchema.Fields["State"].Key) { + continue + } + pass.Reportf(resourceImporterSchema.Fields["State"].Pos(), "%s: resource should not configure %s, replace it with %s", analyzerName, "Importer.State", "Importer.StateContext") + } + } + + } + + return nil, nil +} diff --git a/tools/tfproviderlint/checks/L002/L002_test.go b/tools/tfproviderlint/checks/L002/L002_test.go new file mode 100644 index 0000000000..b96fe91425 --- /dev/null +++ b/tools/tfproviderlint/checks/L002/L002_test.go @@ -0,0 +1,14 @@ +package L002_test + +import ( + "testing" + + "golang.org/x/tools/go/analysis/analysistest" + + "github.com/integrations/terraform-provider-github/tools/tfproviderlint/checks/L002" +) + +func TestL002(t *testing.T) { + testdata := analysistest.TestData() + analysistest.Run(t, testdata, L002.Analyzer, "testdata/src/a") +} diff --git a/tools/tfproviderlint/checks/L002/testdata/go.mod b/tools/tfproviderlint/checks/L002/testdata/go.mod new file mode 100644 index 0000000000..b31853791d --- /dev/null +++ b/tools/tfproviderlint/checks/L002/testdata/go.mod @@ -0,0 +1,39 @@ +module testdata + +go 1.26 + +require github.com/hashicorp/terraform-plugin-sdk/v2 v2.39.0 + +require ( + github.com/agext/levenshtein v1.2.2 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/hashicorp/go-cty v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect + github.com/hashicorp/hcl/v2 v2.24.0 // indirect + github.com/hashicorp/logutils v1.0.0 // indirect + github.com/hashicorp/terraform-plugin-go v0.30.0 // indirect + github.com/hashicorp/terraform-plugin-log v0.10.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/zclconf/go-cty v1.17.0 // indirect + golang.org/x/mod v0.33.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.34.0 // indirect + golang.org/x/tools v0.41.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.36.11 // indirect +) diff --git a/tools/tfproviderlint/checks/L002/testdata/go.sum b/tools/tfproviderlint/checks/L002/testdata/go.sum new file mode 100644 index 0000000000..c681e2cf1f --- /dev/null +++ b/tools/tfproviderlint/checks/L002/testdata/go.sum @@ -0,0 +1,143 @@ +github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= +github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/hashicorp/go-cty v1.5.0 h1:EkQ/v+dDNUqnuVpmS5fPqyY71NXVgT5gf32+57xY8g0= +github.com/hashicorp/go-cty v1.5.0/go.mod h1:lFUCG5kd8exDobgSfyj4ONE/dc822kiYMguVKdHGMLM= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE= +github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= +github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/terraform-plugin-go v0.30.0 h1:VmEiD0n/ewxbvV5VI/bYwNtlSEAXtHaZlSnyUUuQK6k= +github.com/hashicorp/terraform-plugin-go v0.30.0/go.mod h1:8d523ORAW8OHgA9e8JKg0ezL3XUO84H0A25o4NY/jRo= +github.com/hashicorp/terraform-plugin-log v0.10.0 h1:eu2kW6/QBVdN4P3Ju2WiB2W3ObjkAsyfBsL3Wh1fj3g= +github.com/hashicorp/terraform-plugin-log v0.10.0/go.mod h1:/9RR5Cv2aAbrqcTSdNmY1NRHP4E3ekrXRGjqORpXyB0= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.39.0 h1:ltFG/dSs4mMHNpBqHptCtJqYM4FekUDJbUcWj+6HGlg= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.39.0/go.mod h1:xJk7ap8vRI/B2U6TrVs7bu/gTihyor8XBTLSs5Y6z2w= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= +github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0= +github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/tfproviderlint/checks/L002/testdata/src/a/comment_ignore.go b/tools/tfproviderlint/checks/L002/testdata/src/a/comment_ignore.go new file mode 100644 index 0000000000..02a9c96f28 --- /dev/null +++ b/tools/tfproviderlint/checks/L002/testdata/src/a/comment_ignore.go @@ -0,0 +1,42 @@ +package a + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func fcommentignore() { + _ = schema.Resource{ + // lintignore:L002 + Create: func(d *schema.ResourceData, meta any) error { + return nil + }, + } + + _ = schema.Resource{ + // lintignore:L002 + Read: func(d *schema.ResourceData, meta any) error { + return nil + }, + } + + _ = schema.Resource{ + // lintignore:L002 + Update: func(d *schema.ResourceData, meta any) error { + return nil + }, + } + + _ = schema.Resource{ + // lintignore:L002 + Delete: func(d *schema.ResourceData, meta any) error { + return nil + }, + } + + _ = schema.Resource{ + Importer: &schema.ResourceImporter{ + // lintignore:L002 + State: schema.ImportStatePassthrough, + }, + } +} diff --git a/tools/tfproviderlint/checks/L002/testdata/src/a/main.go b/tools/tfproviderlint/checks/L002/testdata/src/a/main.go new file mode 100644 index 0000000000..8a8b3c29df --- /dev/null +++ b/tools/tfproviderlint/checks/L002/testdata/src/a/main.go @@ -0,0 +1,69 @@ +package a + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func f() { + // Test for CreateContext + _ = schema.Resource{ + Create: func(d *schema.ResourceData, meta any) error { // want "L002: resource should not configure Create, replace it with CreateContext" + return nil + }, + } + + // Test for ReadContext + _ = schema.Resource{ + Read: func(d *schema.ResourceData, meta any) error { // want "L002: resource should not configure Read, replace it with ReadContext" + return nil + }, + } + + // Test for UpdateContext + _ = schema.Resource{ + Update: func(d *schema.ResourceData, meta any) error { // want "L002: resource should not configure Update, replace it with UpdateContext" + return nil + }, + } + + // Test for DeleteContext + _ = schema.Resource{ + Delete: func(d *schema.ResourceData, meta any) error { // want "L002: resource should not configure Delete, replace it with DeleteContext" + return nil + }, + } + + // Test for Importer.StateContext + _ = schema.Resource{ + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, // want "L002: resource should not configure Importer.State, replace it with Importer.StateContext" + }, + } + + _ = schema.Resource{ + CreateContext: func(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + return nil + }, + } + + _ = schema.Resource{ + UpdateContext: func(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + return nil + }, + } + + _ = schema.Resource{ + DeleteContext: func(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + return nil + }, + } + + _ = schema.Resource{ + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + } +} diff --git a/tools/tfproviderlint/checks/checks.go b/tools/tfproviderlint/checks/checks.go index 7a1470a7dd..ec3cad56e0 100644 --- a/tools/tfproviderlint/checks/checks.go +++ b/tools/tfproviderlint/checks/checks.go @@ -3,9 +3,11 @@ package checks import ( "golang.org/x/tools/go/analysis" - L001 "github.com/integrations/terraform-provider-github/tools/tfproviderlint/checks/L001" + "github.com/integrations/terraform-provider-github/tools/tfproviderlint/checks/L001" + "github.com/integrations/terraform-provider-github/tools/tfproviderlint/checks/L002" ) var AllChecks = []*analysis.Analyzer{ L001.Analyzer, + L002.Analyzer, } diff --git a/tools/tfproviderlint/helper/schema/type_resourceimporter.go b/tools/tfproviderlint/helper/schema/type_resourceimporter.go new file mode 100644 index 0000000000..6cffac4827 --- /dev/null +++ b/tools/tfproviderlint/helper/schema/type_resourceimporter.go @@ -0,0 +1,23 @@ +package schema + +import ( + "go/types" + + schemahelper "github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema" +) + +const ( + TypeNameResourceImporter = `ResourceImporter` +) + +// IsTypeResourceImporter returns if the type is ResourceImporter from the schema package. +func IsTypeResourceImporter(t types.Type) bool { + switch t := t.(type) { + case *types.Named: + return schemahelper.IsNamedType(t, TypeNameResourceImporter) + case *types.Pointer: + return IsTypeResourceImporter(t.Elem()) + default: + return false + } +} From 157f8fa0c7a4cca4712da9e20b5a81b5bc63b295 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Sun, 8 Mar 2026 18:36:53 +0200 Subject: [PATCH 11/20] Ensure we're using go 1.26 in `tools` Signed-off-by: Timo Sand --- tools/tfproviderlint/checks/L001/testdata/go.mod | 2 +- tools/tfproviderlint/go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/tfproviderlint/checks/L001/testdata/go.mod b/tools/tfproviderlint/checks/L001/testdata/go.mod index 8db7104371..b31853791d 100644 --- a/tools/tfproviderlint/checks/L001/testdata/go.mod +++ b/tools/tfproviderlint/checks/L001/testdata/go.mod @@ -1,6 +1,6 @@ module testdata -go 1.24.4 +go 1.26 require github.com/hashicorp/terraform-plugin-sdk/v2 v2.39.0 diff --git a/tools/tfproviderlint/go.mod b/tools/tfproviderlint/go.mod index 35dc58d30e..3c3215eab5 100644 --- a/tools/tfproviderlint/go.mod +++ b/tools/tfproviderlint/go.mod @@ -1,6 +1,6 @@ module github.com/integrations/terraform-provider-github/tools/tfproviderlint -go 1.24.4 +go 1.26 require ( github.com/bflad/tfproviderlint v0.31.0 From 97527de97e9bcf20dfc934ad7bf9777b5b743165 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Sun, 8 Mar 2026 19:55:23 +0200 Subject: [PATCH 12/20] Add `tools` package to formatter Signed-off-by: Timo Sand --- GNUmakefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 81e6fee090..6eca97419d 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -32,7 +32,8 @@ bin/golangci-lint: mkdir -p $(BIN) GOBIN=$(BIN) go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.10.1 -bin/custom-gcl: bin/golangci-lint $(shell find tools \( -name '*.go' -or -name '*.mod' -or -name '*.sum' \) -and -not -name '*_test.go' -maxdepth 4) +tools_go_files = $(shell find tools \( -name '*.go' -or -name '*.mod' -or -name '*.sum' \) -and -not -name '*_test.go' -maxdepth 4) +bin/custom-gcl: bin/golangci-lint $(tools_go_files) $(BIN)/golangci-lint custom --name custom-gcl --destination $(BIN) tools: bin/custom-gcl go.sum @@ -45,7 +46,7 @@ build: lintcheck fmt: tools @echo "==> Fixing source code formatting..." - $(BIN)/custom-gcl fmt ./... + $(BIN)/custom-gcl fmt ./... ./tools/... lint: tools @echo "==> Checking source code against linters and fixing..." From 58cb90ee1262a3beb0f2be1bd098a071ddaf2cd2 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 10 Mar 2026 22:57:02 +0200 Subject: [PATCH 13/20] Add linter rule for checking that resource CRUD functions are not called Signed-off-by: Timo Sand --- .golangci.strict.yml | 1 + tools/tfproviderlint/checks/L003/L003.go | 144 ++++++++++++++++++ tools/tfproviderlint/checks/L003/L003_test.go | 14 ++ .../checks/L003/testdata/go.mod | 39 +++++ .../checks/L003/testdata/go.sum | 143 +++++++++++++++++ .../L003/testdata/src/a/comment_ignore.go | 26 ++++ .../checks/L003/testdata/src/a/main.go | 51 +++++++ tools/tfproviderlint/checks/checks.go | 2 + 8 files changed, 420 insertions(+) create mode 100644 tools/tfproviderlint/checks/L003/L003.go create mode 100644 tools/tfproviderlint/checks/L003/L003_test.go create mode 100644 tools/tfproviderlint/checks/L003/testdata/go.mod create mode 100644 tools/tfproviderlint/checks/L003/testdata/go.sum create mode 100644 tools/tfproviderlint/checks/L003/testdata/src/a/comment_ignore.go create mode 100644 tools/tfproviderlint/checks/L003/testdata/src/a/main.go diff --git a/.golangci.strict.yml b/.golangci.strict.yml index 9511453912..76885de992 100644 --- a/.golangci.strict.yml +++ b/.golangci.strict.yml @@ -29,3 +29,4 @@ linters: - XR007 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR007 - XS001 # https://github.com/bflad/tfproviderlint/tree/main/passes/XS001 - L002 # file:///./tools/tfproviderlint/checks/L002/README.md + - L003 # file:///./tools/tfproviderlint/checks/L003/L003.go diff --git a/tools/tfproviderlint/checks/L003/L003.go b/tools/tfproviderlint/checks/L003/L003.go new file mode 100644 index 0000000000..93d5a87867 --- /dev/null +++ b/tools/tfproviderlint/checks/L003/L003.go @@ -0,0 +1,144 @@ +package L003 + +import ( + "go/ast" + "go/token" + "go/types" + + tfplsh "github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema" + "github.com/bflad/tfproviderlint/passes/commentignore" + "github.com/bflad/tfproviderlint/passes/helper/schema/resourceinfo" + "golang.org/x/tools/go/analysis" + + "github.com/integrations/terraform-provider-github/tools/tfproviderlint/helper/schema" +) + +const Doc = `check for direct calls to resource CRUD functions + +The L003 analyzer reports cases where functions assigned to resource CRUD fields +(Create, Read, Update, Delete, Importer, etc.) are called directly from other code. +These functions are entry points for the Terraform SDK and must not be called directly.` + +const analyzerName = "L003" + +var Analyzer = &analysis.Analyzer{ + Name: analyzerName, + Doc: Doc, + Requires: []*analysis.Analyzer{ + commentignore.Analyzer, + resourceinfo.Analyzer, + }, + Run: run, +} + +var crudFields = []string{ + tfplsh.ResourceFieldCreate, + tfplsh.ResourceFieldCreateContext, + tfplsh.ResourceFieldCreateWithoutTimeout, + tfplsh.ResourceFieldRead, + tfplsh.ResourceFieldReadContext, + tfplsh.ResourceFieldReadWithoutTimeout, + tfplsh.ResourceFieldUpdate, + tfplsh.ResourceFieldUpdateContext, + tfplsh.ResourceFieldUpdateWithoutTimeout, + tfplsh.ResourceFieldDelete, + tfplsh.ResourceFieldDeleteContext, + tfplsh.ResourceFieldDeleteWithoutTimeout, + tfplsh.ResourceFieldExists, +} + +func buildCRUDFuncSet(pass *analysis.Pass, resources []*tfplsh.ResourceInfo) map[types.Object]string { + crudFuncs := make(map[types.Object]string) + + for _, resource := range resources { + for _, field := range crudFields { + if !resource.DeclaresField(field) { + continue + } + addFunc(pass, resource.Fields[field].Value, field, crudFuncs) + } + addImporterFuncs(pass, resource, crudFuncs) + } + + return crudFuncs +} + +func addFunc(pass *analysis.Pass, value ast.Expr, fieldName string, crudFuncs map[types.Object]string) { + ident, ok := value.(*ast.Ident) + if !ok { + return + } + + obj, ok := pass.TypesInfo.Uses[ident] + if !ok { + return + } + + crudFuncs[obj] = fieldName +} + +func addImporterFuncs(pass *analysis.Pass, resource *tfplsh.ResourceInfo, crudFuncs map[types.Object]string) { + if !resource.DeclaresField(tfplsh.ResourceFieldImporter) { + return + } + + value, ok := resource.Fields[tfplsh.ResourceFieldImporter].Value.(*ast.UnaryExpr) + if !ok || value.Op != token.AND || !schema.IsTypeResourceImporter(pass.TypesInfo.TypeOf(value.X)) { + return + } + + importerSchema := tfplsh.NewSchemaInfo(value.X.(*ast.CompositeLit), pass.TypesInfo) + if importerSchema == nil { + return + } + + for _, field := range []string{"State", "StateContext"} { + if importerSchema.DeclaresField(field) { + addFunc(pass, importerSchema.Fields[field].Value, "Importer."+field, crudFuncs) + } + } +} + +func run(pass *analysis.Pass) (any, error) { + ignorer := pass.ResultOf[commentignore.Analyzer].(*commentignore.Ignorer) + resources := pass.ResultOf[resourceinfo.Analyzer].([]*tfplsh.ResourceInfo) + + crudFuncs := buildCRUDFuncSet(pass, resources) + if len(crudFuncs) == 0 { + return nil, nil + } + + for _, file := range pass.Files { + ast.Inspect(file, func(n ast.Node) bool { + callExpr, ok := n.(*ast.CallExpr) + if !ok { + return true + } + + if ignorer.ShouldIgnore(analyzerName, callExpr) { + return true + } + + ident, ok := callExpr.Fun.(*ast.Ident) + if !ok { + return true + } + + obj, ok := pass.TypesInfo.Uses[ident] + if !ok { + return true + } + + fieldName, isCRUD := crudFuncs[obj] + if !isCRUD { + return true + } + + pass.Reportf(callExpr.Pos(), "%s: function %s is a resource CRUD function (%s) and must not be called directly", analyzerName, ident.Name, fieldName) + + return true + }) + } + + return nil, nil +} diff --git a/tools/tfproviderlint/checks/L003/L003_test.go b/tools/tfproviderlint/checks/L003/L003_test.go new file mode 100644 index 0000000000..6e73c17139 --- /dev/null +++ b/tools/tfproviderlint/checks/L003/L003_test.go @@ -0,0 +1,14 @@ +package L003_test + +import ( + "testing" + + "golang.org/x/tools/go/analysis/analysistest" + + "github.com/integrations/terraform-provider-github/tools/tfproviderlint/checks/L003" +) + +func TestL003(t *testing.T) { + testdata := analysistest.TestData() + analysistest.Run(t, testdata, L003.Analyzer, "testdata/src/a") +} diff --git a/tools/tfproviderlint/checks/L003/testdata/go.mod b/tools/tfproviderlint/checks/L003/testdata/go.mod new file mode 100644 index 0000000000..b31853791d --- /dev/null +++ b/tools/tfproviderlint/checks/L003/testdata/go.mod @@ -0,0 +1,39 @@ +module testdata + +go 1.26 + +require github.com/hashicorp/terraform-plugin-sdk/v2 v2.39.0 + +require ( + github.com/agext/levenshtein v1.2.2 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/hashicorp/go-cty v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect + github.com/hashicorp/hcl/v2 v2.24.0 // indirect + github.com/hashicorp/logutils v1.0.0 // indirect + github.com/hashicorp/terraform-plugin-go v0.30.0 // indirect + github.com/hashicorp/terraform-plugin-log v0.10.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/zclconf/go-cty v1.17.0 // indirect + golang.org/x/mod v0.33.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.34.0 // indirect + golang.org/x/tools v0.41.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.36.11 // indirect +) diff --git a/tools/tfproviderlint/checks/L003/testdata/go.sum b/tools/tfproviderlint/checks/L003/testdata/go.sum new file mode 100644 index 0000000000..c681e2cf1f --- /dev/null +++ b/tools/tfproviderlint/checks/L003/testdata/go.sum @@ -0,0 +1,143 @@ +github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= +github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/hashicorp/go-cty v1.5.0 h1:EkQ/v+dDNUqnuVpmS5fPqyY71NXVgT5gf32+57xY8g0= +github.com/hashicorp/go-cty v1.5.0/go.mod h1:lFUCG5kd8exDobgSfyj4ONE/dc822kiYMguVKdHGMLM= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE= +github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= +github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/terraform-plugin-go v0.30.0 h1:VmEiD0n/ewxbvV5VI/bYwNtlSEAXtHaZlSnyUUuQK6k= +github.com/hashicorp/terraform-plugin-go v0.30.0/go.mod h1:8d523ORAW8OHgA9e8JKg0ezL3XUO84H0A25o4NY/jRo= +github.com/hashicorp/terraform-plugin-log v0.10.0 h1:eu2kW6/QBVdN4P3Ju2WiB2W3ObjkAsyfBsL3Wh1fj3g= +github.com/hashicorp/terraform-plugin-log v0.10.0/go.mod h1:/9RR5Cv2aAbrqcTSdNmY1NRHP4E3ekrXRGjqORpXyB0= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.39.0 h1:ltFG/dSs4mMHNpBqHptCtJqYM4FekUDJbUcWj+6HGlg= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.39.0/go.mod h1:xJk7ap8vRI/B2U6TrVs7bu/gTihyor8XBTLSs5Y6z2w= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= +github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0= +github.com/zclconf/go-cty v1.17.0/go.mod h1:wqFzcImaLTI6A5HfsRwB0nj5n0MRZFwmey8YoFPPs3U= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/tfproviderlint/checks/L003/testdata/src/a/comment_ignore.go b/tools/tfproviderlint/checks/L003/testdata/src/a/comment_ignore.go new file mode 100644 index 0000000000..a40135594c --- /dev/null +++ b/tools/tfproviderlint/checks/L003/testdata/src/a/comment_ignore.go @@ -0,0 +1,26 @@ +package a + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func ignoredCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + return nil +} + +func ignoredRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + return nil +} + +func fcommentignore() { + _ = schema.Resource{ + CreateContext: ignoredCreate, + ReadContext: ignoredRead, + } + + // lintignore:L003 + ignoredRead(nil, nil, nil) +} diff --git a/tools/tfproviderlint/checks/L003/testdata/src/a/main.go b/tools/tfproviderlint/checks/L003/testdata/src/a/main.go new file mode 100644 index 0000000000..8f2e34960d --- /dev/null +++ b/tools/tfproviderlint/checks/L003/testdata/src/a/main.go @@ -0,0 +1,51 @@ +package a + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + return resourceRead(ctx, d, meta) // want "L003: function resourceRead is a resource CRUD function \\(ReadContext\\) and must not be called directly" +} + +func resourceRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + return nil +} + +func resourceUpdate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + return resourceRead(ctx, d, meta) // want "L003: function resourceRead is a resource CRUD function \\(ReadContext\\) and must not be called directly" +} + +func resourceDelete(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + return nil +} + +func resourceImportState(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) { + return nil, nil +} + +func helperFunc() {} + +func f() { + _ = schema.Resource{ + CreateContext: resourceCreate, + ReadContext: resourceRead, + UpdateContext: resourceUpdate, + DeleteContext: resourceDelete, + Importer: &schema.ResourceImporter{ + StateContext: resourceImportState, + }, + } + + resourceCreate(nil, nil, nil) // want "L003: function resourceCreate is a resource CRUD function \\(CreateContext\\) and must not be called directly" + resourceRead(nil, nil, nil) // want "L003: function resourceRead is a resource CRUD function \\(ReadContext\\) and must not be called directly" + resourceUpdate(nil, nil, nil) // want "L003: function resourceUpdate is a resource CRUD function \\(UpdateContext\\) and must not be called directly" + resourceDelete(nil, nil, nil) // want "L003: function resourceDelete is a resource CRUD function \\(DeleteContext\\) and must not be called directly" + _, _ = resourceImportState(nil, nil, nil) // want "L003: function resourceImportState is a resource CRUD function \\(Importer.StateContext\\) and must not be called directly" + + // Calling a non-CRUD function is not a violation + helperFunc() +} diff --git a/tools/tfproviderlint/checks/checks.go b/tools/tfproviderlint/checks/checks.go index ec3cad56e0..6fc1ea4bc2 100644 --- a/tools/tfproviderlint/checks/checks.go +++ b/tools/tfproviderlint/checks/checks.go @@ -5,9 +5,11 @@ import ( "github.com/integrations/terraform-provider-github/tools/tfproviderlint/checks/L001" "github.com/integrations/terraform-provider-github/tools/tfproviderlint/checks/L002" + "github.com/integrations/terraform-provider-github/tools/tfproviderlint/checks/L003" ) var AllChecks = []*analysis.Analyzer{ L001.Analyzer, L002.Analyzer, + L003.Analyzer, } From fb669b43ef5af9088332669d2dc1c8d6cb767271 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Sun, 15 Mar 2026 21:01:35 +0200 Subject: [PATCH 14/20] Ensure `lint-new` is able to determine change-set properly Signed-off-by: Timo Sand --- .github/workflows/ci.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 98d583a2f8..fcf87db22b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -17,7 +17,7 @@ concurrency: permissions: read-all env: - GOLANGCI_LINT_VERSION: v2.10 + GOLANGCI_LINT_VERSION: v2.10.1 defaults: run: @@ -61,6 +61,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + pull-requests: read steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 From 48b83c4b91011dde236a05b925f11c7ab3b396a2 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Sun, 15 Mar 2026 21:05:56 +0200 Subject: [PATCH 15/20] Cleanup linter config files Signed-off-by: Timo Sand --- .golangci.strict.yml | 3 ++- .golangci.yml | 18 ++---------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/.golangci.strict.yml b/.golangci.strict.yml index 76885de992..81e7322364 100644 --- a/.golangci.strict.yml +++ b/.golangci.strict.yml @@ -28,5 +28,6 @@ linters: - XR005 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR005 - XR007 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR007 - XS001 # https://github.com/bflad/tfproviderlint/tree/main/passes/XS001 - - L002 # file:///./tools/tfproviderlint/checks/L002/README.md + # Custom local checks + - L002 # file:///./tools/tfproviderlint/checks/L002/L002.go - L003 # file:///./tools/tfproviderlint/checks/L003/L003.go diff --git a/.golangci.yml b/.golangci.yml index 8ae0ae3f16..c1e4071356 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -39,40 +39,30 @@ linters: enabled-checks: - AT005 # https://github.com/bflad/tfproviderlint/tree/main/passes/AT005 - AT008 # https://github.com/bflad/tfproviderlint/tree/main/passes/AT008 - # - AT009 # https://github.com/bflad/tfproviderlint/tree/main/passes/AT009 # TODO: Enable when we can fix the issues - # - R002 # https://github.com/bflad/tfproviderlint/tree/main/passes/R002 - # - R004 # https://github.com/bflad/tfproviderlint/tree/main/passes/R004 - R005 # https://github.com/bflad/tfproviderlint/tree/main/passes/R005 - R006 # https://github.com/bflad/tfproviderlint/tree/main/passes/R006 - # - R009 # https://github.com/bflad/tfproviderlint/tree/main/passes/R009 # TODO: Enable when we can fix the issues - # - R010 # https://github.com/bflad/tfproviderlint/tree/main/passes/R010 # TODO: Enable when we can fix the issues - R011 # https://github.com/bflad/tfproviderlint/tree/main/passes/R011 - R012 # https://github.com/bflad/tfproviderlint/tree/main/passes/R012 - R013 # https://github.com/bflad/tfproviderlint/tree/main/passes/R013 - R015 # https://github.com/bflad/tfproviderlint/tree/main/passes/R015 - R016 # https://github.com/bflad/tfproviderlint/tree/main/passes/R016 - R017 # https://github.com/bflad/tfproviderlint/tree/main/passes/R017 - # - R018 # https://github.com/bflad/tfproviderlint/tree/main/passes/R018 # TODO: Enable when we can fix the issues - S001 # https://github.com/bflad/tfproviderlint/tree/main/passes/S001 - S002 # https://github.com/bflad/tfproviderlint/tree/main/passes/S002 - S003 # https://github.com/bflad/tfproviderlint/tree/main/passes/S003 - S004 # https://github.com/bflad/tfproviderlint/tree/main/passes/S004 - S005 # https://github.com/bflad/tfproviderlint/tree/main/passes/S005 - # - S006 # https://github.com/bflad/tfproviderlint/tree/main/passes/S006 # TODO: Enable when we can fix the issues - S007 # https://github.com/bflad/tfproviderlint/tree/main/passes/S007 - S008 # https://github.com/bflad/tfproviderlint/tree/main/passes/S008 - S009 # https://github.com/bflad/tfproviderlint/tree/main/passes/S009 - S010 # https://github.com/bflad/tfproviderlint/tree/main/passes/S010 - S011 # https://github.com/bflad/tfproviderlint/tree/main/passes/S011 - S012 # https://github.com/bflad/tfproviderlint/tree/main/passes/S012 - # - S013 # https://github.com/bflad/tfproviderlint/tree/main/passes/S013 # TODO: Enable when we can fix the issues - S014 # https://github.com/bflad/tfproviderlint/tree/main/passes/S014 - S015 # https://github.com/bflad/tfproviderlint/tree/main/passes/S015 - S016 # https://github.com/bflad/tfproviderlint/tree/main/passes/S016 - S017 # https://github.com/bflad/tfproviderlint/tree/main/passes/S017 - S018 # https://github.com/bflad/tfproviderlint/tree/main/passes/S018 - # - S019 # https://github.com/bflad/tfproviderlint/tree/main/passes/S019 # TODO: Enable when we can fix the issues - # - S020 # https://github.com/bflad/tfproviderlint/tree/main/passes/S020 # TODO: Enable when we can fix the issues - S021 # https://github.com/bflad/tfproviderlint/tree/main/passes/S021 - S022 # https://github.com/bflad/tfproviderlint/tree/main/passes/S022 - S023 # https://github.com/bflad/tfproviderlint/tree/main/passes/S023 @@ -89,15 +79,11 @@ linters: - S035 # https://github.com/bflad/tfproviderlint/tree/main/passes/S035 - S036 # https://github.com/bflad/tfproviderlint/tree/main/passes/S036 - S037 # https://github.com/bflad/tfproviderlint/tree/main/passes/S037 - # - XR002 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR002 # TODO: Enable when we can fix the issues - # - XR003 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR003 # TODO: Enable when we can fix the issues - XR004 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR004 - # - XR005 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR005 # TODO: Enable when we can fix the issues - XR006 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR006 - # - XR007 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR007 # TODO: Enable when we can fix the issues - XR008 # https://github.com/bflad/tfproviderlint/tree/main/passes/XR008 - # - XS001 # https://github.com/bflad/tfproviderlint/tree/main/passes/XS001 # TODO: Enable when we can fix the issues - - L001 # file:///./tools/tfproviderlint/checks/L001/README.md + # Custom local checks + - L001 # file:///./tools/tfproviderlint/checks/L001/L001.go exclusions: generated: lax From f0ad816b59f51a732e5d82f03a202de662e5fe0c Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Sun, 15 Mar 2026 21:12:11 +0200 Subject: [PATCH 16/20] Enable all `revive` linter rules for new code Signed-off-by: Timo Sand --- .golangci.strict.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.golangci.strict.yml b/.golangci.strict.yml index 81e7322364..bd2edda58d 100644 --- a/.golangci.strict.yml +++ b/.golangci.strict.yml @@ -6,6 +6,7 @@ version: "2" linters: enable: - forcetypeassert + - revive settings: custom: From a0f5ec59357fd7efa3b25bdd5f39e3b8a761ac8e Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Sun, 15 Mar 2026 21:15:06 +0200 Subject: [PATCH 17/20] Enable running linter tests in CI Signed-off-by: Timo Sand --- .github/workflows/ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fcf87db22b..85c1cecd71 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -39,6 +39,7 @@ jobs: cache: true - run: make build -o lintcheck - run: make test + - run: make test-tools golangci: name: lint runs-on: ubuntu-latest From a21bd809e0654e2987b635cf5ba8d2c3c47e39d6 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 17 Mar 2026 21:46:01 +0200 Subject: [PATCH 18/20] Add some clearer output to make targets Signed-off-by: Timo Sand --- GNUmakefile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 6eca97419d..0341646cb0 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -29,17 +29,19 @@ endif default: build bin/golangci-lint: + @echo "==> Installing golangci-lint..." mkdir -p $(BIN) GOBIN=$(BIN) go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.10.1 tools_go_files = $(shell find tools \( -name '*.go' -or -name '*.mod' -or -name '*.sum' \) -and -not -name '*_test.go' -maxdepth 4) bin/custom-gcl: bin/golangci-lint $(tools_go_files) - $(BIN)/golangci-lint custom --name custom-gcl --destination $(BIN) + @echo "==> Building custom-gcl..." + @$(BIN)/golangci-lint custom --name custom-gcl --destination $(BIN) tools: bin/custom-gcl go.sum go.sum: go.mod $(shell find github -name '*.go') - go mod tidy + @go mod tidy build: lintcheck CGO_ENABLED=0 go build -ldflags="-s -w" ./... @@ -58,16 +60,16 @@ lintcheck: tools $(BIN)/custom-gcl run ./... .golangci.new.yml: .golangci.yml .golangci.strict.yml - yq eval-all 'select(fileIndex == 0) *+ select(fileIndex == 1)' .golangci.yml .golangci.strict.yml > .golangci.new.yml + @yq eval-all 'select(fileIndex == 0) *+ select(fileIndex == 1)' .golangci.yml .golangci.strict.yml > .golangci.new.yml lintcheck-new: tools .golangci.new.yml @branch=$$(git rev-parse --abbrev-ref HEAD); \ - printf "==> Checking source code against linters on branch: \033[1m%s\033[0m...\n" "🌿 $$branch 🌿" + printf "==> Checking changed source code against linters on branch: \033[1m%s\033[0m...\n" "🌿 $$branch 🌿" $(BIN)/custom-gcl run ./... --new-from-merge-base main --config .golangci.new.yml lintcheck-strict: tools .golangci.new.yml @branch=$$(git rev-parse --abbrev-ref HEAD); \ - printf "==> Checking source code against linters on branch: \033[1m%s\033[0m...\n" "🌿 $$branch 🌿" + printf "==> Checking source code against strict linters on branch: \033[1m%s\033[0m...\n" "🌿 $$branch 🌿" $(BIN)/custom-gcl run ./... --config .golangci.new.yml test: From dc392ec918eaf00ccaa8481e66621a036b95b448 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 17 Mar 2026 22:12:37 +0200 Subject: [PATCH 19/20] Separate linter test to own workflow to only run it when necessary Signed-off-by: Timo Sand --- .github/workflows/ci-linter.yaml | 42 ++++++++++++++++++++++++++++++++ .github/workflows/ci.yaml | 5 +++- tools/tfproviderlint/GNUmakefile | 4 +-- 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/ci-linter.yaml diff --git a/.github/workflows/ci-linter.yaml b/.github/workflows/ci-linter.yaml new file mode 100644 index 0000000000..5158ee3f54 --- /dev/null +++ b/.github/workflows/ci-linter.yaml @@ -0,0 +1,42 @@ +name: CI + +on: + push: + branches: + - main + - release-v* + paths: + - tools/tfproviderlint/** + pull_request: + branches: + - main + - release-v* + paths: + - tools/tfproviderlint/** + +concurrency: + group: ci-linter-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +jobs: + test: + name: Custom Linter Tests + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Set-up Go + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version-file: go.mod + cache: true + cache-dependency-path: | + go.sum + tools/tfproviderlint/go.sum + - run: make test-tools diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 85c1cecd71..2bc687695c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -39,7 +39,6 @@ jobs: cache: true - run: make build -o lintcheck - run: make test - - run: make test-tools golangci: name: lint runs-on: ubuntu-latest @@ -71,6 +70,10 @@ jobs: with: go-version-file: go.mod cache: true + cache-dependency-path: | + go.sum + tools/tfproviderlint/go.sum + custom-gcl - run: make .golangci.new.yml - name: golangci-lint uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 diff --git a/tools/tfproviderlint/GNUmakefile b/tools/tfproviderlint/GNUmakefile index 281752b67c..e0035a7b78 100644 --- a/tools/tfproviderlint/GNUmakefile +++ b/tools/tfproviderlint/GNUmakefile @@ -2,10 +2,10 @@ test_go_sums = $(patsubst %/go.mod,%/go.sum,$(wildcard checks/*/testdata/go.mod) .SECONDEXPANSION: checks/%/testdata/go.sum: checks/%/testdata/go.mod $$(wildcard checks/$$*/*.go) - cd $(dir $@) && go mod tidy + @cd $(dir $@) && go mod tidy go.sum: go.mod $(shell find checks -name '*.go' -maxdepth 2) - go mod tidy + @go mod tidy test: go.sum $(test_go_sums) CGO_ENABLED=0 go test ./... -v -count=1 -timeout=30s -parallel=4 From 2263edeb08bffb7a93fbae8435f16ff090babdd5 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Fri, 24 Apr 2026 12:25:27 +0300 Subject: [PATCH 20/20] Fix linter issue Signed-off-by: Timo Sand --- github/resource_github_team_settings.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/resource_github_team_settings.go b/github/resource_github_team_settings.go index a003a7d8b1..fb2b5e14d4 100644 --- a/github/resource_github_team_settings.go +++ b/github/resource_github_team_settings.go @@ -225,7 +225,7 @@ func resourceGithubTeamSettingsRead(ctx context.Context, d *schema.ResourceData, } func resourceGithubTeamSettingsUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - if d.HasChange("review_request_delegation") || d.HasChange("notify") { + if d.HasChanges("review_request_delegation", "notify") { meta := m.(*Owner) graphql := meta.v4client reviewRequestDelegation := d.Get("review_request_delegation").([]any)