1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
package main
import (
"os"
"github.com/bdw/ship/internal/output"
"github.com/spf13/cobra"
)
var hostFlag string
// This file defines the v2 CLI structure.
// The primary command is: ship [PATH] [FLAGS]
// All output is JSON by default.
var rootV2Cmd = &cobra.Command{
Use: "ship [PATH]",
Short: "Deploy code to a VPS. JSON output for agents.",
Long: `Ship deploys code to a VPS. Point it at a directory or binary, get a URL back.
ship ./myproject # auto-detect and deploy
ship ./site --name docs # deploy with specific name
ship ./api --health /healthz # deploy with health check
ship ./preview --ttl 24h # deploy with auto-expiry
All output is JSON. Use --pretty for human-readable output.`,
Args: cobra.MaximumNArgs(1),
RunE: runDeployV2,
SilenceUsage: true,
SilenceErrors: true,
DisableAutoGenTag: true,
}
func initV2() {
// Global flags
rootV2Cmd.PersistentFlags().StringVar(&hostFlag, "host", "", "VPS host (SSH config alias or user@host)")
rootV2Cmd.PersistentFlags().BoolVar(&output.Pretty, "pretty", false, "Human-readable output")
// Deploy flags
rootV2Cmd.Flags().String("name", "", "Deploy name (becomes subdomain)")
rootV2Cmd.Flags().String("domain", "", "Custom domain for deployment")
rootV2Cmd.Flags().String("health", "", "Health check endpoint (e.g., /healthz)")
rootV2Cmd.Flags().String("ttl", "", "Auto-delete after duration (e.g., 1h, 7d)")
rootV2Cmd.Flags().StringArray("env", nil, "Environment variable (KEY=VALUE)")
rootV2Cmd.Flags().String("env-file", "", "Path to .env file")
rootV2Cmd.Flags().Int("container-port", 80, "Port the container listens on (Docker only)")
// Check for SHIP_PRETTY env var
if os.Getenv("SHIP_PRETTY") == "1" {
output.Pretty = true
}
// Add subcommands
rootV2Cmd.AddCommand(listV2Cmd)
rootV2Cmd.AddCommand(statusV2Cmd)
rootV2Cmd.AddCommand(logsV2Cmd)
rootV2Cmd.AddCommand(removeV2Cmd)
rootV2Cmd.AddCommand(hostV2Cmd)
// Initialize host subcommands (from host_v2.go)
initHostV2()
}
func runDeployV2(cmd *cobra.Command, args []string) error {
path := "."
if len(args) > 0 {
path = args[0]
}
opts := deployV2Options{
Host: hostFlag,
Pretty: output.Pretty,
}
// Get flag values
opts.Name, _ = cmd.Flags().GetString("name")
opts.Domain, _ = cmd.Flags().GetString("domain")
opts.Health, _ = cmd.Flags().GetString("health")
opts.TTL, _ = cmd.Flags().GetString("ttl")
opts.Env, _ = cmd.Flags().GetStringArray("env")
opts.EnvFile, _ = cmd.Flags().GetString("env-file")
opts.ContainerPort, _ = cmd.Flags().GetInt("container-port")
// deployV2 handles all output and exits
deployV2(path, opts)
// Should not reach here (deployV2 calls os.Exit)
return nil
}
// Subcommands (list, status, logs, remove) are defined in commands_v2.go
var hostV2Cmd = &cobra.Command{
Use: "host",
Short: "Manage VPS host",
}
// hostInitV2Cmd, hostStatusV2Cmd, and initHostV2() are defined in host_v2.go
|