Skip to content

Fix linting flow #614

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jun 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Unit Tests
name: Build and Test Go Project
on: [push, pull_request]

permissions:
Expand Down
45 changes: 0 additions & 45 deletions .github/workflows/lint.yaml

This file was deleted.

23 changes: 23 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: golangci-lint
on:
push:
branches:
- main
pull_request:

permissions:
contents: read

jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: stable
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
with:
version: v2.1
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ __debug_bin*

# Go
vendor
bin/
60 changes: 25 additions & 35 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,37 @@
# https://golangci-lint.run/usage/configuration
version: "2"

run:
timeout: 5m
tests: true
concurrency: 4

tests: true
linters:
enable:
- govet
- errcheck
- staticcheck
- revive
- ineffassign
- unused
- misspell
- nakedret
- bodyclose
- gocritic
- makezero
- gosec
- makezero
- misspell
- nakedret
- revive
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
paths:
- third_party$
- builtin$
- examples$
settings:
staticcheck:
checks:
- all
- '-QF1008' # Allow embedded structs to be referenced by field
- '-ST1000' # Do not require package comments
revive:
rules:
- name: exported
disabled: true
- name: exported
disabled: true
- name: package-comments
disabled: true

- "all"
- -QF1008
- -ST1000
formatters:
enable:
- gofmt
- goimports

output:
formats:
text:
print-linter-name: true
print-issued-lines: true
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
8 changes: 4 additions & 4 deletions cmd/github-mcp-server/generate_docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ var generateDocsCmd = &cobra.Command{
Use: "generate-docs",
Short: "Generate documentation for tools and toolsets",
Long: `Generate the automated sections of README.md and docs/remote-server.md with current tool and toolset information.`,
RunE: func(cmd *cobra.Command, args []string) error {
RunE: func(_ *cobra.Command, _ []string) error {
return generateAllDocs()
},
}
Expand All @@ -33,17 +33,17 @@ func init() {
}

// mockGetClient returns a mock GitHub client for documentation generation
func mockGetClient(ctx context.Context) (*gogithub.Client, error) {
func mockGetClient(_ context.Context) (*gogithub.Client, error) {
return gogithub.NewClient(nil), nil
}

// mockGetGQLClient returns a mock GraphQL client for documentation generation
func mockGetGQLClient(ctx context.Context) (*githubv4.Client, error) {
func mockGetGQLClient(_ context.Context) (*githubv4.Client, error) {
return githubv4.NewClient(nil), nil
}

// mockGetRawClient returns a mock raw client for documentation generation
func mockGetRawClient(ctx context.Context) (*raw.Client, error) {
func mockGetRawClient(_ context.Context) (*raw.Client, error) {
return nil, nil
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/github-mcp-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func main() {
}
}

func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
func wordSepNormalizeFunc(_ *pflag.FlagSet, name string) pflag.NormalizedName {
from := []string{"_"}
to := "-"
for _, sep := range from {
Expand Down
2 changes: 1 addition & 1 deletion pkg/errors/error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ func TestGitHubErrorContext(t *testing.T) {

t.Run("NewGitHubAPIErrorToCtx with nil context does not error", func(t *testing.T) {
// Given a nil context
var ctx context.Context = nil
var ctx context.Context

// Create a mock GitHub response
resp := &github.Response{
Expand Down
4 changes: 2 additions & 2 deletions pkg/github/actions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ func Test_DownloadWorkflowRunArtifact(t *testing.T) {
Pattern: "/repos/owner/repo/actions/artifacts/123/zip",
Method: "GET",
},
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
// GitHub returns a 302 redirect to the download URL
w.Header().Set("Location", "https://api.github.com/repos/owner/repo/actions/artifacts/123/download")
w.WriteHeader(http.StatusFound)
Expand Down Expand Up @@ -1055,7 +1055,7 @@ func Test_GetJobLogs_WithContentReturn(t *testing.T) {
logContent := "2023-01-01T10:00:00.000Z Starting job...\n2023-01-01T10:00:01.000Z Running tests...\n2023-01-01T10:00:02.000Z Job completed successfully"

// Create a test server to serve log content
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(logContent))
}))
Expand Down
2 changes: 1 addition & 1 deletion pkg/github/issues.go
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ func AssignCodingAgentPrompt(t translations.TranslationHelperFunc) (tool mcp.Pro
return mcp.NewPrompt("AssignCodingAgent",
mcp.WithPromptDescription(t("PROMPT_ASSIGN_CODING_AGENT_DESCRIPTION", "Assign GitHub Coding Agent to multiple tasks in a GitHub repository.")),
mcp.WithArgument("repo", mcp.ArgumentDescription("The repository to assign tasks in (owner/repo)."), mcp.RequiredArgument()),
), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
), func(_ context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
repo := request.Params.Arguments["repo"]

messages := []mcp.PromptMessage{
Expand Down
6 changes: 2 additions & 4 deletions pkg/github/repositories.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ func GetFileContents(getClient GetClientFn, getRawClient raw.GetRawClientFn, t t
return mcp.NewToolResultError(err.Error()), nil
}

rawOpts := &raw.RawContentOpts{}
rawOpts := &raw.ContentOpts{}

if strings.HasPrefix(ref, "refs/pull/") {
prNumber := strings.TrimSuffix(strings.TrimPrefix(ref, "refs/pull/"), "/head")
Expand Down Expand Up @@ -532,9 +532,7 @@ func GetFileContents(getClient GetClientFn, getRawClient raw.GetRawClientFn, t t
_ = resp.Body.Close()
}()

if resp.StatusCode != http.StatusOK {
// If the raw content is not found, we will fall back to the GitHub API (in case it is a directory)
} else {
if resp.StatusCode == http.StatusOK {
// If the raw content is found, return it directly
body, err := io.ReadAll(resp.Body)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/github/repository_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func RepositoryResourceContentsHandler(getClient GetClientFn, getRawClient raw.G
}

opts := &github.RepositoryContentGetOptions{}
rawOpts := &raw.RawContentOpts{}
rawOpts := &raw.ContentOpts{}

sha, ok := request.Params.Arguments["sha"].([]string)
if ok && len(sha) > 0 {
Expand Down
8 changes: 4 additions & 4 deletions pkg/raw/raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ func (c *Client) refURL(owner, repo, ref, path string) string {
return c.url.JoinPath(owner, repo, ref, path).String()
}

func (c *Client) URLFromOpts(opts *RawContentOpts, owner, repo, path string) string {
func (c *Client) URLFromOpts(opts *ContentOpts, owner, repo, path string) string {
if opts == nil {
opts = &RawContentOpts{}
opts = &ContentOpts{}
}
if opts.SHA != "" {
return c.commitURL(owner, repo, opts.SHA, path)
Expand All @@ -56,13 +56,13 @@ func (c *Client) commitURL(owner, repo, sha, path string) string {
return c.url.JoinPath(owner, repo, sha, path).String()
}

type RawContentOpts struct {
type ContentOpts struct {
Ref string
SHA string
}

// GetRawContent fetches the raw content of a file from a GitHub repository.
func (c *Client) GetRawContent(ctx context.Context, owner, repo, path string, opts *RawContentOpts) (*http.Response, error) {
func (c *Client) GetRawContent(ctx context.Context, owner, repo, path string, opts *ContentOpts) (*http.Response, error) {
url := c.URLFromOpts(opts, owner, repo, path)
req, err := c.newRequest(ctx, "GET", url, nil)
if err != nil {
Expand Down
16 changes: 8 additions & 8 deletions pkg/raw/raw_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestGetRawContent(t *testing.T) {
tests := []struct {
name string
pattern mock.EndpointPattern
opts *RawContentOpts
opts *ContentOpts
owner, repo, path string
statusCode int
contentType string
Expand All @@ -36,7 +36,7 @@ func TestGetRawContent(t *testing.T) {
{
name: "branch fetch success",
pattern: GetRawReposContentsByOwnerByRepoByBranchByPath,
opts: &RawContentOpts{Ref: "refs/heads/main"},
opts: &ContentOpts{Ref: "refs/heads/main"},
owner: "octocat", repo: "hello", path: "README.md",
statusCode: 200,
contentType: "text/plain",
Expand All @@ -45,7 +45,7 @@ func TestGetRawContent(t *testing.T) {
{
name: "tag fetch success",
pattern: GetRawReposContentsByOwnerByRepoByTagByPath,
opts: &RawContentOpts{Ref: "refs/tags/v1.0.0"},
opts: &ContentOpts{Ref: "refs/tags/v1.0.0"},
owner: "octocat", repo: "hello", path: "README.md",
statusCode: 200,
contentType: "text/plain",
Expand All @@ -54,7 +54,7 @@ func TestGetRawContent(t *testing.T) {
{
name: "sha fetch success",
pattern: GetRawReposContentsByOwnerByRepoBySHAByPath,
opts: &RawContentOpts{SHA: "abc123"},
opts: &ContentOpts{SHA: "abc123"},
owner: "octocat", repo: "hello", path: "README.md",
statusCode: 200,
contentType: "text/plain",
Expand Down Expand Up @@ -107,7 +107,7 @@ func TestUrlFromOpts(t *testing.T) {

tests := []struct {
name string
opts *RawContentOpts
opts *ContentOpts
owner string
repo string
path string
Expand All @@ -121,19 +121,19 @@ func TestUrlFromOpts(t *testing.T) {
},
{
name: "ref branch",
opts: &RawContentOpts{Ref: "refs/heads/main"},
opts: &ContentOpts{Ref: "refs/heads/main"},
owner: "octocat", repo: "hello", path: "README.md",
want: "https://raw.example.com/octocat/hello/refs/heads/main/README.md",
},
{
name: "ref tag",
opts: &RawContentOpts{Ref: "refs/tags/v1.0.0"},
opts: &ContentOpts{Ref: "refs/tags/v1.0.0"},
owner: "octocat", repo: "hello", path: "README.md",
want: "https://raw.example.com/octocat/hello/refs/tags/v1.0.0/README.md",
},
{
name: "sha",
opts: &RawContentOpts{SHA: "abc123"},
opts: &ContentOpts{SHA: "abc123"},
owner: "octocat", repo: "hello", path: "README.md",
want: "https://raw.example.com/octocat/hello/abc123/README.md",
},
Expand Down
15 changes: 15 additions & 0 deletions script/lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
set -eu

# first run go fmt
gofmt -s -w .

BINDIR="$(git rev-parse --show-toplevel)"/bin
BINARY=$BINDIR/golangci-lint
GOLANGCI_LINT_VERSION=v2.2.1


if [ ! -f "$BINARY" ]; then
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s "$GOLANGCI_LINT_VERSION"
fi

$BINARY run