Skip to content

Commit b9c1cc2

Browse files
hanzeiclaude
andauthored
Update build tooling from starter template and fix linter issues (#964)
* Update build tooling from starter template and fix linter issues - Update Go version from 1.24.6 to 1.24.11 - Update golangci-lint to v2.8.0 with new config format - Update gotestsum to v1.13.0 - Update Node.js version from 16.13.1 to 20.11 - Add manifest-check target to Makefile - Use Go 1.24 features (strings.SplitSeq, slices.Contains) - Replace interface{} with any throughout codebase - Replace custom contains functions with slices.Contains - Convert if-else chains to tagged switches - Simplify embedded field selectors (c.Context.Ctx → c.Ctx) - Use strings.Builder for efficient string concatenation - Apply De Morgan's law simplifications - Fix directory permissions (0755 → 0750) - Add license headers to build files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Restore omitempty on DefaultRepo field Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Use omitzero instead of omitempty for DefaultRepo struct field omitempty has no effect on non-pointer struct fields in JSON encoding. Go 1.24's omitzero correctly omits the field when the struct is its zero value. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Update Go to 1.25, golangci-lint to 2.9, and remove golang-version from CI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Use WaitGroup.Go to simplify goroutine creation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 017064c commit b9c1cc2

32 files changed

+344
-565
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ indent_size = 4
1818
[webapp/package.json]
1919
indent_size = 2
2020

21-
[Makefile,*.mk]
21+
[{Makefile,*.mk}]
2222
indent_style = tab
2323

2424
[*.md]

.github/workflows/ci.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,3 @@ jobs:
1717
plugin-ci:
1818
uses: mattermost/actions-workflows/.github/workflows/plugin-ci.yml@main
1919
secrets: inherit
20-
with:
21-
golang-version: "1.24.6"

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
node_modules
21
bin/
32
dist/
43
webapp/src/manifest.ts

.golangci.yml

Lines changed: 35 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,62 @@
1-
version: 2
1+
version: "2"
22

33
run:
44
timeout: 5m
55
modules-download-mode: readonly
66

7-
linters-settings:
8-
goconst:
9-
min-len: 3
10-
min-occurrences: 2
11-
gofmt:
12-
simplify: true
13-
goimports:
14-
local-prefixes: github.com/mattermost/mattermost-plugin-github
15-
govet:
16-
enable-all: true
17-
disable:
18-
- fieldalignment
19-
misspell:
20-
locale: US
21-
revive:
22-
237
linters:
24-
disable-all: true
8+
default: none
259
enable:
10+
- bidichk
2611
- bodyclose
2712
- errcheck
2813
- gocritic
2914
- gosec
3015
- govet
3116
- ineffassign
17+
- makezero
3218
- misspell
19+
- modernize
3320
- nakedret
3421
- revive
3522
- staticcheck
3623
- unconvert
24+
- unqueryvet
3725
- unused
3826
- whitespace
27+
settings:
28+
govet:
29+
enable-all: true
30+
disable:
31+
- fieldalignment
32+
revive:
33+
rules:
34+
- name: exported
35+
disabled: true
36+
- name: unused-parameter
37+
disabled: true
38+
unqueryvet:
39+
check-sql-builders: true
3940
exclusions:
4041
rules:
41-
- linters:
42-
- revive
43-
text: var-naming|error-naming|exported|increment-decrement|error-strings|if-return|unused-parameter|blank-imports|empty-block|package-comments
44-
- linters:
45-
- errcheck
46-
text: Error return value
47-
- linters:
48-
- staticcheck
49-
text: SA1019
50-
- linters:
51-
- staticcheck
52-
text: ST1023
53-
- linters:
54-
- staticcheck
55-
text: ST1012
56-
- linters:
57-
- staticcheck
58-
text: ST1005
59-
- linters:
60-
- staticcheck
61-
text: QF1011
62-
- linters:
63-
- staticcheck
64-
text: QF1001
65-
- linters:
66-
- staticcheck
67-
text: QF1003
68-
- linters:
69-
- staticcheck
70-
text: QF1012
71-
- linters:
72-
- staticcheck
73-
text: QT1019
74-
- linters:
75-
- staticcheck
76-
text: QF1008
77-
- linters:
78-
- staticcheck
79-
text: QF1004
80-
- linters:
81-
- staticcheck
82-
text: ST1019
83-
- linters:
84-
- staticcheck
85-
text: QF1006
86-
- linters:
87-
- staticcheck
88-
text: QF1002
89-
- linters:
90-
- staticcheck
91-
text: QF1007
92-
- linters:
93-
- gosec
94-
text: G104
95-
- linters:
96-
- gosec
97-
text: G304
98-
- linters:
99-
- gosec
100-
text: G301
42+
- path: server/configuration.go
43+
linters:
44+
- unused
45+
- path: _test\.go
46+
linters:
47+
- bodyclose
10148

10249
formatters:
103-
disable-all: true
10450
enable:
10551
- gofmt
52+
- gofumpt
10653
- goimports
107-
108-
issues:
109-
exclude-rules:
110-
- path: server/manifest.go
111-
linters:
112-
- deadcode
113-
- unused
114-
- varcheck
115-
- path: server/configuration.go
116-
linters:
117-
- unused
118-
- path: _test\.go
119-
linters:
120-
- bodyclose
121-
- goconst
122-
- scopelint # https://github.com/kyoh86/scopelint/issues/4
54+
settings:
55+
gofmt:
56+
simplify: true
57+
rewrite-rules:
58+
- pattern: interface{}
59+
replacement: any
60+
goimports:
61+
local-prefixes:
62+
- github.com/mattermost/mattermost-plugin-github

Makefile

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ major-rc: ## to bump major release candidate version (semver)
170170
.PHONY: all
171171
all: check-style test dist
172172

173+
## Ensures the plugin manifest is valid
174+
.PHONY: manifest-check
175+
manifest-check:
176+
./build/bin/manifest check
177+
173178
## Propagates plugin manifest information into the server/ and webapp/ folders.
174179
.PHONY: apply
175180
apply:
@@ -178,13 +183,14 @@ apply:
178183
## Install go tools
179184
install-go-tools:
180185
@echo Installing go tools
181-
$(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.6.0
182-
$(GO) install gotest.tools/gotestsum@v1.7.0
186+
$(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.9.0
187+
$(GO) install gotest.tools/gotestsum@v1.13.0
188+
183189
$(GO) install github.com/mattermost/mattermost-govet/v2@7d8db289e508999dfcac47b97c9490a0fec12d66
184190

185191
## Runs eslint and golangci-lint
186192
.PHONY: check-style
187-
check-style: apply webapp/node_modules install-go-tools
193+
check-style: manifest-check apply webapp/node_modules install-go-tools
188194
@echo Checking for style guide compliance
189195

190196
ifneq ($(HAS_WEBAPP),)
@@ -362,7 +368,7 @@ endif
362368
.PHONY: coverage
363369
coverage: apply webapp/node_modules
364370
ifneq ($(HAS_SERVER),)
365-
$(GO) test $(GO_TEST_FLAGS) -coverprofile=server/coverage.txt ./...
371+
$(GO) test $(GO_TEST_FLAGS) -coverprofile=server/coverage.txt ./server/...
366372
$(GO) tool cover -html=server/coverage.txt
367373
endif
368374

build/manifest/main.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ import (
1010
"os"
1111
"strings"
1212

13-
"github.com/pkg/errors"
14-
1513
"github.com/mattermost/mattermost/server/public/model"
14+
"github.com/pkg/errors"
1615
)
1716

1817
const pluginIDGoFileTemplate = `// This file is automatically generated. Do not modify it manually.
@@ -91,6 +90,11 @@ func main() {
9190
panic("failed to write manifest to dist directory: " + err.Error())
9291
}
9392

93+
case "check":
94+
if err := manifest.IsValid(); err != nil {
95+
panic("failed to check manifest: " + err.Error())
96+
}
97+
9498
default:
9599
panic("unrecognized command: " + cmd)
96100
}
@@ -101,11 +105,11 @@ func findManifest() (*model.Manifest, error) {
101105
if err != nil {
102106
return nil, errors.Wrap(err, "failed to find manifest in current working directory")
103107
}
104-
manifestFile, err := os.Open(manifestFilePath)
108+
manifestFile, err := os.Open(manifestFilePath) //nolint:gosec
105109
if err != nil {
106110
return nil, errors.Wrapf(err, "failed to open %s", manifestFilePath)
107111
}
108-
defer manifestFile.Close()
112+
defer func() { _ = manifestFile.Close() }()
109113

110114
// Re-decode the manifest, disallowing unknown fields. When we write the manifest back out,
111115
// we don't want to accidentally clobber anything we won't preserve.
@@ -120,8 +124,8 @@ func findManifest() (*model.Manifest, error) {
120124
// commit, and use the first version we find (to prevent causing errors)
121125
if manifest.Version == "" {
122126
var version string
123-
tags := strings.Fields(BuildTagCurrent)
124-
for _, t := range tags {
127+
tags := strings.FieldsSeq(BuildTagCurrent)
128+
for t := range tags {
125129
if strings.HasPrefix(t, "v") {
126130
version = t
127131
break
@@ -139,10 +143,11 @@ func findManifest() (*model.Manifest, error) {
139143

140144
// If no release notes specified, generate one from the latest tag, if present.
141145
if manifest.ReleaseNotesURL == "" && BuildTagLatest != "" {
142-
manifest.ReleaseNotesURL, err = url.JoinPath(manifest.HomepageURL, "releases", "tag", BuildTagLatest)
146+
releaseNotesURL, err := url.JoinPath(manifest.HomepageURL, "releases", "tag", BuildTagLatest)
143147
if err != nil {
144-
return nil, errors.Wrap(err, "failed to generate release notes URL")
148+
return nil, errors.Wrap(err, "failed to build release notes URL")
145149
}
150+
manifest.ReleaseNotesURL = releaseNotesURL
146151
}
147152

148153
return &manifest, nil
@@ -171,8 +176,8 @@ func applyManifest(manifest *model.Manifest) error {
171176
// write generated code to file by using Go file template.
172177
if err := os.WriteFile(
173178
"server/plugin/manifest.go",
174-
[]byte(fmt.Sprintf(pluginIDGoFileTemplate, manifestStr)),
175-
0600,
179+
fmt.Appendf(nil, pluginIDGoFileTemplate, manifestStr),
180+
0o600,
176181
); err != nil {
177182
return errors.Wrap(err, "failed to write server/plugin/manifest.go")
178183
}
@@ -194,8 +199,8 @@ func applyManifest(manifest *model.Manifest) error {
194199
// write generated code to file by using JS file template.
195200
if err := os.WriteFile(
196201
"webapp/src/manifest.ts",
197-
[]byte(fmt.Sprintf(pluginIDJSFileTemplate, manifestStr)),
198-
0600,
202+
fmt.Appendf(nil, pluginIDJSFileTemplate, manifestStr),
203+
0o600,
199204
); err != nil {
200205
return errors.Wrap(err, "failed to open webapp/src/manifest.ts")
201206
}
@@ -211,7 +216,7 @@ func distManifest(manifest *model.Manifest) error {
211216
return err
212217
}
213218

214-
if err := os.WriteFile(fmt.Sprintf("dist/%s/plugin.json", manifest.Id), manifestBytes, 0600); err != nil {
219+
if err := os.WriteFile(fmt.Sprintf("dist/%s/plugin.json", manifest.Id), manifestBytes, 0o600); err != nil {
215220
return errors.Wrap(err, "failed to write plugin.json")
216221
}
217222

build/pluginctl/logs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func checkJSONLogsSetting(ctx context.Context, client *model.Client4) error {
181181
return fmt.Errorf("failed to fetch config: %w", err)
182182
}
183183
if cfg.LogSettings.FileJson == nil || !*cfg.LogSettings.FileJson {
184-
return errors.New("JSON output for file logs are disabled. Please enable LogSettings.FileJson via the configuration in Mattermost.") //nolint:revive,stylecheck
184+
return errors.New("JSON output for file logs is disabled, please enable LogSettings.FileJson via the configuration in Mattermost")
185185
}
186186

187187
return nil

build/pluginctl/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,11 @@ func getUnixClient(socketPath string) (*model.Client4, bool) {
128128
// deploy attempts to upload and enable a plugin via the Client4 API.
129129
// It will fail if plugin uploads are disabled.
130130
func deploy(ctx context.Context, client *model.Client4, pluginID, bundlePath string) error {
131-
pluginBundle, err := os.Open(bundlePath)
131+
pluginBundle, err := os.Open(bundlePath) //nolint:gosec
132132
if err != nil {
133133
return fmt.Errorf("failed to open %s: %w", bundlePath, err)
134134
}
135-
defer pluginBundle.Close()
135+
defer func() { _ = pluginBundle.Close() }()
136136

137137
log.Print("Uploading plugin via API.")
138138
_, _, err = client.UploadPluginForced(ctx, pluginBundle)

build/setup.mk

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
GO_BUILD_FLAGS ?=
2-
31
# Ensure that go is installed. Note that this is independent of whether or not a server is being
42
# built, since the build script itself uses go.
53
ifeq ($(GO),)

client/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func (c *Client) GetConfiguration() (*plugin.Configuration, error) {
7474
if err != nil {
7575
return nil, err
7676
}
77-
defer resp.Body.Close()
77+
defer func() { _ = resp.Body.Close() }()
7878

7979
respBody, err := io.ReadAll(resp.Body)
8080
if err != nil {
@@ -111,7 +111,7 @@ func (c *Client) GetToken(userID string) (*oauth2.Token, error) {
111111
if err != nil {
112112
return nil, err
113113
}
114-
defer resp.Body.Close()
114+
defer func() { _ = resp.Body.Close() }()
115115

116116
respBody, err := io.ReadAll(resp.Body)
117117
if err != nil {

0 commit comments

Comments
 (0)