summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/deploy/deploy.go9
-rw-r--r--cmd/deploy/env.go24
-rw-r--r--cmd/deploy/init.go28
-rw-r--r--cmd/deploy/list.go24
-rw-r--r--cmd/deploy/manage.go93
-rw-r--r--internal/config/config.go65
-rw-r--r--internal/state/state.go13
7 files changed, 84 insertions, 172 deletions
diff --git a/cmd/deploy/deploy.go b/cmd/deploy/deploy.go
index 2b3ab4a..ee7ee4a 100644
--- a/cmd/deploy/deploy.go
+++ b/cmd/deploy/deploy.go
@@ -9,7 +9,6 @@ import (
9 "strconv" 9 "strconv"
10 "strings" 10 "strings"
11 11
12 "github.com/bdw/deploy/internal/config"
13 "github.com/bdw/deploy/internal/ssh" 12 "github.com/bdw/deploy/internal/ssh"
14 "github.com/bdw/deploy/internal/state" 13 "github.com/bdw/deploy/internal/state"
15 "github.com/bdw/deploy/internal/templates" 14 "github.com/bdw/deploy/internal/templates"
@@ -55,14 +54,14 @@ func runDeploy(args []string) {
55 54
56 fs.Parse(args) 55 fs.Parse(args)
57 56
58 // Get host from flag or config 57 // Get host from flag or state default
59 if *host == "" { 58 if *host == "" {
60 cfg, err := config.Load() 59 st, err := state.Load()
61 if err != nil { 60 if err != nil {
62 fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err) 61 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
63 os.Exit(1) 62 os.Exit(1)
64 } 63 }
65 *host = cfg.Host 64 *host = st.GetDefaultHost()
66 } 65 }
67 66
68 if *host == "" || *domain == "" { 67 if *host == "" || *domain == "" {
diff --git a/cmd/deploy/env.go b/cmd/deploy/env.go
index 135fb77..a43cd6a 100644
--- a/cmd/deploy/env.go
+++ b/cmd/deploy/env.go
@@ -6,7 +6,6 @@ import (
6 "os" 6 "os"
7 "strings" 7 "strings"
8 8
9 "github.com/bdw/deploy/internal/config"
10 "github.com/bdw/deploy/internal/ssh" 9 "github.com/bdw/deploy/internal/ssh"
11 "github.com/bdw/deploy/internal/state" 10 "github.com/bdw/deploy/internal/state"
12) 11)
@@ -29,14 +28,16 @@ func runEnv(args []string) {
29 28
30 name := fs.Args()[0] 29 name := fs.Args()[0]
31 30
32 // Get host from flag or config 31 // Load state
32 st, err := state.Load()
33 if err != nil {
34 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
35 os.Exit(1)
36 }
37
38 // Get host from flag or state default
33 if *host == "" { 39 if *host == "" {
34 cfg, err := config.Load() 40 *host = st.GetDefaultHost()
35 if err != nil {
36 fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err)
37 os.Exit(1)
38 }
39 *host = cfg.Host
40 } 41 }
41 42
42 if *host == "" { 43 if *host == "" {
@@ -45,13 +46,6 @@ func runEnv(args []string) {
45 os.Exit(1) 46 os.Exit(1)
46 } 47 }
47 48
48 // Load state
49 st, err := state.Load()
50 if err != nil {
51 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
52 os.Exit(1)
53 }
54
55 // Get app info 49 // Get app info
56 app, err := st.GetApp(*host, name) 50 app, err := st.GetApp(*host, name)
57 if err != nil { 51 if err != nil {
diff --git a/cmd/deploy/init.go b/cmd/deploy/init.go
index 72c7d53..1713879 100644
--- a/cmd/deploy/init.go
+++ b/cmd/deploy/init.go
@@ -6,7 +6,6 @@ import (
6 "os" 6 "os"
7 "strings" 7 "strings"
8 8
9 "github.com/bdw/deploy/internal/config"
10 "github.com/bdw/deploy/internal/ssh" 9 "github.com/bdw/deploy/internal/ssh"
11 "github.com/bdw/deploy/internal/state" 10 "github.com/bdw/deploy/internal/state"
12) 11)
@@ -16,14 +15,16 @@ func runInit(args []string) {
16 host := fs.String("host", "", "VPS host (SSH config alias or user@host)") 15 host := fs.String("host", "", "VPS host (SSH config alias or user@host)")
17 fs.Parse(args) 16 fs.Parse(args)
18 17
19 // Get host from flag or config 18 // Load state
19 st, err := state.Load()
20 if err != nil {
21 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
22 os.Exit(1)
23 }
24
25 // Get host from flag or state default
20 if *host == "" { 26 if *host == "" {
21 cfg, err := config.Load() 27 *host = st.GetDefaultHost()
22 if err != nil {
23 fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err)
24 os.Exit(1)
25 }
26 *host = cfg.Host
27 } 28 }
28 29
29 if *host == "" { 30 if *host == "" {
@@ -115,13 +116,12 @@ import /etc/caddy/sites-enabled/*
115 fmt.Println(" ✓ Caddy is active") 116 fmt.Println(" ✓ Caddy is active")
116 } 117 }
117 118
118 // Initialize local state if needed 119 // Update state
119 st, err := state.Load()
120 if err != nil {
121 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
122 os.Exit(1)
123 }
124 st.GetHost(*host) // Ensure host exists in state 120 st.GetHost(*host) // Ensure host exists in state
121 if st.GetDefaultHost() == "" {
122 st.SetDefaultHost(*host)
123 fmt.Printf(" Set %s as default host\n", *host)
124 }
125 if err := st.Save(); err != nil { 125 if err := st.Save(); err != nil {
126 fmt.Fprintf(os.Stderr, "Error saving state: %v\n", err) 126 fmt.Fprintf(os.Stderr, "Error saving state: %v\n", err)
127 os.Exit(1) 127 os.Exit(1)
diff --git a/cmd/deploy/list.go b/cmd/deploy/list.go
index b74cf35..ce1605b 100644
--- a/cmd/deploy/list.go
+++ b/cmd/deploy/list.go
@@ -6,7 +6,6 @@ import (
6 "os" 6 "os"
7 "text/tabwriter" 7 "text/tabwriter"
8 8
9 "github.com/bdw/deploy/internal/config"
10 "github.com/bdw/deploy/internal/state" 9 "github.com/bdw/deploy/internal/state"
11) 10)
12 11
@@ -15,14 +14,16 @@ func runList(args []string) {
15 host := fs.String("host", "", "VPS host (SSH config alias or user@host)") 14 host := fs.String("host", "", "VPS host (SSH config alias or user@host)")
16 fs.Parse(args) 15 fs.Parse(args)
17 16
18 // Get host from flag or config 17 // Load state
18 st, err := state.Load()
19 if err != nil {
20 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
21 os.Exit(1)
22 }
23
24 // Get host from flag or state default
19 if *host == "" { 25 if *host == "" {
20 cfg, err := config.Load() 26 *host = st.GetDefaultHost()
21 if err != nil {
22 fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err)
23 os.Exit(1)
24 }
25 *host = cfg.Host
26 } 27 }
27 28
28 if *host == "" { 29 if *host == "" {
@@ -31,13 +32,6 @@ func runList(args []string) {
31 os.Exit(1) 32 os.Exit(1)
32 } 33 }
33 34
34 // Load state
35 st, err := state.Load()
36 if err != nil {
37 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
38 os.Exit(1)
39 }
40
41 apps := st.ListApps(*host) 35 apps := st.ListApps(*host)
42 if len(apps) == 0 { 36 if len(apps) == 0 {
43 fmt.Printf("No deployments found for %s\n", *host) 37 fmt.Printf("No deployments found for %s\n", *host)
diff --git a/cmd/deploy/manage.go b/cmd/deploy/manage.go
index 3cee1f4..1f52b92 100644
--- a/cmd/deploy/manage.go
+++ b/cmd/deploy/manage.go
@@ -5,7 +5,6 @@ import (
5 "fmt" 5 "fmt"
6 "os" 6 "os"
7 7
8 "github.com/bdw/deploy/internal/config"
9 "github.com/bdw/deploy/internal/ssh" 8 "github.com/bdw/deploy/internal/ssh"
10 "github.com/bdw/deploy/internal/state" 9 "github.com/bdw/deploy/internal/state"
11) 10)
@@ -23,14 +22,16 @@ func runRemove(args []string) {
23 22
24 name := fs.Args()[0] 23 name := fs.Args()[0]
25 24
26 // Get host from flag or config 25 // Load state
26 st, err := state.Load()
27 if err != nil {
28 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
29 os.Exit(1)
30 }
31
32 // Get host from flag or state default
27 if *host == "" { 33 if *host == "" {
28 cfg, err := config.Load() 34 *host = st.GetDefaultHost()
29 if err != nil {
30 fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err)
31 os.Exit(1)
32 }
33 *host = cfg.Host
34 } 35 }
35 36
36 if *host == "" { 37 if *host == "" {
@@ -39,13 +40,6 @@ func runRemove(args []string) {
39 os.Exit(1) 40 os.Exit(1)
40 } 41 }
41 42
42 // Load state
43 st, err := state.Load()
44 if err != nil {
45 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
46 os.Exit(1)
47 }
48
49 // Get app info 43 // Get app info
50 app, err := st.GetApp(*host, name) 44 app, err := st.GetApp(*host, name)
51 if err != nil { 45 if err != nil {
@@ -128,14 +122,16 @@ func runLogs(args []string) {
128 122
129 name := fs.Args()[0] 123 name := fs.Args()[0]
130 124
131 // Get host from flag or config 125 // Load state
126 st, err := state.Load()
127 if err != nil {
128 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
129 os.Exit(1)
130 }
131
132 // Get host from flag or state default
132 if *host == "" { 133 if *host == "" {
133 cfg, err := config.Load() 134 *host = st.GetDefaultHost()
134 if err != nil {
135 fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err)
136 os.Exit(1)
137 }
138 *host = cfg.Host
139 } 135 }
140 136
141 if *host == "" { 137 if *host == "" {
@@ -144,13 +140,6 @@ func runLogs(args []string) {
144 os.Exit(1) 140 os.Exit(1)
145 } 141 }
146 142
147 // Load state to verify app exists
148 st, err := state.Load()
149 if err != nil {
150 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
151 os.Exit(1)
152 }
153
154 app, err := st.GetApp(*host, name) 143 app, err := st.GetApp(*host, name)
155 if err != nil { 144 if err != nil {
156 fmt.Fprintf(os.Stderr, "Error: %v\n", err) 145 fmt.Fprintf(os.Stderr, "Error: %v\n", err)
@@ -207,14 +196,16 @@ func runStatus(args []string) {
207 196
208 name := fs.Args()[0] 197 name := fs.Args()[0]
209 198
210 // Get host from flag or config 199 // Load state
200 st, err := state.Load()
201 if err != nil {
202 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
203 os.Exit(1)
204 }
205
206 // Get host from flag or state default
211 if *host == "" { 207 if *host == "" {
212 cfg, err := config.Load() 208 *host = st.GetDefaultHost()
213 if err != nil {
214 fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err)
215 os.Exit(1)
216 }
217 *host = cfg.Host
218 } 209 }
219 210
220 if *host == "" { 211 if *host == "" {
@@ -223,13 +214,6 @@ func runStatus(args []string) {
223 os.Exit(1) 214 os.Exit(1)
224 } 215 }
225 216
226 // Load state to verify app exists
227 st, err := state.Load()
228 if err != nil {
229 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
230 os.Exit(1)
231 }
232
233 app, err := st.GetApp(*host, name) 217 app, err := st.GetApp(*host, name)
234 if err != nil { 218 if err != nil {
235 fmt.Fprintf(os.Stderr, "Error: %v\n", err) 219 fmt.Fprintf(os.Stderr, "Error: %v\n", err)
@@ -274,14 +258,16 @@ func runRestart(args []string) {
274 258
275 name := fs.Args()[0] 259 name := fs.Args()[0]
276 260
277 // Get host from flag or config 261 // Load state
262 st, err := state.Load()
263 if err != nil {
264 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
265 os.Exit(1)
266 }
267
268 // Get host from flag or state default
278 if *host == "" { 269 if *host == "" {
279 cfg, err := config.Load() 270 *host = st.GetDefaultHost()
280 if err != nil {
281 fmt.Fprintf(os.Stderr, "Error loading config: %v\n", err)
282 os.Exit(1)
283 }
284 *host = cfg.Host
285 } 271 }
286 272
287 if *host == "" { 273 if *host == "" {
@@ -290,13 +276,6 @@ func runRestart(args []string) {
290 os.Exit(1) 276 os.Exit(1)
291 } 277 }
292 278
293 // Load state to verify app exists
294 st, err := state.Load()
295 if err != nil {
296 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
297 os.Exit(1)
298 }
299
300 app, err := st.GetApp(*host, name) 279 app, err := st.GetApp(*host, name)
301 if err != nil { 280 if err != nil {
302 fmt.Fprintf(os.Stderr, "Error: %v\n", err) 281 fmt.Fprintf(os.Stderr, "Error: %v\n", err)
diff --git a/internal/config/config.go b/internal/config/config.go
deleted file mode 100644
index 8651aa8..0000000
--- a/internal/config/config.go
+++ /dev/null
@@ -1,65 +0,0 @@
1package config
2
3import (
4 "bufio"
5 "os"
6 "path/filepath"
7 "strings"
8)
9
10// Config represents the user's configuration
11type Config struct {
12 Host string
13}
14
15// Load reads config from ~/.config/deploy/config
16func Load() (*Config, error) {
17 path := configPath()
18
19 // If file doesn't exist, return empty config
20 if _, err := os.Stat(path); os.IsNotExist(err) {
21 return &Config{}, nil
22 }
23
24 file, err := os.Open(path)
25 if err != nil {
26 return nil, err
27 }
28 defer file.Close()
29
30 cfg := &Config{}
31 scanner := bufio.NewScanner(file)
32 for scanner.Scan() {
33 line := strings.TrimSpace(scanner.Text())
34 if line == "" || strings.HasPrefix(line, "#") {
35 continue
36 }
37
38 parts := strings.SplitN(line, ":", 2)
39 if len(parts) != 2 {
40 continue
41 }
42
43 key := strings.TrimSpace(parts[0])
44 value := strings.TrimSpace(parts[1])
45
46 switch key {
47 case "host":
48 cfg.Host = value
49 }
50 }
51
52 if err := scanner.Err(); err != nil {
53 return nil, err
54 }
55
56 return cfg, nil
57}
58
59func configPath() string {
60 home, err := os.UserHomeDir()
61 if err != nil {
62 return ".deploy-config"
63 }
64 return filepath.Join(home, ".config", "deploy", "config")
65}
diff --git a/internal/state/state.go b/internal/state/state.go
index eb1dee8..def0bcf 100644
--- a/internal/state/state.go
+++ b/internal/state/state.go
@@ -9,7 +9,8 @@ import (
9 9
10// State represents the entire local deployment state 10// State represents the entire local deployment state
11type State struct { 11type State struct {
12 Hosts map[string]*Host `json:"hosts"` 12 DefaultHost string `json:"default_host,omitempty"`
13 Hosts map[string]*Host `json:"hosts"`
13} 14}
14 15
15// Host represents deployment state for a single VPS 16// Host represents deployment state for a single VPS
@@ -137,6 +138,16 @@ func (s *State) ListApps(host string) map[string]*App {
137 return h.Apps 138 return h.Apps
138} 139}
139 140
141// GetDefaultHost returns the default host, or empty string if not set
142func (s *State) GetDefaultHost() string {
143 return s.DefaultHost
144}
145
146// SetDefaultHost sets the default host
147func (s *State) SetDefaultHost(host string) {
148 s.DefaultHost = host
149}
150
140// statePath returns the path to the state file 151// statePath returns the path to the state file
141func statePath() string { 152func statePath() string {
142 home, err := os.UserHomeDir() 153 home, err := os.UserHomeDir()