Skip to content
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
14 changes: 14 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ permissions:
contents: read

jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v7
with:
version: v2.12.2

unit-tests:
runs-on: ubuntu-latest
steps:
Expand Down
71 changes: 71 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
version: "2"

run:
timeout: 5m

linters:
# Enables the standard set: errcheck, gosimple, govet, ineffassign, staticcheck, unused
default: standard
enable:
- bodyclose # HTTP response bodies are closed
- gocritic # broad style and correctness checks
- misspell # catches common spelling mistakes in comments and strings
- nolintlint # ensures //nolint directives are valid and specific
- unconvert # removes unnecessary type conversions
- unparam # detects function params that always receive the same value
disable:
# errcheck: 312 existing violations — deferred to a dedicated cleanup PR
- errcheck
# revive: 578 existing violations, mostly missing GoDoc on exported symbols — deferred to a dedicated cleanup PR
- revive

settings:
gocritic:
enabled-tags:
- diagnostic
- style
- performance
disabled-checks:
# CLI performance is not sensitive enough to warrant changing all option structs to pointers
- hugeParam
# Same rationale: range-copy cost is negligible in a CLI
- rangeValCopy

revive:
rules:
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-return
- name: error-strings
- name: error-naming
- name: exported
- name: if-return
- name: increment-decrement
- name: var-naming
- name: var-declaration
- name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: unexported-return
- name: indent-error-flow
- name: errorf
- name: empty-block
- name: superfluous-else
- name: unused-parameter
- name: unreachable-code
- name: redefines-builtin-id

exclusions:
rules:
# Test files get more latitude — errcheck and unparam noise is expected there
- path: _test\.go
linters:
- gocritic
- unparam

issues:
max-issues-per-linter: 0
max-same-issues: 0
9 changes: 5 additions & 4 deletions cmd/gen-manpages/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func main() {
}

// Ensure output directory exists
if err := os.MkdirAll(*output, 0755); err != nil {
if err := os.MkdirAll(*output, 0o755); err != nil {
fmt.Fprintf(os.Stderr, "Error: Could not create output directory: %s\n", err)
os.Exit(1)
}
Expand Down Expand Up @@ -70,11 +70,12 @@ func main() {
// List generated files for verbose
if *verbose {
files, err := filepath.Glob(filepath.Join(*output, "*.1"))
if err != nil {
switch {
case err != nil:
fmt.Fprintf(os.Stderr, "Warning: Failed to list generated files: %s\n", err)
} else if len(files) == 0 {
case len(files) == 0:
fmt.Printf("No man pages found in output directory: %s\n", *output)
} else {
default:
fmt.Printf("Generated %d man pages:\n", len(files))
for _, file := range files {
fmt.Printf(" - %s\n", filepath.Base(file))
Expand Down
9 changes: 5 additions & 4 deletions internal/pkg/cli/command/auth/clear.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,20 @@ func NewClearCmd() *cobra.Command {
}

// After clearing things, we need to resolve whether the user is still authenticated
if secrets.DefaultAPIKey.Get() != "" {
switch {
case secrets.DefaultAPIKey.Get() != "":
state.AuthedUser.Update(func(u *state.TargetUser) {
u.AuthContext = state.AuthDefaultAPIKey
})
} else if secrets.ClientId.Get() != "" && secrets.ClientSecret.Get() != "" {
case secrets.ClientId.Get() != "" && secrets.ClientSecret.Get() != "":
state.AuthedUser.Update(func(u *state.TargetUser) {
u.AuthContext = state.AuthServiceAccount
})
} else if secrets.GetOAuth2Token().AccessToken != "" {
case secrets.GetOAuth2Token().AccessToken != "":
state.AuthedUser.Update(func(u *state.TargetUser) {
u.AuthContext = state.AuthUserToken
})
} else {
default:
state.AuthedUser.Update(func(u *state.TargetUser) {
u.AuthContext = state.AuthNone
})
Expand Down
4 changes: 2 additions & 2 deletions internal/pkg/cli/command/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ type mockConfigService struct {
lastDescribeKey string
}

func (m *mockConfigService) Get(key string) (string, bool, string, bool, error) {
func (m *mockConfigService) Get(key string) (value string, sensitive bool, envVarName string, envVarOverride bool, err error) {
m.lastGetKey = key
return m.getValue, m.getSensitive, m.getEnvVarName, m.getEnvVarOverride, m.getErr
}

func (m *mockConfigService) GetStored(key string) (string, bool, error) {
func (m *mockConfigService) GetStored(key string) (value string, sensitive bool, err error) {
m.lastGetStoredKey = key
if m.getStoredOverride {
return m.getStoredValue, m.getStoredSensitive, m.getStoredErr
Expand Down
12 changes: 3 additions & 9 deletions internal/pkg/cli/command/config/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import (
"fmt"
"os"

"github.com/pinecone-io/cli/internal/pkg/utils/exit"
"github.com/pinecone-io/cli/internal/pkg/utils/help"
"github.com/pinecone-io/cli/internal/pkg/utils/msg"
"github.com/pinecone-io/cli/internal/pkg/utils/presenters"
"github.com/pinecone-io/cli/internal/pkg/utils/text"
"github.com/spf13/cobra"
Expand All @@ -33,10 +31,7 @@ func NewListCmd() *cobra.Command {
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
svc := newDefaultConfigService()
if err := runListCmd(svc, options); err != nil {
msg.FailJSON(options.json, "%s", err)
exit.ErrorMsg(err.Error())
}
runListCmd(svc, options)
},
}

Expand All @@ -47,7 +42,7 @@ func NewListCmd() *cobra.Command {
return cmd
}

func runListCmd(svc ConfigService, opts ListCmdOptions) error {
func runListCmd(svc ConfigService, opts ListCmdOptions) {
// --json output for the list command
type listOutput struct {
Key string `json:"key"`
Expand All @@ -74,7 +69,7 @@ func runListCmd(svc ConfigService, opts ListCmdOptions) error {
jsonEntries = append(jsonEntries, entry)
}
fmt.Fprintln(os.Stdout, text.IndentJSON(jsonEntries))
return nil
return
}

w := presenters.NewTabWriter()
Expand Down Expand Up @@ -102,5 +97,4 @@ func runListCmd(svc ConfigService, opts ListCmdOptions) error {
e.Description)
}
w.Flush()
return nil
}
33 changes: 11 additions & 22 deletions internal/pkg/cli/command/config/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ func Test_runListCmd_TabularOutputIncludesHeader(t *testing.T) {
svc := &mockConfigService{listResult: []ConfigEntry{}}

out := testutils.CaptureStdout(t, func() {
err := runListCmd(svc, ListCmdOptions{})
assert.NoError(t, err)
runListCmd(svc, ListCmdOptions{})
})

assert.Contains(t, out, "KEY")
Expand All @@ -30,8 +29,7 @@ func Test_runListCmd_TabularOutputMasksSensitiveKey(t *testing.T) {
}

out := testutils.CaptureStdout(t, func() {
err := runListCmd(svc, ListCmdOptions{})
assert.NoError(t, err)
runListCmd(svc, ListCmdOptions{})
})

assert.Contains(t, out, "api-key")
Expand All @@ -46,8 +44,7 @@ func Test_runListCmd_TabularOutputRevealsSensitiveKey(t *testing.T) {
}

out := testutils.CaptureStdout(t, func() {
err := runListCmd(svc, ListCmdOptions{reveal: true})
assert.NoError(t, err)
runListCmd(svc, ListCmdOptions{reveal: true})
})

assert.Contains(t, out, "sk-supersecret")
Expand All @@ -62,8 +59,7 @@ func Test_runListCmd_JSONOutput(t *testing.T) {
}

out := testutils.CaptureStdout(t, func() {
err := runListCmd(svc, ListCmdOptions{json: true})
assert.NoError(t, err)
runListCmd(svc, ListCmdOptions{json: true})
})

// Sensitive key should be masked in JSON output
Expand All @@ -83,8 +79,7 @@ func Test_runListCmd_AllFlagIncludesHiddenKeys(t *testing.T) {
}

out := testutils.CaptureStdout(t, func() {
err := runListCmd(svc, ListCmdOptions{all: true})
assert.NoError(t, err)
runListCmd(svc, ListCmdOptions{all: true})
})

assert.Contains(t, out, "environment")
Expand All @@ -99,8 +94,7 @@ func Test_runListCmd_JSONAllFlagIncludesHiddenField(t *testing.T) {
}

out := testutils.CaptureStdout(t, func() {
err := runListCmd(svc, ListCmdOptions{json: true, all: true})
assert.NoError(t, err)
runListCmd(svc, ListCmdOptions{json: true, all: true})
})

assert.Contains(t, out, "environment")
Expand All @@ -117,8 +111,7 @@ func Test_runListCmd_JSONOutputRevealsSensitiveKey(t *testing.T) {
}

out := testutils.CaptureStdout(t, func() {
err := runListCmd(svc, ListCmdOptions{json: true, reveal: true})
assert.NoError(t, err)
runListCmd(svc, ListCmdOptions{json: true, reveal: true})
})

assert.Contains(t, out, "sk-supersecret")
Expand All @@ -132,8 +125,7 @@ func Test_runListCmd_TabularOutputAnnotatesActiveEnvVarOverride(t *testing.T) {
}

out := testutils.CaptureStdout(t, func() {
err := runListCmd(svc, ListCmdOptions{all: true})
assert.NoError(t, err)
runListCmd(svc, ListCmdOptions{all: true})
})

assert.Contains(t, out, "staging")
Expand All @@ -148,8 +140,7 @@ func Test_runListCmd_TabularOutputNoAnnotationWithoutOverride(t *testing.T) {
}

out := testutils.CaptureStdout(t, func() {
err := runListCmd(svc, ListCmdOptions{all: true})
assert.NoError(t, err)
runListCmd(svc, ListCmdOptions{all: true})
})

assert.NotContains(t, out, "[$PINECONE_ENVIRONMENT]")
Expand All @@ -164,8 +155,7 @@ func Test_runListCmd_JSONOutputIncludesEnvVarFieldsWhenBound(t *testing.T) {
}

out := testutils.CaptureStdout(t, func() {
err := runListCmd(svc, ListCmdOptions{json: true, all: true})
assert.NoError(t, err)
runListCmd(svc, ListCmdOptions{json: true, all: true})
})

assert.Contains(t, out, `"PINECONE_ENVIRONMENT"`)
Expand All @@ -182,8 +172,7 @@ func Test_runListCmd_JSONOutputEnvVarOverrideIsFalseWhenNotActive(t *testing.T)
}

out := testutils.CaptureStdout(t, func() {
err := runListCmd(svc, ListCmdOptions{json: true, all: true})
assert.NoError(t, err)
runListCmd(svc, ListCmdOptions{json: true, all: true})
})

assert.Contains(t, out, `"PINECONE_ENVIRONMENT"`)
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/cli/command/config/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ func (s *defaultConfigService) Get(key string) (value string, sensitive bool, en
return desc.getStr(), desc.Sensitive, "", false, nil
}

func (s *defaultConfigService) GetStored(key string) (string, bool, error) {
func (s *defaultConfigService) GetStored(key string) (value string, sensitive bool, err error) {
desc, err := lookupKey(key)
if err != nil {
return "", false, err
Expand Down
16 changes: 7 additions & 9 deletions internal/pkg/cli/command/index/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ func runCreateIndexCmd(ctx context.Context, cmd *cobra.Command, service CreateIn

idx, err = service.CreateServerlessIndex(ctx, &args)
if err != nil {
wrapped := fmt.Errorf("Failed to create serverless index %s: %w", style.Emphasis(options.name), err)
wrapped := fmt.Errorf("failed to create serverless index %s: %w", style.Emphasis(options.name), err)
return nil, wrapped
}
case indexTypePod:
Expand Down Expand Up @@ -249,7 +249,7 @@ func runCreateIndexCmd(ctx context.Context, cmd *cobra.Command, service CreateIn

idx, err = service.CreatePodIndex(ctx, &args)
if err != nil {
wrapped := fmt.Errorf("Failed to create pod index %s: %w", style.Emphasis(options.name), err)
wrapped := fmt.Errorf("failed to create pod index %s: %w", style.Emphasis(options.name), err)
return nil, wrapped
}
case indexTypeIntegrated:
Expand Down Expand Up @@ -290,7 +290,7 @@ func runCreateIndexCmd(ctx context.Context, cmd *cobra.Command, service CreateIn

idx, err = service.CreateIndexForModel(ctx, &args)
if err != nil {
wrapped := fmt.Errorf("Failed to create integrated index %s: %w", style.Emphasis(options.name), err)
wrapped := fmt.Errorf("failed to create integrated index %s: %w", style.Emphasis(options.name), err)
return nil, wrapped
}
case indexTypeBYOC:
Expand All @@ -307,11 +307,11 @@ func runCreateIndexCmd(ctx context.Context, cmd *cobra.Command, service CreateIn

idx, err = service.CreateBYOCIndex(ctx, &args)
if err != nil {
wrapped := fmt.Errorf("Failed to create BYOC index %s: %w", style.Emphasis(options.name), err)
wrapped := fmt.Errorf("failed to create BYOC index %s: %w", style.Emphasis(options.name), err)
return nil, wrapped
}
default:
err := fmt.Errorf("Error creating index: invalid index type")
err := fmt.Errorf("error creating index: invalid index type")
return nil, err
}

Expand Down Expand Up @@ -411,10 +411,8 @@ func buildReadCapacityFromFlags(cmd *cobra.Command, mode, nodeType string, shard
default:
return nil, fmt.Errorf("invalid read-mode")
}
} else { // read-mode not provided, return nil if no specific configuration values are passed
if !nodeSet && !shardsSet && !replSet {
return nil, nil
}
} else if !nodeSet && !shardsSet && !replSet { // read-mode not provided, return nil if no specific configuration values are passed
return nil, nil
}

// dedicated mode if ondemand mode was not requested
Expand Down
3 changes: 1 addition & 2 deletions internal/pkg/cli/command/index/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"testing"

"github.com/pinecone-io/go-pinecone/v5/pinecone"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -334,7 +333,7 @@ func Test_createIndexOptions_validate(t *testing.T) {
}

func Test_buildReadCapacityFromFlags(t *testing.T) {
newCmd := func() *cobra.Command { return NewCreateIndexCmd() }
newCmd := NewCreateIndexCmd

t.Run("no flags set returns nil", func(t *testing.T) {
cmd := newCmd()
Expand Down
Loading
Loading