Merge pull request #33 from YaRissi/ci

feat: testing ci with linter
This commit is contained in:
Andras Bacsai
2025-10-29 15:22:39 +01:00
committed by GitHub
114 changed files with 920 additions and 656 deletions
+7
View File
@@ -0,0 +1,7 @@
## Changes
-
## Issues & Discussions
- fix #
+55
View File
@@ -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: v2.5.0 # pin version for consistency
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 -cover ./...
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."
+75
View File
@@ -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
+2 -2
View File
@@ -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)
+8 -4
View File
@@ -1,12 +1,12 @@
package application
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 {
@@ -16,7 +16,7 @@ func NewDeleteCommand() *cobra.Command {
Long: `Delete an application. This action cannot be undone.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
force, _ := cmd.Flags().GetBool("force")
@@ -24,7 +24,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.")
+6 -6
View File
@@ -1,13 +1,13 @@
package env
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 {
@@ -15,10 +15,10 @@ func NewCreateEnvCommand() *cobra.Command {
Use: "create <app_uuid>",
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, "<uuid>"),
Args: cli.ExactArgs(1, "<app_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
uuid := args[0]
ctx := cmd.Context()
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)
}
+8 -4
View File
@@ -1,12 +1,12 @@
package env
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 {
@@ -16,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, "<uuid1> <uuid2>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
appUUID := args[0]
envUUID := args[1]
@@ -31,7 +31,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.")
+6 -6
View File
@@ -1,13 +1,13 @@
package env
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 {
@@ -15,11 +15,11 @@ func NewGetEnvCommand() *cobra.Command {
Use: "get <app_uuid> <env_uuid_or_key>",
Short: "Get environment variable details",
Long: `Get detailed information about a specific environment variable by UUID or key name.`,
Args: cli.ExactArgs(2, "<uuid1> <uuid2>"),
Args: cli.ExactArgs(2, "<app_uuid> <env_uuid_or_key>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
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)
}
+3 -3
View File
@@ -1,13 +1,13 @@
package env
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 {
@@ -17,7 +17,7 @@ func NewListEnvCommand() *cobra.Command {
Long: `List all environment variables for a specific application.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,15 +1,15 @@
package env
import (
"context"
"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 {
@@ -24,7 +24,7 @@ func NewSyncEnvCommand() *cobra.Command {
Example: coolify app env sync abc123 --file .env.production`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,13 +1,13 @@
package env
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 {
@@ -17,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, "<uuid1> <uuid2>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
appUUID := args[0]
envUUID := args[1]
+3 -3
View File
@@ -1,13 +1,13 @@
package application
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 {
@@ -17,7 +17,7 @@ func NewGetCommand() *cobra.Command {
Long: `Retrieve detailed information about a specific application.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+4 -4
View File
@@ -1,14 +1,14 @@
package application
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,8 +16,8 @@ func NewListCommand() *cobra.Command {
Use: "list",
Short: "List all applications",
Long: `List all applications in Coolify.`,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
client, err := cli.GetAPIClient(cmd)
if err != nil {
+3 -3
View File
@@ -1,7 +1,6 @@
package application
import (
"context"
"fmt"
"os"
"os/signal"
@@ -9,9 +8,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 {
@@ -21,7 +21,7 @@ func NewLogsCommand() *cobra.Command {
Long: `Retrieve logs for an application. Use --follow to continuously stream new logs.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,12 +1,12 @@
package application
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 {
@@ -16,7 +16,7 @@ func NewRestartCommand() *cobra.Command {
Long: `Restart a running application.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,12 +1,12 @@
package application
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 {
@@ -17,7 +17,7 @@ func NewStartCommand() *cobra.Command {
Long: `Start an application (initiates a deployment).`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,12 +1,12 @@
package application
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 {
@@ -16,7 +16,7 @@ func NewStopCommand() *cobra.Command {
Long: `Stop a running application.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,14 +1,14 @@
package application
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 {
@@ -18,7 +18,7 @@ func NewUpdateCommand() *cobra.Command {
Long: `Update configuration for a specific application. Only specified fields will be updated.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+2 -1
View File
@@ -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 {
+3 -2
View File
@@ -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())
},
}
+11 -7
View File
@@ -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
@@ -16,7 +17,7 @@ func NewAddCommand() *cobra.Command {
Example: `context add myserver https://coolify.example.com your-api-token`,
Args: cli.ExactArgs(3, "<context_name> <url> <token>"),
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]
@@ -44,12 +45,14 @@ func NewAddCommand() *cobra.Command {
fmt.Printf("%s already exists. Force overwriting.\n", name)
}
viper.Set("instances", instances)
viper.WriteConfig()
return
if err := viper.WriteConfig(); err != nil {
return fmt.Errorf("failed to write config: %w", err)
}
return nil
}
fmt.Printf("%s already exists.\n", name)
fmt.Println("\nNote: Use --force to force overwrite.")
return
return nil
}
}
@@ -77,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
},
}
+12 -7
View File
@@ -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, "<context_name>"),
Short: "Delete a context",
Run: func(cmd *cobra.Command, args []string) {
RunE: func(_ *cobra.Command, args []string) error {
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 {
return fmt.Errorf("failed to write config: %w", 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 {
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)
} else {
@@ -40,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)
},
}
}
+3 -2
View File
@@ -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
+4 -3
View File
@@ -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 {
+23 -11
View File
@@ -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
@@ -18,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
}
@@ -32,13 +40,17 @@ 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, 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
}
}
+8 -5
View File
@@ -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, "<context_name> <token>"),
Short: "Update the API token for a context",
Run: func(cmd *cobra.Command, args []string) {
RunE: func(_ *cobra.Command, args []string) error {
name := args[0]
token := args[1]
var found interface{}
@@ -27,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 {
@@ -38,8 +38,11 @@ func NewSetTokenCommand() *cobra.Command {
}
}
viper.Set("instances", instances)
viper.WriteConfig()
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
},
}
}
+9 -13
View File
@@ -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
@@ -15,7 +16,7 @@ func NewUpdateCommand() *cobra.Command {
Example: `context update myserver --name newname --url https://new.coolify.com --token newtoken`,
Args: cli.ExactArgs(1, "<context_name>"),
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{})
@@ -26,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 <context_name> [--name <new_name>] [--url <new_url>] [--token <new_token>]")
return
return fmt.Errorf("at least one of --name, --url, or --token must be provided")
}
// Find the context
@@ -44,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
@@ -53,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
@@ -72,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
@@ -84,6 +79,7 @@ func NewUpdateCommand() *cobra.Command {
finalName = newName
}
fmt.Printf("Context '%s' updated successfully.\n", finalName)
return nil
},
}
+19 -7
View File
@@ -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,15 +16,22 @@ func NewUseCommand() *cobra.Command {
Example: `context use myserver`,
Args: cli.ExactArgs(1, "<context_name>"),
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{})
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
}
@@ -35,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")
+4 -4
View File
@@ -1,11 +1,11 @@
package context
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,8 +15,8 @@ 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 {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
// Get API client - this will use the current default context
client, err := cli.GetAPIClient(cmd)
+9 -8
View File
@@ -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",
})
}))
+4 -4
View File
@@ -1,11 +1,11 @@
package context
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,8 +13,8 @@ func NewVersionCommand() *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Get current context's Coolify version",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
// Get API client
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,14 +1,14 @@
package backup
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
@@ -21,7 +21,7 @@ func NewCreateCommand() *cobra.Command {
Example: coolify database backup create abc123 --frequency "0 0 * * *" --enabled`,
Args: cli.ExactArgs(1, "<database_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
dbUUID := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -2,14 +2,14 @@ package backup
import (
"bufio"
"context"
"fmt"
"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
@@ -20,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, "<database_uuid> <backup_uuid> <execution_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
dbUUID := args[0]
backupUUID := args[1]
executionUUID := args[2]
+3 -3
View File
@@ -2,14 +2,14 @@ package backup
import (
"bufio"
"context"
"fmt"
"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
@@ -20,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, "<database_uuid> <backup_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
dbUUID := args[0]
backupUUID := args[1]
+3 -3
View File
@@ -1,13 +1,13 @@
package backup
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
@@ -18,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, "<database_uuid> <backup_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
dbUUID := args[0]
backupUUID := args[1]
+3 -3
View File
@@ -1,13 +1,13 @@
package backup
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
@@ -18,7 +18,7 @@ func NewListCommand() *cobra.Command {
Long: `List all backup configurations for a specific database.`,
Args: cli.ExactArgs(1, "<database_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
dbUUID := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,13 +1,13 @@
package backup
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
@@ -18,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, "<database_uuid> <backup_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
dbUUID := args[0]
backupUUID := args[1]
+3 -3
View File
@@ -1,13 +1,13 @@
package backup
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
@@ -18,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, "<database_uuid> <backup_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
dbUUID := args[0]
backupUUID := args[1]
+4 -4
View File
@@ -1,15 +1,15 @@
package database
import (
"context"
"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 {
@@ -25,7 +25,7 @@ Examples:
coolify databases create mysql --server-uuid=<uuid> --project-uuid=<uuid> --environment-name=production --name="My MySQL"`,
Args: cli.ExactArgs(1, "<type>"),
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
@@ -116,7 +116,7 @@ Examples:
}
if cmd.Flags().Changed("postgres-db") {
db, _ := cmd.Flags().GetString("postgres-db")
req.PostgresDb = &db
req.PostgresDB = &db
}
}
+3 -3
View File
@@ -2,14 +2,14 @@ package database
import (
"bufio"
"context"
"fmt"
"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
@@ -20,7 +20,7 @@ func NewDeleteCommand() *cobra.Command {
Long: `Delete a database and optionally clean up its configurations, volumes, and networks.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
force, _ := cmd.Flags().GetBool("force")
+3 -3
View File
@@ -1,13 +1,13 @@
package database
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
@@ -18,7 +18,7 @@ func NewGetCommand() *cobra.Command {
Long: `Get detailed information about a specific database by UUID.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+4 -4
View File
@@ -1,13 +1,13 @@
package database
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,8 +16,8 @@ func NewListCommand() *cobra.Command {
Use: "list",
Short: "List all databases",
Long: `List all databases in Coolify.`,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
client, err := cli.GetAPIClient(cmd)
if err != nil {
+3 -3
View File
@@ -1,12 +1,12 @@
package database
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
@@ -17,7 +17,7 @@ func NewRestartCommand() *cobra.Command {
Long: `Restart a database by UUID.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,12 +1,12 @@
package database
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
@@ -17,7 +17,7 @@ func NewStartCommand() *cobra.Command {
Long: `Start a database by UUID.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,12 +1,12 @@
package database
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
@@ -17,7 +17,7 @@ func NewStopCommand() *cobra.Command {
Long: `Stop a database by UUID.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,13 +1,13 @@
package database
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
@@ -18,7 +18,7 @@ func NewUpdateCommand() *cobra.Command {
Long: `Update a database's configuration by UUID.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
req := &models.DatabaseUpdateRequest{}
+3 -3
View File
@@ -1,13 +1,13 @@
package deployment
import (
"context"
"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
@@ -20,7 +20,7 @@ Provide resource names as comma-separated values.
Example: coolify deploy batch app1,app2,app3`,
Args: cli.ExactArgs(1, "<names>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
namesStr := args[0]
client, err := cli.GetAPIClient(cmd)
+16 -7
View File
@@ -1,13 +1,13 @@
package deployment
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
@@ -18,7 +18,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, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
@@ -31,13 +31,18 @@ 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 {
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.")
@@ -51,7 +56,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)
+3 -3
View File
@@ -1,13 +1,13 @@
package deployment
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
@@ -18,7 +18,7 @@ func NewGetCommand() *cobra.Command {
Long: `Get detailed information about a specific deployment by its UUID.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+4 -4
View File
@@ -1,13 +1,13 @@
package deployment
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,8 +16,8 @@ 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 {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
client, err := cli.GetAPIClient(cmd)
if err != nil {
+3 -3
View File
@@ -1,13 +1,13 @@
package deployment
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
@@ -17,7 +17,7 @@ func NewNameCommand() *cobra.Command {
Short: "Deploy by resource name",
Args: cli.ExactArgs(1, "<resource_name>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
name := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,13 +1,13 @@
package deployment
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
@@ -23,7 +23,7 @@ func NewUUIDCommand() *cobra.Command {
Short: "Deploy by uuid",
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
+4 -4
View File
@@ -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)
}
+3 -3
View File
@@ -1,13 +1,13 @@
package github
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 {
@@ -19,7 +19,7 @@ func NewListBranchesCommand() *cobra.Command {
Example: coolify github branches abc-123-def owner/repository`,
Args: cli.ExactArgs(2, "<app_uuid> <owner/repo>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
appUUID := args[0]
// Parse owner/repo
+12 -12
View File
@@ -1,14 +1,14 @@
package github
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,8 +20,8 @@ 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 {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
client, err := cli.GetAPIClient(cmd)
if err != nil {
@@ -100,14 +100,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
}
+8 -4
View File
@@ -1,12 +1,12 @@
package github
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 {
@@ -16,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, "<app_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
appUUID := args[0]
client, err := cli.GetAPIClient(cmd)
@@ -30,7 +30,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.")
+3 -3
View File
@@ -1,13 +1,13 @@
package github
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 {
@@ -17,7 +17,7 @@ func NewGetCommand() *cobra.Command {
Long: `Get detailed information about a specific GitHub App integration.`,
Args: cli.ExactArgs(1, "<app_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
appUUID := args[0]
client, err := cli.GetAPIClient(cmd)
+4 -4
View File
@@ -1,13 +1,13 @@
package github
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,8 +15,8 @@ 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 {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
client, err := cli.GetAPIClient(cmd)
if err != nil {
+3 -3
View File
@@ -1,13 +1,13 @@
package github
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 {
@@ -17,7 +17,7 @@ func NewListRepositoriesCommand() *cobra.Command {
Long: `List all repositories that are accessible by the specified GitHub App.`,
Args: cli.ExactArgs(1, "<app_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
appUUID := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,13 +1,13 @@
package github
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 {
@@ -17,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, "<app_uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
appUUID := args[0]
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,14 +1,14 @@
package privatekeys
import (
"context"
"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
@@ -19,7 +19,7 @@ func NewCreateCommand() *cobra.Command {
Args: cli.ExactArgs(2, "<key_name> <private_key_or_file>"),
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]
+3 -3
View File
@@ -1,12 +1,12 @@
package privatekeys
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
@@ -16,7 +16,7 @@ func NewDeleteCommand() *cobra.Command {
Args: cli.ExactArgs(1, "<uuid>"),
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)
+4 -4
View File
@@ -1,13 +1,13 @@
package privatekeys
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,8 +15,8 @@ func NewListCommand() *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "List all private keys",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
client, err := cli.GetAPIClient(cmd)
if err != nil {
+4 -4
View File
@@ -1,13 +1,13 @@
package project
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
@@ -23,7 +23,7 @@ func NewGetCommand() *cobra.Command {
Short: "Get a project by uuid",
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
@@ -55,7 +55,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,
+4 -4
View File
@@ -1,13 +1,13 @@
package project
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,8 +22,8 @@ func NewListCommand() *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "List all projects",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
client, err := cli.GetAPIClient(cmd)
if err != nil {
+4 -4
View File
@@ -1,13 +1,13 @@
package resources
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,8 +15,8 @@ func NewListCommand() *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "List all resources",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
client, err := cli.GetAPIClient(cmd)
if err != nil {
+14 -11
View File
@@ -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
},
}
@@ -60,7 +60,7 @@ var rootCmd = &cobra.Command{
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(0)
os.Exit(1)
}
}
@@ -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, &notFoundErr) {
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)
+5 -5
View File
@@ -1,13 +1,13 @@
package server
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
@@ -17,7 +17,7 @@ func NewAddCommand() *cobra.Command {
Args: cli.ExactArgs(3, "<server_name> <ip_address> <private_key_uuid>"),
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)
@@ -28,7 +28,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 +39,7 @@ func NewAddCommand() *cobra.Command {
IP: ip,
Port: port,
User: user,
PrivateKeyUUID: privateKeyUuid,
PrivateKeyUUID: privateKeyUUID,
InstantValidate: validate,
}
+3 -3
View File
@@ -1,13 +1,13 @@
package server
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
@@ -18,7 +18,7 @@ func NewGetDomainsCommand() *cobra.Command {
Args: cli.ExactArgs(1, "<uuid>"),
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)
+3 -3
View File
@@ -1,13 +1,13 @@
package server
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
@@ -17,7 +17,7 @@ func NewGetCommand() *cobra.Command {
Args: cli.ExactArgs(1, "<uuid>"),
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)
+4 -4
View File
@@ -1,13 +1,13 @@
package server
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,8 +15,8 @@ func NewListCommand() *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "List all servers",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
// Get API client
client, err := cli.GetAPIClient(cmd)
+3 -3
View File
@@ -1,12 +1,12 @@
package server
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
@@ -16,7 +16,7 @@ func NewRemoveCommand() *cobra.Command {
Args: cli.ExactArgs(1, "<uuid>"),
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)
+3 -3
View File
@@ -1,12 +1,12 @@
package server
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
@@ -16,7 +16,7 @@ func NewValidateCommand() *cobra.Command {
Args: cli.ExactArgs(1, "<uuid>"),
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)
+9 -5
View File
@@ -1,12 +1,12 @@
package service
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
@@ -17,7 +17,7 @@ func NewDeleteCommand() *cobra.Command {
Long: `Delete a service and optionally clean up its configurations, volumes, and networks.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
@@ -35,7 +35,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 +47,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)
+4 -4
View File
@@ -1,13 +1,13 @@
package env
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 {
@@ -17,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, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
@@ -58,7 +58,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)
+5 -5
View File
@@ -1,12 +1,12 @@
package env
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 {
@@ -16,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, "<uuid1> <uuid2>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
serviceUUID := args[0]
envUUID := args[1]
@@ -31,7 +31,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 +39,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)
+4 -4
View File
@@ -1,13 +1,13 @@
package env
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 {
@@ -17,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, "<uuid1> <uuid2>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
serviceUUID := args[0]
envUUID := args[1]
@@ -26,7 +26,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)
+4 -4
View File
@@ -1,13 +1,13 @@
package env
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 {
@@ -17,7 +17,7 @@ func NewListCommand() *cobra.Command {
Long: `List all environment variables for a specific service.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
@@ -25,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)
envs, err := serviceSvc.ListEnvs(ctx, uuid)
if err != nil {
return fmt.Errorf("failed to list environment variables: %w", err)
+4 -4
View File
@@ -1,15 +1,15 @@
package env
import (
"context"
"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 {
@@ -24,7 +24,7 @@ func NewSyncCommand() *cobra.Command {
Example: coolify service env sync abc123 --file .env.production`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
@@ -55,7 +55,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)
+4 -4
View File
@@ -1,13 +1,13 @@
package env
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 {
@@ -17,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, "<uuid1> <uuid2>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
serviceUUID := args[0]
envUUID := args[1]
@@ -61,7 +61,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)
+4 -4
View File
@@ -1,13 +1,13 @@
package service
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
@@ -18,7 +18,7 @@ func NewGetCommand() *cobra.Command {
Long: `Get detailed information about a specific service.`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
@@ -26,7 +26,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)
+5 -5
View File
@@ -1,13 +1,13 @@
package service
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,15 +16,15 @@ func NewListCommand() *cobra.Command {
Use: "list",
Short: "List all services",
Long: `List all services in Coolify.`,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
client, err := cli.GetAPIClient(cmd)
if err != nil {
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)
+4 -4
View File
@@ -1,12 +1,12 @@
package service
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
@@ -17,7 +17,7 @@ func NewRestartCommand() *cobra.Command {
Long: `Restart a service (restart all containers).`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
@@ -25,7 +25,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)
+4 -4
View File
@@ -1,12 +1,12 @@
package service
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
@@ -17,7 +17,7 @@ func NewStartCommand() *cobra.Command {
Long: `Start a service (deploy all containers).`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
@@ -25,7 +25,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)
+4 -4
View File
@@ -1,12 +1,12 @@
package service
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
@@ -17,7 +17,7 @@ func NewStopCommand() *cobra.Command {
Long: `Stop a service (stop all containers).`,
Args: cli.ExactArgs(1, "<uuid>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
uuid := args[0]
client, err := cli.GetAPIClient(cmd)
@@ -25,7 +25,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)
+4 -4
View File
@@ -1,13 +1,13 @@
package teams
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,8 +16,8 @@ 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 {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
client, err := cli.GetAPIClient(cmd)
if err != nil {
+3 -3
View File
@@ -1,13 +1,13 @@
package teams
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
@@ -18,7 +18,7 @@ func NewGetCommand() *cobra.Command {
Long: `Get detailed information about a specific team by its ID.`,
Args: cli.ExactArgs(1, "<team_id>"),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
ctx := cmd.Context()
teamID := args[0]
client, err := cli.GetAPIClient(cmd)
+4 -4
View File
@@ -1,13 +1,13 @@
package teams
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,8 +16,8 @@ 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 {
ctx := context.Background()
RunE: func(cmd *cobra.Command, _ []string) error {
ctx := cmd.Context()
client, err := cli.GetAPIClient(cmd)
if err != nil {
+3 -3
View File
@@ -1,13 +1,13 @@
package members
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
@@ -18,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 {
+2 -1
View File
@@ -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
+12 -17
View File
@@ -1,57 +1,52 @@
package update
import (
"context"
"fmt"
"log"
"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) {
latest, found, err := selfupdate.DetectLatest(context.Background(), selfupdate.ParseSlug("coollabsio/coolify-cli"))
RunE: func(cmd *cobra.Command, _ []string) error {
latest, found, err := selfupdate.DetectLatest(cmd.Context(), 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
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())
} else {
log.Printf("No new update available. You are already running the latest version: %s", currentVersion.String())
}
return nil
},
}
+3 -2
View File
@@ -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)
},
}
+3 -1
View File
@@ -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
}
+20 -21
View File
@@ -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()
+2 -1
View File
@@ -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
+2 -1
View File
@@ -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
+70 -43
View File
@@ -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)
})
+1 -1
View File
@@ -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)
}
+4 -4
View File
@@ -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"`
+2 -2
View File
@@ -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)
}
})

Some files were not shown because too many files have changed in this diff Show More