From ef91ed987ee6e88d1036c00997e4f301d63e8fbd Mon Sep 17 00:00:00 2001 From: YaRissi <53705290+YaRissi@users.noreply.github.com> Date: Sat, 18 Oct 2025 13:12:21 +0200 Subject: [PATCH 1/9] feat: testing ci with linter and pull request template --- .github/pull_request_template.md | 7 +++ .github/workflows/test.yml | 55 +++++++++++++++++++++++ .golangci.yml | 75 ++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/test.yml create mode 100644 .golangci.yml diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..b3b5a7d --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,7 @@ +## Changes + +- + +## Issues & Discussions + +- fix # diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..b7e3307 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,55 @@ +name: Testing CLI + +on: + push: + branches: ["v4.x"] + pull_request: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Run gofmt + run: diff -u <(echo -n) <(gofmt -d -s .) + + - name: Run golangci-lint + uses: golangci/golangci-lint-action@v8 + with: + version: none + + test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + + - name: Run tests + run: go test -v -race ./... + + go-mod-tidy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + + - name: Run go mod tidy + run: go mod tidy + + - name: Check uncommitted changes + run: git diff --exit-code + + - if: failure() + run: echo "::error::Check failed, please run 'go mod tidy' and commit the changes." \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..93bb9c3 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,75 @@ +version: "2" + +run: + timeout: 5m + +linters: + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - contextcheck + - durationcheck + - errchkjson + - errorlint + - exhaustive + - gocheckcompilerdirectives + - gochecksumtype + - gocritic + - gomoddirectives + - gomodguard + - gosec + - gosmopolitan + - loggercheck + - makezero + - musttag + - nilerr + - nilnesserr + - noctx + - protogetter + - reassign + - recvcheck + - revive + - rowserrcheck + - spancheck + - sqlclosecheck + - testifylint + - unparam + - zerologlint + + settings: + exhaustive: + default-signifies-exhaustive: true + + staticcheck: + checks: ["all", "-ST1005", "-S1016"] + + gosec: + excludes: + - G115 + + gosmopolitan: + allow-time-local: true + + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - std-error-handling + +formatters: + enable: + - gci + - goimports + + settings: + gci: + sections: + - standard + - default + - prefix(github.com/coollabsio) + + exclusions: + generated: lax \ No newline at end of file From 86f77716ee970a7a3d844eda1d32212cf5f759f0 Mon Sep 17 00:00:00 2001 From: YaRissi <53705290+YaRissi@users.noreply.github.com> Date: Sat, 18 Oct 2025 13:13:35 +0200 Subject: [PATCH 2/9] fix: all found problems by the linter --- cmd/application/delete.go | 9 +- cmd/application/env/create.go | 3 +- cmd/application/env/delete.go | 9 +- cmd/application/env/get.go | 3 +- cmd/application/env/list.go | 3 +- cmd/application/env/sync.go | 3 +- cmd/application/env/update.go | 3 +- cmd/application/get.go | 3 +- cmd/application/list.go | 5 +- cmd/application/logs.go | 3 +- cmd/application/restart.go | 3 +- cmd/application/start.go | 3 +- cmd/application/stop.go | 3 +- cmd/application/update.go | 3 +- cmd/completion/completion.go | 3 +- cmd/config/config.go | 5 +- cmd/context/add.go | 10 ++- cmd/context/delete.go | 15 ++-- cmd/context/get.go | 5 +- cmd/context/list.go | 7 +- cmd/context/set_default.go | 17 ++-- cmd/context/set_token.go | 11 ++- cmd/context/update.go | 3 +- cmd/context/use.go | 5 +- cmd/context/verify.go | 5 +- cmd/context/verify_test.go | 17 ++-- cmd/context/version.go | 5 +- cmd/database/backup/create.go | 3 +- cmd/database/backup/delete-execution.go | 3 +- cmd/database/backup/delete.go | 3 +- cmd/database/backup/execution.go | 3 +- cmd/database/backup/list.go | 3 +- cmd/database/backup/trigger.go | 3 +- cmd/database/backup/update.go | 3 +- cmd/database/create.go | 5 +- cmd/database/delete.go | 3 +- cmd/database/get.go | 3 +- cmd/database/list.go | 5 +- cmd/database/restart.go | 3 +- cmd/database/start.go | 3 +- cmd/database/stop.go | 3 +- cmd/database/update.go | 3 +- cmd/deployment/batch.go | 3 +- cmd/deployment/cancel.go | 9 +- cmd/deployment/get.go | 3 +- cmd/deployment/list.go | 5 +- cmd/deployment/name.go | 3 +- cmd/deployment/uuid.go | 3 +- cmd/docs.go | 8 +- cmd/github/branches.go | 3 +- cmd/github/create.go | 21 ++--- cmd/github/delete.go | 9 +- cmd/github/get.go | 3 +- cmd/github/list.go | 5 +- cmd/github/repo.go | 3 +- cmd/github/update.go | 3 +- cmd/privatekeys/create.go | 3 +- cmd/privatekeys/delete.go | 3 +- cmd/privatekeys/list.go | 5 +- cmd/project/get.go | 5 +- cmd/project/list.go | 5 +- cmd/resources/list.go | 5 +- cmd/root.go | 23 ++--- cmd/server/add.go | 7 +- cmd/server/domain.go | 3 +- cmd/server/get.go | 3 +- cmd/server/list.go | 5 +- cmd/server/remove.go | 3 +- cmd/server/validate.go | 3 +- cmd/service/delete.go | 11 ++- cmd/service/env/create.go | 5 +- cmd/service/env/delete.go | 7 +- cmd/service/env/get.go | 5 +- cmd/service/env/list.go | 5 +- cmd/service/env/sync.go | 5 +- cmd/service/env/update.go | 5 +- cmd/service/get.go | 5 +- cmd/service/list.go | 7 +- cmd/service/restart.go | 5 +- cmd/service/start.go | 5 +- cmd/service/stop.go | 5 +- cmd/teams/current.go | 5 +- cmd/teams/get.go | 3 +- cmd/teams/list.go | 5 +- cmd/teams/members/list.go | 3 +- cmd/teams/teams.go | 3 +- cmd/update/update.go | 5 +- cmd/version/version.go | 5 +- internal/api/client.go | 4 +- internal/api/client_test.go | 41 +++++---- internal/cli/client.go | 3 +- internal/cli/helpers.go | 3 +- internal/config/config_test.go | 113 +++++++++++++++--------- internal/config/loader.go | 2 +- internal/models/database.go | 8 +- internal/output/formatter_test.go | 4 +- internal/output/table.go | 46 +++++++--- internal/parser/env_test.go | 16 ++-- internal/service/application_test.go | 105 +++++++++++----------- internal/service/database.go | 2 +- internal/service/database_test.go | 69 +++++++-------- internal/service/deployment_test.go | 5 +- internal/service/privatekey_test.go | 11 +-- internal/service/project_test.go | 9 +- internal/service/resource_test.go | 7 +- internal/service/server_test.go | 19 ++-- internal/service/service.go | 38 ++++---- internal/service/service_test.go | 107 +++++++++++----------- internal/service/team_test.go | 10 +-- internal/version/checker.go | 10 ++- 110 files changed, 639 insertions(+), 459 deletions(-) diff --git a/cmd/application/delete.go b/cmd/application/delete.go index 7d0c6d4..9c0c1d7 100644 --- a/cmd/application/delete.go +++ b/cmd/application/delete.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewDeleteCommand() *cobra.Command { @@ -24,7 +25,11 @@ func NewDeleteCommand() *cobra.Command { if !force { var response string fmt.Printf("Are you sure you want to delete application %s? This cannot be undone. (yes/no): ", uuid) - fmt.Scanln(&response) + _, err := fmt.Scanln(&response) + + if err != nil { + return fmt.Errorf("failed to read input: %w", err) + } if response != "yes" && response != "y" { fmt.Println("Delete cancelled.") diff --git a/cmd/application/env/create.go b/cmd/application/env/create.go index 46a6dad..fd6b336 100644 --- a/cmd/application/env/create.go +++ b/cmd/application/env/create.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewCreateEnvCommand() *cobra.Command { diff --git a/cmd/application/env/delete.go b/cmd/application/env/delete.go index 46b66c3..530c1ca 100644 --- a/cmd/application/env/delete.go +++ b/cmd/application/env/delete.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewDeleteEnvCommand() *cobra.Command { @@ -31,7 +32,11 @@ func NewDeleteEnvCommand() *cobra.Command { if !force { var response string fmt.Printf("Are you sure you want to delete this environment variable? (yes/no): ") - fmt.Scanln(&response) + _, err := fmt.Scanln(&response) + + if err != nil { + return fmt.Errorf("failed to read confirmation: %w", err) + } if response != "yes" && response != "y" { fmt.Println("Delete cancelled.") diff --git a/cmd/application/env/get.go b/cmd/application/env/get.go index 9a4dfce..a10e4d1 100644 --- a/cmd/application/env/get.go +++ b/cmd/application/env/get.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewGetEnvCommand() *cobra.Command { diff --git a/cmd/application/env/list.go b/cmd/application/env/list.go index d535d40..9a6f8b0 100644 --- a/cmd/application/env/list.go +++ b/cmd/application/env/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewListEnvCommand() *cobra.Command { diff --git a/cmd/application/env/sync.go b/cmd/application/env/sync.go index d8eb285..7728423 100644 --- a/cmd/application/env/sync.go +++ b/cmd/application/env/sync.go @@ -5,11 +5,12 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/parser" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewSyncEnvCommand() *cobra.Command { diff --git a/cmd/application/env/update.go b/cmd/application/env/update.go index 23abe9e..0e83c4e 100644 --- a/cmd/application/env/update.go +++ b/cmd/application/env/update.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewUpdateEnvCommand() *cobra.Command { diff --git a/cmd/application/get.go b/cmd/application/get.go index e42d2f3..fa48ebf 100644 --- a/cmd/application/get.go +++ b/cmd/application/get.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewGetCommand() *cobra.Command { diff --git a/cmd/application/list.go b/cmd/application/list.go index 8cb6dc1..3c371ee 100644 --- a/cmd/application/list.go +++ b/cmd/application/list.go @@ -4,11 +4,12 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewListCommand() *cobra.Command { @@ -16,7 +17,7 @@ func NewListCommand() *cobra.Command { Use: "list", Short: "List all applications", Long: `List all applications in Coolify.`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() client, err := cli.GetAPIClient(cmd) diff --git a/cmd/application/logs.go b/cmd/application/logs.go index 6e194c1..e65f041 100644 --- a/cmd/application/logs.go +++ b/cmd/application/logs.go @@ -9,9 +9,10 @@ import ( "syscall" "time" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewLogsCommand() *cobra.Command { diff --git a/cmd/application/restart.go b/cmd/application/restart.go index 71fed59..e6a7362 100644 --- a/cmd/application/restart.go +++ b/cmd/application/restart.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewRestartCommand() *cobra.Command { diff --git a/cmd/application/start.go b/cmd/application/start.go index b105aec..056e553 100644 --- a/cmd/application/start.go +++ b/cmd/application/start.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewStartCommand() *cobra.Command { diff --git a/cmd/application/stop.go b/cmd/application/stop.go index 9f9b68b..f60b514 100644 --- a/cmd/application/stop.go +++ b/cmd/application/stop.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewStopCommand() *cobra.Command { diff --git a/cmd/application/update.go b/cmd/application/update.go index 0f72383..ed98a62 100644 --- a/cmd/application/update.go +++ b/cmd/application/update.go @@ -4,11 +4,12 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewUpdateCommand() *cobra.Command { diff --git a/cmd/completion/completion.go b/cmd/completion/completion.go index d72b3c8..414b076 100644 --- a/cmd/completion/completion.go +++ b/cmd/completion/completion.go @@ -4,8 +4,9 @@ import ( "fmt" "os" - "github.com/coollabsio/coolify-cli/internal/cli" "github.com/spf13/cobra" + + "github.com/coollabsio/coolify-cli/internal/cli" ) func NewCompletionsCommand() *cobra.Command { diff --git a/cmd/config/config.go b/cmd/config/config.go index e513109..b6a55a7 100644 --- a/cmd/config/config.go +++ b/cmd/config/config.go @@ -3,8 +3,9 @@ package config import ( "fmt" - "github.com/coollabsio/coolify-cli/internal/config" "github.com/spf13/cobra" + + "github.com/coollabsio/coolify-cli/internal/config" ) // NewConfigCommand creates the config command @@ -13,7 +14,7 @@ func NewConfigCommand() *cobra.Command { Use: "config", Short: "Show configuration file location", Long: "Display the path to the Coolify CLI configuration file", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println(config.Path()) }, } diff --git a/cmd/context/add.go b/cmd/context/add.go index 019ac51..865806d 100644 --- a/cmd/context/add.go +++ b/cmd/context/add.go @@ -3,10 +3,11 @@ package context import ( "fmt" - "github.com/coollabsio/coolify-cli/internal/cli" - "github.com/coollabsio/coolify-cli/internal/config" "github.com/spf13/cobra" "github.com/spf13/viper" + + "github.com/coollabsio/coolify-cli/internal/cli" + "github.com/coollabsio/coolify-cli/internal/config" ) // NewAddCommand creates the add command @@ -44,7 +45,10 @@ func NewAddCommand() *cobra.Command { fmt.Printf("%s already exists. Force overwriting.\n", name) } viper.Set("instances", instances) - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + fmt.Printf("failed to write config: %v\n", err) + return + } return } fmt.Printf("%s already exists.\n", name) diff --git a/cmd/context/delete.go b/cmd/context/delete.go index 4ffa21e..34e6d7f 100644 --- a/cmd/context/delete.go +++ b/cmd/context/delete.go @@ -2,11 +2,12 @@ package context import ( "fmt" + "slices" - "github.com/coollabsio/coolify-cli/internal/cli" "github.com/spf13/cobra" "github.com/spf13/viper" - "slices" + + "github.com/coollabsio/coolify-cli/internal/cli" ) // NewDeleteCommand creates the delete command @@ -17,7 +18,7 @@ func NewDeleteCommand() *cobra.Command { Args: cli.ExactArgs(1, ""), Short: "Delete a context", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { Name := args[0] instances := viper.Get("instances").([]interface{}) for i, instance := range instances { @@ -25,13 +26,17 @@ func NewDeleteCommand() *cobra.Command { if instanceMap["name"] == Name { instances = slices.Delete(instances, i, i+1) viper.Set("instances", instances) - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + fmt.Printf("failed to write config: %v\n", err) + } if instanceMap["default"] == true { if len(instances) > 0 { instances[0].(map[string]interface{})["default"] = true viper.Set("instances", instances) - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + fmt.Printf("failed to write config: %v\n", err) + } newDefaultName := instances[0].(map[string]interface{})["name"] fmt.Printf("Context '%s' deleted. '%s' is now the default context.\n", Name, newDefaultName) } else { diff --git a/cmd/context/get.go b/cmd/context/get.go index 7ff18dc..8a31a9d 100644 --- a/cmd/context/get.go +++ b/cmd/context/get.go @@ -3,11 +3,12 @@ package context import ( "fmt" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/config" "github.com/coollabsio/coolify-cli/internal/output" - "github.com/spf13/cobra" - "github.com/spf13/viper" ) // NewGetCommand creates the get command diff --git a/cmd/context/list.go b/cmd/context/list.go index 47f6949..03a7f59 100644 --- a/cmd/context/list.go +++ b/cmd/context/list.go @@ -1,10 +1,11 @@ package context import ( - "github.com/coollabsio/coolify-cli/internal/config" - "github.com/coollabsio/coolify-cli/internal/output" "github.com/spf13/cobra" "github.com/spf13/viper" + + "github.com/coollabsio/coolify-cli/internal/config" + "github.com/coollabsio/coolify-cli/internal/output" ) // NewListCommand creates the list command @@ -12,7 +13,7 @@ func NewListCommand() *cobra.Command { return &cobra.Command{ Use: "list", Short: "List all configured contexts", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { // Get instances from viper (returns []interface{}) instancesRaw := viper.Get("instances") if instancesRaw == nil { diff --git a/cmd/context/set_default.go b/cmd/context/set_default.go index 9ac49e4..7b03c60 100644 --- a/cmd/context/set_default.go +++ b/cmd/context/set_default.go @@ -3,9 +3,10 @@ package context import ( "fmt" - "github.com/coollabsio/coolify-cli/internal/cli" "github.com/spf13/cobra" "github.com/spf13/viper" + + "github.com/coollabsio/coolify-cli/internal/cli" ) // NewSetTokenCommand creates the set-token command @@ -32,13 +33,13 @@ func NewSetDefaultCommand() *cobra.Command { if !found { return fmt.Errorf("Context '%s' not found", name) - } else { - // Only unset other defaults if we found the target instance - for _, instance := range instances { - instanceMap := instance.(map[string]interface{}) - if instanceMap["name"] != name { - instanceMap["default"] = false - } + } + + // Only unset other defaults if we found the target instance + for _, instance := range instances { + instanceMap := instance.(map[string]interface{}) + if instanceMap["name"] != name { + instanceMap["default"] = false } } diff --git a/cmd/context/set_token.go b/cmd/context/set_token.go index 273648d..db19575 100644 --- a/cmd/context/set_token.go +++ b/cmd/context/set_token.go @@ -3,9 +3,10 @@ package context import ( "fmt" - "github.com/coollabsio/coolify-cli/internal/cli" "github.com/spf13/cobra" "github.com/spf13/viper" + + "github.com/coollabsio/coolify-cli/internal/cli" ) // NewSetTokenCommand creates the set-token command @@ -15,7 +16,7 @@ func NewSetTokenCommand() *cobra.Command { Example: `context set-token myserver your-new-api-token`, Args: cli.ExactArgs(2, " "), Short: "Update the API token for a context", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, args []string) { name := args[0] token := args[1] var found interface{} @@ -38,7 +39,11 @@ func NewSetTokenCommand() *cobra.Command { } } viper.Set("instances", instances) - viper.WriteConfig() + err := viper.WriteConfig() + if err != nil { + fmt.Printf("Failed to update token for context '%s': %v\n", name, err) + return + } fmt.Printf("Token updated for context '%s'.\n", name) }, } diff --git a/cmd/context/update.go b/cmd/context/update.go index 103695b..0ff7639 100644 --- a/cmd/context/update.go +++ b/cmd/context/update.go @@ -3,9 +3,10 @@ package context import ( "fmt" - "github.com/coollabsio/coolify-cli/internal/cli" "github.com/spf13/cobra" "github.com/spf13/viper" + + "github.com/coollabsio/coolify-cli/internal/cli" ) // NewUpdateCommand creates the update command diff --git a/cmd/context/use.go b/cmd/context/use.go index 2729241..e422e9f 100644 --- a/cmd/context/use.go +++ b/cmd/context/use.go @@ -3,9 +3,10 @@ package context import ( "fmt" - "github.com/coollabsio/coolify-cli/internal/cli" "github.com/spf13/cobra" "github.com/spf13/viper" + + "github.com/coollabsio/coolify-cli/internal/cli" ) // NewUseCommand creates the use command @@ -15,7 +16,7 @@ func NewUseCommand() *cobra.Command { Example: `context use myserver`, Args: cli.ExactArgs(1, ""), Short: "Switch to a different context (set as default)", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { name := args[0] instances := viper.Get("instances").([]interface{}) diff --git a/cmd/context/verify.go b/cmd/context/verify.go index 639d59b..5b027c7 100644 --- a/cmd/context/verify.go +++ b/cmd/context/verify.go @@ -4,8 +4,9 @@ import ( "context" "fmt" - "github.com/coollabsio/coolify-cli/internal/cli" "github.com/spf13/cobra" + + "github.com/coollabsio/coolify-cli/internal/cli" ) // NewVerifyCommand creates the verify command for contexts @@ -15,7 +16,7 @@ func NewVerifyCommand() *cobra.Command { Short: "Verify current context connection and authentication", Long: `Verify that the current context is properly configured by testing the connection to the Coolify instance and validating the API token.`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() // Get API client - this will use the current default context diff --git a/cmd/context/verify_test.go b/cmd/context/verify_test.go index 55c25d1..6a6959e 100644 --- a/cmd/context/verify_test.go +++ b/cmd/context/verify_test.go @@ -7,9 +7,10 @@ import ( "net/http/httptest" "testing" - "github.com/coollabsio/coolify-cli/internal/api" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/coollabsio/coolify-cli/internal/api" ) // TestVerifyCommand_APIIntegration tests the verify logic using the API client directly @@ -21,7 +22,7 @@ func TestVerifyCommand_APIIntegration(t *testing.T) { assert.Equal(t, "/api/v1/version", r.URL.Path) assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization")) w.WriteHeader(http.StatusOK) - w.Write([]byte("4.0.0-beta.383")) + _, _ = w.Write([]byte("4.0.0-beta.383")) })) defer server.Close() @@ -36,9 +37,9 @@ func TestVerifyCommand_APIIntegration(t *testing.T) { t.Run("unauthorized - invalid token", func(t *testing.T) { // Create a test HTTP server that returns 401 - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnauthorized) - json.NewEncoder(w).Encode(map[string]string{ + _ = json.NewEncoder(w).Encode(map[string]string{ "message": "Invalid token", }) })) @@ -55,9 +56,9 @@ func TestVerifyCommand_APIIntegration(t *testing.T) { t.Run("server error", func(t *testing.T) { // Create a test HTTP server that returns 500 - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) - json.NewEncoder(w).Encode(map[string]string{ + _ = json.NewEncoder(w).Encode(map[string]string{ "error": "Internal server error", }) })) @@ -76,9 +77,9 @@ func TestVerifyCommand_APIIntegration(t *testing.T) { t.Run("not found", func(t *testing.T) { // Create a test HTTP server that returns 404 - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) - json.NewEncoder(w).Encode(map[string]string{ + _ = json.NewEncoder(w).Encode(map[string]string{ "message": "Endpoint not found", }) })) diff --git a/cmd/context/version.go b/cmd/context/version.go index 963d7ea..38fa65a 100644 --- a/cmd/context/version.go +++ b/cmd/context/version.go @@ -4,8 +4,9 @@ import ( "context" "fmt" - "github.com/coollabsio/coolify-cli/internal/cli" "github.com/spf13/cobra" + + "github.com/coollabsio/coolify-cli/internal/cli" ) // NewVersionCommand creates the version command for contexts @@ -13,7 +14,7 @@ func NewVersionCommand() *cobra.Command { return &cobra.Command{ Use: "version", Short: "Get current context's Coolify version", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() // Get API client diff --git a/cmd/database/backup/create.go b/cmd/database/backup/create.go index 1e5cebb..1577881 100644 --- a/cmd/database/backup/create.go +++ b/cmd/database/backup/create.go @@ -4,11 +4,12 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewCreateCommand creates a new database diff --git a/cmd/database/backup/delete-execution.go b/cmd/database/backup/delete-execution.go index ee635dd..bb63d96 100644 --- a/cmd/database/backup/delete-execution.go +++ b/cmd/database/backup/delete-execution.go @@ -7,9 +7,10 @@ import ( "os" "strings" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewDeleteExecutionCommand lists all databases diff --git a/cmd/database/backup/delete.go b/cmd/database/backup/delete.go index 57e4a80..63638f1 100644 --- a/cmd/database/backup/delete.go +++ b/cmd/database/backup/delete.go @@ -7,9 +7,10 @@ import ( "os" "strings" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewDeleteCommand deletes a database diff --git a/cmd/database/backup/execution.go b/cmd/database/backup/execution.go index bedb8d7..8d44bc1 100644 --- a/cmd/database/backup/execution.go +++ b/cmd/database/backup/execution.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewExecutionCommand lists all databases diff --git a/cmd/database/backup/list.go b/cmd/database/backup/list.go index c556d39..5b2419a 100644 --- a/cmd/database/backup/list.go +++ b/cmd/database/backup/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewListCommand lists all databases diff --git a/cmd/database/backup/trigger.go b/cmd/database/backup/trigger.go index 55c7d18..a0bc49a 100644 --- a/cmd/database/backup/trigger.go +++ b/cmd/database/backup/trigger.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewTriggerCommand triggers a database backup diff --git a/cmd/database/backup/update.go b/cmd/database/backup/update.go index 75e8274..cb3ddf7 100644 --- a/cmd/database/backup/update.go +++ b/cmd/database/backup/update.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewUpdateCommand updates a database diff --git a/cmd/database/create.go b/cmd/database/create.go index 01fe1e0..96a8feb 100644 --- a/cmd/database/create.go +++ b/cmd/database/create.go @@ -5,11 +5,12 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewCreateCommand() *cobra.Command { @@ -116,7 +117,7 @@ Examples: } if cmd.Flags().Changed("postgres-db") { db, _ := cmd.Flags().GetString("postgres-db") - req.PostgresDb = &db + req.PostgresDB = &db } } diff --git a/cmd/database/delete.go b/cmd/database/delete.go index d66dd4a..a7bbb1c 100644 --- a/cmd/database/delete.go +++ b/cmd/database/delete.go @@ -7,9 +7,10 @@ import ( "os" "strings" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewDeleteCommand deletes a database diff --git a/cmd/database/get.go b/cmd/database/get.go index 959f2dd..f1b3ca8 100644 --- a/cmd/database/get.go +++ b/cmd/database/get.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewGetCommand gets database details diff --git a/cmd/database/list.go b/cmd/database/list.go index f14702d..ec22855 100644 --- a/cmd/database/list.go +++ b/cmd/database/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewListCommand lists all databases @@ -16,7 +17,7 @@ func NewListCommand() *cobra.Command { Use: "list", Short: "List all databases", Long: `List all databases in Coolify.`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() client, err := cli.GetAPIClient(cmd) diff --git a/cmd/database/restart.go b/cmd/database/restart.go index 1478bce..3d918f0 100644 --- a/cmd/database/restart.go +++ b/cmd/database/restart.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewRestartCommand restarts a database diff --git a/cmd/database/start.go b/cmd/database/start.go index 5417334..3582f5d 100644 --- a/cmd/database/start.go +++ b/cmd/database/start.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewStartCommand starts a database diff --git a/cmd/database/stop.go b/cmd/database/stop.go index fc774fc..08b7c70 100644 --- a/cmd/database/stop.go +++ b/cmd/database/stop.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewStopCommand stops a database diff --git a/cmd/database/update.go b/cmd/database/update.go index 5f99e59..ba33415 100644 --- a/cmd/database/update.go +++ b/cmd/database/update.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewUpdateCommand updates a database diff --git a/cmd/deployment/batch.go b/cmd/deployment/batch.go index 31dbf08..46a6c4c 100644 --- a/cmd/deployment/batch.go +++ b/cmd/deployment/batch.go @@ -5,9 +5,10 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewBatchCommand deploys multiple resources by name diff --git a/cmd/deployment/cancel.go b/cmd/deployment/cancel.go index 7e7f8da..51215b8 100644 --- a/cmd/deployment/cancel.go +++ b/cmd/deployment/cancel.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewCancelCommand cancels a deployment @@ -35,9 +36,11 @@ func NewCancelCommand() *cobra.Command { // Prompt for confirmation unless --force is used if !force { - var response string fmt.Printf("Are you sure you want to cancel deployment %s? (yes/no): ", uuid) - fmt.Scanln(&response) + var response string + if _, err := fmt.Scanln(&response); err != nil { + return fmt.Errorf("failed to read confirmation: %w", err) + } if response != "yes" && response != "y" { fmt.Println("Cancel aborted.") diff --git a/cmd/deployment/get.go b/cmd/deployment/get.go index 155f07b..16af068 100644 --- a/cmd/deployment/get.go +++ b/cmd/deployment/get.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewGetCommand gets deployment details diff --git a/cmd/deployment/list.go b/cmd/deployment/list.go index 62cc283..db9ed02 100644 --- a/cmd/deployment/list.go +++ b/cmd/deployment/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewListCommand lists all deployments @@ -16,7 +17,7 @@ func NewListCommand() *cobra.Command { Use: "list", Short: "List all deployments", Long: `List all currently running deployments across all resources.`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() client, err := cli.GetAPIClient(cmd) diff --git a/cmd/deployment/name.go b/cmd/deployment/name.go index ef4b7f2..4896d8e 100644 --- a/cmd/deployment/name.go +++ b/cmd/deployment/name.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewNameCommand deploys a resource by name diff --git a/cmd/deployment/uuid.go b/cmd/deployment/uuid.go index 4df4b9c..569e672 100644 --- a/cmd/deployment/uuid.go +++ b/cmd/deployment/uuid.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // ResultDisplay represents a deploy result for table display diff --git a/cmd/docs.go b/cmd/docs.go index f1f1b11..ce774d3 100644 --- a/cmd/docs.go +++ b/cmd/docs.go @@ -23,11 +23,11 @@ var manCmd = &cobra.Command{ The man pages will be written to the specified directory (default: ./man).`, Example: ` coolify docs man coolify docs man --output-dir=/usr/local/share/man/man1`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { outputDir, _ := cmd.Flags().GetString("output-dir") // Create output directory if it doesn't exist - if err := os.MkdirAll(outputDir, 0755); err != nil { + if err := os.MkdirAll(outputDir, 0750); err != nil { return fmt.Errorf("failed to create output directory: %w", err) } @@ -65,11 +65,11 @@ var markdownCmd = &cobra.Command{ The markdown files will be written to the specified directory (default: ./docs).`, Example: ` coolify docs markdown coolify docs markdown --output-dir=./documentation`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { outputDir, _ := cmd.Flags().GetString("output-dir") // Create output directory if it doesn't exist - if err := os.MkdirAll(outputDir, 0755); err != nil { + if err := os.MkdirAll(outputDir, 0750); err != nil { return fmt.Errorf("failed to create output directory: %w", err) } diff --git a/cmd/github/branches.go b/cmd/github/branches.go index 98d4a41..3bab9c2 100644 --- a/cmd/github/branches.go +++ b/cmd/github/branches.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewListBranchesCommand() *cobra.Command { diff --git a/cmd/github/create.go b/cmd/github/create.go index 5c58aef..78ef420 100644 --- a/cmd/github/create.go +++ b/cmd/github/create.go @@ -4,11 +4,12 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewCreateCommand() *cobra.Command { @@ -20,7 +21,7 @@ func NewCreateCommand() *cobra.Command { Required flags: --name, --api-url, --html-url, --app-id, --installation-id, --client-id, --client-secret, --private-key-uuid Example: coolify github create --name "My GitHub App" --api-url "https://api.github.com" --html-url "https://github.com" --app-id 123456 --installation-id 789012 --client-id "Iv1.abc123" --client-secret "secret123" --private-key-uuid "abc-123-def-456"`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() client, err := cli.GetAPIClient(cmd) @@ -100,14 +101,14 @@ Example: coolify github create --name "My GitHub App" --api-url "https://api.git createCmd.Flags().String("private-key-uuid", "", "UUID of existing private key (required)") createCmd.Flags().Bool("system-wide", false, "Is this app system-wide (cloud only)") - createCmd.MarkFlagRequired("name") - createCmd.MarkFlagRequired("api-url") - createCmd.MarkFlagRequired("html-url") - createCmd.MarkFlagRequired("app-id") - createCmd.MarkFlagRequired("installation-id") - createCmd.MarkFlagRequired("client-id") - createCmd.MarkFlagRequired("client-secret") - createCmd.MarkFlagRequired("private-key-uuid") + _ = createCmd.MarkFlagRequired("name") + _ = createCmd.MarkFlagRequired("api-url") + _ = createCmd.MarkFlagRequired("html-url") + _ = createCmd.MarkFlagRequired("app-id") + _ = createCmd.MarkFlagRequired("installation-id") + _ = createCmd.MarkFlagRequired("client-id") + _ = createCmd.MarkFlagRequired("client-secret") + _ = createCmd.MarkFlagRequired("private-key-uuid") return createCmd } diff --git a/cmd/github/delete.go b/cmd/github/delete.go index d96b62c..2be782b 100644 --- a/cmd/github/delete.go +++ b/cmd/github/delete.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewDeleteCommand() *cobra.Command { @@ -30,7 +31,11 @@ func NewDeleteCommand() *cobra.Command { if !force { var response string fmt.Printf("Are you sure you want to delete GitHub App %s? This cannot be undone. (yes/no): ", appUUID) - fmt.Scanln(&response) + _, err := fmt.Scanln(&response) + + if err != nil { + return fmt.Errorf("failed to read confirmation: %w", err) + } if response != "yes" && response != "y" { fmt.Println("Delete cancelled.") diff --git a/cmd/github/get.go b/cmd/github/get.go index d7be84a..eff837d 100644 --- a/cmd/github/get.go +++ b/cmd/github/get.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewGetCommand() *cobra.Command { diff --git a/cmd/github/list.go b/cmd/github/list.go index 8f0e39a..f3430eb 100644 --- a/cmd/github/list.go +++ b/cmd/github/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewListCommand() *cobra.Command { @@ -15,7 +16,7 @@ func NewListCommand() *cobra.Command { Use: "list", Short: "List all GitHub App integrations", Long: `List all GitHub App integrations configured in Coolify.`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() client, err := cli.GetAPIClient(cmd) diff --git a/cmd/github/repo.go b/cmd/github/repo.go index bd5873b..9eb7bb9 100644 --- a/cmd/github/repo.go +++ b/cmd/github/repo.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewListRepositoriesCommand() *cobra.Command { diff --git a/cmd/github/update.go b/cmd/github/update.go index f3897d8..fa93c77 100644 --- a/cmd/github/update.go +++ b/cmd/github/update.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewUpdateCommand() *cobra.Command { diff --git a/cmd/privatekeys/create.go b/cmd/privatekeys/create.go index aac135b..b17f47f 100644 --- a/cmd/privatekeys/create.go +++ b/cmd/privatekeys/create.go @@ -5,10 +5,11 @@ import ( "fmt" "os" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewCreateCommand creates the create command diff --git a/cmd/privatekeys/delete.go b/cmd/privatekeys/delete.go index cedc18e..4ab2076 100644 --- a/cmd/privatekeys/delete.go +++ b/cmd/privatekeys/delete.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewDeleteCommand creates the delete command diff --git a/cmd/privatekeys/list.go b/cmd/privatekeys/list.go index 2e61ce1..2a2acd6 100644 --- a/cmd/privatekeys/list.go +++ b/cmd/privatekeys/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewListCommand creates the list command @@ -15,7 +16,7 @@ func NewListCommand() *cobra.Command { return &cobra.Command{ Use: "list", Short: "List all private keys", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() client, err := cli.GetAPIClient(cmd) diff --git a/cmd/project/get.go b/cmd/project/get.go index f0400fc..fe058a4 100644 --- a/cmd/project/get.go +++ b/cmd/project/get.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // EnvironmentRow represents an environment for display @@ -55,7 +56,7 @@ func NewGetCommand() *cobra.Command { var rows []EnvironmentRow // If the project has environments, expand them - if project.Environments != nil && len(project.Environments) > 0 { + if len(project.Environments) > 0 { for _, env := range project.Environments { rows = append(rows, EnvironmentRow{ UUID: env.UUID, diff --git a/cmd/project/list.go b/cmd/project/list.go index b660ff4..db81532 100644 --- a/cmd/project/list.go +++ b/cmd/project/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // ListRow represents a project for list display (without environments) @@ -22,7 +23,7 @@ func NewListCommand() *cobra.Command { return &cobra.Command{ Use: "list", Short: "List all projects", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() client, err := cli.GetAPIClient(cmd) diff --git a/cmd/resources/list.go b/cmd/resources/list.go index 8fb48f9..e0166aa 100644 --- a/cmd/resources/list.go +++ b/cmd/resources/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewListCommand returns the list projects command @@ -15,7 +16,7 @@ func NewListCommand() *cobra.Command { return &cobra.Command{ Use: "list", Short: "List all resources", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() client, err := cli.GetAPIClient(cmd) diff --git a/cmd/root.go b/cmd/root.go index c55e964..920842e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,10 +1,14 @@ package cmd import ( + "errors" "fmt" "log" "os" - "text/tabwriter" + + compareVersion "github.com/hashicorp/go-version" + "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/coollabsio/coolify-cli/cmd/application" "github.com/coollabsio/coolify-cli/cmd/completion" @@ -23,9 +27,6 @@ import ( cliversion "github.com/coollabsio/coolify-cli/cmd/version" "github.com/coollabsio/coolify-cli/internal/config" "github.com/coollabsio/coolify-cli/internal/version" - compareVersion "github.com/hashicorp/go-version" - "github.com/spf13/cobra" - "github.com/spf13/viper" ) // Legacy global variables - kept for backward compatibility during migration @@ -39,10 +40,9 @@ var ( Debug bool ShowSensitive bool Format string - JsonMode bool + JSONMode bool PrettyMode bool SetDefaultInstance bool - w = tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', tabwriter.Debug) ) var rootCmd = &cobra.Command{ @@ -51,7 +51,7 @@ var rootCmd = &cobra.Command{ Long: `A CLI tool to interact with Coolify API.`, SilenceUsage: true, // Don't show usage on errors SilenceErrors: false, // Still print errors - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + PersistentPreRunE: func(_ *cobra.Command, _ []string) error { return nil }, } @@ -71,7 +71,7 @@ func init() { Long: fmt.Sprintf("A CLI tool to interact with Coolify API.\nVersion: %s", version.CliVersion), SilenceUsage: true, // Don't show usage on errors SilenceErrors: false, // Still print errors - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + PersistentPreRunE: func(_ *cobra.Command, _ []string) error { return nil }, } @@ -112,11 +112,14 @@ func initConfig() { // Ensure config directory exists configDir := config.Path()[:len(config.Path())-len("/config.json")] if _, err := os.Stat(configDir); os.IsNotExist(err) { - os.MkdirAll(configDir, 0755) + if err := os.MkdirAll(configDir, 0750); err != nil { + log.Printf("Failed to create config directory: %v\n", err) + } } if err := viper.ReadInConfig(); err != nil { - if _, ok := err.(viper.ConfigFileNotFoundError); ok { + var notFoundErr viper.ConfigFileNotFoundError + if errors.As(err, ¬FoundErr) { log.Println("Config file not found. Creating a new one at", config.Path()) if err := config.CreateDefault(); err != nil { log.Printf("Failed to create default config: %v\n", err) diff --git a/cmd/server/add.go b/cmd/server/add.go index 9e1dacc..7146c01 100644 --- a/cmd/server/add.go +++ b/cmd/server/add.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewAddCommand creates the add command @@ -28,7 +29,7 @@ func NewAddCommand() *cobra.Command { // Parse arguments and flags name := args[0] ip := args[1] - privateKeyUuid := args[2] + privateKeyUUID := args[2] port, _ := cmd.Flags().GetInt("port") user, _ := cmd.Flags().GetString("user") validate, _ := cmd.Flags().GetBool("validate") @@ -39,7 +40,7 @@ func NewAddCommand() *cobra.Command { IP: ip, Port: port, User: user, - PrivateKeyUUID: privateKeyUuid, + PrivateKeyUUID: privateKeyUUID, InstantValidate: validate, } diff --git a/cmd/server/domain.go b/cmd/server/domain.go index 2e3ab19..89de1d5 100644 --- a/cmd/server/domain.go +++ b/cmd/server/domain.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewGetCommand creates the get command diff --git a/cmd/server/get.go b/cmd/server/get.go index 9779094..cb79f1c 100644 --- a/cmd/server/get.go +++ b/cmd/server/get.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewGetCommand creates the get command diff --git a/cmd/server/list.go b/cmd/server/list.go index 53c9da7..1bfe070 100644 --- a/cmd/server/list.go +++ b/cmd/server/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewListCommand creates the list command @@ -15,7 +16,7 @@ func NewListCommand() *cobra.Command { return &cobra.Command{ Use: "list", Short: "List all servers", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() // Get API client diff --git a/cmd/server/remove.go b/cmd/server/remove.go index 7de131d..9f5a69f 100644 --- a/cmd/server/remove.go +++ b/cmd/server/remove.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewRemoveCommand creates the remove command diff --git a/cmd/server/validate.go b/cmd/server/validate.go index f1124f8..db84624 100644 --- a/cmd/server/validate.go +++ b/cmd/server/validate.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewValidateCommand creates the validate command diff --git a/cmd/service/delete.go b/cmd/service/delete.go index 80c9bf3..cea0540 100644 --- a/cmd/service/delete.go +++ b/cmd/service/delete.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewDeleteCommand deletes a service @@ -35,7 +36,11 @@ func NewDeleteCommand() *cobra.Command { if !force { var response string fmt.Printf("Are you sure you want to delete this service? (yes/no): ") - fmt.Scanln(&response) + _, err := fmt.Scanln(&response) + + if err != nil { + return fmt.Errorf("failed to read confirmation: %w", err) + } if response != "yes" && response != "y" { fmt.Println("Delete cancelled.") @@ -43,7 +48,7 @@ func NewDeleteCommand() *cobra.Command { } } - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) err = serviceSvc.Delete(ctx, uuid, deleteConfigurations, deleteVolumes, dockerCleanup, deleteConnectedNetworks) if err != nil { return fmt.Errorf("failed to delete service: %w", err) diff --git a/cmd/service/env/create.go b/cmd/service/env/create.go index 8e27e99..2a27ba0 100644 --- a/cmd/service/env/create.go +++ b/cmd/service/env/create.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewCreateCommand() *cobra.Command { @@ -58,7 +59,7 @@ func NewCreateCommand() *cobra.Command { req.IsMultiline = &isMultiline } - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) env, err := serviceSvc.CreateEnv(ctx, uuid, req) if err != nil { return fmt.Errorf("failed to create environment variable: %w", err) diff --git a/cmd/service/env/delete.go b/cmd/service/env/delete.go index 806be05..ae4cd36 100644 --- a/cmd/service/env/delete.go +++ b/cmd/service/env/delete.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewDeleteCommand() *cobra.Command { @@ -31,7 +32,7 @@ func NewDeleteCommand() *cobra.Command { if !force { var response string fmt.Printf("Are you sure you want to delete this environment variable? (yes/no): ") - fmt.Scanln(&response) + _, _ = fmt.Scanln(&response) if response != "yes" && response != "y" { fmt.Println("Delete cancelled.") @@ -39,7 +40,7 @@ func NewDeleteCommand() *cobra.Command { } } - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) err = serviceSvc.DeleteEnv(ctx, serviceUUID, envUUID) if err != nil { return fmt.Errorf("failed to delete environment variable: %w", err) diff --git a/cmd/service/env/get.go b/cmd/service/env/get.go index 8a92ba3..b004645 100644 --- a/cmd/service/env/get.go +++ b/cmd/service/env/get.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewGetCommand() *cobra.Command { @@ -26,7 +27,7 @@ func NewGetCommand() *cobra.Command { return fmt.Errorf("failed to get API client: %w", err) } - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) env, err := serviceSvc.GetEnv(ctx, serviceUUID, envUUID) if err != nil { return fmt.Errorf("failed to get environment variable: %w", err) diff --git a/cmd/service/env/list.go b/cmd/service/env/list.go index a1ba557..5c5619b 100644 --- a/cmd/service/env/list.go +++ b/cmd/service/env/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewListCommand() *cobra.Command { @@ -25,7 +26,7 @@ func NewListCommand() *cobra.Command { return fmt.Errorf("failed to get API client: %w", err) } - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) envs, err := serviceSvc.ListEnvs(ctx, uuid) if err != nil { return fmt.Errorf("failed to list environment variables: %w", err) diff --git a/cmd/service/env/sync.go b/cmd/service/env/sync.go index ed880f9..91b2a6a 100644 --- a/cmd/service/env/sync.go +++ b/cmd/service/env/sync.go @@ -5,11 +5,12 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/parser" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewSyncCommand() *cobra.Command { @@ -55,7 +56,7 @@ Example: coolify service env sync abc123 --file .env.production`, fmt.Printf("Found %d environment variables in file. Syncing...\n", len(envVars)) // Fetch existing environment variables - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) existingEnvs, err := serviceSvc.ListEnvs(ctx, uuid) if err != nil { return fmt.Errorf("failed to list existing environment variables: %w", err) diff --git a/cmd/service/env/update.go b/cmd/service/env/update.go index 0afdab2..52a990c 100644 --- a/cmd/service/env/update.go +++ b/cmd/service/env/update.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/models" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) func NewUpdateCommand() *cobra.Command { @@ -61,7 +62,7 @@ func NewUpdateCommand() *cobra.Command { return fmt.Errorf("at least one field must be provided to update (--key, --value, --build-time, --preview, --is-literal, or --is-multiline)") } - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) env, err := serviceSvc.UpdateEnv(ctx, serviceUUID, req) if err != nil { return fmt.Errorf("failed to update environment variable: %w", err) diff --git a/cmd/service/get.go b/cmd/service/get.go index e284679..83764d9 100644 --- a/cmd/service/get.go +++ b/cmd/service/get.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewGetCommand gets service details @@ -26,7 +27,7 @@ func NewGetCommand() *cobra.Command { return fmt.Errorf("failed to get API client: %w", err) } - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) svc, err := serviceSvc.Get(ctx, uuid) if err != nil { return fmt.Errorf("failed to get service: %w", err) diff --git a/cmd/service/list.go b/cmd/service/list.go index f626bc5..56d5323 100644 --- a/cmd/service/list.go +++ b/cmd/service/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewListCommand lists all services @@ -16,7 +17,7 @@ func NewListCommand() *cobra.Command { Use: "list", Short: "List all services", Long: `List all services in Coolify.`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() client, err := cli.GetAPIClient(cmd) @@ -24,7 +25,7 @@ func NewListCommand() *cobra.Command { return fmt.Errorf("failed to get API client: %w", err) } - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) services, err := serviceSvc.List(ctx) if err != nil { return fmt.Errorf("failed to list services: %w", err) diff --git a/cmd/service/restart.go b/cmd/service/restart.go index b9a278d..a8c4502 100644 --- a/cmd/service/restart.go +++ b/cmd/service/restart.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewRestartCommand restarts a service @@ -25,7 +26,7 @@ func NewRestartCommand() *cobra.Command { return fmt.Errorf("failed to get API client: %w", err) } - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) resp, err := serviceSvc.Restart(ctx, uuid) if err != nil { return fmt.Errorf("failed to restart service: %w", err) diff --git a/cmd/service/start.go b/cmd/service/start.go index 44f4943..bb8ab3c 100644 --- a/cmd/service/start.go +++ b/cmd/service/start.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewStartCommand starts a service @@ -25,7 +26,7 @@ func NewStartCommand() *cobra.Command { return fmt.Errorf("failed to get API client: %w", err) } - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) resp, err := serviceSvc.Start(ctx, uuid) if err != nil { return fmt.Errorf("failed to start service: %w", err) diff --git a/cmd/service/stop.go b/cmd/service/stop.go index a3de935..3812639 100644 --- a/cmd/service/stop.go +++ b/cmd/service/stop.go @@ -4,9 +4,10 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewStopCommand stops a service @@ -25,7 +26,7 @@ func NewStopCommand() *cobra.Command { return fmt.Errorf("failed to get API client: %w", err) } - serviceSvc := service.NewServiceService(client) + serviceSvc := service.NewService(client) resp, err := serviceSvc.Stop(ctx, uuid) if err != nil { return fmt.Errorf("failed to stop service: %w", err) diff --git a/cmd/teams/current.go b/cmd/teams/current.go index 85ec396..6e97fce 100644 --- a/cmd/teams/current.go +++ b/cmd/teams/current.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewCurrentCommand creates the current command @@ -16,7 +17,7 @@ func NewCurrentCommand() *cobra.Command { Use: "current", Short: "Get currently authenticated team", Long: `Get details of the team associated with the current authentication token.`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() client, err := cli.GetAPIClient(cmd) diff --git a/cmd/teams/get.go b/cmd/teams/get.go index 46fb4f4..1561267 100644 --- a/cmd/teams/get.go +++ b/cmd/teams/get.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewGetCommand creates the get command diff --git a/cmd/teams/list.go b/cmd/teams/list.go index 92ce078..9f6270b 100644 --- a/cmd/teams/list.go +++ b/cmd/teams/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewListCommand creates the list command @@ -16,7 +17,7 @@ func NewListCommand() *cobra.Command { Use: "list", Short: "List all teams", Long: `List all teams you have access to.`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() client, err := cli.GetAPIClient(cmd) diff --git a/cmd/teams/members/list.go b/cmd/teams/members/list.go index 3bbd77d..3c6c763 100644 --- a/cmd/teams/members/list.go +++ b/cmd/teams/members/list.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/cli" "github.com/coollabsio/coolify-cli/internal/output" "github.com/coollabsio/coolify-cli/internal/service" - "github.com/spf13/cobra" ) // NewListCommand creates the list command diff --git a/cmd/teams/teams.go b/cmd/teams/teams.go index 5ab5c5a..d2ad9a8 100644 --- a/cmd/teams/teams.go +++ b/cmd/teams/teams.go @@ -1,8 +1,9 @@ package teams import ( - "github.com/coollabsio/coolify-cli/cmd/teams/members" "github.com/spf13/cobra" + + "github.com/coollabsio/coolify-cli/cmd/teams/members" ) // NewTeamsCommand creates the teams parent command diff --git a/cmd/update/update.go b/cmd/update/update.go index 320d22d..523c37f 100644 --- a/cmd/update/update.go +++ b/cmd/update/update.go @@ -7,17 +7,18 @@ import ( "os" "runtime" - "github.com/coollabsio/coolify-cli/internal/version" selfupdate "github.com/creativeprojects/go-selfupdate" compareVersion "github.com/hashicorp/go-version" "github.com/spf13/cobra" + + "github.com/coollabsio/coolify-cli/internal/version" ) func NewUpdateCommand() *cobra.Command { return &cobra.Command{ Use: "update", Short: "Update Coolify CLI", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { latest, found, err := selfupdate.DetectLatest(context.Background(), selfupdate.ParseSlug("coollabsio/coolify-cli")) if err != nil { log.Printf("Error occurred while detecting version: %v", err) diff --git a/cmd/version/version.go b/cmd/version/version.go index a0137a6..e8e4917 100644 --- a/cmd/version/version.go +++ b/cmd/version/version.go @@ -3,8 +3,9 @@ package version import ( "fmt" - "github.com/coollabsio/coolify-cli/internal/version" "github.com/spf13/cobra" + + "github.com/coollabsio/coolify-cli/internal/version" ) // NewVersionCommand creates the version command @@ -12,7 +13,7 @@ func NewVersionCommand() *cobra.Command { return &cobra.Command{ Use: "version", Short: "Current Coolify CLI version", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println(version.CliVersion) }, } diff --git a/internal/api/client.go b/internal/api/client.go index 5e53ce1..46e29f2 100644 --- a/internal/api/client.go +++ b/internal/api/client.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io" "log" @@ -102,7 +103,8 @@ func (c *Client) doRequest(ctx context.Context, method, path string, body, resul lastErr = err // Don't retry on client errors (4xx) except 429 (rate limit) - if apiErr, ok := err.(*Error); ok { + var apiErr *Error + if errors.As(err, &apiErr) { if apiErr.StatusCode >= 400 && apiErr.StatusCode < 500 && apiErr.StatusCode != 429 { return err } diff --git a/internal/api/client_test.go b/internal/api/client_test.go index 1a7400d..932ecee 100644 --- a/internal/api/client_test.go +++ b/internal/api/client_test.go @@ -51,7 +51,7 @@ func TestClient_Get_Success(t *testing.T) { assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization")) w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode([]ServerResponse{ + _ = json.NewEncoder(w).Encode([]ServerResponse{ {UUID: "uuid-1", Name: "server-1"}, {UUID: "uuid-2", Name: "server-2"}, }) @@ -73,7 +73,7 @@ func TestClient_Get_StringResponse(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/version", r.URL.Path) w.WriteHeader(http.StatusOK) - w.Write([]byte("4.0.0")) + _, _ = w.Write([]byte("4.0.0")) })) defer server.Close() @@ -87,9 +87,9 @@ func TestClient_Get_StringResponse(t *testing.T) { } func TestClient_Get_NotFound(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) - json.NewEncoder(w).Encode(map[string]string{ + _ = json.NewEncoder(w).Encode(map[string]string{ "message": "Server not found", }) })) @@ -110,9 +110,9 @@ func TestClient_Get_NotFound(t *testing.T) { } func TestClient_Get_Unauthorized(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusUnauthorized) - json.NewEncoder(w).Encode(map[string]string{ + _ = json.NewEncoder(w).Encode(map[string]string{ "message": "Invalid token", }) })) @@ -145,13 +145,12 @@ func TestClient_Post_Success(t *testing.T) { assert.Equal(t, "application/json", r.Header.Get("Content-Type")) var req CreateServerRequest - err := json.NewDecoder(r.Body).Decode(&req) - require.NoError(t, err) + _ = json.NewDecoder(r.Body).Decode(&req) assert.Equal(t, "test-server", req.Name) assert.Equal(t, "192.168.1.100", req.IP) w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode(CreateServerResponse{ + _ = json.NewEncoder(w).Encode(CreateServerResponse{ UUID: "new-uuid", Message: "Server created", }) @@ -174,9 +173,9 @@ func TestClient_Post_Success(t *testing.T) { } func TestClient_Post_BadRequest(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(map[string]string{ + _ = json.NewEncoder(w).Encode(map[string]string{ "message": "Invalid IP address", }) })) @@ -200,7 +199,7 @@ func TestClient_Delete_Success(t *testing.T) { assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization")) w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode(map[string]string{ + _ = json.NewEncoder(w).Encode(map[string]string{ "message": "Server deleted", }) })) @@ -217,7 +216,7 @@ func TestClient_GetVersion(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/version", r.URL.Path) w.WriteHeader(http.StatusOK) - w.Write([]byte("4.0.0-beta.383")) + _, _ = w.Write([]byte("4.0.0-beta.383")) })) defer server.Close() @@ -231,14 +230,14 @@ func TestClient_GetVersion(t *testing.T) { func TestClient_Retry_Success(t *testing.T) { attempts := 0 - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { attempts++ if attempts < 3 { w.WriteHeader(http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) - w.Write([]byte("success")) + _, _ = w.Write([]byte("success")) })) defer server.Close() @@ -254,10 +253,10 @@ func TestClient_Retry_Success(t *testing.T) { func TestClient_Retry_NoRetryOn4xx(t *testing.T) { attempts := 0 - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { attempts++ w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(map[string]string{"message": "Bad request"}) + _ = json.NewEncoder(w).Encode(map[string]string{"message": "Bad request"}) })) defer server.Close() @@ -272,7 +271,7 @@ func TestClient_Retry_NoRetryOn4xx(t *testing.T) { } func TestClient_ContextCancellation(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { time.Sleep(100 * time.Millisecond) w.WriteHeader(http.StatusOK) })) @@ -292,7 +291,7 @@ func TestClient_ContextCancellation(t *testing.T) { } func TestClient_Timeout(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { time.Sleep(2 * time.Second) w.WriteHeader(http.StatusOK) })) @@ -308,9 +307,9 @@ func TestClient_Timeout(t *testing.T) { } func TestClient_Debug(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) - w.Write([]byte("test")) + _, _ = w.Write([]byte("test")) })) defer server.Close() diff --git a/internal/cli/client.go b/internal/cli/client.go index 159a113..0f58b40 100644 --- a/internal/cli/client.go +++ b/internal/cli/client.go @@ -3,9 +3,10 @@ package cli import ( "fmt" + "github.com/spf13/cobra" + "github.com/coollabsio/coolify-cli/internal/api" "github.com/coollabsio/coolify-cli/internal/config" - "github.com/spf13/cobra" ) // GetAPIClient creates an API client from command flags or config diff --git a/internal/cli/helpers.go b/internal/cli/helpers.go index e4a54a4..c80840e 100644 --- a/internal/cli/helpers.go +++ b/internal/cli/helpers.go @@ -4,9 +4,10 @@ import ( "context" "fmt" - "github.com/coollabsio/coolify-cli/internal/api" compareVersion "github.com/hashicorp/go-version" "github.com/spf13/cobra" + + "github.com/coollabsio/coolify-cli/internal/api" ) // SensitiveInformationOverlay is the string used to hide sensitive data diff --git a/internal/config/config_test.go b/internal/config/config_test.go index c226b0f..7a057b3 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -119,19 +119,20 @@ func TestConfig_AddInstance(t *testing.T) { t.Run("add second instance keeps first as default", func(t *testing.T) { cfg := New() - cfg.AddInstance(Instance{ + err1 := cfg.AddInstance(Instance{ Name: "first", FQDN: "https://first.io", Token: "token1", }) - err := cfg.AddInstance(Instance{ + err2 := cfg.AddInstance(Instance{ Name: "second", FQDN: "https://second.io", Token: "token2", }) - require.NoError(t, err) + require.NoError(t, err1) + require.NoError(t, err2) assert.Len(t, cfg.Instances, 2) assert.True(t, cfg.Instances[0].Default) assert.False(t, cfg.Instances[1].Default) @@ -140,20 +141,21 @@ func TestConfig_AddInstance(t *testing.T) { t.Run("add instance with default flag", func(t *testing.T) { cfg := New() - cfg.AddInstance(Instance{ + err1 := cfg.AddInstance(Instance{ Name: "first", FQDN: "https://first.io", Token: "token1", }) - err := cfg.AddInstance(Instance{ + err2 := cfg.AddInstance(Instance{ Name: "second", FQDN: "https://second.io", Token: "token2", Default: true, }) - require.NoError(t, err) + require.NoError(t, err1) + require.NoError(t, err2) assert.False(t, cfg.Instances[0].Default) assert.True(t, cfg.Instances[1].Default) }) @@ -161,19 +163,20 @@ func TestConfig_AddInstance(t *testing.T) { t.Run("duplicate name returns error", func(t *testing.T) { cfg := New() - cfg.AddInstance(Instance{ + err := cfg.AddInstance(Instance{ Name: "test", FQDN: "https://test.io", Token: "token1", }) + require.NoError(t, err) - err := cfg.AddInstance(Instance{ + err = cfg.AddInstance(Instance{ Name: "test", FQDN: "https://other.io", Token: "token2", }) - require.Error(t, err) + assert.Contains(t, err.Error(), "already exists") }) @@ -194,41 +197,54 @@ func TestConfig_AddInstance(t *testing.T) { func TestConfig_RemoveInstance(t *testing.T) { t.Run("remove existing instance", func(t *testing.T) { cfg := New() - cfg.AddInstance(Instance{ + err := cfg.AddInstance(Instance{ Name: "first", FQDN: "https://first.io", Token: "token1", }) - cfg.AddInstance(Instance{ + require.NoError(t, err) + + err = cfg.AddInstance(Instance{ Name: "second", FQDN: "https://second.io", Token: "token2", }) - - err := cfg.RemoveInstance("second") - require.NoError(t, err) + + err = cfg.RemoveInstance("second") + require.NoError(t, err) + assert.Len(t, cfg.Instances, 1) assert.Equal(t, "first", cfg.Instances[0].Name) }) t.Run("remove default instance makes first default", func(t *testing.T) { cfg := New() - cfg.AddInstance(Instance{ + // Setup: Create two instances with second as default + err := cfg.AddInstance(Instance{ Name: "first", FQDN: "https://first.io", Token: "token1", }) - cfg.AddInstance(Instance{ + require.NoError(t, err) + + err = cfg.AddInstance(Instance{ Name: "second", FQDN: "https://second.io", Token: "token2", }) - cfg.SetDefault("second") - - err := cfg.RemoveInstance("second") - require.NoError(t, err) + + err = cfg.SetDefault("second") + require.NoError(t, err) + + // Act: Remove the default instance + err = cfg.RemoveInstance("second") + require.NoError(t, err) + + // Assert: Verify removal and default reassignment + assert.Len(t, cfg.Instances, 1) + assert.Equal(t, "first", cfg.Instances[0].Name) assert.True(t, cfg.Instances[0].Default) }) @@ -244,11 +260,12 @@ func TestConfig_RemoveInstance(t *testing.T) { func TestConfig_GetInstance(t *testing.T) { cfg := New() - cfg.AddInstance(Instance{ + err := cfg.AddInstance(Instance{ Name: "test", FQDN: "https://test.io", Token: "test-token", }) + require.NoError(t, err) t.Run("get existing instance", func(t *testing.T) { instance, err := cfg.GetInstance("test") @@ -269,12 +286,13 @@ func TestConfig_GetInstance(t *testing.T) { func TestConfig_GetDefault(t *testing.T) { t.Run("get default instance", func(t *testing.T) { cfg := New() - cfg.AddInstance(Instance{ + err := cfg.AddInstance(Instance{ Name: "test", FQDN: "https://test.io", Token: "test-token", Default: true, }) + require.NoError(t, err) instance, err := cfg.GetDefault() @@ -295,20 +313,23 @@ func TestConfig_GetDefault(t *testing.T) { func TestConfig_SetDefault(t *testing.T) { t.Run("set existing instance as default", func(t *testing.T) { cfg := New() - cfg.AddInstance(Instance{ + err := cfg.AddInstance(Instance{ Name: "first", FQDN: "https://first.io", Token: "token1", }) - cfg.AddInstance(Instance{ + require.NoError(t, err) + + err = cfg.AddInstance(Instance{ Name: "second", FQDN: "https://second.io", Token: "token2", }) - - err := cfg.SetDefault("second") - require.NoError(t, err) + + err = cfg.SetDefault("second") + require.NoError(t, err) + assert.False(t, cfg.Instances[0].Default) assert.True(t, cfg.Instances[1].Default) }) @@ -326,15 +347,16 @@ func TestConfig_SetDefault(t *testing.T) { func TestConfig_UpdateInstanceToken(t *testing.T) { t.Run("update existing instance token", func(t *testing.T) { cfg := New() - cfg.AddInstance(Instance{ + err := cfg.AddInstance(Instance{ Name: "test", FQDN: "https://test.io", Token: "old-token", }) - - err := cfg.UpdateInstanceToken("test", "new-token") - require.NoError(t, err) + + err = cfg.UpdateInstanceToken("test", "new-token") + require.NoError(t, err) + instance, _ := cfg.GetInstance("test") assert.Equal(t, "new-token", instance.Token) }) @@ -350,15 +372,16 @@ func TestConfig_UpdateInstanceToken(t *testing.T) { t.Run("empty token returns error", func(t *testing.T) { cfg := New() - cfg.AddInstance(Instance{ + err := cfg.AddInstance(Instance{ Name: "test", FQDN: "https://test.io", Token: "old-token", }) + require.NoError(t, err) - err := cfg.UpdateInstanceToken("test", "") - + err = cfg.UpdateInstanceToken("test", "") require.Error(t, err) + assert.Contains(t, err.Error(), "cannot be empty") }) } @@ -366,14 +389,14 @@ func TestConfig_UpdateInstanceToken(t *testing.T) { func TestConfig_Validate(t *testing.T) { t.Run("valid config", func(t *testing.T) { cfg := New() - cfg.AddInstance(Instance{ + err := cfg.AddInstance(Instance{ Name: "test", FQDN: "https://test.io", Token: "token", }) + require.NoError(t, err) - err := cfg.Validate() - + err = cfg.Validate() require.NoError(t, err) }) @@ -441,7 +464,8 @@ func TestLoadFromFile(t *testing.T) { } data, _ := json.Marshal(validConfig) - os.WriteFile(configPath, data, 0600) + err := os.WriteFile(configPath, data, 0600) + require.NoError(t, err) // Load config cfg, err := LoadFromFile(configPath) @@ -462,9 +486,10 @@ func TestLoadFromFile(t *testing.T) { tmpDir := t.TempDir() configPath := filepath.Join(tmpDir, "config.json") - os.WriteFile(configPath, []byte("invalid json"), 0600) + err := os.WriteFile(configPath, []byte("invalid json"), 0600) + require.NoError(t, err) - _, err := LoadFromFile(configPath) + _, err = LoadFromFile(configPath) require.Error(t, err) assert.Contains(t, err.Error(), "failed to parse") @@ -477,13 +502,14 @@ func TestSaveToFile(t *testing.T) { configPath := filepath.Join(tmpDir, "config.json") cfg := New() - cfg.AddInstance(Instance{ + err := cfg.AddInstance(Instance{ Name: "test", FQDN: "https://test.io", Token: "test-token", }) + require.NoError(t, err) - err := SaveToFile(configPath, cfg) + err = SaveToFile(configPath, cfg) require.NoError(t, err) @@ -493,7 +519,8 @@ func TestSaveToFile(t *testing.T) { // Verify content data, _ := os.ReadFile(configPath) var loaded Config - json.Unmarshal(data, &loaded) + err = json.Unmarshal(data, &loaded) + require.NoError(t, err) assert.Len(t, loaded.Instances, 1) assert.Equal(t, "test", loaded.Instances[0].Name) }) diff --git a/internal/config/loader.go b/internal/config/loader.go index db2d240..5fdb575 100644 --- a/internal/config/loader.go +++ b/internal/config/loader.go @@ -39,7 +39,7 @@ func SaveToFile(path string, cfg *Config) error { // Ensure directory exists dir := filepath.Dir(path) - if err := os.MkdirAll(dir, 0755); err != nil { + if err := os.MkdirAll(dir, 0750); err != nil { return fmt.Errorf("failed to create config directory: %w", err) } diff --git a/internal/models/database.go b/internal/models/database.go index b1b1584..afffec3 100644 --- a/internal/models/database.go +++ b/internal/models/database.go @@ -21,12 +21,12 @@ type Database struct { LimitsMemoryReservation *string `json:"limits_memory_reservation,omitempty" table:"-"` LimitsCpus *string `json:"limits_cpus,omitempty" table:"-"` LimitsCpuset *string `json:"limits_cpuset,omitempty" table:"-"` - LimitsCpuShares *int `json:"limits_cpu_shares,omitempty" table:"-"` + LimitsCPUShares *int `json:"limits_cpu_shares,omitempty" table:"-"` // PostgreSQL specific PostgresUser *string `json:"postgres_user,omitempty" table:"-"` PostgresPassword *string `json:"postgres_password,omitempty" table:"-"` - PostgresDb *string `json:"postgres_db,omitempty" table:"-"` + PostgresDB *string `json:"postgres_db,omitempty" table:"-"` PostgresInitdbArgs *string `json:"postgres_initdb_args,omitempty" table:"-"` PostgresHostAuthMethod *string `json:"postgres_host_auth_method,omitempty" table:"-"` PostgresConf *string `json:"postgres_conf,omitempty" table:"-"` @@ -99,12 +99,12 @@ type DatabaseCreateRequest struct { LimitsMemoryReservation *string `json:"limits_memory_reservation,omitempty" table:"-"` LimitsCpus *string `json:"limits_cpus,omitempty" table:"-"` LimitsCpuset *string `json:"limits_cpuset,omitempty" table:"-"` - LimitsCpuShares *int `json:"limits_cpu_shares,omitempty" table:"-"` + LimitsCPUShares *int `json:"limits_cpu_shares,omitempty" table:"-"` // PostgreSQL specific PostgresUser *string `json:"postgres_user,omitempty"` PostgresPassword *string `json:"postgres_password,omitempty"` - PostgresDb *string `json:"postgres_db,omitempty" table:"-"` + PostgresDB *string `json:"postgres_db,omitempty" table:"-"` PostgresInitdbArgs *string `json:"postgres_initdb_args,omitempty"` PostgresHostAuthMethod *string `json:"postgres_host_auth_method,omitempty"` PostgresConf *string `json:"postgres_conf,omitempty"` diff --git a/internal/output/formatter_test.go b/internal/output/formatter_test.go index 7115f9b..05c3abb 100644 --- a/internal/output/formatter_test.go +++ b/internal/output/formatter_test.go @@ -34,10 +34,10 @@ func TestNewFormatter(t *testing.T) { formatter, err := NewFormatter(tt.format, opts) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) assert.Nil(t, formatter) } else { - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, formatter) } }) diff --git a/internal/output/table.go b/internal/output/table.go index 2c22774..fbe578e 100644 --- a/internal/output/table.go +++ b/internal/output/table.go @@ -2,6 +2,7 @@ package output import ( "fmt" + "os" "reflect" "strings" "text/tabwriter" @@ -17,11 +18,14 @@ func NewTableFormatter(opts Options) *TableFormatter { return &TableFormatter{opts: opts} } -// Format formats the data as a table -func (f *TableFormatter) Format(data interface{}) error { +func (f *TableFormatter) Format(data any) error { // TODO w := tabwriter.NewWriter(f.opts.Writer, 0, 0, 2, ' ', tabwriter.Debug) defer func() { - w.Flush() + err := w.Flush() + if err != nil { + fmt.Fprintf(os.Stderr, "failed to flush table writer: %v\n", err) + return + } // Add a final newline after table output fmt.Fprintln(f.opts.Writer) }() @@ -49,7 +53,9 @@ func (f *TableFormatter) Format(data interface{}) error { // formatSlice formats a slice of structs as a table func (f *TableFormatter) formatSlice(w *tabwriter.Writer, val reflect.Value) error { if val.Len() == 0 { - fmt.Fprintln(w, "No data") + if _, err := fmt.Fprintln(w, "No data"); err != nil { + return fmt.Errorf("failed to write no data message: %w", err) + } return nil } @@ -61,8 +67,10 @@ func (f *TableFormatter) formatSlice(w *tabwriter.Writer, val reflect.Value) err if firstElem.Kind() != reflect.Struct { // Simple slice (e.g., []string) - for i := 0; i < val.Len(); i++ { - fmt.Fprintf(w, "%v\n", val.Index(i).Interface()) + for i := range val.Len() { + if _, err := fmt.Fprintf(w, "%v\n", val.Index(i).Interface()); err != nil { + return fmt.Errorf("failed to write slice element: %w", err) + } } return nil } @@ -71,10 +79,12 @@ func (f *TableFormatter) formatSlice(w *tabwriter.Writer, val reflect.Value) err headers := f.getHeaders(firstElem.Type()) // Add # as first column header headersWithNum := append([]string{"#"}, headers...) - fmt.Fprintln(w, strings.Join(headersWithNum, "\t")) + if _, err := fmt.Fprintln(w, strings.Join(headersWithNum, "\t")); err != nil { + return fmt.Errorf("failed to write table headers: %w", err) + } // Print rows - for i := 0; i < val.Len(); i++ { + for i := range val.Len() { elem := val.Index(i) if elem.Kind() == reflect.Ptr { elem = elem.Elem() @@ -82,7 +92,9 @@ func (f *TableFormatter) formatSlice(w *tabwriter.Writer, val reflect.Value) err row := f.formatStructRow(elem) // Add row number (1-indexed) as first column rowWithNum := append([]string{fmt.Sprintf("%d", i+1)}, row...) - fmt.Fprintln(w, strings.Join(rowWithNum, "\t")) + if _, err := fmt.Fprintln(w, strings.Join(rowWithNum, "\t")); err != nil { + return fmt.Errorf("failed to write table row: %w", err) + } } return nil @@ -92,24 +104,32 @@ func (f *TableFormatter) formatSlice(w *tabwriter.Writer, val reflect.Value) err func (f *TableFormatter) formatStruct(w *tabwriter.Writer, val reflect.Value) error { // Get headers headers := f.getHeaders(val.Type()) - fmt.Fprintln(w, strings.Join(headers, "\t")) + if _, err := fmt.Fprintln(w, strings.Join(headers, "\t")); err != nil { + return fmt.Errorf("failed to write struct headers: %w", err) + } // Get row data row := f.formatStructRow(val) - fmt.Fprintln(w, strings.Join(row, "\t")) + if _, err := fmt.Fprintln(w, strings.Join(row, "\t")); err != nil { + return fmt.Errorf("failed to write struct row: %w", err) + } return nil } // formatMap formats a map as a table func (f *TableFormatter) formatMap(w *tabwriter.Writer, val reflect.Value) error { - fmt.Fprintln(w, "Key\tValue") + if _, err := fmt.Fprintln(w, "Key\tValue"); err != nil { + return fmt.Errorf("failed to write map headers: %w", err) + } iter := val.MapRange() for iter.Next() { key := iter.Key() value := iter.Value() - fmt.Fprintf(w, "%v\t%v\n", key.Interface(), f.formatValue(value)) + if _, err := fmt.Fprintf(w, "%v\t%v\n", key.Interface(), f.formatValue(value)); err != nil { + return fmt.Errorf("failed to write map entry: %w", err) + } } return nil diff --git a/internal/parser/env_test.go b/internal/parser/env_test.go index cd3752b..444b7eb 100644 --- a/internal/parser/env_test.go +++ b/internal/parser/env_test.go @@ -132,7 +132,7 @@ KEY2=value` require.NoError(t, err) assert.Len(t, envVars, 2) assert.Equal(t, "KEY1", envVars[0].Key) - assert.Equal(t, "", envVars[0].Value) + assert.Empty(t, envVars[0].Value) assert.Equal(t, "KEY2", envVars[1].Key) assert.Equal(t, "value", envVars[1].Value) } @@ -161,7 +161,7 @@ KEY2=value` defer os.Remove(tmpFile) _, err := ParseEnvFile(tmpFile) - assert.Error(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "missing '='") } @@ -173,7 +173,7 @@ KEY2=value` defer os.Remove(tmpFile) _, err := ParseEnvFile(tmpFile) - assert.Error(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "empty key") } @@ -185,13 +185,13 @@ KEY2=value` defer os.Remove(tmpFile) _, err := ParseEnvFile(tmpFile) - assert.Error(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "unclosed quoted value") } func TestParseEnvFile_FileNotFound(t *testing.T) { _, err := ParseEnvFile("/nonexistent/file.env") - assert.Error(t, err) + require.Error(t, err) assert.Contains(t, err.Error(), "failed to open file") } @@ -203,7 +203,7 @@ func TestParseEnvFile_EmptyFile(t *testing.T) { envVars, err := ParseEnvFile(tmpFile) require.NoError(t, err) - assert.Len(t, envVars, 0) + assert.Empty(t, envVars) } func TestParseEnvFile_OnlyComments(t *testing.T) { @@ -216,14 +216,14 @@ func TestParseEnvFile_OnlyComments(t *testing.T) { envVars, err := ParseEnvFile(tmpFile) require.NoError(t, err) - assert.Len(t, envVars, 0) + assert.Empty(t, envVars) } // Helper function to create a temporary .env file func createTempEnvFile(t *testing.T, content string) string { tmpDir := t.TempDir() tmpFile := filepath.Join(tmpDir, ".env") - err := os.WriteFile(tmpFile, []byte(content), 0644) + err := os.WriteFile(tmpFile, []byte(content), 0600) require.NoError(t, err) return tmpFile } diff --git a/internal/service/application_test.go b/internal/service/application_test.go index 46944c5..ff2936e 100644 --- a/internal/service/application_test.go +++ b/internal/service/application_test.go @@ -7,10 +7,11 @@ import ( "net/http/httptest" "testing" - "github.com/coollabsio/coolify-cli/internal/api" - "github.com/coollabsio/coolify-cli/internal/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/coollabsio/coolify-cli/internal/api" + "github.com/coollabsio/coolify-cli/internal/models" ) func TestApplicationService_List(t *testing.T) { @@ -52,7 +53,7 @@ func TestApplicationService_List(t *testing.T) { assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization")) w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(applications) + _ = json.NewEncoder(w).Encode(applications) })) defer server.Close() @@ -77,7 +78,7 @@ func TestApplicationService_List_Empty(t *testing.T) { assert.Equal(t, "GET", r.Method) w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode([]models.Application{}) + _ = json.NewEncoder(w).Encode([]models.Application{}) })) defer server.Close() @@ -90,9 +91,9 @@ func TestApplicationService_List_Empty(t *testing.T) { } func TestApplicationService_List_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`{"message":"internal server error"}`)) + _, _ = w.Write([]byte(`{"message":"internal server error"}`)) })) defer server.Close() @@ -128,7 +129,7 @@ func TestApplicationService_Get(t *testing.T) { assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization")) w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(application) + _ = json.NewEncoder(w).Encode(application) })) defer server.Close() @@ -146,9 +147,9 @@ func TestApplicationService_Get(t *testing.T) { } func TestApplicationService_Get_NotFound(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) - w.Write([]byte(`{"message":"application not found"}`)) + _, _ = w.Write([]byte(`{"message":"application not found"}`)) })) defer server.Close() @@ -162,9 +163,9 @@ func TestApplicationService_Get_NotFound(t *testing.T) { } func TestApplicationService_Get_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`{"message":"internal server error"}`)) + _, _ = w.Write([]byte(`{"message":"internal server error"}`)) })) defer server.Close() @@ -189,7 +190,8 @@ func TestApplicationService_Update(t *testing.T) { // Verify request body var req models.ApplicationUpdateRequest - json.NewDecoder(r.Body).Decode(&req) + _ = json.NewDecoder(r.Body).Decode(&req) + assert.NotNil(t, req.Name) assert.Equal(t, newName, *req.Name) assert.NotNil(t, req.GitBranch) @@ -208,7 +210,7 @@ func TestApplicationService_Update(t *testing.T) { } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(updatedApp) + _ = json.NewEncoder(w).Encode(updatedApp) })) defer server.Close() @@ -237,7 +239,8 @@ func TestApplicationService_Update_PartialUpdate(t *testing.T) { // Verify only domains field is in request var req models.ApplicationUpdateRequest - json.NewDecoder(r.Body).Decode(&req) + _ = json.NewDecoder(r.Body).Decode(&req) + assert.Nil(t, req.Name) assert.Nil(t, req.GitBranch) assert.NotNil(t, req.Domains) @@ -256,7 +259,7 @@ func TestApplicationService_Update_PartialUpdate(t *testing.T) { } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(updatedApp) + _ = json.NewEncoder(w).Encode(updatedApp) })) defer server.Close() @@ -275,9 +278,9 @@ func TestApplicationService_Update_PartialUpdate(t *testing.T) { } func TestApplicationService_Update_NotFound(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) - w.Write([]byte(`{"message":"application not found"}`)) + _, _ = w.Write([]byte(`{"message":"application not found"}`)) })) defer server.Close() @@ -296,9 +299,9 @@ func TestApplicationService_Update_NotFound(t *testing.T) { } func TestApplicationService_Update_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`{"message":"internal server error"}`)) + _, _ = w.Write([]byte(`{"message":"internal server error"}`)) })) defer server.Close() @@ -334,9 +337,9 @@ func TestApplicationService_Delete(t *testing.T) { } func TestApplicationService_Delete_NotFound(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) - w.Write([]byte(`{"message":"application not found"}`)) + _, _ = w.Write([]byte(`{"message":"application not found"}`)) })) defer server.Close() @@ -349,9 +352,9 @@ func TestApplicationService_Delete_NotFound(t *testing.T) { } func TestApplicationService_Delete_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`{"message":"internal server error"}`)) + _, _ = w.Write([]byte(`{"message":"internal server error"}`)) })) defer server.Close() @@ -375,7 +378,7 @@ func TestApplicationService_Start(t *testing.T) { DeploymentUUID: &deploymentUUID, } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resp) + _ = json.NewEncoder(w).Encode(resp) })) defer server.Close() @@ -399,7 +402,7 @@ func TestApplicationService_Start_WithForce(t *testing.T) { Message: "Deployment request queued.", } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resp) + _ = json.NewEncoder(w).Encode(resp) })) defer server.Close() @@ -420,7 +423,7 @@ func TestApplicationService_Start_WithInstantDeploy(t *testing.T) { Message: "Deployment request queued.", } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resp) + _ = json.NewEncoder(w).Encode(resp) })) defer server.Close() @@ -433,9 +436,9 @@ func TestApplicationService_Start_WithInstantDeploy(t *testing.T) { } func TestApplicationService_Start_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`{"message":"failed to start application"}`)) + _, _ = w.Write([]byte(`{"message":"failed to start application"}`)) })) defer server.Close() @@ -458,7 +461,7 @@ func TestApplicationService_Stop(t *testing.T) { Message: "Application stopped successfully", } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resp) + _ = json.NewEncoder(w).Encode(resp) })) defer server.Close() @@ -472,9 +475,9 @@ func TestApplicationService_Stop(t *testing.T) { } func TestApplicationService_Stop_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`{"message":"failed to stop application"}`)) + _, _ = w.Write([]byte(`{"message":"failed to stop application"}`)) })) defer server.Close() @@ -497,7 +500,7 @@ func TestApplicationService_Restart(t *testing.T) { Message: "Application restarted successfully", } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resp) + _ = json.NewEncoder(w).Encode(resp) })) defer server.Close() @@ -511,9 +514,9 @@ func TestApplicationService_Restart(t *testing.T) { } func TestApplicationService_Restart_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`{"message":"failed to restart application"}`)) + _, _ = w.Write([]byte(`{"message":"failed to restart application"}`)) })) defer server.Close() @@ -536,7 +539,7 @@ func TestApplicationService_Logs(t *testing.T) { Logs: "[2025-10-15 12:00:00] Application started\n[2025-10-15 12:00:01] Server listening on port 3000\n", } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resp) + _ = json.NewEncoder(w).Encode(resp) })) defer server.Close() @@ -559,7 +562,7 @@ func TestApplicationService_Logs_WithLines(t *testing.T) { Logs: "[2025-10-15 12:00:00] Log line\n", } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resp) + _ = json.NewEncoder(w).Encode(resp) })) defer server.Close() @@ -572,9 +575,9 @@ func TestApplicationService_Logs_WithLines(t *testing.T) { } func TestApplicationService_Logs_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) - w.Write([]byte(`{"message":"application not found"}`)) + _, _ = w.Write([]byte(`{"message":"application not found"}`)) })) defer server.Close() @@ -612,7 +615,7 @@ func TestApplicationService_ListEnvs(t *testing.T) { }, } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(envs) + _ = json.NewEncoder(w).Encode(envs) })) defer server.Close() @@ -630,7 +633,7 @@ func TestApplicationService_ListEnvs_Empty(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/applications/app-uuid-123/envs", r.URL.Path) w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode([]models.EnvironmentVariable{}) + _ = json.NewEncoder(w).Encode([]models.EnvironmentVariable{}) })) defer server.Close() @@ -639,13 +642,13 @@ func TestApplicationService_ListEnvs_Empty(t *testing.T) { result, err := svc.ListEnvs(context.Background(), "app-uuid-123") require.NoError(t, err) - assert.Len(t, result, 0) + assert.Empty(t, result) } func TestApplicationService_ListEnvs_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) - w.Write([]byte(`{"message":"application not found"}`)) + _, _ = w.Write([]byte(`{"message":"application not found"}`)) })) defer server.Close() @@ -674,7 +677,7 @@ func TestApplicationService_CreateEnv(t *testing.T) { } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) - json.NewEncoder(w).Encode(env) + _ = json.NewEncoder(w).Encode(env) })) defer server.Close() @@ -696,9 +699,9 @@ func TestApplicationService_CreateEnv(t *testing.T) { } func TestApplicationService_CreateEnv_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(`{"message":"key already exists"}`)) + _, _ = w.Write([]byte(`{"message":"key already exists"}`)) })) defer server.Close() @@ -727,7 +730,7 @@ func TestApplicationService_UpdateEnv(t *testing.T) { Value: "newsecret456", } w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(env) + _ = json.NewEncoder(w).Encode(env) })) defer server.Close() @@ -748,9 +751,9 @@ func TestApplicationService_UpdateEnv(t *testing.T) { } func TestApplicationService_UpdateEnv_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) - w.Write([]byte(`{"message":"environment variable not found"}`)) + _, _ = w.Write([]byte(`{"message":"environment variable not found"}`)) })) defer server.Close() @@ -785,9 +788,9 @@ func TestApplicationService_DeleteEnv(t *testing.T) { } func TestApplicationService_DeleteEnv_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) - w.Write([]byte(`{"message":"environment variable not found"}`)) + _, _ = w.Write([]byte(`{"message":"environment variable not found"}`)) })) defer server.Close() diff --git a/internal/service/database.go b/internal/service/database.go index aef5c27..abf0719 100644 --- a/internal/service/database.go +++ b/internal/service/database.go @@ -176,7 +176,7 @@ func (s *DatabaseService) DeleteBackupExecution(ctx context.Context, dbUUID, bac // inferDatabaseType determines the database type from available fields func inferDatabaseType(db *models.Database) string { // Check for PostgreSQL - if db.PostgresUser != nil || db.PostgresPassword != nil || db.PostgresDb != nil { + if db.PostgresUser != nil || db.PostgresPassword != nil || db.PostgresDB != nil { return "postgresql" } diff --git a/internal/service/database_test.go b/internal/service/database_test.go index e8eff3d..7a06866 100644 --- a/internal/service/database_test.go +++ b/internal/service/database_test.go @@ -8,10 +8,11 @@ import ( "net/http/httptest" "testing" - "github.com/coollabsio/coolify-cli/internal/api" - "github.com/coollabsio/coolify-cli/internal/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/coollabsio/coolify-cli/internal/api" + "github.com/coollabsio/coolify-cli/internal/models" ) func TestDatabaseService_List(t *testing.T) { @@ -61,7 +62,7 @@ func TestDatabaseService_List(t *testing.T) { assert.Equal(t, "/api/v1/databases", r.URL.Path) assert.Equal(t, http.MethodGet, r.Method) w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.serverResponse)) + _, _ = w.Write([]byte(tt.serverResponse)) })) defer server.Close() @@ -71,7 +72,7 @@ func TestDatabaseService_List(t *testing.T) { databases, err := dbService.List(context.Background()) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -123,7 +124,7 @@ func TestDatabaseService_Get(t *testing.T) { assert.Equal(t, "/api/v1/databases/"+tt.uuid, r.URL.Path) assert.Equal(t, http.MethodGet, r.Method) w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.serverResponse)) + _, _ = w.Write([]byte(tt.serverResponse)) })) defer server.Close() @@ -133,7 +134,7 @@ func TestDatabaseService_Get(t *testing.T) { database, err := dbService.Get(context.Background(), tt.uuid) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -193,12 +194,11 @@ func TestDatabaseService_Create(t *testing.T) { assert.Equal(t, http.MethodPost, r.Method) var req models.DatabaseCreateRequest - err := json.NewDecoder(r.Body).Decode(&req) - require.NoError(t, err) + _ = json.NewDecoder(r.Body).Decode(&req) assert.Equal(t, tt.request.ServerUUID, req.ServerUUID) w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.serverResponse)) + _, _ = w.Write([]byte(tt.serverResponse)) })) defer server.Close() @@ -208,7 +208,7 @@ func TestDatabaseService_Create(t *testing.T) { database, err := dbService.Create(context.Background(), tt.dbType, tt.request) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -253,12 +253,11 @@ func TestDatabaseService_Update(t *testing.T) { assert.Equal(t, http.MethodPatch, r.Method) var req models.DatabaseUpdateRequest - err := json.NewDecoder(r.Body).Decode(&req) - require.NoError(t, err) + _ = json.NewDecoder(r.Body).Decode(&req) w.WriteHeader(tt.statusCode) if tt.statusCode == http.StatusNotFound { - w.Write([]byte(`{"error":"not found"}`)) + _, _ = w.Write([]byte(`{"error":"not found"}`)) } })) defer server.Close() @@ -269,7 +268,7 @@ func TestDatabaseService_Update(t *testing.T) { err := dbService.Update(context.Background(), tt.uuid, tt.request) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -335,9 +334,9 @@ func TestDatabaseService_Delete(t *testing.T) { w.WriteHeader(tt.statusCode) if tt.statusCode == http.StatusOK { - w.Write([]byte(`{"message":"Database deleted"}`)) + _, _ = w.Write([]byte(`{"message":"Database deleted"}`)) } else { - w.Write([]byte(`{"error":"not found"}`)) + _, _ = w.Write([]byte(`{"error":"not found"}`)) } })) defer server.Close() @@ -348,7 +347,7 @@ func TestDatabaseService_Delete(t *testing.T) { err := dbService.Delete(context.Background(), tt.uuid, tt.deleteConfigurations, tt.deleteVolumes, tt.dockerCleanup, tt.deleteConnectedNetworks) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -389,7 +388,7 @@ func TestDatabaseService_Start(t *testing.T) { assert.Equal(t, "/api/v1/databases/"+tt.uuid+"/start", r.URL.Path) assert.Equal(t, http.MethodGet, r.Method) w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.serverResponse)) + _, _ = w.Write([]byte(tt.serverResponse)) })) defer server.Close() @@ -399,7 +398,7 @@ func TestDatabaseService_Start(t *testing.T) { response, err := dbService.Start(context.Background(), tt.uuid) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -441,7 +440,7 @@ func TestDatabaseService_Stop(t *testing.T) { assert.Equal(t, "/api/v1/databases/"+tt.uuid+"/stop", r.URL.Path) assert.Equal(t, http.MethodGet, r.Method) w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.serverResponse)) + _, _ = w.Write([]byte(tt.serverResponse)) })) defer server.Close() @@ -451,7 +450,7 @@ func TestDatabaseService_Stop(t *testing.T) { response, err := dbService.Stop(context.Background(), tt.uuid) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -493,7 +492,7 @@ func TestDatabaseService_Restart(t *testing.T) { assert.Equal(t, "/api/v1/databases/"+tt.uuid+"/restart", r.URL.Path) assert.Equal(t, http.MethodGet, r.Method) w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.serverResponse)) + _, _ = w.Write([]byte(tt.serverResponse)) })) defer server.Close() @@ -503,7 +502,7 @@ func TestDatabaseService_Restart(t *testing.T) { response, err := dbService.Restart(context.Background(), tt.uuid) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -561,7 +560,7 @@ func TestDatabaseService_ListBackups(t *testing.T) { assert.Equal(t, "/api/v1/databases/"+tt.dbUUID+"/backups", r.URL.Path) assert.Equal(t, http.MethodGet, r.Method) w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.serverResponse)) + _, _ = w.Write([]byte(tt.serverResponse)) })) defer server.Close() @@ -571,7 +570,7 @@ func TestDatabaseService_ListBackups(t *testing.T) { backups, err := dbService.ListBackups(context.Background(), tt.dbUUID) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -619,7 +618,7 @@ func TestDatabaseService_UpdateBackup(t *testing.T) { assert.Equal(t, http.MethodPatch, r.Method) w.WriteHeader(tt.statusCode) if tt.statusCode == http.StatusNotFound { - w.Write([]byte(`{"error":"not found"}`)) + _, _ = w.Write([]byte(`{"error":"not found"}`)) } })) defer server.Close() @@ -630,7 +629,7 @@ func TestDatabaseService_UpdateBackup(t *testing.T) { err := dbService.UpdateBackup(context.Background(), tt.dbUUID, tt.backupUUID, tt.request) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -682,9 +681,9 @@ func TestDatabaseService_DeleteBackup(t *testing.T) { assert.Contains(t, r.URL.RawQuery, fmt.Sprintf("delete_s3=%t", tt.deleteS3)) w.WriteHeader(tt.statusCode) if tt.statusCode == http.StatusOK { - w.Write([]byte(`{"message":"Backup deleted"}`)) + _, _ = w.Write([]byte(`{"message":"Backup deleted"}`)) } else { - w.Write([]byte(`{"error":"not found"}`)) + _, _ = w.Write([]byte(`{"error":"not found"}`)) } })) defer server.Close() @@ -695,7 +694,7 @@ func TestDatabaseService_DeleteBackup(t *testing.T) { err := dbService.DeleteBackup(context.Background(), tt.dbUUID, tt.backupUUID, tt.deleteS3) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -760,7 +759,7 @@ func TestDatabaseService_ListBackupExecutions(t *testing.T) { assert.Equal(t, "/api/v1/databases/"+tt.dbUUID+"/backups/"+tt.backupUUID+"/executions", r.URL.Path) assert.Equal(t, http.MethodGet, r.Method) w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.serverResponse)) + _, _ = w.Write([]byte(tt.serverResponse)) })) defer server.Close() @@ -770,7 +769,7 @@ func TestDatabaseService_ListBackupExecutions(t *testing.T) { executions, err := dbService.ListBackupExecutions(context.Background(), tt.dbUUID, tt.backupUUID) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } @@ -827,9 +826,9 @@ func TestDatabaseService_DeleteBackupExecution(t *testing.T) { assert.Contains(t, r.URL.RawQuery, fmt.Sprintf("delete_s3=%t", tt.deleteS3)) w.WriteHeader(tt.statusCode) if tt.statusCode == http.StatusOK { - w.Write([]byte(`{"message":"Backup execution deleted"}`)) + _, _ = w.Write([]byte(`{"message":"Backup execution deleted"}`)) } else { - w.Write([]byte(`{"error":"not found"}`)) + _, _ = w.Write([]byte(`{"error":"not found"}`)) } })) defer server.Close() @@ -840,7 +839,7 @@ func TestDatabaseService_DeleteBackupExecution(t *testing.T) { err := dbService.DeleteBackupExecution(context.Background(), tt.dbUUID, tt.backupUUID, tt.executionUUID, tt.deleteS3) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } diff --git a/internal/service/deployment_test.go b/internal/service/deployment_test.go index d74c187..24a5274 100644 --- a/internal/service/deployment_test.go +++ b/internal/service/deployment_test.go @@ -7,9 +7,10 @@ import ( "net/http/httptest" "testing" - "github.com/coollabsio/coolify-cli/internal/api" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/coollabsio/coolify-cli/internal/api" ) func TestDeploymentService_Deploy(t *testing.T) { @@ -59,7 +60,7 @@ func TestDeploymentService_Deploy(t *testing.T) { assert.Equal(t, "GET", r.Method) w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(tt.response) + _ = json.NewEncoder(w).Encode(tt.response) })) defer server.Close() diff --git a/internal/service/privatekey_test.go b/internal/service/privatekey_test.go index a726638..0895033 100644 --- a/internal/service/privatekey_test.go +++ b/internal/service/privatekey_test.go @@ -7,10 +7,11 @@ import ( "net/http/httptest" "testing" - "github.com/coollabsio/coolify-cli/internal/api" - "github.com/coollabsio/coolify-cli/internal/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/coollabsio/coolify-cli/internal/api" + "github.com/coollabsio/coolify-cli/internal/models" ) func TestPrivateKeyService_List(t *testing.T) { @@ -30,7 +31,7 @@ func TestPrivateKeyService_List(t *testing.T) { assert.Equal(t, "GET", r.Method) w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(keys) + _ = json.NewEncoder(w).Encode(keys) })) defer server.Close() @@ -60,11 +61,11 @@ func TestPrivateKeyService_Create(t *testing.T) { assert.Equal(t, "POST", r.Method) var receivedReq models.PrivateKeyCreateRequest - json.NewDecoder(r.Body).Decode(&receivedReq) + _ = json.NewDecoder(r.Body).Decode(&receivedReq) assert.Equal(t, req.Name, receivedReq.Name) w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(key) + _ = json.NewEncoder(w).Encode(key) })) defer server.Close() diff --git a/internal/service/project_test.go b/internal/service/project_test.go index 4b1a90a..567c43f 100644 --- a/internal/service/project_test.go +++ b/internal/service/project_test.go @@ -7,10 +7,11 @@ import ( "net/http/httptest" "testing" - "github.com/coollabsio/coolify-cli/internal/api" - "github.com/coollabsio/coolify-cli/internal/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/coollabsio/coolify-cli/internal/api" + "github.com/coollabsio/coolify-cli/internal/models" ) func TestProjectService_List(t *testing.T) { @@ -34,7 +35,7 @@ func TestProjectService_List(t *testing.T) { assert.Equal(t, "GET", r.Method) w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(projects) + _ = json.NewEncoder(w).Encode(projects) })) defer server.Close() @@ -61,7 +62,7 @@ func TestProjectService_Get(t *testing.T) { assert.Equal(t, "GET", r.Method) w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(project) + _ = json.NewEncoder(w).Encode(project) })) defer server.Close() diff --git a/internal/service/resource_test.go b/internal/service/resource_test.go index 0d76d4c..8401d76 100644 --- a/internal/service/resource_test.go +++ b/internal/service/resource_test.go @@ -7,10 +7,11 @@ import ( "net/http/httptest" "testing" - "github.com/coollabsio/coolify-cli/internal/api" - "github.com/coollabsio/coolify-cli/internal/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/coollabsio/coolify-cli/internal/api" + "github.com/coollabsio/coolify-cli/internal/models" ) func TestResourceService_List(t *testing.T) { @@ -32,7 +33,7 @@ func TestResourceService_List(t *testing.T) { assert.Equal(t, "GET", r.Method) w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resources) + _ = json.NewEncoder(w).Encode(resources) })) defer server.Close() diff --git a/internal/service/server_test.go b/internal/service/server_test.go index 8bb2e55..d351fc5 100644 --- a/internal/service/server_test.go +++ b/internal/service/server_test.go @@ -7,10 +7,11 @@ import ( "net/http/httptest" "testing" - "github.com/coollabsio/coolify-cli/internal/api" - "github.com/coollabsio/coolify-cli/internal/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/coollabsio/coolify-cli/internal/api" + "github.com/coollabsio/coolify-cli/internal/models" ) func TestServerService_List(t *testing.T) { @@ -22,7 +23,7 @@ func TestServerService_List(t *testing.T) { {UUID: "uuid-1", Name: "server-1"}, {UUID: "uuid-2", Name: "server-2"}, } - json.NewEncoder(w).Encode(servers) + _ = json.NewEncoder(w).Encode(servers) })) defer server.Close() @@ -47,7 +48,7 @@ func TestServerService_Get(t *testing.T) { Name: "test-server", IP: "192.168.1.100", } - json.NewEncoder(w).Encode(server) + _ = json.NewEncoder(w).Encode(server) })) defer server.Close() @@ -73,7 +74,7 @@ func TestServerService_GetResources(t *testing.T) { {UUID: "res-1", Name: "resource-1", Type: "application"}, }, } - json.NewEncoder(w).Encode(resources) + _ = json.NewEncoder(w).Encode(resources) })) defer server.Close() @@ -93,13 +94,13 @@ func TestServerService_Create(t *testing.T) { assert.Equal(t, "POST", r.Method) var req models.ServerCreateRequest - json.NewDecoder(r.Body).Decode(&req) + _ = json.NewDecoder(r.Body).Decode(&req) assert.Equal(t, "new-server", req.Name) assert.Equal(t, "192.168.1.200", req.IP) response := models.Response{Message: "Server created"} - json.NewEncoder(w).Encode(response) + _ = json.NewEncoder(w).Encode(response) })) defer server.Close() @@ -126,7 +127,7 @@ func TestServerService_Delete(t *testing.T) { assert.Equal(t, "DELETE", r.Method) w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode(models.Response{Message: "Server deleted"}) + _ = json.NewEncoder(w).Encode(models.Response{Message: "Server deleted"}) })) defer server.Close() @@ -144,7 +145,7 @@ func TestServerService_Validate(t *testing.T) { assert.Equal(t, "GET", r.Method) response := models.Response{Message: "Server is valid"} - json.NewEncoder(w).Encode(response) + _ = json.NewEncoder(w).Encode(response) })) defer server.Close() diff --git a/internal/service/service.go b/internal/service/service.go index 50ae86b..32b796f 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -8,18 +8,18 @@ import ( "github.com/coollabsio/coolify-cli/internal/models" ) -// ServiceService handles service-related operations -type ServiceService struct { +// Service handles service-related operations +type Service struct { client *api.Client } -// NewServiceService creates a new service service instance -func NewServiceService(client *api.Client) *ServiceService { - return &ServiceService{client: client} +// NewService creates a new service instance +func NewService(client *api.Client) *Service { + return &Service{client: client} } // List retrieves all services -func (s *ServiceService) List(ctx context.Context) ([]models.Service, error) { +func (s *Service) List(ctx context.Context) ([]models.Service, error) { var services []models.Service err := s.client.Get(ctx, "services", &services) if err != nil { @@ -29,7 +29,7 @@ func (s *ServiceService) List(ctx context.Context) ([]models.Service, error) { } // Get retrieves a service by UUID -func (s *ServiceService) Get(ctx context.Context, uuid string) (*models.Service, error) { +func (s *Service) Get(ctx context.Context, uuid string) (*models.Service, error) { var service models.Service err := s.client.Get(ctx, fmt.Sprintf("services/%s", uuid), &service) if err != nil { @@ -39,7 +39,7 @@ func (s *ServiceService) Get(ctx context.Context, uuid string) (*models.Service, } // Create creates a new service -func (s *ServiceService) Create(ctx context.Context, req *models.ServiceCreateRequest) (*models.Service, error) { +func (s *Service) Create(ctx context.Context, req *models.ServiceCreateRequest) (*models.Service, error) { var service models.Service err := s.client.Post(ctx, "services", req, &service) if err != nil { @@ -49,7 +49,7 @@ func (s *ServiceService) Create(ctx context.Context, req *models.ServiceCreateRe } // Update updates a service -func (s *ServiceService) Update(ctx context.Context, uuid string, req *models.ServiceUpdateRequest) (*models.Service, error) { +func (s *Service) Update(ctx context.Context, uuid string, req *models.ServiceUpdateRequest) (*models.Service, error) { var service models.Service err := s.client.Patch(ctx, fmt.Sprintf("services/%s", uuid), req, &service) if err != nil { @@ -59,7 +59,7 @@ func (s *ServiceService) Update(ctx context.Context, uuid string, req *models.Se } // Delete deletes a service -func (s *ServiceService) Delete(ctx context.Context, uuid string, deleteConfigurations, deleteVolumes, dockerCleanup, deleteConnectedNetworks bool) error { +func (s *Service) Delete(ctx context.Context, uuid string, deleteConfigurations, deleteVolumes, dockerCleanup, deleteConnectedNetworks bool) error { url := fmt.Sprintf("services/%s?delete_configurations=%t&delete_volumes=%t&docker_cleanup=%t&delete_connected_networks=%t", uuid, deleteConfigurations, deleteVolumes, dockerCleanup, deleteConnectedNetworks) @@ -71,7 +71,7 @@ func (s *ServiceService) Delete(ctx context.Context, uuid string, deleteConfigur } // Start starts a service -func (s *ServiceService) Start(ctx context.Context, uuid string) (*models.ServiceLifecycleResponse, error) { +func (s *Service) Start(ctx context.Context, uuid string) (*models.ServiceLifecycleResponse, error) { var resp models.ServiceLifecycleResponse err := s.client.Post(ctx, fmt.Sprintf("services/%s/start", uuid), nil, &resp) if err != nil { @@ -81,7 +81,7 @@ func (s *ServiceService) Start(ctx context.Context, uuid string) (*models.Servic } // Stop stops a service -func (s *ServiceService) Stop(ctx context.Context, uuid string) (*models.ServiceLifecycleResponse, error) { +func (s *Service) Stop(ctx context.Context, uuid string) (*models.ServiceLifecycleResponse, error) { var resp models.ServiceLifecycleResponse err := s.client.Post(ctx, fmt.Sprintf("services/%s/stop", uuid), nil, &resp) if err != nil { @@ -91,7 +91,7 @@ func (s *ServiceService) Stop(ctx context.Context, uuid string) (*models.Service } // Restart restarts a service -func (s *ServiceService) Restart(ctx context.Context, uuid string) (*models.ServiceLifecycleResponse, error) { +func (s *Service) Restart(ctx context.Context, uuid string) (*models.ServiceLifecycleResponse, error) { var resp models.ServiceLifecycleResponse err := s.client.Post(ctx, fmt.Sprintf("services/%s/restart", uuid), nil, &resp) if err != nil { @@ -101,7 +101,7 @@ func (s *ServiceService) Restart(ctx context.Context, uuid string) (*models.Serv } // ListEnvs retrieves all environment variables for a service -func (s *ServiceService) ListEnvs(ctx context.Context, uuid string) ([]models.EnvironmentVariable, error) { +func (s *Service) ListEnvs(ctx context.Context, uuid string) ([]models.EnvironmentVariable, error) { var envs []models.EnvironmentVariable err := s.client.Get(ctx, fmt.Sprintf("services/%s/envs", uuid), &envs) if err != nil { @@ -111,7 +111,7 @@ func (s *ServiceService) ListEnvs(ctx context.Context, uuid string) ([]models.En } // GetEnv retrieves a single environment variable by UUID or key -func (s *ServiceService) GetEnv(ctx context.Context, serviceUUID, envIdentifier string) (*models.EnvironmentVariable, error) { +func (s *Service) GetEnv(ctx context.Context, serviceUUID, envIdentifier string) (*models.EnvironmentVariable, error) { envs, err := s.ListEnvs(ctx, serviceUUID) if err != nil { return nil, err @@ -128,7 +128,7 @@ func (s *ServiceService) GetEnv(ctx context.Context, serviceUUID, envIdentifier } // CreateEnv creates a new environment variable for a service -func (s *ServiceService) CreateEnv(ctx context.Context, uuid string, req *models.EnvironmentVariableCreateRequest) (*models.EnvironmentVariable, error) { +func (s *Service) CreateEnv(ctx context.Context, uuid string, req *models.EnvironmentVariableCreateRequest) (*models.EnvironmentVariable, error) { var env models.EnvironmentVariable err := s.client.Post(ctx, fmt.Sprintf("services/%s/envs", uuid), req, &env) if err != nil { @@ -138,7 +138,7 @@ func (s *ServiceService) CreateEnv(ctx context.Context, uuid string, req *models } // UpdateEnv updates an environment variable for a service -func (s *ServiceService) UpdateEnv(ctx context.Context, serviceUUID string, req *models.EnvironmentVariableUpdateRequest) (*models.EnvironmentVariable, error) { +func (s *Service) UpdateEnv(ctx context.Context, serviceUUID string, req *models.EnvironmentVariableUpdateRequest) (*models.EnvironmentVariable, error) { var env models.EnvironmentVariable err := s.client.Patch(ctx, fmt.Sprintf("services/%s/envs", serviceUUID), req, &env) if err != nil { @@ -148,7 +148,7 @@ func (s *ServiceService) UpdateEnv(ctx context.Context, serviceUUID string, req } // DeleteEnv deletes an environment variable from a service -func (s *ServiceService) DeleteEnv(ctx context.Context, serviceUUID, envUUID string) error { +func (s *Service) DeleteEnv(ctx context.Context, serviceUUID, envUUID string) error { err := s.client.Delete(ctx, fmt.Sprintf("services/%s/envs/%s", serviceUUID, envUUID)) if err != nil { return fmt.Errorf("failed to delete environment variable %s from service %s: %w", envUUID, serviceUUID, err) @@ -157,7 +157,7 @@ func (s *ServiceService) DeleteEnv(ctx context.Context, serviceUUID, envUUID str } // BulkUpdateEnvs updates multiple environment variables in a single request -func (s *ServiceService) BulkUpdateEnvs(ctx context.Context, serviceUUID string, req *BulkUpdateEnvsRequest) (*BulkUpdateEnvsResponse, error) { +func (s *Service) BulkUpdateEnvs(ctx context.Context, serviceUUID string, req *BulkUpdateEnvsRequest) (*BulkUpdateEnvsResponse, error) { var response BulkUpdateEnvsResponse err := s.client.Patch(ctx, fmt.Sprintf("services/%s/envs/bulk", serviceUUID), req, &response) if err != nil { diff --git a/internal/service/service_test.go b/internal/service/service_test.go index ef4efb9..3b51bc1 100644 --- a/internal/service/service_test.go +++ b/internal/service/service_test.go @@ -6,19 +6,20 @@ import ( "net/http/httptest" "testing" - "github.com/coollabsio/coolify-cli/internal/api" - "github.com/coollabsio/coolify-cli/internal/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/coollabsio/coolify-cli/internal/api" + "github.com/coollabsio/coolify-cli/internal/models" ) -func TestServiceService_List(t *testing.T) { +func TestService_List(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/services", r.URL.Path) assert.Equal(t, "GET", r.Method) w.WriteHeader(http.StatusOK) - w.Write([]byte(`[ + _, _ = w.Write([]byte(`[ { "id": 1, "uuid": "service-uuid-1", @@ -40,7 +41,7 @@ func TestServiceService_List(t *testing.T) { defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) services, err := svc.List(context.Background()) @@ -54,44 +55,44 @@ func TestServiceService_List(t *testing.T) { assert.Equal(t, "stopped", services[1].Status) } -func TestServiceService_List_Empty(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +func TestService_List_Empty(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) - w.Write([]byte(`[]`)) + _, _ = w.Write([]byte(`[]`)) })) defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) services, err := svc.List(context.Background()) require.NoError(t, err) - assert.Len(t, services, 0) + assert.Empty(t, services) } -func TestServiceService_List_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +func TestService_List_Error(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`{"error": "internal server error"}`)) + _, _ = w.Write([]byte(`{"error": "internal server error"}`)) })) defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) _, err := svc.List(context.Background()) require.Error(t, err) } -func TestServiceService_Get(t *testing.T) { +func TestService_Get(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/services/service-uuid-123", r.URL.Path) assert.Equal(t, "GET", r.Method) w.WriteHeader(http.StatusOK) - w.Write([]byte(`{ + _, _ = w.Write([]byte(`{ "id": 1, "uuid": "service-uuid-123", "name": "PostgreSQL 16", @@ -112,7 +113,7 @@ func TestServiceService_Get(t *testing.T) { defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) service, err := svc.Get(context.Background(), "service-uuid-123") @@ -126,33 +127,33 @@ func TestServiceService_Get(t *testing.T) { assert.Equal(t, "db-uuid-1", service.Databases[0].UUID) } -func TestServiceService_Get_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +func TestService_Get_Error(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) - w.Write([]byte(`{"error": "service not found"}`)) + _, _ = w.Write([]byte(`{"error": "service not found"}`)) })) defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) _, err := svc.Get(context.Background(), "nonexistent") require.Error(t, err) } -func TestServiceService_Start(t *testing.T) { +func TestService_Start(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/services/service-uuid-123/start", r.URL.Path) assert.Equal(t, "POST", r.Method) w.WriteHeader(http.StatusOK) - w.Write([]byte(`{"message": "Service starting request queued."}`)) + _, _ = w.Write([]byte(`{"message": "Service starting request queued."}`)) })) defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) resp, err := svc.Start(context.Background(), "service-uuid-123") @@ -160,33 +161,33 @@ func TestServiceService_Start(t *testing.T) { assert.Equal(t, "Service starting request queued.", resp.Message) } -func TestServiceService_Start_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +func TestService_Start_Error(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(`{"error": "service already running"}`)) + _, _ = w.Write([]byte(`{"error": "service already running"}`)) })) defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) _, err := svc.Start(context.Background(), "service-uuid-123") require.Error(t, err) } -func TestServiceService_Stop(t *testing.T) { +func TestService_Stop(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/services/service-uuid-123/stop", r.URL.Path) assert.Equal(t, "POST", r.Method) w.WriteHeader(http.StatusOK) - w.Write([]byte(`{"message": "Service stopping request queued."}`)) + _, _ = w.Write([]byte(`{"message": "Service stopping request queued."}`)) })) defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) resp, err := svc.Stop(context.Background(), "service-uuid-123") @@ -194,33 +195,33 @@ func TestServiceService_Stop(t *testing.T) { assert.Equal(t, "Service stopping request queued.", resp.Message) } -func TestServiceService_Stop_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +func TestService_Stop_Error(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(`{"error": "service already stopped"}`)) + _, _ = w.Write([]byte(`{"error": "service already stopped"}`)) })) defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) _, err := svc.Stop(context.Background(), "service-uuid-123") require.Error(t, err) } -func TestServiceService_Restart(t *testing.T) { +func TestService_Restart(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/services/service-uuid-123/restart", r.URL.Path) assert.Equal(t, "POST", r.Method) w.WriteHeader(http.StatusOK) - w.Write([]byte(`{"message": "Service restarting request queued."}`)) + _, _ = w.Write([]byte(`{"message": "Service restarting request queued."}`)) })) defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) resp, err := svc.Restart(context.Background(), "service-uuid-123") @@ -228,28 +229,28 @@ func TestServiceService_Restart(t *testing.T) { assert.Equal(t, "Service restarting request queued.", resp.Message) } -func TestServiceService_Restart_Error(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +func TestService_Restart_Error(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNotFound) - w.Write([]byte(`{"error": "service not found"}`)) + _, _ = w.Write([]byte(`{"error": "service not found"}`)) })) defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) _, err := svc.Restart(context.Background(), "service-uuid-123") require.Error(t, err) } -func TestServiceService_ListEnvs(t *testing.T) { +func TestService_ListEnvs(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/services/service-uuid-123/envs", r.URL.Path) assert.Equal(t, "GET", r.Method) w.WriteHeader(http.StatusOK) - w.Write([]byte(`[ + _, _ = w.Write([]byte(`[ { "uuid": "env-1", "key": "DATABASE_URL", @@ -269,7 +270,7 @@ func TestServiceService_ListEnvs(t *testing.T) { defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) envs, err := svc.ListEnvs(context.Background(), "service-uuid-123") @@ -279,13 +280,13 @@ func TestServiceService_ListEnvs(t *testing.T) { assert.Equal(t, "API_KEY", envs[1].Key) } -func TestServiceService_CreateEnv(t *testing.T) { +func TestService_CreateEnv(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/services/service-uuid-123/envs", r.URL.Path) assert.Equal(t, "POST", r.Method) w.WriteHeader(http.StatusOK) - w.Write([]byte(`{ + _, _ = w.Write([]byte(`{ "uuid": "env-new", "key": "NEW_VAR", "value": "new_value", @@ -296,7 +297,7 @@ func TestServiceService_CreateEnv(t *testing.T) { defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) env, err := svc.CreateEnv(context.Background(), "service-uuid-123", &models.EnvironmentVariableCreateRequest{ Key: "NEW_VAR", @@ -308,13 +309,13 @@ func TestServiceService_CreateEnv(t *testing.T) { assert.Equal(t, "new_value", env.Value) } -func TestServiceService_UpdateEnv(t *testing.T) { +func TestService_UpdateEnv(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/services/service-uuid-123/envs", r.URL.Path) assert.Equal(t, "PATCH", r.Method) w.WriteHeader(http.StatusOK) - w.Write([]byte(`{ + _, _ = w.Write([]byte(`{ "uuid": "env-123", "key": "UPDATED_VAR", "value": "updated_value", @@ -325,7 +326,7 @@ func TestServiceService_UpdateEnv(t *testing.T) { defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) newKey := "UPDATED_VAR" env, err := svc.UpdateEnv(context.Background(), "service-uuid-123", &models.EnvironmentVariableUpdateRequest{ @@ -337,7 +338,7 @@ func TestServiceService_UpdateEnv(t *testing.T) { assert.Equal(t, "UPDATED_VAR", env.Key) } -func TestServiceService_DeleteEnv(t *testing.T) { +func TestService_DeleteEnv(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/services/service-uuid-123/envs/env-456", r.URL.Path) assert.Equal(t, "DELETE", r.Method) @@ -347,7 +348,7 @@ func TestServiceService_DeleteEnv(t *testing.T) { defer server.Close() client := api.NewClient(server.URL, "test-token") - svc := NewServiceService(client) + svc := NewService(client) err := svc.DeleteEnv(context.Background(), "service-uuid-123", "env-456") diff --git a/internal/service/team_test.go b/internal/service/team_test.go index f5cf077..3580376 100644 --- a/internal/service/team_test.go +++ b/internal/service/team_test.go @@ -51,7 +51,7 @@ func TestTeamService_List(t *testing.T) { t.Errorf("Expected path /api/v1/teams, got %s", r.URL.Path) } w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.response)) + _, _ = w.Write([]byte(tt.response)) })) defer server.Close() @@ -104,7 +104,7 @@ func TestTeamService_Get(t *testing.T) { t.Errorf("Expected path %s, got %s", expectedPath, r.URL.Path) } w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.response)) + _, _ = w.Write([]byte(tt.response)) })) defer server.Close() @@ -155,7 +155,7 @@ func TestTeamService_Current(t *testing.T) { t.Errorf("Expected path /api/v1/teams/current, got %s", r.URL.Path) } w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.response)) + _, _ = w.Write([]byte(tt.response)) })) defer server.Close() @@ -214,7 +214,7 @@ func TestTeamService_ListMembers(t *testing.T) { t.Errorf("Expected path %s, got %s", expectedPath, r.URL.Path) } w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.response)) + _, _ = w.Write([]byte(tt.response)) })) defer server.Close() @@ -262,7 +262,7 @@ func TestTeamService_CurrentMembers(t *testing.T) { t.Errorf("Expected path /api/v1/teams/current/members, got %s", r.URL.Path) } w.WriteHeader(tt.statusCode) - w.Write([]byte(tt.response)) + _, _ = w.Write([]byte(tt.response)) })) defer server.Close() diff --git a/internal/version/checker.go b/internal/version/checker.go index 8bdc73b..0236d9a 100644 --- a/internal/version/checker.go +++ b/internal/version/checker.go @@ -1,6 +1,7 @@ package version import ( + "context" "encoding/json" "fmt" "io" @@ -14,7 +15,7 @@ import ( ) // CliVersion is the CLI version -const CliVersion = "1.0.3" +const CliVersion = "1.0.4" // CheckInterval for version checking const CheckInterval = 10 * time.Minute @@ -39,10 +40,13 @@ func CheckLatestVersionOfCli(debug bool) (string, error) { // Update check time viper.Set("lastupdatechecktime", time.Now().Format(time.RFC3339)) - viper.WriteConfig() + if err := viper.WriteConfig(); err != nil { + log.Printf("Failed to write config: %v\n", err) + } url := "https://api.github.com/repos/coollabsio/coolify-cli/git/refs/tags" - req, err := http.NewRequest("GET", url, nil) + ctx := context.Background() + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { return "", err } From 14a3f00c578daa16880c095647cda0880ca055d8 Mon Sep 17 00:00:00 2001 From: YaRissi <53705290+YaRissi@users.noreply.github.com> Date: Sat, 18 Oct 2025 13:37:31 +0200 Subject: [PATCH 3/9] refactor: update command handlers to use RunE for error handling --- cmd/context/add.go | 12 ++++++------ cmd/context/delete.go | 10 +++++----- cmd/context/set_token.go | 12 +++++------- cmd/context/update.go | 19 +++++++------------ cmd/root.go | 2 +- cmd/update/update.go | 21 ++++++++------------- 6 files changed, 32 insertions(+), 44 deletions(-) diff --git a/cmd/context/add.go b/cmd/context/add.go index 865806d..b8873ef 100644 --- a/cmd/context/add.go +++ b/cmd/context/add.go @@ -17,7 +17,7 @@ func NewAddCommand() *cobra.Command { Example: `context add myserver https://coolify.example.com your-api-token`, Args: cli.ExactArgs(3, " "), Short: "Add a new context", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { name := args[0] host := args[1] token := args[2] @@ -46,14 +46,13 @@ func NewAddCommand() *cobra.Command { } viper.Set("instances", instances) if err := viper.WriteConfig(); err != nil { - fmt.Printf("failed to write config: %v\n", err) - return + return fmt.Errorf("failed to write config: %w", err) } - return + return nil } fmt.Printf("%s already exists.\n", name) fmt.Println("\nNote: Use --force to force overwrite.") - return + return nil } } @@ -81,8 +80,9 @@ func NewAddCommand() *cobra.Command { viper.Set("instances", instances) if err := viper.WriteConfig(); err != nil { - fmt.Printf("failed to write config: %v\n", err) + return fmt.Errorf("failed to write config: %w", err) } + return nil }, } diff --git a/cmd/context/delete.go b/cmd/context/delete.go index 34e6d7f..53f709e 100644 --- a/cmd/context/delete.go +++ b/cmd/context/delete.go @@ -18,7 +18,7 @@ func NewDeleteCommand() *cobra.Command { Args: cli.ExactArgs(1, ""), Short: "Delete a context", - Run: func(_ *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, args []string) error { Name := args[0] instances := viper.Get("instances").([]interface{}) for i, instance := range instances { @@ -27,7 +27,7 @@ func NewDeleteCommand() *cobra.Command { instances = slices.Delete(instances, i, i+1) viper.Set("instances", instances) if err := viper.WriteConfig(); err != nil { - fmt.Printf("failed to write config: %v\n", err) + return fmt.Errorf("failed to write config: %w", err) } if instanceMap["default"] == true { @@ -35,7 +35,7 @@ func NewDeleteCommand() *cobra.Command { instances[0].(map[string]interface{})["default"] = true viper.Set("instances", instances) if err := viper.WriteConfig(); err != nil { - fmt.Printf("failed to write config: %v\n", err) + return fmt.Errorf("failed to write config: %w", err) } newDefaultName := instances[0].(map[string]interface{})["name"] fmt.Printf("Context '%s' deleted. '%s' is now the default context.\n", Name, newDefaultName) @@ -45,10 +45,10 @@ func NewDeleteCommand() *cobra.Command { } else { fmt.Printf("Context '%s' deleted.\n", Name) } - return + return nil } } - fmt.Printf("Context '%s' not found.\n", Name) + return fmt.Errorf("context '%s' not found", Name) }, } } diff --git a/cmd/context/set_token.go b/cmd/context/set_token.go index db19575..57b5da3 100644 --- a/cmd/context/set_token.go +++ b/cmd/context/set_token.go @@ -16,7 +16,7 @@ func NewSetTokenCommand() *cobra.Command { Example: `context set-token myserver your-new-api-token`, Args: cli.ExactArgs(2, " "), Short: "Update the API token for a context", - Run: func(_ *cobra.Command, args []string) { + RunE: func(_ *cobra.Command, args []string) error { name := args[0] token := args[1] var found interface{} @@ -28,8 +28,7 @@ func NewSetTokenCommand() *cobra.Command { } } if found == nil { - fmt.Printf("Context '%s' not found.\n", name) - return + return fmt.Errorf("context '%s' not found", name) } instances := viper.Get("instances").([]interface{}) for _, instance := range instances { @@ -39,12 +38,11 @@ func NewSetTokenCommand() *cobra.Command { } } viper.Set("instances", instances) - err := viper.WriteConfig() - if err != nil { - fmt.Printf("Failed to update token for context '%s': %v\n", name, err) - return + if err := viper.WriteConfig(); err != nil { + return fmt.Errorf("failed to update token for context '%s': %w", name, err) } fmt.Printf("Token updated for context '%s'.\n", name) + return nil }, } } diff --git a/cmd/context/update.go b/cmd/context/update.go index 0ff7639..c35a825 100644 --- a/cmd/context/update.go +++ b/cmd/context/update.go @@ -16,7 +16,7 @@ func NewUpdateCommand() *cobra.Command { Example: `context update myserver --name newname --url https://new.coolify.com --token newtoken`, Args: cli.ExactArgs(1, ""), Short: "Update a context's properties (name, URL, token)", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { oldName := args[0] instances := viper.Get("instances").([]interface{}) @@ -27,9 +27,7 @@ func NewUpdateCommand() *cobra.Command { // Check if at least one flag is provided if newName == "" && newURL == "" && newToken == "" { - fmt.Println("Error: At least one of --name, --url, or --token must be provided") - fmt.Println("\nUsage: coolify context update [--name ] [--url ] [--token ]") - return + return fmt.Errorf("at least one of --name, --url, or --token must be provided") } // Find the context @@ -45,8 +43,7 @@ func NewUpdateCommand() *cobra.Command { } if !found { - fmt.Printf("Context '%s' not found.\n", oldName) - return + return fmt.Errorf("context '%s' not found", oldName) } // If renaming, check if new name already exists @@ -54,8 +51,7 @@ func NewUpdateCommand() *cobra.Command { for _, instance := range instances { instanceMap := instance.(map[string]interface{}) if instanceMap["name"] == newName { - fmt.Printf("Error: Context with name '%s' already exists.\n", newName) - return + return fmt.Errorf("context with name '%s' already exists", newName) } } contextToUpdate["name"] = newName @@ -73,10 +69,8 @@ func NewUpdateCommand() *cobra.Command { // Save changes viper.Set("instances", instances) - err := viper.WriteConfig() - if err != nil { - fmt.Printf("Error saving config: %v\n", err) - return + if err := viper.WriteConfig(); err != nil { + return fmt.Errorf("failed to save config: %w", err) } // Use the new name if renamed, otherwise use old name @@ -85,6 +79,7 @@ func NewUpdateCommand() *cobra.Command { finalName = newName } fmt.Printf("Context '%s' updated successfully.\n", finalName) + return nil }, } diff --git a/cmd/root.go b/cmd/root.go index 920842e..01b8d8e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -60,7 +60,7 @@ var rootCmd = &cobra.Command{ func Execute() { err := rootCmd.Execute() if err != nil { - os.Exit(0) + os.Exit(1) } } diff --git a/cmd/update/update.go b/cmd/update/update.go index 523c37f..43e5c97 100644 --- a/cmd/update/update.go +++ b/cmd/update/update.go @@ -18,41 +18,36 @@ func NewUpdateCommand() *cobra.Command { return &cobra.Command{ Use: "update", Short: "Update Coolify CLI", - Run: func(_ *cobra.Command, _ []string) { + RunE: func(_ *cobra.Command, _ []string) error { latest, found, err := selfupdate.DetectLatest(context.Background(), selfupdate.ParseSlug("coollabsio/coolify-cli")) if err != nil { - log.Printf("Error occurred while detecting version: %v", err) - return + return fmt.Errorf("failed to detect latest version: %w", err) } if !found { - log.Printf("Latest version for %s/%s could not be found from github repository", runtime.GOOS, runtime.GOARCH) - return + return fmt.Errorf("latest version for %s/%s could not be found from github repository", runtime.GOOS, runtime.GOARCH) } currentVersion, err := compareVersion.NewVersion(version.CliVersion) if err != nil { - log.Printf("Could not parse current version: %v", err) - return + return fmt.Errorf("failed to parse current version: %w", err) } latestVersion, err := compareVersion.NewVersion(latest.Version()) if err != nil { - log.Printf("Could not parse latest version: %v", err) - return + return fmt.Errorf("failed to parse latest version: %w", err) } if currentVersion.LessThan(latestVersion) { exe, err := os.Executable() if err != nil { - log.Printf("Could not locate executable path: %v", err) - return + return fmt.Errorf("could not locate executable path: %w", err) } if err := selfupdate.UpdateTo(context.Background(), latest.AssetURL, latest.AssetName, exe); err != nil { - fmt.Printf("Error occurred while updating binary: %v", err) - return + return fmt.Errorf("error occurred while updating binary: %w", err) } log.Printf("Successfully updated to version %s", latest.Version()) } else { log.Printf("No new update available. You are already running the latest version: %s", currentVersion.String()) } + return nil }, } From dcf0b39c1b9251708e02d4af5aaf7559d3c4c87c Mon Sep 17 00:00:00 2001 From: YaRissi <53705290+YaRissi@users.noreply.github.com> Date: Sat, 18 Oct 2025 13:46:46 +0200 Subject: [PATCH 4/9] fix: golangci-lint version --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b7e3307..5f2f9bb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: - name: Run golangci-lint uses: golangci/golangci-lint-action@v8 with: - version: none + version: v2.5.0 # pin version for consistency test: runs-on: ubuntu-latest From c369689131f440f9dd070bf64c0c87d51dfb041a Mon Sep 17 00:00:00 2001 From: YaRissi <53705290+YaRissi@users.noreply.github.com> Date: Sat, 18 Oct 2025 13:50:45 +0200 Subject: [PATCH 5/9] add coverage to test command --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5f2f9bb..15734ba 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,7 +32,7 @@ jobs: go-version-file: 'go.mod' - name: Run tests - run: go test -v -race ./... + run: go test -v -race -cover ./... go-mod-tidy: runs-on: ubuntu-latest From 51f33cfc5ee1821d0c1a115f55c172ba0f8820e0 Mon Sep 17 00:00:00 2001 From: YaRissi <53705290+YaRissi@users.noreply.github.com> Date: Tue, 28 Oct 2025 23:15:02 +0100 Subject: [PATCH 6/9] reactor: change context.Background zu cmd.Context --- CONTRIBUTING.md | 4 ++-- cmd/application/delete.go | 3 +-- cmd/application/env/create.go | 3 +-- cmd/application/env/delete.go | 3 +-- cmd/application/env/get.go | 3 +-- cmd/application/env/list.go | 3 +-- cmd/application/env/sync.go | 3 +-- cmd/application/env/update.go | 3 +-- cmd/application/get.go | 3 +-- cmd/application/list.go | 3 +-- cmd/application/logs.go | 3 +-- cmd/application/restart.go | 3 +-- cmd/application/start.go | 3 +-- cmd/application/stop.go | 3 +-- cmd/application/update.go | 3 +-- cmd/context/verify.go | 3 +-- cmd/context/version.go | 3 +-- cmd/database/backup/create.go | 3 +-- cmd/database/backup/delete-execution.go | 3 +-- cmd/database/backup/delete.go | 3 +-- cmd/database/backup/execution.go | 3 +-- cmd/database/backup/list.go | 3 +-- cmd/database/backup/trigger.go | 3 +-- cmd/database/backup/update.go | 3 +-- cmd/database/create.go | 3 +-- cmd/database/delete.go | 3 +-- cmd/database/get.go | 3 +-- cmd/database/list.go | 3 +-- cmd/database/restart.go | 3 +-- cmd/database/start.go | 3 +-- cmd/database/stop.go | 3 +-- cmd/database/update.go | 3 +-- cmd/deployment/batch.go | 3 +-- cmd/deployment/cancel.go | 13 ++++++++++--- cmd/deployment/get.go | 3 +-- cmd/deployment/list.go | 3 +-- cmd/deployment/name.go | 3 +-- cmd/deployment/uuid.go | 3 +-- cmd/github/branches.go | 3 +-- cmd/github/create.go | 3 +-- cmd/github/delete.go | 3 +-- cmd/github/get.go | 3 +-- cmd/github/list.go | 3 +-- cmd/github/repo.go | 3 +-- cmd/github/update.go | 3 +-- cmd/privatekeys/create.go | 3 +-- cmd/privatekeys/delete.go | 3 +-- cmd/privatekeys/list.go | 3 +-- cmd/project/get.go | 3 +-- cmd/project/list.go | 3 +-- cmd/resources/list.go | 3 +-- cmd/server/add.go | 3 +-- cmd/server/domain.go | 3 +-- cmd/server/get.go | 3 +-- cmd/server/list.go | 3 +-- cmd/server/remove.go | 3 +-- cmd/server/validate.go | 3 +-- cmd/service/delete.go | 3 +-- cmd/service/env/create.go | 3 +-- cmd/service/env/delete.go | 3 +-- cmd/service/env/get.go | 3 +-- cmd/service/env/list.go | 3 +-- cmd/service/env/sync.go | 3 +-- cmd/service/env/update.go | 3 +-- cmd/service/get.go | 3 +-- cmd/service/list.go | 3 +-- cmd/service/restart.go | 3 +-- cmd/service/start.go | 3 +-- cmd/service/stop.go | 3 +-- cmd/teams/current.go | 3 +-- cmd/teams/get.go | 3 +-- cmd/teams/list.go | 3 +-- cmd/teams/members/list.go | 3 +-- cmd/update/update.go | 5 ++--- internal/output/table.go | 17 +++++++++-------- internal/version/checker.go | 3 +-- 76 files changed, 95 insertions(+), 160 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b3e904c..a3fdac6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -177,7 +177,7 @@ func NewListCommand() *cobra.Command { Use: "list", Short: "List all myfeature resources", RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() // Get API client client, err := cli.GetAPIClient(cmd) @@ -330,7 +330,7 @@ func TestMyFeatureService_List(t *testing.T) { client := api.NewClient(server.URL, "test-token") svc := NewMyFeatureService(client) - items, err := svc.List(context.Background()) + items, err := svc.List(cmd.Context()) require.NoError(t, err) assert.Len(t, items, 2) diff --git a/cmd/application/delete.go b/cmd/application/delete.go index 9c0c1d7..83bf053 100644 --- a/cmd/application/delete.go +++ b/cmd/application/delete.go @@ -1,7 +1,6 @@ package application import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewDeleteCommand() *cobra.Command { Long: `Delete an application. This action cannot be undone.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] force, _ := cmd.Flags().GetBool("force") diff --git a/cmd/application/env/create.go b/cmd/application/env/create.go index fd6b336..880417f 100644 --- a/cmd/application/env/create.go +++ b/cmd/application/env/create.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewCreateEnvCommand() *cobra.Command { Long: `Create a new environment variable for a specific application. Use --key and --value flags to specify the variable.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/application/env/delete.go b/cmd/application/env/delete.go index 530c1ca..7eb2d78 100644 --- a/cmd/application/env/delete.go +++ b/cmd/application/env/delete.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewDeleteEnvCommand() *cobra.Command { Long: `Delete an environment variable from an application. First UUID is the application, second is the specific environment variable to delete.`, Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() appUUID := args[0] envUUID := args[1] diff --git a/cmd/application/env/get.go b/cmd/application/env/get.go index a10e4d1..f46d202 100644 --- a/cmd/application/env/get.go +++ b/cmd/application/env/get.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewGetEnvCommand() *cobra.Command { Long: `Get detailed information about a specific environment variable by UUID or key name.`, Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() appUUID := args[0] envUUID := args[1] diff --git a/cmd/application/env/list.go b/cmd/application/env/list.go index 9a6f8b0..24bcd3f 100644 --- a/cmd/application/env/list.go +++ b/cmd/application/env/list.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewListEnvCommand() *cobra.Command { Long: `List all environment variables for a specific application.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/application/env/sync.go b/cmd/application/env/sync.go index 7728423..d676301 100644 --- a/cmd/application/env/sync.go +++ b/cmd/application/env/sync.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "strings" @@ -25,7 +24,7 @@ func NewSyncEnvCommand() *cobra.Command { Example: coolify app env sync abc123 --file .env.production`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/application/env/update.go b/cmd/application/env/update.go index 0e83c4e..4ff5ec0 100644 --- a/cmd/application/env/update.go +++ b/cmd/application/env/update.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewUpdateEnvCommand() *cobra.Command { Long: `Update an existing environment variable. First UUID is the application, second is the specific environment variable to update.`, Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() appUUID := args[0] envUUID := args[1] diff --git a/cmd/application/get.go b/cmd/application/get.go index fa48ebf..c04f162 100644 --- a/cmd/application/get.go +++ b/cmd/application/get.go @@ -1,7 +1,6 @@ package application import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewGetCommand() *cobra.Command { Long: `Retrieve detailed information about a specific application.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/application/list.go b/cmd/application/list.go index 3c371ee..5199859 100644 --- a/cmd/application/list.go +++ b/cmd/application/list.go @@ -1,7 +1,6 @@ package application import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewListCommand() *cobra.Command { Short: "List all applications", Long: `List all applications in Coolify.`, RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/application/logs.go b/cmd/application/logs.go index e65f041..8069f93 100644 --- a/cmd/application/logs.go +++ b/cmd/application/logs.go @@ -1,7 +1,6 @@ package application import ( - "context" "fmt" "os" "os/signal" @@ -22,7 +21,7 @@ func NewLogsCommand() *cobra.Command { Long: `Retrieve logs for an application. Use --follow to continuously stream new logs.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/application/restart.go b/cmd/application/restart.go index e6a7362..a223613 100644 --- a/cmd/application/restart.go +++ b/cmd/application/restart.go @@ -1,7 +1,6 @@ package application import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewRestartCommand() *cobra.Command { Long: `Restart a running application.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/application/start.go b/cmd/application/start.go index 056e553..2c4c72b 100644 --- a/cmd/application/start.go +++ b/cmd/application/start.go @@ -1,7 +1,6 @@ package application import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewStartCommand() *cobra.Command { Long: `Start an application (initiates a deployment).`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/application/stop.go b/cmd/application/stop.go index f60b514..2171557 100644 --- a/cmd/application/stop.go +++ b/cmd/application/stop.go @@ -1,7 +1,6 @@ package application import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewStopCommand() *cobra.Command { Long: `Stop a running application.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/application/update.go b/cmd/application/update.go index ed98a62..e360ad6 100644 --- a/cmd/application/update.go +++ b/cmd/application/update.go @@ -1,7 +1,6 @@ package application import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewUpdateCommand() *cobra.Command { Long: `Update configuration for a specific application. Only specified fields will be updated.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/context/verify.go b/cmd/context/verify.go index 5b027c7..74e57b6 100644 --- a/cmd/context/verify.go +++ b/cmd/context/verify.go @@ -1,7 +1,6 @@ package context import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewVerifyCommand() *cobra.Command { Long: `Verify that the current context is properly configured by testing the connection to the Coolify instance and validating the API token.`, RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() // Get API client - this will use the current default context client, err := cli.GetAPIClient(cmd) diff --git a/cmd/context/version.go b/cmd/context/version.go index 38fa65a..3e9a489 100644 --- a/cmd/context/version.go +++ b/cmd/context/version.go @@ -1,7 +1,6 @@ package context import ( - "context" "fmt" "github.com/spf13/cobra" @@ -15,7 +14,7 @@ func NewVersionCommand() *cobra.Command { Use: "version", Short: "Get current context's Coolify version", RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() // Get API client client, err := cli.GetAPIClient(cmd) diff --git a/cmd/database/backup/create.go b/cmd/database/backup/create.go index 1577881..4466ac4 100644 --- a/cmd/database/backup/create.go +++ b/cmd/database/backup/create.go @@ -1,7 +1,6 @@ package backup import ( - "context" "fmt" "github.com/spf13/cobra" @@ -22,7 +21,7 @@ func NewCreateCommand() *cobra.Command { Example: coolify database backup create abc123 --frequency "0 0 * * *" --enabled`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() dbUUID := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/database/backup/delete-execution.go b/cmd/database/backup/delete-execution.go index bb63d96..028d65f 100644 --- a/cmd/database/backup/delete-execution.go +++ b/cmd/database/backup/delete-execution.go @@ -2,7 +2,6 @@ package backup import ( "bufio" - "context" "fmt" "os" "strings" @@ -21,7 +20,7 @@ func NewDeleteExecutionCommand() *cobra.Command { Long: `Delete a specific backup execution and optionally from S3. First UUID is the database, second is the backup configuration, third is the specific execution.`, Args: cli.ExactArgs(3, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() dbUUID := args[0] backupUUID := args[1] executionUUID := args[2] diff --git a/cmd/database/backup/delete.go b/cmd/database/backup/delete.go index 63638f1..50a4591 100644 --- a/cmd/database/backup/delete.go +++ b/cmd/database/backup/delete.go @@ -2,7 +2,6 @@ package backup import ( "bufio" - "context" "fmt" "os" "strings" @@ -21,7 +20,7 @@ func NewDeleteCommand() *cobra.Command { Long: `Delete a backup configuration and optionally all its executions from S3. First UUID is the database, second is the specific backup configuration.`, Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() dbUUID := args[0] backupUUID := args[1] diff --git a/cmd/database/backup/execution.go b/cmd/database/backup/execution.go index 8d44bc1..37d760d 100644 --- a/cmd/database/backup/execution.go +++ b/cmd/database/backup/execution.go @@ -1,7 +1,6 @@ package backup import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewExecutionCommand() *cobra.Command { Long: `List all executions for a backup configuration. First UUID is the database, second is the specific backup configuration.`, Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() dbUUID := args[0] backupUUID := args[1] diff --git a/cmd/database/backup/list.go b/cmd/database/backup/list.go index 5b2419a..64f36b2 100644 --- a/cmd/database/backup/list.go +++ b/cmd/database/backup/list.go @@ -1,7 +1,6 @@ package backup import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewListCommand() *cobra.Command { Long: `List all backup configurations for a specific database.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() dbUUID := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/database/backup/trigger.go b/cmd/database/backup/trigger.go index a0bc49a..d0bbcc0 100644 --- a/cmd/database/backup/trigger.go +++ b/cmd/database/backup/trigger.go @@ -1,7 +1,6 @@ package backup import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewTriggerCommand() *cobra.Command { Long: `Trigger an immediate backup for a specific backup configuration. First UUID is the database, second is the specific backup configuration to trigger.`, Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() dbUUID := args[0] backupUUID := args[1] diff --git a/cmd/database/backup/update.go b/cmd/database/backup/update.go index cb3ddf7..bd1e84b 100644 --- a/cmd/database/backup/update.go +++ b/cmd/database/backup/update.go @@ -1,7 +1,6 @@ package backup import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewUpdateCommand() *cobra.Command { Long: `Update a backup configuration settings (frequency, retention, S3, etc.). First UUID is the database, second is the specific backup configuration.`, Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() dbUUID := args[0] backupUUID := args[1] diff --git a/cmd/database/create.go b/cmd/database/create.go index 96a8feb..a89ac7c 100644 --- a/cmd/database/create.go +++ b/cmd/database/create.go @@ -1,7 +1,6 @@ package database import ( - "context" "fmt" "strings" @@ -26,7 +25,7 @@ Examples: coolify databases create mysql --server-uuid= --project-uuid= --environment-name=production --name="My MySQL"`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() dbType := args[0] validTypes := []string{"postgresql", "mysql", "mariadb", "mongodb", "redis", "keydb", "clickhouse", "dragonfly"} isValid := false diff --git a/cmd/database/delete.go b/cmd/database/delete.go index a7bbb1c..13393fc 100644 --- a/cmd/database/delete.go +++ b/cmd/database/delete.go @@ -2,7 +2,6 @@ package database import ( "bufio" - "context" "fmt" "os" "strings" @@ -21,7 +20,7 @@ func NewDeleteCommand() *cobra.Command { Long: `Delete a database and optionally clean up its configurations, volumes, and networks.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] force, _ := cmd.Flags().GetBool("force") diff --git a/cmd/database/get.go b/cmd/database/get.go index f1b3ca8..32d2e32 100644 --- a/cmd/database/get.go +++ b/cmd/database/get.go @@ -1,7 +1,6 @@ package database import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewGetCommand() *cobra.Command { Long: `Get detailed information about a specific database by UUID.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/database/list.go b/cmd/database/list.go index ec22855..bca5583 100644 --- a/cmd/database/list.go +++ b/cmd/database/list.go @@ -1,7 +1,6 @@ package database import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewListCommand() *cobra.Command { Short: "List all databases", Long: `List all databases in Coolify.`, RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/database/restart.go b/cmd/database/restart.go index 3d918f0..0419144 100644 --- a/cmd/database/restart.go +++ b/cmd/database/restart.go @@ -1,7 +1,6 @@ package database import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewRestartCommand() *cobra.Command { Long: `Restart a database by UUID.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/database/start.go b/cmd/database/start.go index 3582f5d..36997f9 100644 --- a/cmd/database/start.go +++ b/cmd/database/start.go @@ -1,7 +1,6 @@ package database import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewStartCommand() *cobra.Command { Long: `Start a database by UUID.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/database/stop.go b/cmd/database/stop.go index 08b7c70..8401d93 100644 --- a/cmd/database/stop.go +++ b/cmd/database/stop.go @@ -1,7 +1,6 @@ package database import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewStopCommand() *cobra.Command { Long: `Stop a database by UUID.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/database/update.go b/cmd/database/update.go index ba33415..20c58af 100644 --- a/cmd/database/update.go +++ b/cmd/database/update.go @@ -1,7 +1,6 @@ package database import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewUpdateCommand() *cobra.Command { Long: `Update a database's configuration by UUID.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] req := &models.DatabaseUpdateRequest{} diff --git a/cmd/deployment/batch.go b/cmd/deployment/batch.go index 46a6c4c..8cbc610 100644 --- a/cmd/deployment/batch.go +++ b/cmd/deployment/batch.go @@ -1,7 +1,6 @@ package deployment import ( - "context" "fmt" "strings" @@ -21,7 +20,7 @@ Provide resource names as comma-separated values. Example: coolify deploy batch app1,app2,app3`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() namesStr := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/deployment/cancel.go b/cmd/deployment/cancel.go index 51215b8..d508aa0 100644 --- a/cmd/deployment/cancel.go +++ b/cmd/deployment/cancel.go @@ -19,7 +19,7 @@ func NewCancelCommand() *cobra.Command { Long: `Cancel an in-progress deployment. This will stop the deployment process and clean up any temporary resources.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) @@ -32,7 +32,10 @@ func NewCancelCommand() *cobra.Command { return err } - force, _ := cmd.Flags().GetBool("force") + force, err := cmd.Flags().GetBool("force") + if err != nil { + return fmt.Errorf("failed to parse force flag: %w", err) + } // Prompt for confirmation unless --force is used if !force { @@ -54,7 +57,11 @@ func NewCancelCommand() *cobra.Command { return fmt.Errorf("failed to cancel deployment: %w", err) } - format, _ := cmd.Flags().GetString("format") + format, err := cmd.Flags().GetString("format") + if err != nil { + return fmt.Errorf("failed to get format flag: %w", err) + } + formatter, err := output.NewFormatter(format, output.Options{}) if err != nil { return fmt.Errorf("failed to create formatter: %w", err) diff --git a/cmd/deployment/get.go b/cmd/deployment/get.go index 16af068..0bf0f45 100644 --- a/cmd/deployment/get.go +++ b/cmd/deployment/get.go @@ -1,7 +1,6 @@ package deployment import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewGetCommand() *cobra.Command { Long: `Get detailed information about a specific deployment by its UUID.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/deployment/list.go b/cmd/deployment/list.go index db9ed02..e54dc13 100644 --- a/cmd/deployment/list.go +++ b/cmd/deployment/list.go @@ -1,7 +1,6 @@ package deployment import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewListCommand() *cobra.Command { Short: "List all deployments", Long: `List all currently running deployments across all resources.`, RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/deployment/name.go b/cmd/deployment/name.go index 4896d8e..a200651 100644 --- a/cmd/deployment/name.go +++ b/cmd/deployment/name.go @@ -1,7 +1,6 @@ package deployment import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewNameCommand() *cobra.Command { Short: "Deploy by resource name", Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() name := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/deployment/uuid.go b/cmd/deployment/uuid.go index 569e672..d906fd2 100644 --- a/cmd/deployment/uuid.go +++ b/cmd/deployment/uuid.go @@ -1,7 +1,6 @@ package deployment import ( - "context" "fmt" "github.com/spf13/cobra" @@ -24,7 +23,7 @@ func NewUUIDCommand() *cobra.Command { Short: "Deploy by uuid", Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/github/branches.go b/cmd/github/branches.go index 3bab9c2..66b135d 100644 --- a/cmd/github/branches.go +++ b/cmd/github/branches.go @@ -1,7 +1,6 @@ package github import ( - "context" "fmt" "github.com/spf13/cobra" @@ -20,7 +19,7 @@ func NewListBranchesCommand() *cobra.Command { Example: coolify github branches abc-123-def owner/repository`, Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() appUUID := args[0] // Parse owner/repo diff --git a/cmd/github/create.go b/cmd/github/create.go index 78ef420..4f558f6 100644 --- a/cmd/github/create.go +++ b/cmd/github/create.go @@ -1,7 +1,6 @@ package github import ( - "context" "fmt" "github.com/spf13/cobra" @@ -22,7 +21,7 @@ Required flags: --name, --api-url, --html-url, --app-id, --installation-id, --cl Example: coolify github create --name "My GitHub App" --api-url "https://api.github.com" --html-url "https://github.com" --app-id 123456 --installation-id 789012 --client-id "Iv1.abc123" --client-secret "secret123" --private-key-uuid "abc-123-def-456"`, RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/github/delete.go b/cmd/github/delete.go index 2be782b..7e80107 100644 --- a/cmd/github/delete.go +++ b/cmd/github/delete.go @@ -1,7 +1,6 @@ package github import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewDeleteCommand() *cobra.Command { Long: `Delete a GitHub App integration. The app must not be used by any applications.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() appUUID := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/github/get.go b/cmd/github/get.go index eff837d..9087900 100644 --- a/cmd/github/get.go +++ b/cmd/github/get.go @@ -1,7 +1,6 @@ package github import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewGetCommand() *cobra.Command { Long: `Get detailed information about a specific GitHub App integration.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() appUUID := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/github/list.go b/cmd/github/list.go index f3430eb..c7a6a8b 100644 --- a/cmd/github/list.go +++ b/cmd/github/list.go @@ -1,7 +1,6 @@ package github import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewListCommand() *cobra.Command { Short: "List all GitHub App integrations", Long: `List all GitHub App integrations configured in Coolify.`, RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/github/repo.go b/cmd/github/repo.go index 9eb7bb9..b66641f 100644 --- a/cmd/github/repo.go +++ b/cmd/github/repo.go @@ -1,7 +1,6 @@ package github import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewListRepositoriesCommand() *cobra.Command { Long: `List all repositories that are accessible by the specified GitHub App.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() appUUID := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/github/update.go b/cmd/github/update.go index fa93c77..df779b2 100644 --- a/cmd/github/update.go +++ b/cmd/github/update.go @@ -1,7 +1,6 @@ package github import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewUpdateCommand() *cobra.Command { Long: `Update an existing GitHub App integration. Provide the app UUID and the fields you want to update.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() appUUID := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/privatekeys/create.go b/cmd/privatekeys/create.go index b17f47f..e66dd4d 100644 --- a/cmd/privatekeys/create.go +++ b/cmd/privatekeys/create.go @@ -1,7 +1,6 @@ package privatekeys import ( - "context" "fmt" "os" @@ -20,7 +19,7 @@ func NewCreateCommand() *cobra.Command { Args: cli.ExactArgs(2, " "), Short: "Add a private key", RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() name := args[0] privateKeyInput := args[1] diff --git a/cmd/privatekeys/delete.go b/cmd/privatekeys/delete.go index 4ab2076..3ff4eb1 100644 --- a/cmd/privatekeys/delete.go +++ b/cmd/privatekeys/delete.go @@ -1,7 +1,6 @@ package privatekeys import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewDeleteCommand() *cobra.Command { Args: cli.ExactArgs(1, ""), Short: "Remove a private key", RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/privatekeys/list.go b/cmd/privatekeys/list.go index 2a2acd6..b34a3e9 100644 --- a/cmd/privatekeys/list.go +++ b/cmd/privatekeys/list.go @@ -1,7 +1,6 @@ package privatekeys import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewListCommand() *cobra.Command { Use: "list", Short: "List all private keys", RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/project/get.go b/cmd/project/get.go index fe058a4..03ebdf0 100644 --- a/cmd/project/get.go +++ b/cmd/project/get.go @@ -1,7 +1,6 @@ package project import ( - "context" "fmt" "github.com/spf13/cobra" @@ -24,7 +23,7 @@ func NewGetCommand() *cobra.Command { Short: "Get a project by uuid", Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/project/list.go b/cmd/project/list.go index db81532..3218985 100644 --- a/cmd/project/list.go +++ b/cmd/project/list.go @@ -1,7 +1,6 @@ package project import ( - "context" "fmt" "github.com/spf13/cobra" @@ -24,7 +23,7 @@ func NewListCommand() *cobra.Command { Use: "list", Short: "List all projects", RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/resources/list.go b/cmd/resources/list.go index e0166aa..ddbc677 100644 --- a/cmd/resources/list.go +++ b/cmd/resources/list.go @@ -1,7 +1,6 @@ package resources import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewListCommand() *cobra.Command { Use: "list", Short: "List all resources", RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/server/add.go b/cmd/server/add.go index 7146c01..2a2cf80 100644 --- a/cmd/server/add.go +++ b/cmd/server/add.go @@ -1,7 +1,6 @@ package server import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewAddCommand() *cobra.Command { Args: cli.ExactArgs(3, " "), Short: "Add a server", RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() // Get API client client, err := cli.GetAPIClient(cmd) diff --git a/cmd/server/domain.go b/cmd/server/domain.go index 89de1d5..9dc97f8 100644 --- a/cmd/server/domain.go +++ b/cmd/server/domain.go @@ -1,7 +1,6 @@ package server import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewGetDomainsCommand() *cobra.Command { Args: cli.ExactArgs(1, ""), Short: "Get server domains by uuid", RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() // Get API client client, err := cli.GetAPIClient(cmd) diff --git a/cmd/server/get.go b/cmd/server/get.go index cb79f1c..9f8e483 100644 --- a/cmd/server/get.go +++ b/cmd/server/get.go @@ -1,7 +1,6 @@ package server import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewGetCommand() *cobra.Command { Args: cli.ExactArgs(1, ""), Short: "Get server details by uuid", RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() // Get API client client, err := cli.GetAPIClient(cmd) diff --git a/cmd/server/list.go b/cmd/server/list.go index 1bfe070..efdabd3 100644 --- a/cmd/server/list.go +++ b/cmd/server/list.go @@ -1,7 +1,6 @@ package server import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewListCommand() *cobra.Command { Use: "list", Short: "List all servers", RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() // Get API client client, err := cli.GetAPIClient(cmd) diff --git a/cmd/server/remove.go b/cmd/server/remove.go index 9f5a69f..c9c833e 100644 --- a/cmd/server/remove.go +++ b/cmd/server/remove.go @@ -1,7 +1,6 @@ package server import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewRemoveCommand() *cobra.Command { Args: cli.ExactArgs(1, ""), Short: "Remove a server", RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() // Get API client client, err := cli.GetAPIClient(cmd) diff --git a/cmd/server/validate.go b/cmd/server/validate.go index db84624..b46a648 100644 --- a/cmd/server/validate.go +++ b/cmd/server/validate.go @@ -1,7 +1,6 @@ package server import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewValidateCommand() *cobra.Command { Args: cli.ExactArgs(1, ""), Short: "Validate a server", RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() // Get API client client, err := cli.GetAPIClient(cmd) diff --git a/cmd/service/delete.go b/cmd/service/delete.go index cea0540..47016b8 100644 --- a/cmd/service/delete.go +++ b/cmd/service/delete.go @@ -1,7 +1,6 @@ package service import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewDeleteCommand() *cobra.Command { Long: `Delete a service and optionally clean up its configurations, volumes, and networks.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/service/env/create.go b/cmd/service/env/create.go index 2a27ba0..8f5ea65 100644 --- a/cmd/service/env/create.go +++ b/cmd/service/env/create.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewCreateCommand() *cobra.Command { Long: `Create a new environment variable for a specific service. Use --key and --value flags to specify the variable.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/service/env/delete.go b/cmd/service/env/delete.go index ae4cd36..6dcdb6b 100644 --- a/cmd/service/env/delete.go +++ b/cmd/service/env/delete.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "github.com/spf13/cobra" @@ -17,7 +16,7 @@ func NewDeleteCommand() *cobra.Command { Long: `Delete an environment variable from a service. First UUID is the service, second is the specific environment variable to delete.`, Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() serviceUUID := args[0] envUUID := args[1] diff --git a/cmd/service/env/get.go b/cmd/service/env/get.go index b004645..5af3026 100644 --- a/cmd/service/env/get.go +++ b/cmd/service/env/get.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewGetCommand() *cobra.Command { Long: `Get detailed information about a specific environment variable. First UUID is the service, second is the environment variable UUID or key name.`, Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() serviceUUID := args[0] envUUID := args[1] diff --git a/cmd/service/env/list.go b/cmd/service/env/list.go index 5c5619b..608c6a1 100644 --- a/cmd/service/env/list.go +++ b/cmd/service/env/list.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewListCommand() *cobra.Command { Long: `List all environment variables for a specific service.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/service/env/sync.go b/cmd/service/env/sync.go index 91b2a6a..6d08095 100644 --- a/cmd/service/env/sync.go +++ b/cmd/service/env/sync.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "strings" @@ -25,7 +24,7 @@ func NewSyncCommand() *cobra.Command { Example: coolify service env sync abc123 --file .env.production`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/service/env/update.go b/cmd/service/env/update.go index 52a990c..17246e7 100644 --- a/cmd/service/env/update.go +++ b/cmd/service/env/update.go @@ -1,7 +1,6 @@ package env import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewUpdateCommand() *cobra.Command { Long: `Update an existing environment variable. First UUID is the service, second is the specific environment variable to update.`, Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() serviceUUID := args[0] envUUID := args[1] diff --git a/cmd/service/get.go b/cmd/service/get.go index 83764d9..b3c1500 100644 --- a/cmd/service/get.go +++ b/cmd/service/get.go @@ -1,7 +1,6 @@ package service import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewGetCommand() *cobra.Command { Long: `Get detailed information about a specific service.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/service/list.go b/cmd/service/list.go index 56d5323..0e4ad15 100644 --- a/cmd/service/list.go +++ b/cmd/service/list.go @@ -1,7 +1,6 @@ package service import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewListCommand() *cobra.Command { Short: "List all services", Long: `List all services in Coolify.`, RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/service/restart.go b/cmd/service/restart.go index a8c4502..c7019b3 100644 --- a/cmd/service/restart.go +++ b/cmd/service/restart.go @@ -1,7 +1,6 @@ package service import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewRestartCommand() *cobra.Command { Long: `Restart a service (restart all containers).`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/service/start.go b/cmd/service/start.go index bb8ab3c..c952f9f 100644 --- a/cmd/service/start.go +++ b/cmd/service/start.go @@ -1,7 +1,6 @@ package service import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewStartCommand() *cobra.Command { Long: `Start a service (deploy all containers).`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/service/stop.go b/cmd/service/stop.go index 3812639..90f4fdb 100644 --- a/cmd/service/stop.go +++ b/cmd/service/stop.go @@ -1,7 +1,6 @@ package service import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewStopCommand() *cobra.Command { Long: `Stop a service (stop all containers).`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() uuid := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/teams/current.go b/cmd/teams/current.go index 6e97fce..fc3d7c6 100644 --- a/cmd/teams/current.go +++ b/cmd/teams/current.go @@ -1,7 +1,6 @@ package teams import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewCurrentCommand() *cobra.Command { Short: "Get currently authenticated team", Long: `Get details of the team associated with the current authentication token.`, RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/teams/get.go b/cmd/teams/get.go index 1561267..7be22be 100644 --- a/cmd/teams/get.go +++ b/cmd/teams/get.go @@ -1,7 +1,6 @@ package teams import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewGetCommand() *cobra.Command { Long: `Get detailed information about a specific team by its ID.`, Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() teamID := args[0] client, err := cli.GetAPIClient(cmd) diff --git a/cmd/teams/list.go b/cmd/teams/list.go index 9f6270b..0332546 100644 --- a/cmd/teams/list.go +++ b/cmd/teams/list.go @@ -1,7 +1,6 @@ package teams import ( - "context" "fmt" "github.com/spf13/cobra" @@ -18,7 +17,7 @@ func NewListCommand() *cobra.Command { Short: "List all teams", Long: `List all teams you have access to.`, RunE: func(cmd *cobra.Command, _ []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/teams/members/list.go b/cmd/teams/members/list.go index 3c6c763..319285e 100644 --- a/cmd/teams/members/list.go +++ b/cmd/teams/members/list.go @@ -1,7 +1,6 @@ package members import ( - "context" "fmt" "github.com/spf13/cobra" @@ -19,7 +18,7 @@ func NewListCommand() *cobra.Command { Long: `List members of a specific team by ID, or list members of the current team if no ID is provided.`, Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() + ctx := cmd.Context() client, err := cli.GetAPIClient(cmd) if err != nil { diff --git a/cmd/update/update.go b/cmd/update/update.go index 43e5c97..7674f60 100644 --- a/cmd/update/update.go +++ b/cmd/update/update.go @@ -1,7 +1,6 @@ package update import ( - "context" "fmt" "log" "os" @@ -19,7 +18,7 @@ func NewUpdateCommand() *cobra.Command { Use: "update", Short: "Update Coolify CLI", RunE: func(_ *cobra.Command, _ []string) error { - latest, found, err := selfupdate.DetectLatest(context.Background(), selfupdate.ParseSlug("coollabsio/coolify-cli")) + latest, found, err := selfupdate.DetectLatest(cmd.Context(), selfupdate.ParseSlug("coollabsio/coolify-cli")) if err != nil { return fmt.Errorf("failed to detect latest version: %w", err) } @@ -40,7 +39,7 @@ func NewUpdateCommand() *cobra.Command { if err != nil { return fmt.Errorf("could not locate executable path: %w", err) } - if err := selfupdate.UpdateTo(context.Background(), latest.AssetURL, latest.AssetName, exe); err != nil { + if err := selfupdate.UpdateTo(cmd.Context(), latest.AssetURL, latest.AssetName, exe); err != nil { return fmt.Errorf("error occurred while updating binary: %w", err) } log.Printf("Successfully updated to version %s", latest.Version()) diff --git a/internal/output/table.go b/internal/output/table.go index fbe578e..a060456 100644 --- a/internal/output/table.go +++ b/internal/output/table.go @@ -2,7 +2,6 @@ package output import ( "fmt" - "os" "reflect" "strings" "text/tabwriter" @@ -18,16 +17,18 @@ func NewTableFormatter(opts Options) *TableFormatter { return &TableFormatter{opts: opts} } -func (f *TableFormatter) Format(data any) error { // TODO +func (f *TableFormatter) Format(data any) (err error) { w := tabwriter.NewWriter(f.opts.Writer, 0, 0, 2, ' ', tabwriter.Debug) defer func() { - err := w.Flush() - if err != nil { - fmt.Fprintf(os.Stderr, "failed to flush table writer: %v\n", err) - return + if flushErr := w.Flush(); flushErr != nil { + if err == nil { + err = fmt.Errorf("failed to flush table writer: %w", flushErr) + } + } + // Add a final newline nach table output, aber nur wenn kein Fehler + if err == nil { + fmt.Fprintln(f.opts.Writer) } - // Add a final newline after table output - fmt.Fprintln(f.opts.Writer) }() // Handle different data types diff --git a/internal/version/checker.go b/internal/version/checker.go index 0236d9a..f6252e3 100644 --- a/internal/version/checker.go +++ b/internal/version/checker.go @@ -1,7 +1,6 @@ package version import ( - "context" "encoding/json" "fmt" "io" @@ -45,7 +44,7 @@ func CheckLatestVersionOfCli(debug bool) (string, error) { } url := "https://api.github.com/repos/coollabsio/coolify-cli/git/refs/tags" - ctx := context.Background() + ctx := cmd.Context() req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { return "", err From 9cef9ebee76fa28c63001ad48eb2110032e58a68 Mon Sep 17 00:00:00 2001 From: YaRissi <53705290+YaRissi@users.noreply.github.com> Date: Tue, 28 Oct 2025 23:27:03 +0100 Subject: [PATCH 7/9] fix: improve error handling in commands --- cmd/application/env/create.go | 6 +++--- cmd/application/env/get.go | 6 +++--- cmd/context/set_default.go | 21 ++++++++++++++++----- cmd/context/use.go | 13 ++++++++++--- cmd/deployment/cancel.go | 1 - cmd/update/update.go | 2 +- internal/version/checker.go | 3 ++- 7 files changed, 35 insertions(+), 17 deletions(-) diff --git a/cmd/application/env/create.go b/cmd/application/env/create.go index 880417f..8066eff 100644 --- a/cmd/application/env/create.go +++ b/cmd/application/env/create.go @@ -15,10 +15,10 @@ func NewCreateEnvCommand() *cobra.Command { Use: "create ", Short: "Create an environment variable for an application", Long: `Create a new environment variable for a specific application. Use --key and --value flags to specify the variable.`, - Args: cli.ExactArgs(1, ""), + Args: cli.ExactArgs(1, ""), RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() - uuid := args[0] + appUUID := args[0] client, err := cli.GetAPIClient(cmd) if err != nil { @@ -58,7 +58,7 @@ func NewCreateEnvCommand() *cobra.Command { } appSvc := service.NewApplicationService(client) - env, err := appSvc.CreateEnv(ctx, uuid, req) + env, err := appSvc.CreateEnv(ctx, appUUID, req) if err != nil { return fmt.Errorf("failed to create environment variable: %w", err) } diff --git a/cmd/application/env/get.go b/cmd/application/env/get.go index f46d202..a8f75f0 100644 --- a/cmd/application/env/get.go +++ b/cmd/application/env/get.go @@ -15,11 +15,11 @@ func NewGetEnvCommand() *cobra.Command { Use: "get ", Short: "Get environment variable details", Long: `Get detailed information about a specific environment variable by UUID or key name.`, - Args: cli.ExactArgs(2, " "), + Args: cli.ExactArgs(2, " "), RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() appUUID := args[0] - envUUID := args[1] + envUUIDOrKey := args[1] client, err := cli.GetAPIClient(cmd) if err != nil { @@ -27,7 +27,7 @@ func NewGetEnvCommand() *cobra.Command { } appSvc := service.NewApplicationService(client) - env, err := appSvc.GetEnv(ctx, appUUID, envUUID) + env, err := appSvc.GetEnv(ctx, appUUID, envUUIDOrKey) if err != nil { return fmt.Errorf("failed to get environment variable: %w", err) } diff --git a/cmd/context/set_default.go b/cmd/context/set_default.go index 7b03c60..f3e8260 100644 --- a/cmd/context/set_default.go +++ b/cmd/context/set_default.go @@ -19,13 +19,20 @@ func NewSetDefaultCommand() *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { name := args[0] - instances := viper.Get("instances").([]interface{}) + raw := viper.Get("instances") + instances, ok := raw.([]interface{}) + if !ok { + return fmt.Errorf("invalid instances configuration") + } // Check if instance exists var found bool for _, instance := range instances { - instanceMap := instance.(map[string]interface{}) - if instanceMap["name"] == name { + instanceMap, ok := instance.(map[string]interface{}) + if !ok { + return fmt.Errorf("invalid instance configuration") + } + if val, ok := instanceMap["name"].(string); ok && val == name { found = true instanceMap["default"] = true } @@ -37,8 +44,12 @@ func NewSetDefaultCommand() *cobra.Command { // Only unset other defaults if we found the target instance for _, instance := range instances { - instanceMap := instance.(map[string]interface{}) - if instanceMap["name"] != name { + instanceMap, ok := instance.(map[string]interface{}) + if !ok { + return fmt.Errorf("invalid instance configuration") + } + + if val, ok := instanceMap["name"].(string); ok && val != name { instanceMap["default"] = false } } diff --git a/cmd/context/use.go b/cmd/context/use.go index e422e9f..6be7d05 100644 --- a/cmd/context/use.go +++ b/cmd/context/use.go @@ -18,13 +18,20 @@ func NewUseCommand() *cobra.Command { Short: "Switch to a different context (set as default)", RunE: func(_ *cobra.Command, args []string) error { name := args[0] - instances := viper.Get("instances").([]interface{}) + raw := viper.Get("instances") + instances, ok := raw.([]interface{}) + if !ok { + return fmt.Errorf("invalid instances configuration") + } // Check if instance exists var found bool for _, instance := range instances { - instanceMap := instance.(map[string]interface{}) - if instanceMap["name"] == name { + instanceMap, ok := instance.(map[string]interface{}) + if !ok { + return fmt.Errorf("invalid instance configuration") + } + if val, ok := instanceMap["name"].(string); ok && val == name { found = true break } diff --git a/cmd/deployment/cancel.go b/cmd/deployment/cancel.go index d508aa0..b0d97bf 100644 --- a/cmd/deployment/cancel.go +++ b/cmd/deployment/cancel.go @@ -1,7 +1,6 @@ package deployment import ( - "context" "fmt" "github.com/spf13/cobra" diff --git a/cmd/update/update.go b/cmd/update/update.go index 7674f60..ac10c55 100644 --- a/cmd/update/update.go +++ b/cmd/update/update.go @@ -17,7 +17,7 @@ func NewUpdateCommand() *cobra.Command { return &cobra.Command{ Use: "update", Short: "Update Coolify CLI", - RunE: func(_ *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { latest, found, err := selfupdate.DetectLatest(cmd.Context(), selfupdate.ParseSlug("coollabsio/coolify-cli")) if err != nil { return fmt.Errorf("failed to detect latest version: %w", err) diff --git a/internal/version/checker.go b/internal/version/checker.go index f6252e3..0236d9a 100644 --- a/internal/version/checker.go +++ b/internal/version/checker.go @@ -1,6 +1,7 @@ package version import ( + "context" "encoding/json" "fmt" "io" @@ -44,7 +45,7 @@ func CheckLatestVersionOfCli(debug bool) (string, error) { } url := "https://api.github.com/repos/coollabsio/coolify-cli/git/refs/tags" - ctx := cmd.Context() + ctx := context.Background() req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { return "", err From 1078a9d3ca42b9bb95d3ded7112525e7407e2b55 Mon Sep 17 00:00:00 2001 From: YaRissi <53705290+YaRissi@users.noreply.github.com> Date: Tue, 28 Oct 2025 23:42:04 +0100 Subject: [PATCH 8/9] fix: improve instance validation and error handling in context switching --- cmd/context/use.go | 8 ++++++-- internal/output/table.go | 8 +++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/cmd/context/use.go b/cmd/context/use.go index 6be7d05..84df3d8 100644 --- a/cmd/context/use.go +++ b/cmd/context/use.go @@ -43,8 +43,12 @@ func NewUseCommand() *cobra.Command { // Update default for _, instance := range instances { - instanceMap := instance.(map[string]interface{}) - if instanceMap["name"] == name { + instanceMap, ok := instance.(map[string]interface{}) + if !ok { + return fmt.Errorf("invalid instance configuration") + } + + if val, ok := instanceMap["name"].(string); ok && val == name { instanceMap["default"] = true } else { delete(instanceMap, "default") diff --git a/internal/output/table.go b/internal/output/table.go index a060456..6ff302b 100644 --- a/internal/output/table.go +++ b/internal/output/table.go @@ -27,7 +27,9 @@ func (f *TableFormatter) Format(data any) (err error) { } // Add a final newline nach table output, aber nur wenn kein Fehler if err == nil { - fmt.Fprintln(f.opts.Writer) + if _, nlErr := fmt.Fprintln(f.opts.Writer); nlErr != nil { + err = fmt.Errorf("failed to write trailing newline: %w", nlErr) + } } }() @@ -68,7 +70,7 @@ func (f *TableFormatter) formatSlice(w *tabwriter.Writer, val reflect.Value) err if firstElem.Kind() != reflect.Struct { // Simple slice (e.g., []string) - for i := range val.Len() { + for i := 0; i < val.Len(); i++ { if _, err := fmt.Fprintf(w, "%v\n", val.Index(i).Interface()); err != nil { return fmt.Errorf("failed to write slice element: %w", err) } @@ -85,7 +87,7 @@ func (f *TableFormatter) formatSlice(w *tabwriter.Writer, val reflect.Value) err } // Print rows - for i := range val.Len() { + for i := 0; i < val.Len(); i++ { elem := val.Index(i) if elem.Kind() == reflect.Ptr { elem = elem.Elem() From 9f5a44be0458f8356018d744f070c7c68b97d401 Mon Sep 17 00:00:00 2001 From: YaRissi <53705290+YaRissi@users.noreply.github.com> Date: Tue, 28 Oct 2025 23:51:16 +0100 Subject: [PATCH 9/9] fix: comment --- internal/output/table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/output/table.go b/internal/output/table.go index 6ff302b..d42242b 100644 --- a/internal/output/table.go +++ b/internal/output/table.go @@ -25,7 +25,7 @@ func (f *TableFormatter) Format(data any) (err error) { err = fmt.Errorf("failed to flush table writer: %w", flushErr) } } - // Add a final newline nach table output, aber nur wenn kein Fehler + // Add a final newline nach table output, but only if no error occurred if err == nil { if _, nlErr := fmt.Fprintln(f.opts.Writer); nlErr != nil { err = fmt.Errorf("failed to write trailing newline: %w", nlErr)