Skip to content

Commit 9ba00d7

Browse files
committed
chore: harden linting, add golangci-lint, bump to v0.4.13
- Promote ESLint no-explicit-any and no-unused-vars from warn to error - Add no-console rule (allow warn/error) - Remove dead no-require-imports override - Fix all ESLint violations (type-safe casts, useMemo stabilization, ref cleanup pattern, proper component prop types) - Add .golangci.yml (v2) with bug detection, style, and test linters - Fix errcheck (fmt.Fprintln) and capitalized error strings - Run gofmt on all Go files - Add go vet, gofmt check, and golangci-lint to CI pipeline - Expand Go test scope to ./... - Add lint/lint-fix recipes to Justfile, update check recipe - Bump version to 0.4.13
1 parent 64b5ec8 commit 9ba00d7

35 files changed

+210
-134
lines changed

.github/workflows/ci.yml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,23 @@ jobs:
4444
working-directory: applets
4545
run: go mod download
4646

47+
- name: Go vet
48+
working-directory: applets
49+
run: go vet ./...
50+
51+
- name: Go format check
52+
working-directory: applets
53+
run: gofmt -l . | tee /tmp/gofmt.out && test ! -s /tmp/gofmt.out
54+
55+
- name: golangci-lint
56+
uses: golangci/golangci-lint-action@v7
57+
with:
58+
version: v2.8.0
59+
working-directory: applets
60+
4761
- name: Run Go tests
4862
working-directory: applets
49-
run: go test ./internal/... ./cmd/... -count=1
63+
run: go test ./... -count=1
5064

5165
- name: Install JS dependencies
5266
working-directory: applets

.golangci.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
version: "2"
2+
3+
linters:
4+
enable:
5+
# Bug detection
6+
- errcheck
7+
- govet
8+
- staticcheck
9+
- ineffassign
10+
- unused
11+
- bodyclose
12+
- nilerr
13+
- noctx
14+
- durationcheck
15+
- errchkjson
16+
- makezero
17+
# Style (library-appropriate)
18+
- asciicheck
19+
- bidichk
20+
- copyloopvar
21+
- errname
22+
- misspell
23+
- nakedret
24+
- nolintlint
25+
- unconvert
26+
- usestdlibvars
27+
- wastedassign
28+
- whitespace
29+
# Testing
30+
- testifylint
31+
- thelper
32+
33+
run:
34+
exclude-dirs:
35+
- tmp
36+
- node_modules
37+
- dist

Justfile

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ vet:
1414
fmt:
1515
go fmt ./...
1616

17+
# Run golangci-lint
18+
lint:
19+
golangci-lint run ./...
20+
21+
# Run golangci-lint with auto-fix
22+
lint-fix:
23+
golangci-lint run --fix ./...
24+
1725
# Build the npm package
1826
build-npm:
1927
cd ui && pnpm build
@@ -30,8 +38,8 @@ watch-npm:
3038
lint-npm:
3139
cd ui && pnpm lint
3240

33-
# Run all checks (vet + test)
34-
check: vet test
41+
# Run all checks (vet + lint + test)
42+
check: vet lint test
3543

3644
# Clean build artifacts
3745
clean:

constructors.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import (
66
"github.com/iota-uz/applets/internal/context"
77
"github.com/iota-uz/applets/internal/controller"
88
"github.com/iota-uz/applets/internal/registry"
9-
"github.com/iota-uz/applets/internal/rpc"
109
"github.com/iota-uz/applets/internal/router"
10+
"github.com/iota-uz/applets/internal/rpc"
1111
"github.com/iota-uz/applets/internal/stream"
1212
"github.com/iota-uz/go-i18n/v2/i18n"
1313
"github.com/sirupsen/logrus"

eslint.config.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,15 @@ export default [
4242
'react/react-in-jsx-scope': 'off',
4343
'react/prop-types': 'off',
4444
'react/no-unescaped-entities': ['error', { forbid: ['>', '}'] }],
45-
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
46-
'@typescript-eslint/no-explicit-any': 'warn',
47-
'@typescript-eslint/no-require-imports': 'off',
45+
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
46+
'@typescript-eslint/no-explicit-any': 'error',
47+
'no-console': ['error', { allow: ['warn', 'error'] }],
48+
},
49+
},
50+
{
51+
files: ['ui/.storybook/**/*.ts', 'ui/.storybook/**/*.tsx'],
52+
rules: {
53+
'no-console': 'off',
4854
},
4955
},
5056
{
@@ -63,7 +69,9 @@ export default [
6369
...reactHooks.configs.recommended.rules,
6470
'react/react-in-jsx-scope': 'off',
6571
'react/prop-types': 'off',
66-
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
72+
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
73+
'@typescript-eslint/no-explicit-any': 'error',
74+
'no-console': ['error', { allow: ['warn', 'error'] }],
6775
},
6876
},
6977
];

internal/api/context_types.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import (
77

88
// InitialContext is serialized and injected into the frontend (e.g. window.__APPLET_CONTEXT__).
99
type InitialContext struct {
10-
User UserContext `json:"user"`
11-
Tenant TenantContext `json:"tenant"`
12-
Locale LocaleContext `json:"locale"`
13-
Config AppConfig `json:"config"`
14-
Route RouteContext `json:"route"`
15-
Session SessionContext `json:"session"`
16-
Error *ErrorContext `json:"error,omitempty"`
10+
User UserContext `json:"user"`
11+
Tenant TenantContext `json:"tenant"`
12+
Locale LocaleContext `json:"locale"`
13+
Config AppConfig `json:"config"`
14+
Route RouteContext `json:"route"`
15+
Session SessionContext `json:"session"`
16+
Error *ErrorContext `json:"error,omitempty"`
1717
Extensions map[string]interface{} `json:"extensions,omitempty"`
1818
}
1919

internal/api/types.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,16 @@ type I18nConfig struct {
5252
// Config holds all configuration for integrating an applet with the host.
5353
type Config struct {
5454
WindowGlobal string
55-
Endpoints EndpointConfig
56-
Assets AssetConfig
57-
Shell ShellConfig
58-
Router AppletRouter
59-
I18n I18nConfig
55+
Endpoints EndpointConfig
56+
Assets AssetConfig
57+
Shell ShellConfig
58+
Router AppletRouter
59+
I18n I18nConfig
6060
RoutePatterns []string
6161
CustomContext ContextExtender
62-
Middleware []mux.MiddlewareFunc
63-
Mount MountConfig
64-
RPC *RPCConfig
62+
Middleware []mux.MiddlewareFunc
63+
Mount MountConfig
64+
RPC *RPCConfig
6565
}
6666

6767
// LayoutFactory produces a layout component for an applet request.

internal/cli/check.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func runCheck(cmd *cobra.Command, _ []string) error {
4040
if found && len(violations) > 0 {
4141
stderr := cmd.ErrOrStderr()
4242
for _, v := range violations {
43-
fmt.Fprintln(stderr, v)
43+
_, _ = fmt.Fprintln(stderr, v)
4444
}
4545
failed = true
4646
}

internal/cli/deps.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,18 @@ import (
1212
// NewDepsCommand returns the deps command with check subcommand.
1313
func NewDepsCommand() *cobra.Command {
1414
depsCmd := &cobra.Command{
15-
Use: "deps",
16-
Short: "Applet dependency checks",
17-
Long: `Validate applet SDK dependency policy (e.g. exact version pinning, no local links).`,
15+
Use: "deps",
16+
Short: "Applet dependency checks",
17+
Long: `Validate applet SDK dependency policy (e.g. exact version pinning, no local links).`,
1818
Example: ` applet deps check`,
1919
}
2020

2121
checkCmd := &cobra.Command{
22-
Use: "check",
23-
Short: "Check applet SDK dependency policy",
24-
Long: `Scans modules/*/presentation/web/package.json for @iota-uz/sdk and ensures exact version pinning with no file/link/workspace specifiers.`,
22+
Use: "check",
23+
Short: "Check applet SDK dependency policy",
24+
Long: `Scans modules/*/presentation/web/package.json for @iota-uz/sdk and ensures exact version pinning with no file/link/workspace specifiers.`,
2525
Example: ` applet deps check`,
26-
RunE: runDepsCheck,
26+
RunE: runDepsCheck,
2727
}
2828
depsCmd.AddCommand(checkCmd)
2929

internal/cli/rpc.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import (
66

77
"github.com/spf13/cobra"
88

9-
"github.com/iota-uz/applets/internal/config"
109
"github.com/iota-uz/applets/internal/applet/rpccodegen"
10+
"github.com/iota-uz/applets/internal/config"
1111
)
1212

1313
// NewRPCCommand returns the `applet rpc` subcommand (gen, check, etc.).
@@ -25,9 +25,9 @@ func NewRPCCommand() *cobra.Command {
2525
func NewRPCCheckCommand() *cobra.Command {
2626
var name string
2727
cmd := &cobra.Command{
28-
Use: "check",
29-
Short: "Verify RPC contract is up to date for an applet",
30-
Long: `Exits with an error if the on-disk rpc.generated.ts does not match what would be generated from the Go router. Use "applet rpc gen --name <name>" to fix.`,
28+
Use: "check",
29+
Short: "Verify RPC contract is up to date for an applet",
30+
Long: `Exits with an error if the on-disk rpc.generated.ts does not match what would be generated from the Go router. Use "applet rpc gen --name <name>" to fix.`,
3131
Example: ` applet rpc check --name bichat`,
3232
Args: cobra.NoArgs,
3333
RunE: func(cmd *cobra.Command, _ []string) error {
@@ -63,9 +63,9 @@ func NewRPCCheckCommand() *cobra.Command {
6363
func NewRPCGenCommand() *cobra.Command {
6464
var name string
6565
cmd := &cobra.Command{
66-
Use: "gen",
67-
Short: "Generate RPC contract TypeScript from Go router",
68-
Long: `Generates rpc.generated.ts for the given applet. Requires --name.`,
66+
Use: "gen",
67+
Short: "Generate RPC contract TypeScript from Go router",
68+
Long: `Generates rpc.generated.ts for the given applet. Requires --name.`,
6969
Example: ` applet rpc gen --name bichat`,
7070
Args: cobra.NoArgs,
7171
RunE: func(cmd *cobra.Command, _ []string) error {

0 commit comments

Comments
 (0)