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
|
||||
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
|
||||
run: golangci-lint run --timeout=5m
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,6 +4,7 @@ build/*
|
|||
.mcpregistry*
|
||||
**/bin
|
||||
cmd/registry/registry
|
||||
.DS_Store
|
||||
validate-examples
|
||||
validate-schemas
|
||||
.idea/
|
||||
|
|
|
|||
132
.golangci.yml
132
.golangci.yml
|
|
@ -1,19 +1,11 @@
|
|||
# GolangCI-Lint configuration
|
||||
# See: https://golangci-lint.run/usage/configuration/
|
||||
|
||||
version: "2"
|
||||
run:
|
||||
timeout: 5m
|
||||
modules-download-mode: readonly
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- errcheck
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unused
|
||||
- asasalint
|
||||
- asciicheck
|
||||
- bidichk
|
||||
|
|
@ -28,14 +20,11 @@ linters:
|
|||
- exhaustive
|
||||
- forbidigo
|
||||
- funlen
|
||||
- gci
|
||||
- gocognit
|
||||
- goconst
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- godox
|
||||
- gofmt
|
||||
- goimports
|
||||
- gomoddirectives
|
||||
- gomodguard
|
||||
- goprintffuncname
|
||||
|
|
@ -59,8 +48,7 @@ linters:
|
|||
- revive
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
- stylecheck
|
||||
- tenv
|
||||
- staticcheck
|
||||
- testpackage
|
||||
- thelper
|
||||
- tparallel
|
||||
|
|
@ -69,55 +57,69 @@ linters:
|
|||
- usestdlibvars
|
||||
- wastedassign
|
||||
- whitespace
|
||||
|
||||
linters-settings:
|
||||
revive:
|
||||
settings:
|
||||
cyclop:
|
||||
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:
|
||||
- name: use-any
|
||||
disabled: false
|
||||
severity: error
|
||||
cyclop:
|
||||
max-complexity: 50
|
||||
funlen:
|
||||
lines: 150
|
||||
statements: 150
|
||||
gocognit:
|
||||
min-complexity: 50
|
||||
gocyclo:
|
||||
min-complexity: 25
|
||||
goconst:
|
||||
min-len: 3
|
||||
min-occurrences: 3
|
||||
mnd:
|
||||
checks:
|
||||
- argument
|
||||
- case
|
||||
- condition
|
||||
- operation
|
||||
- return
|
||||
lll:
|
||||
line-length: 150
|
||||
misspell:
|
||||
locale: US
|
||||
nestif:
|
||||
min-complexity: 8
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
# Exclude some linters from running on tests files.
|
||||
- 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
|
||||
- linters:
|
||||
- dupl
|
||||
- errcheck
|
||||
- funlen
|
||||
- gocyclo
|
||||
- gosec
|
||||
- mnd
|
||||
path: _test\.go
|
||||
- linters:
|
||||
- lll
|
||||
path: docs/
|
||||
- linters:
|
||||
- mnd
|
||||
path: integrationtests/
|
||||
- linters:
|
||||
- gomoddirectives
|
||||
path: go\.mod
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
formatters:
|
||||
enable:
|
||||
- gci
|
||||
- gofmt
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
|
@ -10,9 +10,9 @@ MCP Registry is a community-driven registry service for Model Context Protocol (
|
|||
### Prerequisites
|
||||
- **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
|
||||
- **golangci-lint v1.61.0** - Install with:
|
||||
- **golangci-lint v2.3.1** - Install with:
|
||||
```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)
|
||||
|
|
@ -72,7 +72,7 @@ gofmt -s -l .
|
|||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ The MCP Registry service provides a centralized repository for MCP server entrie
|
|||
- Docker (optional, but recommended for development)
|
||||
|
||||
For development:
|
||||
- golangci-lint v1.61.0 - Install with:
|
||||
- golangci-lint v2.3.1 - Install with:
|
||||
```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
|
||||
|
|
|
|||
|
|
@ -23,17 +23,17 @@ type MockRegistryService struct {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func (m *MockRegistryService) Publish(serverDetail *model.ServerDetail) error {
|
||||
args := m.Mock.Called(serverDetail)
|
||||
args := m.Called(serverDetail)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
|
|
@ -45,17 +45,17 @@ type MockAuthService struct {
|
|||
func (m *MockAuthService) StartAuthFlow(
|
||||
ctx context.Context, method model.AuthMethod, repoRef string,
|
||||
) (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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
@ -416,8 +416,8 @@ func TestPublishHandler(t *testing.T) {
|
|||
}
|
||||
|
||||
// Assert that all expectations were met
|
||||
mockRegistry.Mock.AssertExpectations(t)
|
||||
mockAuthService.Mock.AssertExpectations(t)
|
||||
mockRegistry.AssertExpectations(t)
|
||||
mockAuthService.AssertExpectations(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -487,7 +487,7 @@ func TestPublishHandlerBearerTokenParsing(t *testing.T) {
|
|||
handler.ServeHTTP(rr, req)
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
publishedServer, err := registryService.GetByID(response["id"])
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, publishReq.ServerDetail.Name, publishedServer.Name)
|
||||
assert.Equal(t, publishReq.ServerDetail.Description, publishedServer.Description)
|
||||
assert.Equal(t, publishReq.ServerDetail.VersionDetail.Version, publishedServer.VersionDetail.Version)
|
||||
assert.Equal(t, publishReq.Name, publishedServer.Name)
|
||||
assert.Equal(t, publishReq.Description, publishedServer.Description)
|
||||
assert.Equal(t, publishReq.VersionDetail.Version, publishedServer.VersionDetail.Version)
|
||||
assert.Len(t, publishedServer.Packages, 1)
|
||||
assert.Len(t, publishedServer.Remotes, 1)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -60,12 +60,8 @@ func ServersHandler(registry service.RegistryService) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
if parsedLimit > 100 {
|
||||
// Cap maximum limit to prevent excessive queries
|
||||
limit = 100
|
||||
} else {
|
||||
limit = parsedLimit
|
||||
}
|
||||
// Cap maximum limit to prevent excessive queries
|
||||
limit = min(parsedLimit, 100)
|
||||
}
|
||||
|
||||
// Use the GetAll method to get paginated results
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ func TestServersHandler(t *testing.T) {
|
|||
}
|
||||
|
||||
// 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)
|
||||
|
||||
// Verify mock expectations
|
||||
mockRegistry.Mock.AssertExpectations(t)
|
||||
mockRegistry.AssertExpectations(t)
|
||||
}
|
||||
|
||||
// TestServersDetailHandlerIntegration tests the servers detail handler with actual HTTP requests
|
||||
|
|
@ -387,5 +387,5 @@ func TestServersDetailHandlerIntegration(t *testing.T) {
|
|||
assert.Equal(t, *serverDetail, serverDetailResp)
|
||||
|
||||
// Verify mock expectations
|
||||
mockRegistry.Mock.AssertExpectations(t)
|
||||
mockRegistry.AssertExpectations(t)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,10 +48,7 @@ func compareSemanticVersions(version1, version2 string) int {
|
|||
parts2 := strings.Split(version2, ".")
|
||||
|
||||
// Pad with zeros if needed
|
||||
maxLen := len(parts1)
|
||||
if len(parts2) > maxLen {
|
||||
maxLen = len(parts2)
|
||||
}
|
||||
maxLen := max(len(parts2), len(parts1))
|
||||
|
||||
for len(parts1) < maxLen {
|
||||
parts1 = append(parts1, "0")
|
||||
|
|
@ -162,10 +159,7 @@ func (db *MemoryDB) List(
|
|||
})
|
||||
|
||||
// Apply pagination
|
||||
endIdx := startIdx + limit
|
||||
if endIdx > len(filteredEntries) {
|
||||
endIdx = len(filteredEntries)
|
||||
}
|
||||
endIdx := min(startIdx+limit, len(filteredEntries))
|
||||
|
||||
var result []*model.Server
|
||||
if startIdx < len(filteredEntries) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue