|
| 1 | +# AR Golang CI Lints |
| 2 | + |
| 3 | +Custom Go linters used on Wormhole CI. Each linter is a [golangci-lint |
| 4 | +module plugin](https://golangci-lint.run/plugins/module-plugins/) and lives |
| 5 | +as its own Go module under `rules/<linter>/`. |
| 6 | + |
| 7 | +Prefer to use the `release` builds. |
| 8 | + |
| 9 | +Currently supported linters: |
| 10 | + |
| 11 | +| Name | Purpose | Features | |
| 12 | +| -------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | |
| 13 | +| `channelcheck` | Flag channel usage patterns that can deadlock or block. | • Blocking channel sends outside a `select`<br>• Unbuffered channel creation (`make(chan T)`)<br>• Ignore specific channels | |
| 14 | + |
| 15 | + |
| 16 | +## Build & test |
| 17 | +``` |
| 18 | +make build # bin/wormhole-lint |
| 19 | +make build-golangci-lint # bin/wormhole-golangci-lint |
| 20 | +make test # root + each rules/<linter> module |
| 21 | +``` |
| 22 | + |
| 23 | +`make build-golangci-lint` first installs the pinned upstream |
| 24 | +`golangci-lint` into `bin/` (per `GOLANGCI_LINT_VERSION`), then runs |
| 25 | +`golangci-lint custom`. |
| 26 | + |
| 27 | +## Use |
| 28 | + |
| 29 | +Standalone: |
| 30 | + |
| 31 | +``` |
| 32 | +bin/wormhole-lint ./... |
| 33 | +``` |
| 34 | + |
| 35 | +Via the custom golangci-lint: |
| 36 | + |
| 37 | +``` |
| 38 | +bin/wormhole-golangci-lint run --timeout=10m ./... |
| 39 | +``` |
| 40 | + |
| 41 | +## Enable a plugin in `.golangci.yml` |
| 42 | + |
| 43 | +Module plugins are addressed under `linters.settings.custom.<name>` and |
| 44 | +enabled in `linters.enable` by the plugin's registered name. Example for |
| 45 | +`channelcheck`: |
| 46 | + |
| 47 | +```yaml |
| 48 | +version: "2" |
| 49 | +linters: |
| 50 | + enable: |
| 51 | + - channelcheck |
| 52 | + settings: |
| 53 | + custom: |
| 54 | + channelcheck: |
| 55 | + type: module |
| 56 | + description: reports channel blocking issues |
| 57 | + settings: |
| 58 | + blocking: true |
| 59 | + unbuffered: false |
| 60 | + bufferMax: 0 |
| 61 | + ignoreChannelsByName: [errC] |
| 62 | +``` |
| 63 | +
|
| 64 | +## Development |
| 65 | +
|
| 66 | +### Adding a new linter |
| 67 | +
|
| 68 | +1. Scaffold the module: |
| 69 | + ``` |
| 70 | + mkdir -p rules/<linter> && cd rules/<linter> |
| 71 | + go mod init github.com/certusone/wormhole/linters/rules/<linter> |
| 72 | + ``` |
| 73 | +2. Implement `<linter>.go` following the channelcheck reference |
| 74 | + (`rules/channelcheck/channelcheck.go`): |
| 75 | + - Export an `Analyzer` of type `*analysis.Analyzer`. |
| 76 | + - Define a `Settings` struct and a `New(any) (register.LinterPlugin, error)` |
| 77 | + constructor that decodes settings via |
| 78 | + `register.DecodeSettings[Settings]`. |
| 79 | + - Implement `BuildAnalyzers()` and `GetLoadMode()` on your plugin type. |
| 80 | + - In `init()`, call `register.Plugin("<name>", New)` so |
| 81 | + `golangci-lint custom` picks it up. |
| 82 | +3. Add tests + fixtures under `rules/<linter>/testdata/` following |
| 83 | + `rules/channelcheck/channelcheck_test.go`. |
| 84 | +4. Wire it into the root module so the aggregator can import it: |
| 85 | + - In root `go.mod`, add |
| 86 | + `require github.com/certusone/wormhole/linters/rules/<linter> v0.0.0` and |
| 87 | + `replace github.com/certusone/wormhole/linters/rules/<linter> => ./rules/<linter>`. |
| 88 | + - In `cmd/wormhole-lint/main.go`, add the import and append |
| 89 | + `<linter>.Analyzer` to the `multichecker.Main` call. |
| 90 | +5. Wire it into `.custom-gcl.yml` so the custom golangci-lint picks it up: |
| 91 | + ```yaml |
| 92 | + plugins: |
| 93 | + - module: github.com/certusone/wormhole/linters/rules/<linter> |
| 94 | + path: ./rules/<linter> |
| 95 | + ``` |
| 96 | +6. `make test && make build && make build-golangci-lint` to verify. |
| 97 | + |
| 98 | +### Layout |
| 99 | + |
| 100 | +``` |
| 101 | +.custom-gcl.yml # plugin manifest for `golangci-lint custom` |
| 102 | +Makefile |
| 103 | +go.mod # root module: cmd/* + replaces for each rules/<linter> |
| 104 | +cmd/ |
| 105 | + wormhole-lint/ # multichecker aggregator binary |
| 106 | +rules/ |
| 107 | + channelcheck/ # standalone Go module per linter |
| 108 | + channelcheck.go |
| 109 | + channelcheck_test.go |
| 110 | + go.mod |
| 111 | + testdata/ |
| 112 | +``` |
0 commit comments