mirror of
https://github.com/coollabsio/coolify-cli.git
synced 2026-06-19 07:35:04 +00:00
Merge remote-tracking branch 'origin/v4.x' into coolify-init-wireguard-mesh
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/coollabsio/coolify-cli/cmd/application/create"
|
||||
"github.com/coollabsio/coolify-cli/cmd/application/env"
|
||||
"github.com/coollabsio/coolify-cli/cmd/application/previews"
|
||||
"github.com/coollabsio/coolify-cli/cmd/application/storage"
|
||||
)
|
||||
|
||||
@@ -57,5 +58,15 @@ func NewAppCommand() *cobra.Command {
|
||||
storageCmd.AddCommand(storage.NewDeleteCommand())
|
||||
cmd.AddCommand(storageCmd)
|
||||
|
||||
// Add previews subcommand with its children
|
||||
previewsCmd := &cobra.Command{
|
||||
Use: "previews",
|
||||
Aliases: []string{"preview"},
|
||||
Short: "Manage application preview deployments",
|
||||
Long: `Manage preview deployments created from pull requests. Requires the application UUID.`,
|
||||
}
|
||||
previewsCmd.AddCommand(previews.NewDeletePreviewCommand())
|
||||
cmd.AddCommand(previewsCmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package previews
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/coollabsio/coolify-cli/internal/cli"
|
||||
"github.com/coollabsio/coolify-cli/internal/service"
|
||||
)
|
||||
|
||||
func NewDeletePreviewCommand() *cobra.Command {
|
||||
deletePreviewCmd := &cobra.Command{
|
||||
Use: "delete <app_uuid> <pr_id>",
|
||||
Short: "Delete a preview deployment",
|
||||
Long: `Delete a preview deployment for an application. First argument is the application UUID, second is the pull request ID.`,
|
||||
Args: cli.ExactArgs(2, "<app_uuid> <pr_id>"),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx := cmd.Context()
|
||||
appUUID := args[0]
|
||||
prID := args[1]
|
||||
|
||||
prIDInt, err := strconv.Atoi(prID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid pr_id: must be an integer")
|
||||
}
|
||||
if prIDInt <= 0 {
|
||||
return fmt.Errorf("invalid pr_id: must be a positive integer")
|
||||
}
|
||||
|
||||
client, err := cli.GetAPIClient(cmd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get API client: %w", err)
|
||||
}
|
||||
|
||||
if err := cli.CheckMinimumVersion(ctx, client, "4.0.0-beta.474"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
force, _ := cmd.Flags().GetBool("force")
|
||||
|
||||
// Prompt for confirmation unless --force is used
|
||||
if !force {
|
||||
var response string
|
||||
fmt.Printf("Are you sure you want to delete the preview deployment for PR %s? (yes/no): ", prID)
|
||||
_, 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.")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
appSvc := service.NewApplicationService(client)
|
||||
err = appSvc.DeletePreview(ctx, appUUID, prID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete preview deployment: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Preview deployment for PR %s deleted successfully.\n", prID)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
deletePreviewCmd.Flags().Bool("force", false, "Skip confirmation prompt")
|
||||
return deletePreviewCmd
|
||||
}
|
||||
@@ -59,6 +59,15 @@ func (s *ApplicationService) Delete(ctx context.Context, uuid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeletePreview deletes a preview deployment for an application
|
||||
func (s *ApplicationService) DeletePreview(ctx context.Context, appUUID, prID string) error {
|
||||
err := s.client.Delete(ctx, fmt.Sprintf("applications/%s/previews/%s", appUUID, prID))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete preview %s for application %s: %w", prID, appUUID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start starts an application (initiates deployment)
|
||||
func (s *ApplicationService) Start(ctx context.Context, uuid string, force bool, instantDeploy bool) (*models.ApplicationLifecycleResponse, error) {
|
||||
var resp models.ApplicationLifecycleResponse
|
||||
|
||||
@@ -402,6 +402,54 @@ func TestApplicationService_Delete_Error(t *testing.T) {
|
||||
assert.Contains(t, err.Error(), "failed to delete application")
|
||||
}
|
||||
|
||||
func TestApplicationService_DeletePreview_Success(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
assert.Equal(t, "/api/v1/applications/app-uuid-123/previews/42", r.URL.Path)
|
||||
assert.Equal(t, "DELETE", r.Method)
|
||||
assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization"))
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte(`{"message":"Preview deletion request queued."}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := api.NewClient(server.URL, "test-token")
|
||||
svc := NewApplicationService(client)
|
||||
|
||||
err := svc.DeletePreview(context.Background(), "app-uuid-123", "42")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestApplicationService_DeletePreview_NotFound(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
_, _ = w.Write([]byte(`{"message":"Preview not found."}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := api.NewClient(server.URL, "test-token")
|
||||
svc := NewApplicationService(client)
|
||||
|
||||
err := svc.DeletePreview(context.Background(), "app-uuid-123", "999")
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "failed to delete preview")
|
||||
}
|
||||
|
||||
func TestApplicationService_DeletePreview_ServerError(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
_, _ = w.Write([]byte(`{"message":"internal server error"}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := api.NewClient(server.URL, "test-token")
|
||||
svc := NewApplicationService(client)
|
||||
|
||||
err := svc.DeletePreview(context.Background(), "app-uuid-123", "42")
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "failed to delete preview")
|
||||
}
|
||||
|
||||
func TestApplicationService_Start(t *testing.T) {
|
||||
deploymentUUID := "deploy-uuid-123"
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
// Version variables injected by GoReleaser at build time via ldflags
|
||||
var (
|
||||
version = "v1.6.1"
|
||||
version = "v1.6.2"
|
||||
)
|
||||
|
||||
// GitHubAPIURL is the URL for fetching CLI version tags (exported for testing)
|
||||
|
||||
@@ -51,6 +51,7 @@ All commands support `--format` flag:
|
||||
|
||||
Aliases are derived from the CLI command tree:
|
||||
- `coolify app env` | `coolify app envs` | `coolify app environment`
|
||||
- `coolify app previews` | `coolify app preview`
|
||||
- `coolify app start` | `coolify app deploy`
|
||||
- `coolify app storage` | `coolify app storages`
|
||||
- `coolify app` | `coolify apps` | `coolify application` | `coolify applications`
|
||||
@@ -851,6 +852,15 @@ Parameters:
|
||||
required: false
|
||||
default: 100
|
||||
|
||||
Command: coolify app previews delete <app_uuid> <pr_id>
|
||||
Description: Delete a preview deployment for an application. First argument is the application UUID, second is the pull request ID.
|
||||
Parameters:
|
||||
- name: --force
|
||||
type: boolean
|
||||
description: Skip confirmation prompt
|
||||
required: false
|
||||
default: false
|
||||
|
||||
Command: coolify app restart <uuid>
|
||||
Description: Restart a running application.
|
||||
Parameters: (None)
|
||||
|
||||
Reference in New Issue
Block a user