summaryrefslogtreecommitdiffstats
path: root/cmd/ship/env/set.go
diff options
context:
space:
mode:
authorClawd <ai@clawd.bot>2026-02-17 07:54:26 -0800
committerClawd <ai@clawd.bot>2026-02-17 07:54:26 -0800
commit6b2c04728cd914f27ae62c1df0bf5df24ac9a628 (patch)
tree8a103ac79194a05fae438b0da105589aaa6b78d9 /cmd/ship/env/set.go
parent5e5de4ea1aa98f75d470e4a61644d4b9f100c4b0 (diff)
Remove v1 code, simplify state to just base_domain
- Delete all v1 commands (deploy, init, list, status, remove, etc.) - Delete v1 env/ and host/ subcommand directories - Simplify state.go: remove NextPort, Apps, AllocatePort, etc. - Local state now only tracks default_host + base_domain per host - Ports and deploys are tracked on the server (/etc/ship/ports/) - host init now creates minimal state.json
Diffstat (limited to 'cmd/ship/env/set.go')
-rw-r--r--cmd/ship/env/set.go135
1 files changed, 0 insertions, 135 deletions
diff --git a/cmd/ship/env/set.go b/cmd/ship/env/set.go
deleted file mode 100644
index d4292f3..0000000
--- a/cmd/ship/env/set.go
+++ /dev/null
@@ -1,135 +0,0 @@
1package env
2
3import (
4 "bufio"
5 "fmt"
6 "os"
7 "strings"
8
9 "github.com/bdw/ship/internal/ssh"
10 "github.com/bdw/ship/internal/state"
11 "github.com/spf13/cobra"
12)
13
14var setCmd = &cobra.Command{
15 Use: "set <app> KEY=VALUE...",
16 Short: "Set environment variable(s)",
17 Long: "Set one or more environment variables for an app. Variables are specified as KEY=VALUE pairs.",
18 Args: cobra.MinimumNArgs(2),
19 RunE: runSet,
20}
21
22func init() {
23 setCmd.Flags().StringP("file", "f", "", "Load environment from file")
24}
25
26func runSet(cmd *cobra.Command, args []string) error {
27 name := args[0]
28 if err := state.ValidateName(name); err != nil {
29 return err
30 }
31 envVars := args[1:]
32
33 st, err := state.Load()
34 if err != nil {
35 return fmt.Errorf("error loading state: %w", err)
36 }
37
38 host, _ := cmd.Flags().GetString("host")
39 if host == "" {
40 host = st.GetDefaultHost()
41 }
42
43 if host == "" {
44 return fmt.Errorf("--host is required")
45 }
46
47 app, err := st.GetApp(host, name)
48 if err != nil {
49 return err
50 }
51
52 if app.Type != "app" {
53 return fmt.Errorf("env is only available for apps, not static sites")
54 }
55
56 if app.Env == nil {
57 app.Env = make(map[string]string)
58 }
59
60 // Set variables from args
61 for _, e := range envVars {
62 parts := strings.SplitN(e, "=", 2)
63 if len(parts) == 2 {
64 app.Env[parts[0]] = parts[1]
65 fmt.Printf("Set %s\n", parts[0])
66 } else {
67 return fmt.Errorf("invalid format: %s (expected KEY=VALUE)", e)
68 }
69 }
70
71 // Set variables from file if provided
72 envFile, _ := cmd.Flags().GetString("file")
73 if envFile != "" {
74 fileEnv, err := parseEnvFile(envFile)
75 if err != nil {
76 return fmt.Errorf("error reading env file: %w", err)
77 }
78 for k, v := range fileEnv {
79 app.Env[k] = v
80 fmt.Printf("Set %s\n", k)
81 }
82 }
83
84 if err := st.Save(); err != nil {
85 return fmt.Errorf("error saving state: %w", err)
86 }
87
88 client, err := ssh.Connect(host)
89 if err != nil {
90 return fmt.Errorf("error connecting to VPS: %w", err)
91 }
92 defer client.Close()
93
94 fmt.Println("-> Updating environment file on VPS...")
95 envFilePath := fmt.Sprintf("/etc/ship/env/%s.env", name)
96 envContent := ""
97 for k, v := range app.Env {
98 envContent += fmt.Sprintf("%s=%s\n", k, v)
99 }
100 if err := client.WriteSudoFile(envFilePath, envContent); err != nil {
101 return fmt.Errorf("error updating env file: %w", err)
102 }
103
104 fmt.Println("-> Restarting service...")
105 if _, err := client.RunSudo(fmt.Sprintf("systemctl restart %s", name)); err != nil {
106 return fmt.Errorf("error restarting service: %w", err)
107 }
108
109 fmt.Println("Environment variables updated successfully")
110 return nil
111}
112
113func parseEnvFile(path string) (map[string]string, error) {
114 file, err := os.Open(path)
115 if err != nil {
116 return nil, err
117 }
118 defer file.Close()
119
120 env := make(map[string]string)
121 scanner := bufio.NewScanner(file)
122 for scanner.Scan() {
123 line := strings.TrimSpace(scanner.Text())
124 if line == "" || strings.HasPrefix(line, "#") {
125 continue
126 }
127
128 parts := strings.SplitN(line, "=", 2)
129 if len(parts) == 2 {
130 env[parts[0]] = parts[1]
131 }
132 }
133
134 return env, scanner.Err()
135}