From 778bef5ee6941056e06326d1eaaa6956d7307a85 Mon Sep 17 00:00:00 2001 From: Clawd Date: Sat, 18 Apr 2026 14:40:17 -0700 Subject: Remove Go implementation — ship is skills-only now MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The skills/ directory fully replaces the old Go CLI. Drop all Go source, build files, planning docs, and the stale SECURITY.md (which described the old git-user push-deploy model that no longer exists). Trim .gitignore to match the new tree. --- cmd/ship/commands.go | 365 --------------------------------------------------- 1 file changed, 365 deletions(-) delete mode 100644 cmd/ship/commands.go (limited to 'cmd/ship/commands.go') diff --git a/cmd/ship/commands.go b/cmd/ship/commands.go deleted file mode 100644 index 1b0d09c..0000000 --- a/cmd/ship/commands.go +++ /dev/null @@ -1,365 +0,0 @@ -package main - -import ( - "fmt" - "strconv" - "strings" - "time" - - "github.com/bdw/ship/internal/output" - "github.com/bdw/ship/internal/ssh" - "github.com/bdw/ship/internal/state" - "github.com/spf13/cobra" -) - -// listV2Cmd lists all deployments -var listV2Cmd = &cobra.Command{ - Use: "list", - Short: "List all deployments", - RunE: runListV2, -} - -func runListV2(cmd *cobra.Command, args []string) error { - st, err := state.Load() - if err != nil { - output.PrintAndExit(output.Err(output.ErrHostNotConfigured, err.Error())) - } - - hostName := hostFlag - if hostName == "" { - hostName = st.DefaultHost - } - if hostName == "" { - output.PrintAndExit(output.Err(output.ErrHostNotConfigured, "no host specified")) - } - - hostConfig := st.GetHost(hostName) - - client, err := ssh.Connect(hostName) - if err != nil { - output.PrintAndExit(output.Err(output.ErrSSHConnectFailed, err.Error())) - } - defer client.Close() - - var deploys []output.DeployInfo - - // Get all deployed services by checking /etc/ship/ports and /var/www - // Check ports (apps and docker) - portsOut, _ := client.Run("ls /etc/ship/ports/ 2>/dev/null || true") - for _, name := range strings.Fields(portsOut) { - if name == "" { - continue - } - - // Get actual domain from Caddyfile (first word of first line) - domain := fmt.Sprintf("%s.%s", name, hostConfig.BaseDomain) - caddyOut, _ := client.Run(fmt.Sprintf("head -1 /etc/caddy/sites-enabled/%s.caddy 2>/dev/null | awk '{print $1}'", name)) - if d := strings.TrimSpace(caddyOut); d != "" && d != "{" { - domain = d - } - - info := output.DeployInfo{ - Name: name, - URL: fmt.Sprintf("https://%s", domain), - } - - // Check if it's docker or binary - dockerOut, _ := client.Run(fmt.Sprintf("docker inspect %s 2>/dev/null && echo docker", name)) - if strings.Contains(dockerOut, "docker") { - info.Type = "docker" - } else { - info.Type = "binary" - } - - // Check if running - statusOut, _ := client.RunSudo(fmt.Sprintf("systemctl is-active %s 2>/dev/null || echo inactive", name)) - info.Running = strings.TrimSpace(statusOut) == "active" - - // Check TTL - ttlOut, _ := client.Run(fmt.Sprintf("cat /etc/ship/ttl/%s 2>/dev/null || true", name)) - if ttlOut != "" { - if expires, err := strconv.ParseInt(strings.TrimSpace(ttlOut), 10, 64); err == nil { - info.Expires = time.Unix(expires, 0).UTC().Format(time.RFC3339) - } - } - - deploys = append(deploys, info) - } - - // Check static sites in /var/www - wwwOut, _ := client.Run("ls -d /var/www/*/ 2>/dev/null | xargs -n1 basename 2>/dev/null || true") - for _, name := range strings.Fields(wwwOut) { - if name == "" || name == "html" { - continue - } - - // Skip if already in ports (would be an app, not static) - found := false - for _, d := range deploys { - if d.Name == name { - found = true - break - } - } - if found { - continue - } - - // Get actual domain from Caddyfile - domain := fmt.Sprintf("%s.%s", name, hostConfig.BaseDomain) - caddyOut, _ := client.Run(fmt.Sprintf("head -1 /etc/caddy/sites-enabled/%s.caddy 2>/dev/null | awk '{print $1}'", name)) - if d := strings.TrimSpace(caddyOut); d != "" && d != "{" { - domain = d - } - - info := output.DeployInfo{ - Name: name, - URL: fmt.Sprintf("https://%s", domain), - Type: "static", - Running: true, // Static sites are always "running" - } - - // Check TTL - ttlOut, _ := client.Run(fmt.Sprintf("cat /etc/ship/ttl/%s 2>/dev/null || true", name)) - if ttlOut != "" { - if expires, err := strconv.ParseInt(strings.TrimSpace(ttlOut), 10, 64); err == nil { - info.Expires = time.Unix(expires, 0).UTC().Format(time.RFC3339) - } - } - - deploys = append(deploys, info) - } - - output.PrintAndExit(&output.ListResponse{ - Status: "ok", - Deploys: deploys, - }) - return nil -} - -// statusV2Cmd shows status for a single deployment -var statusV2Cmd = &cobra.Command{ - Use: "status NAME", - Short: "Check status of a deployment", - Args: cobra.ExactArgs(1), - RunE: runStatusV2, -} - -func runStatusV2(cmd *cobra.Command, args []string) error { - name := args[0] - - st, err := state.Load() - if err != nil { - output.PrintAndExit(output.Err(output.ErrHostNotConfigured, err.Error())) - } - - hostName := hostFlag - if hostName == "" { - hostName = st.DefaultHost - } - if hostName == "" { - output.PrintAndExit(output.Err(output.ErrHostNotConfigured, "no host specified")) - } - - hostConfig := st.GetHost(hostName) - - client, err := ssh.Connect(hostName) - if err != nil { - output.PrintAndExit(output.Err(output.ErrSSHConnectFailed, err.Error())) - } - defer client.Close() - - // Check if deployment exists - portOut, _ := client.Run(fmt.Sprintf("cat /etc/ship/ports/%s 2>/dev/null || true", name)) - wwwExists, _ := client.Run(fmt.Sprintf("test -d /var/www/%s && echo exists || true", name)) - - if strings.TrimSpace(portOut) == "" && strings.TrimSpace(wwwExists) == "" { - output.PrintAndExit(output.ErrWithName(output.ErrNotFound, "deployment not found", name)) - } - - // Get actual domain from Caddyfile - domain := fmt.Sprintf("%s.%s", name, hostConfig.BaseDomain) - caddyOut, _ := client.Run(fmt.Sprintf("head -1 /etc/caddy/sites-enabled/%s.caddy 2>/dev/null | awk '{print $1}'", name)) - if d := strings.TrimSpace(caddyOut); d != "" && d != "{" { - domain = d - } - - resp := &output.StatusResponse{ - Status: "ok", - Name: name, - URL: fmt.Sprintf("https://%s", domain), - } - - // Determine type and get details - if portOut != "" { - port, _ := strconv.Atoi(strings.TrimSpace(portOut)) - resp.Port = port - - // Check if docker - dockerOut, _ := client.Run(fmt.Sprintf("docker inspect %s 2>/dev/null && echo docker", name)) - if strings.Contains(dockerOut, "docker") { - resp.Type = "docker" - } else { - resp.Type = "binary" - } - - // Check if running - statusOut, _ := client.RunSudo(fmt.Sprintf("systemctl is-active %s 2>/dev/null || echo inactive", name)) - resp.Running = strings.TrimSpace(statusOut) == "active" - } else { - resp.Type = "static" - resp.Running = true - } - - // Check TTL - ttlOut, _ := client.Run(fmt.Sprintf("cat /etc/ship/ttl/%s 2>/dev/null || true", name)) - if ttlOut != "" { - if expires, err := strconv.ParseInt(strings.TrimSpace(ttlOut), 10, 64); err == nil { - resp.Expires = time.Unix(expires, 0).UTC().Format(time.RFC3339) - } - } - - output.PrintAndExit(resp) - return nil -} - -// logsV2Cmd shows logs for a deployment -var logsV2Cmd = &cobra.Command{ - Use: "logs NAME", - Short: "View logs for a deployment", - Args: cobra.ExactArgs(1), - RunE: runLogsV2, -} - -func init() { - logsV2Cmd.Flags().Int("lines", 50, "Number of log lines to show") -} - -func runLogsV2(cmd *cobra.Command, args []string) error { - name := args[0] - lines, _ := cmd.Flags().GetInt("lines") - - st, err := state.Load() - if err != nil { - output.PrintAndExit(output.Err(output.ErrHostNotConfigured, err.Error())) - } - - hostName := hostFlag - if hostName == "" { - hostName = st.DefaultHost - } - if hostName == "" { - output.PrintAndExit(output.Err(output.ErrHostNotConfigured, "no host specified")) - } - - client, err := ssh.Connect(hostName) - if err != nil { - output.PrintAndExit(output.Err(output.ErrSSHConnectFailed, err.Error())) - } - defer client.Close() - - // Check if it's a static site (no logs) - portOut, _ := client.Run(fmt.Sprintf("cat /etc/ship/ports/%s 2>/dev/null || true", name)) - if strings.TrimSpace(portOut) == "" { - // Check if static site exists - wwwExists, _ := client.Run(fmt.Sprintf("test -d /var/www/%s && echo exists || true", name)) - if strings.TrimSpace(wwwExists) == "" { - output.PrintAndExit(output.ErrWithName(output.ErrNotFound, "deployment not found", name)) - } - // Static site - check Caddy access logs - logsOut, err := client.RunSudo(fmt.Sprintf("journalctl -u caddy -n %d --no-pager 2>/dev/null | grep %s || echo 'No logs found'", lines*2, name)) - if err != nil { - output.PrintAndExit(output.Err(output.ErrServiceFailed, err.Error())) - } - logLines := strings.Split(strings.TrimSpace(logsOut), "\n") - output.PrintAndExit(&output.LogsResponse{ - Status: "ok", - Name: name, - Lines: logLines, - }) - return nil - } - - // Get journalctl logs - logsOut, err := client.RunSudo(fmt.Sprintf("journalctl -u %s -n %d --no-pager 2>/dev/null || echo 'No logs found'", name, lines)) - if err != nil { - output.PrintAndExit(output.Err(output.ErrServiceFailed, err.Error())) - } - - logLines := strings.Split(strings.TrimSpace(logsOut), "\n") - - output.PrintAndExit(&output.LogsResponse{ - Status: "ok", - Name: name, - Lines: logLines, - }) - return nil -} - -// removeV2Cmd removes a deployment -var removeV2Cmd = &cobra.Command{ - Use: "remove NAME", - Short: "Remove a deployment", - Args: cobra.ExactArgs(1), - RunE: runRemoveV2, -} - -func runRemoveV2(cmd *cobra.Command, args []string) error { - name := args[0] - - st, err := state.Load() - if err != nil { - output.PrintAndExit(output.Err(output.ErrHostNotConfigured, err.Error())) - } - - hostName := hostFlag - if hostName == "" { - hostName = st.DefaultHost - } - if hostName == "" { - output.PrintAndExit(output.Err(output.ErrHostNotConfigured, "no host specified")) - } - - client, err := ssh.Connect(hostName) - if err != nil { - output.PrintAndExit(output.Err(output.ErrSSHConnectFailed, err.Error())) - } - defer client.Close() - - // Check if deployment exists - portOut, _ := client.Run(fmt.Sprintf("cat /etc/ship/ports/%s 2>/dev/null || true", name)) - wwwExists, _ := client.Run(fmt.Sprintf("test -d /var/www/%s && echo exists || true", name)) - - if strings.TrimSpace(portOut) == "" && strings.TrimSpace(wwwExists) == "" { - output.PrintAndExit(output.ErrWithName(output.ErrNotFound, "deployment not found", name)) - } - - // Stop and disable service - client.RunSudo(fmt.Sprintf("systemctl stop %s 2>/dev/null || true", name)) - client.RunSudo(fmt.Sprintf("systemctl disable %s 2>/dev/null || true", name)) - - // Remove files - client.RunSudo(fmt.Sprintf("rm -f /etc/systemd/system/%s.service", name)) - client.RunSudo(fmt.Sprintf("rm -f /etc/caddy/sites-enabled/%s.caddy", name)) - client.RunSudo(fmt.Sprintf("rm -rf /var/www/%s", name)) - client.RunSudo(fmt.Sprintf("rm -rf /var/lib/%s", name)) - client.RunSudo(fmt.Sprintf("rm -f /usr/local/bin/%s", name)) - client.RunSudo(fmt.Sprintf("rm -f /etc/ship/env/%s.env", name)) - client.RunSudo(fmt.Sprintf("rm -f /etc/ship/ports/%s", name)) - client.RunSudo(fmt.Sprintf("rm -f /etc/ship/ttl/%s", name)) - - // Remove docker container and image - client.Run(fmt.Sprintf("docker rm -f %s 2>/dev/null || true", name)) - client.Run(fmt.Sprintf("docker rmi %s 2>/dev/null || true", name)) - - // Reload services - client.RunSudo("systemctl daemon-reload") - client.RunSudo("systemctl reload caddy") - - output.PrintAndExit(&output.RemoveResponse{ - Status: "ok", - Name: name, - Removed: true, - }) - return nil -} -- cgit v1.2.3