feat: migrate golangci-lint from v1 to v2 (#144)
Migrate golangci-lint from v1 to v2. ## Motivation and Context The golangci-lint has been upgraded to v2 since March 2025. The v2 of golangci-lint has simplified the linters management. ## How Has This Been Tested? Tested locally with golangci-lint@v2.1.6 ## Breaking Changes No. ## Types of changes - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist <!-- Go over all the following points, and put an `x` in all the boxes that apply. --> - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [ ] I have added or updated documentation as needed ## Additional context <!-- Add any other context, implementation notes, or design decisions --> --------- Co-authored-by: haokunt <haokunt@opera.com> Co-authored-by: Avinash Sridhar <sridharavinash@users.noreply.github.com> Co-authored-by: Adam Jones <adamj+git@anthropic.com>
This commit is contained in:
parent
502b628ac8
commit
6ba612942e
9 changed files with 94 additions and 101 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
|
@ -25,7 +25,7 @@ jobs:
|
||||||
|
|
||||||
- name: Install golangci-lint
|
- name: Install golangci-lint
|
||||||
run: |
|
run: |
|
||||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.61.0
|
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.3.1
|
||||||
|
|
||||||
- name: Run golangci-lint
|
- name: Run golangci-lint
|
||||||
run: golangci-lint run --timeout=5m
|
run: golangci-lint run --timeout=5m
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,6 +4,7 @@ build/*
|
||||||
.mcpregistry*
|
.mcpregistry*
|
||||||
**/bin
|
**/bin
|
||||||
cmd/registry/registry
|
cmd/registry/registry
|
||||||
|
.DS_Store
|
||||||
validate-examples
|
validate-examples
|
||||||
validate-schemas
|
validate-schemas
|
||||||
.idea/
|
.idea/
|
||||||
|
|
|
||||||
132
.golangci.yml
132
.golangci.yml
|
|
@ -1,19 +1,11 @@
|
||||||
# GolangCI-Lint configuration
|
# GolangCI-Lint configuration
|
||||||
# See: https://golangci-lint.run/usage/configuration/
|
# See: https://golangci-lint.run/usage/configuration/
|
||||||
|
|
||||||
|
version: "2"
|
||||||
run:
|
run:
|
||||||
timeout: 5m
|
|
||||||
modules-download-mode: readonly
|
modules-download-mode: readonly
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- errcheck
|
|
||||||
- gosimple
|
|
||||||
- govet
|
|
||||||
- ineffassign
|
|
||||||
- staticcheck
|
|
||||||
- typecheck
|
|
||||||
- unused
|
|
||||||
- asasalint
|
- asasalint
|
||||||
- asciicheck
|
- asciicheck
|
||||||
- bidichk
|
- bidichk
|
||||||
|
|
@ -28,14 +20,11 @@ linters:
|
||||||
- exhaustive
|
- exhaustive
|
||||||
- forbidigo
|
- forbidigo
|
||||||
- funlen
|
- funlen
|
||||||
- gci
|
|
||||||
- gocognit
|
- gocognit
|
||||||
- goconst
|
- goconst
|
||||||
- gocritic
|
- gocritic
|
||||||
- gocyclo
|
- gocyclo
|
||||||
- godox
|
- godox
|
||||||
- gofmt
|
|
||||||
- goimports
|
|
||||||
- gomoddirectives
|
- gomoddirectives
|
||||||
- gomodguard
|
- gomodguard
|
||||||
- goprintffuncname
|
- goprintffuncname
|
||||||
|
|
@ -59,8 +48,7 @@ linters:
|
||||||
- revive
|
- revive
|
||||||
- rowserrcheck
|
- rowserrcheck
|
||||||
- sqlclosecheck
|
- sqlclosecheck
|
||||||
- stylecheck
|
- staticcheck
|
||||||
- tenv
|
|
||||||
- testpackage
|
- testpackage
|
||||||
- thelper
|
- thelper
|
||||||
- tparallel
|
- tparallel
|
||||||
|
|
@ -69,55 +57,69 @@ linters:
|
||||||
- usestdlibvars
|
- usestdlibvars
|
||||||
- wastedassign
|
- wastedassign
|
||||||
- whitespace
|
- whitespace
|
||||||
|
settings:
|
||||||
linters-settings:
|
cyclop:
|
||||||
revive:
|
max-complexity: 50
|
||||||
|
funlen:
|
||||||
|
lines: 150
|
||||||
|
statements: 150
|
||||||
|
gocognit:
|
||||||
|
min-complexity: 50
|
||||||
|
goconst:
|
||||||
|
min-len: 3
|
||||||
|
min-occurrences: 3
|
||||||
|
gocyclo:
|
||||||
|
min-complexity: 25
|
||||||
|
lll:
|
||||||
|
line-length: 150
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
mnd:
|
||||||
|
checks:
|
||||||
|
- argument
|
||||||
|
- case
|
||||||
|
- condition
|
||||||
|
- operation
|
||||||
|
- return
|
||||||
|
nestif:
|
||||||
|
min-complexity: 8
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
presets:
|
||||||
|
- comments
|
||||||
|
- common-false-positives
|
||||||
|
- legacy
|
||||||
|
- std-error-handling
|
||||||
rules:
|
rules:
|
||||||
- name: use-any
|
- linters:
|
||||||
disabled: false
|
- dupl
|
||||||
severity: error
|
- errcheck
|
||||||
cyclop:
|
- funlen
|
||||||
max-complexity: 50
|
- gocyclo
|
||||||
funlen:
|
- gosec
|
||||||
lines: 150
|
- mnd
|
||||||
statements: 150
|
path: _test\.go
|
||||||
gocognit:
|
- linters:
|
||||||
min-complexity: 50
|
- lll
|
||||||
gocyclo:
|
path: docs/
|
||||||
min-complexity: 25
|
- linters:
|
||||||
goconst:
|
- mnd
|
||||||
min-len: 3
|
path: integrationtests/
|
||||||
min-occurrences: 3
|
- linters:
|
||||||
mnd:
|
- gomoddirectives
|
||||||
checks:
|
path: go\.mod
|
||||||
- argument
|
paths:
|
||||||
- case
|
- third_party$
|
||||||
- condition
|
- builtin$
|
||||||
- operation
|
- examples$
|
||||||
- return
|
formatters:
|
||||||
lll:
|
enable:
|
||||||
line-length: 150
|
- gci
|
||||||
misspell:
|
- gofmt
|
||||||
locale: US
|
- goimports
|
||||||
nestif:
|
exclusions:
|
||||||
min-complexity: 8
|
generated: lax
|
||||||
|
paths:
|
||||||
issues:
|
- third_party$
|
||||||
exclude-rules:
|
- builtin$
|
||||||
# Exclude some linters from running on tests files.
|
- examples$
|
||||||
- path: _test\.go
|
|
||||||
linters:
|
|
||||||
- mnd
|
|
||||||
- funlen
|
|
||||||
- gocyclo
|
|
||||||
- errcheck
|
|
||||||
- dupl
|
|
||||||
- gosec
|
|
||||||
# Ignore long lines in generated code
|
|
||||||
- path: docs/
|
|
||||||
linters:
|
|
||||||
- lll
|
|
||||||
# Allow local replacement directives in go.mod
|
|
||||||
- path: go\.mod
|
|
||||||
linters:
|
|
||||||
- gomoddirectives
|
|
||||||
|
|
@ -10,9 +10,9 @@ MCP Registry is a community-driven registry service for Model Context Protocol (
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
- **Go 1.23.x** - The project requires this specific version (check with `go version`)
|
- **Go 1.23.x** - The project requires this specific version (check with `go version`)
|
||||||
- Consider using a Go version manager like `g` or `gvm` if you work on multiple projects
|
- Consider using a Go version manager like `g` or `gvm` if you work on multiple projects
|
||||||
- **golangci-lint v1.61.0** - Install with:
|
- **golangci-lint v2.3.1** - Install with:
|
||||||
```bash
|
```bash
|
||||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.61.0
|
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.3.1
|
||||||
```
|
```
|
||||||
|
|
||||||
### Git Hooks (Optional)
|
### Git Hooks (Optional)
|
||||||
|
|
@ -72,7 +72,7 @@ gofmt -s -l .
|
||||||
gofmt -s -w .
|
gofmt -s -w .
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: The project uses golangci-lint v1.61.0 with 62 enabled linters. Always run linting locally before pushing to avoid CI failures.
|
**Note**: The project uses golangci-lint v2.3.1 with 62 enabled linters. Always run linting locally before pushing to avoid CI failures.
|
||||||
|
|
||||||
## Architecture Overview
|
## Architecture Overview
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@ The MCP Registry service provides a centralized repository for MCP server entrie
|
||||||
- Docker (optional, but recommended for development)
|
- Docker (optional, but recommended for development)
|
||||||
|
|
||||||
For development:
|
For development:
|
||||||
- golangci-lint v1.61.0 - Install with:
|
- golangci-lint v2.3.1 - Install with:
|
||||||
```bash
|
```bash
|
||||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.61.0
|
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.3.1
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
|
||||||
|
|
@ -23,17 +23,17 @@ type MockRegistryService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockRegistryService) List(cursor string, limit int) ([]model.Server, string, error) {
|
func (m *MockRegistryService) List(cursor string, limit int) ([]model.Server, string, error) {
|
||||||
args := m.Mock.Called(cursor, limit)
|
args := m.Called(cursor, limit)
|
||||||
return args.Get(0).([]model.Server), args.String(1), args.Error(2)
|
return args.Get(0).([]model.Server), args.String(1), args.Error(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockRegistryService) GetByID(id string) (*model.ServerDetail, error) {
|
func (m *MockRegistryService) GetByID(id string) (*model.ServerDetail, error) {
|
||||||
args := m.Mock.Called(id)
|
args := m.Called(id)
|
||||||
return args.Get(0).(*model.ServerDetail), args.Error(1)
|
return args.Get(0).(*model.ServerDetail), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockRegistryService) Publish(serverDetail *model.ServerDetail) error {
|
func (m *MockRegistryService) Publish(serverDetail *model.ServerDetail) error {
|
||||||
args := m.Mock.Called(serverDetail)
|
args := m.Called(serverDetail)
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,17 +45,17 @@ type MockAuthService struct {
|
||||||
func (m *MockAuthService) StartAuthFlow(
|
func (m *MockAuthService) StartAuthFlow(
|
||||||
ctx context.Context, method model.AuthMethod, repoRef string,
|
ctx context.Context, method model.AuthMethod, repoRef string,
|
||||||
) (map[string]string, string, error) {
|
) (map[string]string, string, error) {
|
||||||
args := m.Mock.Called(ctx, method, repoRef)
|
args := m.Called(ctx, method, repoRef)
|
||||||
return args.Get(0).(map[string]string), args.String(1), args.Error(2)
|
return args.Get(0).(map[string]string), args.String(1), args.Error(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockAuthService) CheckAuthStatus(ctx context.Context, statusToken string) (string, error) {
|
func (m *MockAuthService) CheckAuthStatus(ctx context.Context, statusToken string) (string, error) {
|
||||||
args := m.Mock.Called(ctx, statusToken)
|
args := m.Called(ctx, statusToken)
|
||||||
return args.String(0), args.Error(1)
|
return args.String(0), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockAuthService) ValidateAuth(ctx context.Context, authentication model.Authentication) (bool, error) {
|
func (m *MockAuthService) ValidateAuth(ctx context.Context, authentication model.Authentication) (bool, error) {
|
||||||
args := m.Mock.Called(ctx, authentication)
|
args := m.Called(ctx, authentication)
|
||||||
return args.Bool(0), args.Error(1)
|
return args.Bool(0), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -416,8 +416,8 @@ func TestPublishHandler(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert that all expectations were met
|
// Assert that all expectations were met
|
||||||
mockRegistry.Mock.AssertExpectations(t)
|
mockRegistry.AssertExpectations(t)
|
||||||
mockAuthService.Mock.AssertExpectations(t)
|
mockAuthService.AssertExpectations(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -487,7 +487,7 @@ func TestPublishHandlerBearerTokenParsing(t *testing.T) {
|
||||||
handler.ServeHTTP(rr, req)
|
handler.ServeHTTP(rr, req)
|
||||||
|
|
||||||
assert.Equal(t, http.StatusCreated, rr.Code)
|
assert.Equal(t, http.StatusCreated, rr.Code)
|
||||||
mockAuthService.Mock.AssertExpectations(t)
|
mockAuthService.AssertExpectations(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -552,7 +552,7 @@ func TestPublishHandlerAuthMethodSelection(t *testing.T) {
|
||||||
handler.ServeHTTP(rr, req)
|
handler.ServeHTTP(rr, req)
|
||||||
|
|
||||||
assert.Equal(t, http.StatusCreated, rr.Code)
|
assert.Equal(t, http.StatusCreated, rr.Code)
|
||||||
mockAuthService.Mock.AssertExpectations(t)
|
mockAuthService.AssertExpectations(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -639,9 +639,9 @@ func TestPublishIntegration(t *testing.T) {
|
||||||
// Verify the server was actually published by retrieving it
|
// Verify the server was actually published by retrieving it
|
||||||
publishedServer, err := registryService.GetByID(response["id"])
|
publishedServer, err := registryService.GetByID(response["id"])
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, publishReq.ServerDetail.Name, publishedServer.Name)
|
assert.Equal(t, publishReq.Name, publishedServer.Name)
|
||||||
assert.Equal(t, publishReq.ServerDetail.Description, publishedServer.Description)
|
assert.Equal(t, publishReq.Description, publishedServer.Description)
|
||||||
assert.Equal(t, publishReq.ServerDetail.VersionDetail.Version, publishedServer.VersionDetail.Version)
|
assert.Equal(t, publishReq.VersionDetail.Version, publishedServer.VersionDetail.Version)
|
||||||
assert.Len(t, publishedServer.Packages, 1)
|
assert.Len(t, publishedServer.Packages, 1)
|
||||||
assert.Len(t, publishedServer.Remotes, 1)
|
assert.Len(t, publishedServer.Remotes, 1)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -60,12 +60,8 @@ func ServersHandler(registry service.RegistryService) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsedLimit > 100 {
|
// Cap maximum limit to prevent excessive queries
|
||||||
// Cap maximum limit to prevent excessive queries
|
limit = min(parsedLimit, 100)
|
||||||
limit = 100
|
|
||||||
} else {
|
|
||||||
limit = parsedLimit
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the GetAll method to get paginated results
|
// Use the GetAll method to get paginated results
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,7 @@ func TestServersHandler(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify mock expectations
|
// Verify mock expectations
|
||||||
mockRegistry.Mock.AssertExpectations(t)
|
mockRegistry.AssertExpectations(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -321,7 +321,7 @@ func TestServersHandlerIntegration(t *testing.T) {
|
||||||
assert.Empty(t, paginatedResp.Metadata.NextCursor)
|
assert.Empty(t, paginatedResp.Metadata.NextCursor)
|
||||||
|
|
||||||
// Verify mock expectations
|
// Verify mock expectations
|
||||||
mockRegistry.Mock.AssertExpectations(t)
|
mockRegistry.AssertExpectations(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestServersDetailHandlerIntegration tests the servers detail handler with actual HTTP requests
|
// TestServersDetailHandlerIntegration tests the servers detail handler with actual HTTP requests
|
||||||
|
|
@ -387,5 +387,5 @@ func TestServersDetailHandlerIntegration(t *testing.T) {
|
||||||
assert.Equal(t, *serverDetail, serverDetailResp)
|
assert.Equal(t, *serverDetail, serverDetailResp)
|
||||||
|
|
||||||
// Verify mock expectations
|
// Verify mock expectations
|
||||||
mockRegistry.Mock.AssertExpectations(t)
|
mockRegistry.AssertExpectations(t)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,7 @@ func compareSemanticVersions(version1, version2 string) int {
|
||||||
parts2 := strings.Split(version2, ".")
|
parts2 := strings.Split(version2, ".")
|
||||||
|
|
||||||
// Pad with zeros if needed
|
// Pad with zeros if needed
|
||||||
maxLen := len(parts1)
|
maxLen := max(len(parts2), len(parts1))
|
||||||
if len(parts2) > maxLen {
|
|
||||||
maxLen = len(parts2)
|
|
||||||
}
|
|
||||||
|
|
||||||
for len(parts1) < maxLen {
|
for len(parts1) < maxLen {
|
||||||
parts1 = append(parts1, "0")
|
parts1 = append(parts1, "0")
|
||||||
|
|
@ -162,10 +159,7 @@ func (db *MemoryDB) List(
|
||||||
})
|
})
|
||||||
|
|
||||||
// Apply pagination
|
// Apply pagination
|
||||||
endIdx := startIdx + limit
|
endIdx := min(startIdx+limit, len(filteredEntries))
|
||||||
if endIdx > len(filteredEntries) {
|
|
||||||
endIdx = len(filteredEntries)
|
|
||||||
}
|
|
||||||
|
|
||||||
var result []*model.Server
|
var result []*model.Server
|
||||||
if startIdx < len(filteredEntries) {
|
if startIdx < len(filteredEntries) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue