diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 00000000..553514a9 --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,58 @@ +name: Lint +on: + push: + paths: + - "**.go" + - go.mod + - go.sum + pull_request: + paths: + - "**.go" + - go.mod + - go.sum + +permissions: + contents: read + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + + - name: Verify dependencies + run: | + go mod verify + go mod download + + LINT_VERSION=1.64.8 + curl -fsSL https://github.com/golangci/golangci-lint/releases/download/v${LINT_VERSION}/golangci-lint-${LINT_VERSION}-linux-amd64.tar.gz | \ + tar xz --strip-components 1 --wildcards \*/golangci-lint + mkdir -p bin && mv golangci-lint bin/ + + - name: Run checks + run: | + STATUS=0 + assert-nothing-changed() { + local diff + "$@" >/dev/null || return 1 + if ! diff="$(git diff -U1 --color --exit-code)"; then + printf '\e[31mError: running `\e[1m%s\e[22m` results in modifications that you must check into version control:\e[0m\n%s\n\n' "$*" "$diff" >&2 + git checkout -- . + STATUS=1 + fi + } + + assert-nothing-changed go fmt ./... + assert-nothing-changed go mod tidy + + bin/golangci-lint run --out-format=colored-line-number --timeout=3m || STATUS=$? + + exit $STATUS diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..43e3d62d --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,28 @@ +run: + timeout: 5m + tests: true + concurrency: 4 + +linters: + enable: + - govet + - errcheck + - staticcheck + - gofmt + - goimports + - revive + - ineffassign + - typecheck + - unused + - gosimple + - misspell + - nakedret + - bodyclose + - gocritic + - makezero + - gosec + +output: + formats: colored-line-number + print-issued-lines: true + print-linter-name: true diff --git a/cmd/github-mcp-server/main.go b/cmd/github-mcp-server/main.go index 5e8c520e..f523c1fd 100644 --- a/cmd/github-mcp-server/main.go +++ b/cmd/github-mcp-server/main.go @@ -30,7 +30,7 @@ var ( Use: "stdio", Short: "Start stdio server", Long: `Start a server that communicates via standard input/output streams using JSON-RPC messages.`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { logFile := viper.GetString("log-file") readOnly := viper.GetBool("read-only") exportTranslations := viper.GetBool("export-translations") @@ -57,11 +57,11 @@ func init() { rootCmd.PersistentFlags().String("gh-host", "", "Specify the GitHub hostname (for GitHub Enterprise etc.)") // Bind flag to viper - viper.BindPFlag("read-only", rootCmd.PersistentFlags().Lookup("read-only")) - viper.BindPFlag("log-file", rootCmd.PersistentFlags().Lookup("log-file")) - viper.BindPFlag("enable-command-logging", rootCmd.PersistentFlags().Lookup("enable-command-logging")) - viper.BindPFlag("export-translations", rootCmd.PersistentFlags().Lookup("export-translations")) - viper.BindPFlag("gh-host", rootCmd.PersistentFlags().Lookup("gh-host")) + _ = viper.BindPFlag("read-only", rootCmd.PersistentFlags().Lookup("read-only")) + _ = viper.BindPFlag("log-file", rootCmd.PersistentFlags().Lookup("log-file")) + _ = viper.BindPFlag("enable-command-logging", rootCmd.PersistentFlags().Lookup("enable-command-logging")) + _ = viper.BindPFlag("export-translations", rootCmd.PersistentFlags().Lookup("export-translations")) + _ = viper.BindPFlag("gh-host", rootCmd.PersistentFlags().Lookup("gh-host")) // Add subcommands rootCmd.AddCommand(stdioCmd) diff --git a/cmd/mcpcurl/main.go b/cmd/mcpcurl/main.go index 77dfd4f0..bcc46e00 100644 --- a/cmd/mcpcurl/main.go +++ b/cmd/mcpcurl/main.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "fmt" - "golang.org/x/exp/rand" "io" "os" "os/exec" @@ -13,6 +12,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "golang.org/x/exp/rand" ) type ( @@ -99,7 +99,7 @@ var ( Use: "mcpcurl", Short: "CLI tool with dynamically generated commands", Long: "A CLI tool for interacting with MCP API based on dynamically loaded schemas", - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { // Skip validation for help and completion commands if cmd.Name() == "help" || cmd.Name() == "completion" { return nil @@ -119,7 +119,7 @@ var ( Use: "schema", Short: "Fetch schema from MCP server", Long: "Fetches the tools schema from the MCP server specified by --stdio-server-cmd", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { serverCmd, _ := cmd.Flags().GetString("stdio-server-cmd") if serverCmd == "" { return fmt.Errorf("--stdio-server-cmd is required") @@ -206,7 +206,7 @@ func addCommandFromTool(toolsCmd *cobra.Command, tool *Tool, prettyPrint bool) { cmd := &cobra.Command{ Use: tool.Name, Short: tool.Description, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { // Build a map of arguments from flags arguments, err := buildArgumentsMap(cmd, tool) if err != nil { @@ -257,7 +257,7 @@ func addCommandFromTool(toolsCmd *cobra.Command, tool *Tool, prettyPrint bool) { // Enhance description to indicate if parameter is optional description := prop.Description if !isRequired { - description = description + " (optional)" + description += " (optional)" } switch prop.Type { @@ -265,7 +265,7 @@ func addCommandFromTool(toolsCmd *cobra.Command, tool *Tool, prettyPrint bool) { cmd.Flags().String(name, "", description) if len(prop.Enum) > 0 { // Add validation in PreRun for enum values - cmd.PreRunE = func(cmd *cobra.Command, args []string) error { + cmd.PreRunE = func(cmd *cobra.Command, _ []string) error { for flagName, property := range tool.InputSchema.Properties { if len(property.Enum) > 0 { value, _ := cmd.Flags().GetString(flagName) @@ -373,7 +373,7 @@ func executeServerCommand(cmdStr, jsonRequest string) (string, error) { return "", fmt.Errorf("empty command") } - cmd := exec.Command(cmdParts[0], cmdParts[1:]...) + cmd := exec.Command(cmdParts[0], cmdParts[1:]...) //nolint:gosec //mcpcurl is a test command that needs to execute arbitrary shell commands // Setup stdin pipe stdin, err := cmd.StdinPipe() diff --git a/pkg/github/code_scanning_test.go b/pkg/github/code_scanning_test.go index 89012334..6263a7f0 100644 --- a/pkg/github/code_scanning_test.go +++ b/pkg/github/code_scanning_test.go @@ -62,7 +62,7 @@ func Test_GetCodeScanningAlert(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposCodeScanningAlertsByOwnerByRepoByAlertNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Not Found"}`)) }), @@ -176,7 +176,7 @@ func Test_ListCodeScanningAlerts(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposCodeScanningAlertsByOwnerByRepo, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnauthorized) _, _ = w.Write([]byte(`{"message": "Unauthorized access"}`)) }), diff --git a/pkg/github/helper_test.go b/pkg/github/helper_test.go index 5e71f418..72241623 100644 --- a/pkg/github/helper_test.go +++ b/pkg/github/helper_test.go @@ -2,19 +2,19 @@ package github import ( "encoding/json" - "github.com/stretchr/testify/assert" "net/http" "testing" "github.com/mark3labs/mcp-go/mcp" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // mockResponse is a helper function to create a mock HTTP response handler -// that returns a specified status code and marshalled body. +// that returns a specified status code and marshaled body. func mockResponse(t *testing.T, code int, body interface{}) http.HandlerFunc { t.Helper() - return func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(code) b, err := json.Marshal(body) require.NoError(t, err) diff --git a/pkg/github/issues_test.go b/pkg/github/issues_test.go index c2de6579..edc531ae 100644 --- a/pkg/github/issues_test.go +++ b/pkg/github/issues_test.go @@ -164,7 +164,7 @@ func Test_AddIssueComment(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.PostReposIssuesCommentsByOwnerByRepoByIssueNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnprocessableEntity) _, _ = w.Write([]byte(`{"message": "Invalid request"}`)) }), @@ -323,7 +323,7 @@ func Test_SearchIssues(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetSearchIssues, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) _, _ = w.Write([]byte(`{"message": "Validation Failed"}`)) }), @@ -463,7 +463,7 @@ func Test_CreateIssue(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.PostReposIssuesByOwnerByRepo, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnprocessableEntity) _, _ = w.Write([]byte(`{"message": "Validation failed"}`)) }), @@ -646,7 +646,7 @@ func Test_ListIssues(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposIssuesByOwnerByRepo, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Repository not found"}`)) }), @@ -799,7 +799,7 @@ func Test_UpdateIssue(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.PatchReposIssuesByOwnerByRepoByIssueNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Issue not found"}`)) }), @@ -819,7 +819,7 @@ func Test_UpdateIssue(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.PatchReposIssuesByOwnerByRepoByIssueNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnprocessableEntity) _, _ = w.Write([]byte(`{"message": "Invalid state value"}`)) }), @@ -881,7 +881,7 @@ func Test_UpdateIssue(t *testing.T) { } // Check assignees if expected - if tc.expectedIssue.Assignees != nil && len(tc.expectedIssue.Assignees) > 0 { + if len(tc.expectedIssue.Assignees) > 0 { assert.Len(t, returnedIssue.Assignees, len(tc.expectedIssue.Assignees)) for i, assignee := range returnedIssue.Assignees { assert.Equal(t, *tc.expectedIssue.Assignees[i].Login, *assignee.Login) @@ -889,7 +889,7 @@ func Test_UpdateIssue(t *testing.T) { } // Check labels if expected - if tc.expectedIssue.Labels != nil && len(tc.expectedIssue.Labels) > 0 { + if len(tc.expectedIssue.Labels) > 0 { assert.Len(t, returnedIssue.Labels, len(tc.expectedIssue.Labels)) for i, label := range returnedIssue.Labels { assert.Equal(t, *tc.expectedIssue.Labels[i].Name, *label.Name) diff --git a/pkg/github/pullrequests_test.go b/pkg/github/pullrequests_test.go index 15c5e070..6432c571 100644 --- a/pkg/github/pullrequests_test.go +++ b/pkg/github/pullrequests_test.go @@ -74,7 +74,7 @@ func Test_GetPullRequest(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposPullsByOwnerByRepoByPullNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Not Found"}`)) }), @@ -193,7 +193,7 @@ func Test_ListPullRequests(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposPullsByOwnerByRepo, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) _, _ = w.Write([]byte(`{"message": "Invalid request"}`)) }), @@ -302,7 +302,7 @@ func Test_MergePullRequest(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.PutReposPullsMergeByOwnerByRepoByPullNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusMethodNotAllowed) _, _ = w.Write([]byte(`{"message": "Pull request cannot be merged"}`)) }), @@ -414,7 +414,7 @@ func Test_GetPullRequestFiles(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposPullsFilesByOwnerByRepoByPullNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Not Found"}`)) }), @@ -551,7 +551,7 @@ func Test_GetPullRequestStatus(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposPullsByOwnerByRepoByPullNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Not Found"}`)) }), @@ -574,7 +574,7 @@ func Test_GetPullRequestStatus(t *testing.T) { ), mock.WithRequestMatchHandler( mock.GetReposCommitsStatusesByOwnerByRepoByRef, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Not Found"}`)) }), @@ -695,7 +695,7 @@ func Test_UpdatePullRequestBranch(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.PutReposPullsUpdateBranchByOwnerByRepoByPullNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusConflict) _, _ = w.Write([]byte(`{"message": "Merge conflict"}`)) }), @@ -811,7 +811,7 @@ func Test_GetPullRequestComments(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposPullsCommentsByOwnerByRepoByPullNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Not Found"}`)) }), @@ -934,7 +934,7 @@ func Test_GetPullRequestReviews(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposPullsReviewsByOwnerByRepoByPullNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Not Found"}`)) }), @@ -1099,7 +1099,7 @@ func Test_CreatePullRequestReview(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.PostReposPullsReviewsByOwnerByRepoByPullNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnprocessableEntity) _, _ = w.Write([]byte(`{"message": "Invalid comment format"}`)) }), @@ -1126,7 +1126,7 @@ func Test_CreatePullRequestReview(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.PostReposPullsReviewsByOwnerByRepoByPullNumber, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnprocessableEntity) _, _ = w.Write([]byte(`{"message": "Invalid comment format"}`)) }), diff --git a/pkg/github/repositories_test.go b/pkg/github/repositories_test.go index 34e8850a..1b416d8c 100644 --- a/pkg/github/repositories_test.go +++ b/pkg/github/repositories_test.go @@ -105,7 +105,7 @@ func Test_GetFileContents(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposContentsByOwnerByRepoByPath, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Not Found"}`)) }), @@ -234,7 +234,7 @@ func Test_ForkRepository(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.PostReposForksByOwnerByRepo, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusForbidden) _, _ = w.Write([]byte(`{"message": "Forbidden"}`)) }), @@ -370,7 +370,7 @@ func Test_CreateBranch(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposByOwnerByRepo, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Repository not found"}`)) }), @@ -389,7 +389,7 @@ func Test_CreateBranch(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposGitRefByOwnerByRepoByRef, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Reference not found"}`)) }), @@ -413,7 +413,7 @@ func Test_CreateBranch(t *testing.T) { ), mock.WithRequestMatchHandler( mock.PostReposGitRefsByOwnerByRepo, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnprocessableEntity) _, _ = w.Write([]byte(`{"message": "Reference already exists"}`)) }), @@ -573,7 +573,7 @@ func Test_ListCommits(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetReposCommitsByOwnerByRepo, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = w.Write([]byte(`{"message": "Not Found"}`)) }), @@ -717,7 +717,7 @@ func Test_CreateOrUpdateFile(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.PutReposContentsByOwnerByRepoByPath, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnprocessableEntity) _, _ = w.Write([]byte(`{"message": "Invalid request"}`)) }), @@ -856,7 +856,7 @@ func Test_CreateRepository(t *testing.T) { Pattern: "/user/repos", Method: "POST", }, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnprocessableEntity) _, _ = w.Write([]byte(`{"message": "Repository creation failed"}`)) }), diff --git a/pkg/github/search_test.go b/pkg/github/search_test.go index bee2d8d9..69fa7ca4 100644 --- a/pkg/github/search_test.go +++ b/pkg/github/search_test.go @@ -92,7 +92,7 @@ func Test_SearchRepositories(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetSearchRepositories, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) _, _ = w.Write([]byte(`{"message": "Invalid query"}`)) }), @@ -229,7 +229,7 @@ func Test_SearchCode(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetSearchCode, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) _, _ = w.Write([]byte(`{"message": "Validation Failed"}`)) }), @@ -370,7 +370,7 @@ func Test_SearchUsers(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetSearchUsers, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) _, _ = w.Write([]byte(`{"message": "Validation Failed"}`)) }), diff --git a/pkg/github/server.go b/pkg/github/server.go index d8b3714c..c01e0918 100644 --- a/pkg/github/server.go +++ b/pkg/github/server.go @@ -90,7 +90,7 @@ func getMe(client *github.Client, t translations.TranslationHelperFunc) (tool mc mcp.Description("Optional: reason the session was created"), ), ), - func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + func(ctx context.Context, _ mcp.CallToolRequest) (*mcp.CallToolResult, error) { user, resp, err := client.Users.Get(ctx, "") if err != nil { return nil, fmt.Errorf("failed to get user: %w", err) diff --git a/pkg/github/server_test.go b/pkg/github/server_test.go index 5e7ac9d4..a4d819f7 100644 --- a/pkg/github/server_test.go +++ b/pkg/github/server_test.go @@ -80,7 +80,7 @@ func Test_GetMe(t *testing.T) { mockedClient: mock.NewMockedHTTPClient( mock.WithRequestMatchHandler( mock.GetUser, - http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnauthorized) _, _ = w.Write([]byte(`{"message": "Unauthorized"}`)) }), diff --git a/pkg/translations/translations.go b/pkg/translations/translations.go index dd23323e..8f19f158 100644 --- a/pkg/translations/translations.go +++ b/pkg/translations/translations.go @@ -2,6 +2,7 @@ package translations import ( "encoding/json" + "fmt" "log" "os" "strings" @@ -11,7 +12,7 @@ import ( type TranslationHelperFunc func(key string, defaultValue string) string -func NullTranslationHelper(key string, defaultValue string) string { +func NullTranslationHelper(_ string, defaultValue string) string { return defaultValue } @@ -52,26 +53,30 @@ func TranslationHelper() (TranslationHelperFunc, func()) { return translationKeyMap[key] }, func() { // dump the translationKeyMap to a json file - DumpTranslationKeyMap(translationKeyMap) + if err := DumpTranslationKeyMap(translationKeyMap); err != nil { + log.Fatalf("Could not dump translation key map: %v", err) + } } } // dump translationKeyMap to a json file called github-mcp-server.json -func DumpTranslationKeyMap(translationKeyMap map[string]string) { +func DumpTranslationKeyMap(translationKeyMap map[string]string) error { file, err := os.Create("github-mcp-server.json") if err != nil { - log.Fatalf("Error creating file: %v", err) + return fmt.Errorf("error creating file: %v", err) } - defer file.Close() + defer func() { _ = file.Close() }() // marshal the map to json jsonData, err := json.MarshalIndent(translationKeyMap, "", " ") if err != nil { - log.Fatalf("Error marshaling map to JSON: %v", err) + return fmt.Errorf("error marshaling map to JSON: %v", err) } // write the json data to the file if _, err := file.Write(jsonData); err != nil { - log.Fatalf("Error writing to file: %v", err) + return fmt.Errorf("error writing to file: %v", err) } + + return nil }