Presentation slides and material for talk presented at Gophercon India 2024.
Ideally the slides should have been accessible at https://go-talks.appspot.com/github.com/sudo-suhas/operationalising-golangci-lint-v2/2024-12-gophercon-india.slide. However, due to golang/go#58906, the functionality is currently broken.
As an alternative, the slides have been hosted via Google App Engine and can be accessed here.
golangci-lint-linters-v1.61.0 sheet
This sheet helps to manage the configuration for golangci-lint. It can also help with generating
the 2 configuration files.
v1.61.0 of golangci-lint.
This sheet lists the linters that were available in version v1.61.0 with the following columns:
- Linter: The name of the linter with a link to the source or website for it. If applicable, there is also a link to the golangci-lintβs documentation for configuring the linter. For example, https://staticcheck.io/ and https://golangci-lint.run/usage/linters/#staticcheck.
- Description: A short description of the linter.
- Status: This field indicates whether the linter is enabled or disabled.
- Comments: Self explanatory. The comments try to justify why a particular linter is enabled or disabled.
- Settings: If the linter is enabled, the value in this field is used to configure the linter.
The settings are in TOML format. These settings are hand-coded with 2 exceptions. In case of
gocriticandrevive, the settings are generated from their respective sheets (explained below).
This sheet lists the checks that were available in version v0.11.5 of gocritic that was packaged
into golangci-lint@v1.61.0. The sheet is similar to the available-linters sheet and is used to
manage the 100+ checks provided by gocritic. The checks that are enabled along with their optional
settings are used to build the complete settings for gocritic in golangci-lintβs configuration.
π The function BUILD_GOCRITIC_SETTINGS is defined in the Apps Script project
linked to the sheet.
This sheet lists the checks that were available in version v1.4.0 of revive that was packaged
into golangci-lint@v1.61.0. The sheet is similar to the available-linters sheet and is used to
manage the 77 checks provided by revive. The checks that are enabled along with their optional
settings are used to build the complete settings for revive in golangci-lintβs configuration.
π The function BUILD_REVIVE_SETTINGS is defined in the Apps Script project
linked to the sheet.
This has the static header and footer for the generation of golangci-lint configuration.
This has the configuration for golangci-lint generated by stitching together the following:
- Header from the
sectionssheet. - Linters enabled in the
available-linterssheet. - Linter settings for enabled linters in
available-linterssheet. - Footer from the
sectionssheet.
The configuration is updated in a few seconds whenever any change is made in the sheet by the Apps Script project linked to the sheet.
"" with " and remove the quotes at the beginning and the end.
One way to use the sheet is to copy the generated configuration and modify as needed. However, if you want to be able to edit the sheet and regenerate the configuration, follow the instructions below.
Step by step instructions
Make a copy of the sheet. This will copy over the apps script project as well:
Open the apps script project via "Extensions > Apps Script". Open the triggers tab and create a new trigger with the following settings:
When you click "Save" it will ask you to authorise the apps script. This isn't an app verified by Google so you will need to click "Advanced" and click "Go to golangci-lint-linters-v1.61.0 (v2) ( unsafe)"
Finally click "Allow" to complete setting up the trigger. Now, whenever any cell in the sheet is
edited the configuration in .golangci.toml will be rebuilt.
YAML: probably not so great after all
When we are creating a new project, it is straightforward to integrate golangci-lint into it.
However, if we are integrating golangci-lint into a pre-existing project where either the linter
was not integrated or the configuration was minimal, we need a strategy to iteratively fix the large
number of issues that would be reported by the linter with the new/updated configuration. Fixing all
the issues in a single effort can be inhibitively expensive. golangci-lint provides a mechanism
for doing so by reporting issues only for new and modified lines in the commit.
See golangci-lint FAQ.
Most repositories utilise multiple tools for formatting, code/doc generation and testing. Some examples:
golangci-lint: github.com/golangci/golangci-lintgofumpt: github.com/mvdan/gofumptmockery: github.com/vektra/mockery
The version of these tools needs to be kept consistent between local and CI. Sometimes the version of these tools are different across projects and different developers might have different local versions of these tools.
We can leverage Go modules to manage the necessary tooling by doing the following:
- Add a
go.modfile undertoolsdirectory:go mod init github.com/netskope/spm-{{repo}}/tools - Add a
tools.gofile in the same folder with a build constraint so that it does not get included in the build://go:build tools package tools import ( _ "github.com/golangci/golangci-lint/cmd/golangci-lint" // add more imports as needed )
- Run
go mod tidyto sync thetools/go.modwith the tools that are declared intools.go.
Using the tools/go.mod, we can build the tool binaries. Task can be used for building the
binaries on demand and for managing the commonly used commands. Taskfile is a more modern
replacement for Makefiles and also has features for re-building the tools based on checksum of
module files. Taskfile example: Taskfile.yml
Developer workflow (with Task)
To install task on macOS with Homebrew, following command needs to be executed:
brew install go-task
For other operating systems please refer task installation page.
Users can install and cache tools locally for formatting, linter checks etc. by using the below command:
task install-tools
User can run task --list to list all configured commands for the current repository.
Formatting issues can be reported by github.com/mvdan/gofumpt
and github.com/daixiang0/gci. We just need to run task fmt to fix all formatting issues.
It is also possible to only fix the order of import statements by running task imports.
β task fmt
task: Task "install-gci" is up to date
task: Task "install-gofumpt" is up to date
task: [imports] .tools/gci write ./ --section standard --section default --section "Prefix(github.com/netskope,github.com/netSkope)" --skip-generated --skip-vendor
task: [fmt] .tools/gofumpt -l -w -extra .
By integrating the tools to the IDE, we can enable format on save so that files are always formatted correctly.
- Install the Go Linter plugin for GoLand.
- Under Tools | Go Linter, For the "Path to golangci-lint", select the
golangci-lintbinary present in the.toolsdirectory inside the project (runtask install-toolsif binary is not present under.tools).
Go Linter should automatically pick .golangci.toml as the configuration file. It is recommended to
use this with the IDE plugin to avoid running some of the heavy linters like unused during
development. task lint can be used to lint the source files against .golangci-prod.toml.
- Open IDE preferences with
β+,. - Navigate to the 'File Watchers' settings: Tools | File Watchers.
- Click the 'Import' icon (import icon) and select the file
.idea/watchers-cfg.xml. To show hidden folders in the Finder app on macOS, pressβ+β§+..
These file watchers will run gci and gofumpt for updating import lines and formatting the code
idiomatically on saving the file.
- Under Code Style | Go:
- Select the "Imports" tab and set "Sorting type" to "None".
- Under the "Other" tab:
- Deselect "On Reformat Code action"
- Select "Add a leading space to comments". under "Except for comments starting with:" add
nolintandgo:. - Under Tools | Actions on Save, deselect "Reformat Code".
False positives are inevitable but golangci-lint provides flexible mechanisms for working around
false positives. We can either use //nolint directives to ignore a specific error or we can update
the .golangci-lint*.toml and add an exclude-rule.
See https://golangci-lint.run/usage/false-positives/ for more details.
When adding or updating exclude-rules, remember to update both .golangci.toml and
.golangci-prod.toml.