Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .custom-gcl.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
version: v1.62.0
plugins:
- module: 'github.com/stackitcloud/stackit-sdk-go/tools'
import: 'github.com/stackitcloud/stackit-sdk-go/tools/linters/pkgstutter'
path: ./tools
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ bin/
*.vscode/

go.work.sum
custom-gcl
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ project-tools: ## Install project tools

# LINT
lint-golangci-lint: ## Lint Go code
@golangci-lint custom
@echo ">> Linting with golangci-lint"
@$(SCRIPTS_BASE)/lint-golangci-lint.sh "${skip-non-generated-files}" "${service}"

Expand Down
5 changes: 5 additions & 0 deletions golang-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ run:
# timeout for analysis, e.g. 30s, 5m, default is 1m
timeout: 5m
linters-settings:
custom:
pkgstutter:
type: module
description: "A custom local linter"
goimports:
# put imports beginning with prefix after 3rd-party packages;
# it's a comma-separated list of prefixes
Expand Down Expand Up @@ -64,6 +68,7 @@ linters-settings:
- dupImport # https://github.com/go-critic/go-critic/issues/845
linters:
enable:
- pkgstutter # custom local linter
# https://golangci-lint.run/usage/linters/
# default linters
- gosimple
Expand Down
8 changes: 4 additions & 4 deletions scripts/lint-golangci-lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ lint_service() {
echo ">> Linting service ${service}"
cd ${SERVICES_PATH}/${service}
if [ "${SKIP_NON_GENERATED_FILES}" = true ]; then
golangci-lint run ${GOLANG_CI_ARGS} --skip-dirs wait # All manually maintained files are in subfolders
${ROOT_DIR}/custom-gcl run ${GOLANG_CI_ARGS} --skip-dirs wait # All manually maintained files are in subfolders
else
golangci-lint run ${GOLANG_CI_ARGS}
${ROOT_DIR}/custom-gcl run ${GOLANG_CI_ARGS}
fi
}

Expand All @@ -48,7 +48,7 @@ else
if [ "${SKIP_NON_GENERATED_FILES}" = false ]; then
echo ">> Linting core"
cd ${CORE_PATH}
golangci-lint run ${GOLANG_CI_ARGS}
${ROOT_DIR}/custom-gcl run ${GOLANG_CI_ARGS}
fi

for service_dir in ${SERVICES_PATH}/*; do
Expand All @@ -61,7 +61,7 @@ else
example=$(basename ${example_dir})
echo ">> Linting example ${example}"
cd ${example_dir}
golangci-lint run ${GOLANG_CI_ARGS}
${ROOT_DIR}/custom-gcl run ${GOLANG_CI_ARGS}
done
fi
fi
8 changes: 8 additions & 0 deletions tools/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/stackitcloud/stackit-sdk-go/tools

go 1.25.9

require (
github.com/golangci/plugin-module-register v0.1.2
golang.org/x/tools v0.45.0
)
4 changes: 4 additions & 0 deletions tools/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
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/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8=
golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0=
56 changes: 56 additions & 0 deletions tools/linters/pkgstutter/pkgstutter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package pkgstutter

import (
"strings"

"github.com/golangci/plugin-module-register/register"
"golang.org/x/tools/go/analysis"
)

var Analyzer = &analysis.Analyzer{
Name: "pkgstutter",
Doc: "Prevents stuttering package names, e.g. github.com/foo/bar/wait/wait",
Run: run,
}

func run(pass *analysis.Pass) (any, error) {
pkgPath := pass.Pkg.Path()
parts := strings.Split(pkgPath, "/")

// Check for adjacent identical parts in the path
for i := 1; i < len(parts); i++ {
if parts[i] == parts[i-1] {
// If a stutter is found, report it at the package declaration
// of the first file in the package to pinpoint the error.
if len(pass.Files) > 0 {
pass.Reportf(
pass.Files[0].Package,
"package path %q contains stuttering (%s/%s)",
pkgPath, parts[i-1], parts[i],
)
}
// Break after the first finding to avoid spamming multiple errors for the same package
break
}
}

return nil, nil
}

func init() {
register.Plugin("pkgstutter", New)
}

func New(settings any) (register.LinterPlugin, error) {
return &plugin{}, nil
}

type plugin struct{}

func (p *plugin) BuildAnalyzers() ([]*analysis.Analyzer, error) {
return []*analysis.Analyzer{Analyzer}, nil
}

func (p *plugin) GetLoadMode() string {
return register.LoadModeTypesInfo
}
Loading