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
13 changes: 5 additions & 8 deletions .github/workflows/checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ name: Checks
permissions:
checks: write
contents: read
pull-requests: read
jobs:
checks:
name: Checks
Expand All @@ -42,13 +41,11 @@ jobs:
- name: Dependency Licenses Review
run: make check-dependency-licenses
- name: Check for spelling errors
uses: reviewdog/action-misspell@v1
with:
exclude: ./vendor/*
fail_on_error: true
github_token: ${{ secrets.GITHUB_TOKEN }}
ignore: importas
reporter: github-check
uses: crate-ci/typos@v1
env:
CLICOLOR: "1"
- name: Delete typos binary
run: rm typos
- name: Check if source code files have license header
run: make check-addlicense
- name: REUSE Compliance Check
Expand Down
1 change: 0 additions & 1 deletion .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ linters:
- ineffassign
- intrange
- iotamixing
- misspell
- modernize
- nilerr
- nolintlint
Expand Down
11 changes: 11 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: 2025 SAP SE
#
# SPDX-License-Identifier: Apache-2.0

[default.extend-words]

[files]
extend-exclude = [
"go.mod",
"vendor/",
]
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ run-shellcheck: FORCE install-shellcheck
@printf "\e[1;36m>> shellcheck\e[0m\n"
@find . \( -path './vendor/*' -prune \) -o -type f \( -name '*.bash' -o -name '*.ksh' -o -name '*.zsh' -o -name '*.sh' -o -name '*.shlib' \) -exec shellcheck {} +

run-typos: FORCE
@printf "\e[1;36m>> typos\e[0m\n"
@printf "\e[1;36m>> Typos install instructions can be found here https://github.com/crate-ci/typos#install \e[0m\n"
@typos

build/cover.out: FORCE | build
@printf "\e[1;36m>> Running tests\e[0m\n"
@env $(GO_TESTENV) go test -shuffle=on -coverprofile=build/coverprofile.out $(GO_BUILDFLAGS) -ldflags '-s -w -X github.com/sapcc/go-api-declarations/bininfo.binName=go-makefile-maker -X github.com/sapcc/go-api-declarations/bininfo.version=$(BININFO_VERSION) -X github.com/sapcc/go-api-declarations/bininfo.commit=$(BININFO_COMMIT_HASH) -X github.com/sapcc/go-api-declarations/bininfo.buildDate=$(BININFO_BUILD_DATE) $(GO_LDFLAGS)' -covermode=count -coverpkg=$(subst $(space),$(comma),$(GO_COVERPKGS)) $(GO_TESTFLAGS) $(GO_TESTPKGS)
Expand Down Expand Up @@ -212,6 +217,7 @@ help: FORCE
@printf " \e[36mcheck\e[0m Run the test suite (unit tests and golangci-lint).\n"
@printf " \e[36mrun-golangci-lint\e[0m Install and run golangci-lint. Installing is used in CI, but you should probably install golangci-lint using your package manager.\n"
@printf " \e[36mrun-shellcheck\e[0m Install and run shellcheck. Installing is used in CI, but you should probably install shellcheck using your package manager.\n"
@printf " \e[36mrun-typos\e[0m Check for spelling errors using typos.\n"
@printf " \e[36mbuild/cover.out\e[0m Run tests and generate coverage report.\n"
@printf " \e[36mbuild/cover.html\e[0m Generate an HTML file with source code annotations from the coverage report.\n"
@printf " \e[36mcheck-addlicense\e[0m Check license headers in all non-vendored .go files with addlicense.\n"
Expand Down
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ The config file has the following sections:
* [renovate](#renovate)
* [reuse](#reuse)
* [shellCheck](#shellCheck)
* [spellCheck](#spellcheck)
* [testPackages](#testpackages)
* [typos](#typos)
* [variables](#variables)
* [verbatim](#verbatim)
* [githubWorkflow](#githubworkflow)
Expand Down Expand Up @@ -473,18 +473,23 @@ Whether to run [`ShellCheck`](https://www.shellcheck.net/) on all shell scripts

`opts` specifies additional options to pass to `shellcheck`. The `-e` option can be used to ignore specific shellcheck warnings.

### `spellCheck`
### `typos`

```yaml
spellCheck:
ignoreWords:
- example
- exampleTwo
typos:
enabled: true
extendExcludes:
- internal/compress/constants.go
- internal/compress/testdata/
extendWords:
reenforced: reenforced # do not correct to the semantically different word "reinforced"
```

`golangci-lint` (if `golangciLint.createConfig` is `true`) and the spell check GitHub workflow (`githubWorkflow.spellCheck`) use [`misspell`][misspell] to check for spelling errors.
Whether to run [`typos`](https://github.com/crate-ci/typos) to check for spelling mistakes.

`typos.extendExcludes` maps to typos `files.extend-excludes` and allows to exclude some files or paths from spell checking.

If `spellCheck.ignoreWords` is defined then both `golangci-lint` and spell check workflow will give this word list to `misspell` so that they can be ignored during its checks.
`typos.extendWords` maps to typos `default.extend-words` and allows to add custom word mappings to the dictionary. The key is hereby the wrong spelling and the value the correct spelling.


### `testPackages`
Expand Down Expand Up @@ -714,7 +719,6 @@ githubWorkflow:
[doublestar-pattern]: https://github.com/bmatcuk/doublestar#patterns
[go-licence-detector]: https://github.com/elastic/go-licence-detector
[govulncheck]: https://github.com/golang/vuln
[misspell]: https://github.com/client9/misspell
[ref-onpushpull]: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#onpushpull_requestpaths
[ref-pattern-cheat-sheet]: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
[ref-runs-on]: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on
Expand Down
33 changes: 28 additions & 5 deletions internal/core/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ type Configuration struct {
Nix NixConfig `yaml:"nix"`
Renovate RenovateConfig `yaml:"renovate"`
ShellCheck ShellCheckConfiguration `yaml:"shellCheck"`
SpellCheck SpellCheckConfiguration `yaml:"spellCheck"`
Test TestConfiguration `yaml:"testPackages"`
Reuse ReuseConfiguration `yaml:"reuse"`
Verbatim string `yaml:"verbatim"`
VariableValues map[string]string `yaml:"variables"`
// Deprecated: use `typos` instead.
SpellCheck SpellCheckConfiguration `yaml:"spellCheck"`
Test TestConfiguration `yaml:"testPackages"`
Typos TyposConfiguration `yaml:"typos"`
Reuse ReuseConfiguration `yaml:"reuse"`
Verbatim string `yaml:"verbatim"`
VariableValues map[string]string `yaml:"variables"`
}

// Variable returns the value of this variable if it's overridden in the config,
Expand Down Expand Up @@ -139,6 +141,18 @@ type SpellCheckConfiguration struct {
IgnoreWords []string `yaml:"ignoreWords"`
}

// TyposConfiguration appears in type Configuration.
type TyposConfiguration struct {
Enabled Option[bool] `yaml:"enabled"`
ExtendExcludes []string `yaml:"extendExcludes"`
ExtendWords map[string]string `yaml:"extendWords"`
}

// IsEnabled encodes that the default state for the Enabled field is `true`.
func (c TyposConfiguration) IsEnabled() bool {
return c.Enabled.UnwrapOr(true)
}

///////////////////////////////////////////////////////////////////////////////
// GitHub workflow configuration

Expand Down Expand Up @@ -214,6 +228,11 @@ func (s ShellCheckConfiguration) AllIgnorePaths(g GolangConfiguration) []string
return s.IgnorePaths
}

// IsEnabled encodes that the default state for the Enabled field is `true`.
func (s ShellCheckConfiguration) IsEnabled() bool {
return s.Enabled.UnwrapOr(true)
}

type PackageRule struct {
MatchPackageNames []string `yaml:"matchPackageNames" json:"matchPackageNames,omitempty"`
MatchUpdateTypes []string `yaml:"matchUpdateTypes" json:"matchUpdateTypes,omitempty"`
Expand Down Expand Up @@ -298,6 +317,10 @@ type NixConfig struct {
// Helper functions

func (c *Configuration) Validate() {
if len(c.SpellCheck.IgnoreWords) > 0 {
logg.Fatal("SpellCheck/misspell is deprecated, please migrate to typos")
}

if c.Dockerfile.Enabled {
if c.Metadata.URL == "" {
logg.Fatal("metadata.url must be set when docker.enabled is true")
Expand Down
2 changes: 1 addition & 1 deletion internal/core/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,6 @@ const (
GoCoverageReportAction = "fgrosse/[email protected]"
GolangciLintAction = "golangci/golangci-lint-action@v9"
GoreleaserAction = "goreleaser/goreleaser-action@v6"
MisspellAction = "reviewdog/action-misspell@v1"
ReuseAction = "fsfe/reuse-action@v6"
TyposAction = "crate-ci/typos@v1"
)
37 changes: 12 additions & 25 deletions internal/ghworkflow/workflow_checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
package ghworkflow

import (
"fmt"
"strings"

"github.com/sapcc/go-makefile-maker/internal/core"
)

Expand All @@ -27,7 +24,7 @@ func checksWorkflow(cfg core.Configuration) {
},
})

if cfg.ShellCheck.Enabled.UnwrapOr(true) {
if cfg.ShellCheck.IsEnabled() {
// delete the pretty out of date installed version of shellcheck so that make install-shellcheck installs the current version
if !ghwCfg.IsSelfHostedRunner {
j.addStep(jobStep{
Expand All @@ -48,27 +45,17 @@ func checksWorkflow(cfg core.Configuration) {
})
}

if !ghwCfg.IsSelfHostedRunner {
with := map[string]any{
"exclude": "./vendor/*",
"reporter": "github-check",
"fail_on_error": true,
"github_token": "${{ secrets.GITHUB_TOKEN }}",
"ignore": "importas", //nolint:misspell //importas is a valid linter name, so we always ignore it
}
ignoreWords := cfg.SpellCheck.IgnoreWords
if len(ignoreWords) > 0 {
with["ignore"] = fmt.Sprintf("%s,%s", with["ignore"], strings.Join(ignoreWords, ","))
}

w.Permissions.Checks = tokenScopeWrite // for nicer output in pull request diffs
w.Permissions.PullRequests = tokenScopeRead // for private repos
j.addStep(jobStep{
Name: "Check for spelling errors",
Uses: core.MisspellAction,
With: with,
})
}
j.addStep(jobStep{
Name: "Check for spelling errors",
Uses: core.TyposAction,
Env: map[string]string{
"CLICOLOR": "1",
},
})
j.addStep(jobStep{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As always, surprising actions should be documented.

Suggested change
j.addStep(jobStep{
// TyposAction drops its binary into the repository root; if we do not clean this up,
// `reuse lint` will complain about it not having license information
j.addStep(jobStep{

Name: "Delete typos binary",
Run: "rm typos",
})

if ghwCfg.License.IsEnabled() {
j.addStep(jobStep{
Expand Down
10 changes: 1 addition & 9 deletions internal/golangcilint/golangci.yaml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ linters:
- ineffassign
- intrange
- iotamixing
- misspell
- modernize
- nilerr
- nolintlint
Expand Down Expand Up @@ -157,16 +156,9 @@ linters:
{{- if .WithControllerGen }}
modernize:
disable:
# omitzero requires removing omitempty tags in kubernetes api struct types which are nested, which is intepreted by controller-gen and breaks the CRDs.
# omitzero requires removing omitempty tags in kubernetes api struct types which are nested, which is interpreted by controller-gen and breaks the CRDs.
- omitzero
{{- end }}
{{- if .MisspellIgnoreWords }}
misspell:
ignore-rules:
{{- range .MisspellIgnoreWords }}
- {{ . }}
{{- end }}
{{- end }}
perfsprint:
# modernize generates nicer fix code
concat-loop: false
Expand Down
17 changes: 8 additions & 9 deletions internal/golangcilint/golangci_lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@ func RenderConfig(cfg core.Configuration, sr golang.ScanResult) {
}

must.Succeed(util.WriteFileFromTemplate(".golangci.yaml", configTemplate, map[string]any{
"EnableVendoring": cfg.Golang.EnableVendoring,
"GoMinorVersion": must.Return(strconv.Atoi(strings.Split(sr.GoVersion, ".")[1])),
"ModulePath": sr.ModulePath,
"MisspellIgnoreWords": cfg.SpellCheck.IgnoreWords,
"ErrcheckExcludes": cfg.GolangciLint.ErrcheckExcludes,
"SkipDirs": cfg.GolangciLint.SkipDirs,
"Timeout": timeout,
"ReviveRules": cfg.GolangciLint.ReviveRules,
"WithControllerGen": cfg.ControllerGen.Enabled.UnwrapOr(sr.KubernetesController),
"EnableVendoring": cfg.Golang.EnableVendoring,
"GoMinorVersion": must.Return(strconv.Atoi(strings.Split(sr.GoVersion, ".")[1])),
"ModulePath": sr.ModulePath,
"ErrcheckExcludes": cfg.GolangciLint.ErrcheckExcludes,
"SkipDirs": cfg.GolangciLint.SkipDirs,
"Timeout": timeout,
"ReviveRules": cfg.GolangciLint.ReviveRules,
"WithControllerGen": cfg.ControllerGen.Enabled.UnwrapOr(sr.KubernetesController),
}))
}
17 changes: 15 additions & 2 deletions internal/makefile/makefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ endif
prepareStaticRecipe = append(prepareStaticRecipe, "install-goimports", "install-golangci-lint")
}

if cfg.ShellCheck.Enabled.UnwrapOr(true) {
if cfg.ShellCheck.IsEnabled() {
prepare.addRule(rule{
description: "Install shellcheck required by run-shellcheck/static-check",
phony: true,
Expand Down Expand Up @@ -348,7 +348,7 @@ endif
},
})

if cfg.ShellCheck.Enabled.UnwrapOr(true) {
if cfg.ShellCheck.IsEnabled() {
// add target to run shellcheck
var ignorePathArgs strings.Builder
for _, path := range cfg.ShellCheck.AllIgnorePaths(cfg.Golang) {
Expand All @@ -375,6 +375,19 @@ endif
})
}

if cfg.Typos.IsEnabled() {
test.addRule(rule{
description: "Check for spelling errors using typos.",
phony: true,
target: "run-typos",
recipe: []string{
`@printf "\e[1;36m>> typos\e[0m\n"`,
`@printf "\e[1;36m>> Typos install instructions can be found here https://github.com/crate-ci/typos#install \e[0m\n"`,
`@typos`,
},
})
}

// add targets for test runner incl. coverage report
testRule := rule{
description: "Run tests and generate coverage report.",
Expand Down
5 changes: 4 additions & 1 deletion internal/nix/nix-shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,12 @@ func RenderShell(cfg core.Configuration, sr golang.ScanResult, renderGoreleaserC
if cfg.Renovate.Enabled {
packages = append(packages, "renovate")
}
if cfg.Reuse.Enabled.UnwrapOr(true) {
if cfg.Reuse.IsEnabled() {
packages = append(packages, "reuse")
}
if cfg.Typos.IsEnabled() {
packages = append(packages, "typos")
}
packages = append(packages, cfg.Nix.ExtraPackages...)

slices.Sort(packages)
Expand Down
31 changes: 31 additions & 0 deletions internal/typos/typos.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company
// SPDX-License-Identifier: Apache-2.0

package typos

import (
_ "embed"

"github.com/sapcc/go-bits/must"

"github.com/sapcc/go-makefile-maker/internal/core"
"github.com/sapcc/go-makefile-maker/internal/util"
)

var (
//go:embed typos.toml.tmpl
typosConfigTemplate string
)

func RenderConfig(cfg core.Configuration) {
extendExcludes := []string{"go.mod"}
if cfg.Golang.EnableVendoring {
extendExcludes = append(extendExcludes, "vendor/")
}
extendExcludes = append(extendExcludes, cfg.Typos.ExtendExcludes...)

must.Succeed(util.WriteFileFromTemplate(".typos.toml", typosConfigTemplate, map[string]any{
"ExtendExcludes": extendExcludes,
"ExtendWords": cfg.Typos.ExtendWords,
}))
}
13 changes: 13 additions & 0 deletions internal/typos/typos.toml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: 2025 SAP SE
#
# SPDX-License-Identifier: Apache-2.0

[default.extend-words]
{{ range $key, $value := .ExtendWords -}}
{{$key}} = "{{$value}}"
{{ end }}
[files]
extend-exclude = [
{{- range .ExtendExcludes}}
"{{.}}",{{ end }}
]
Loading