From a8ad8e934d15d2bf84f942414a89af1d2691adbc Mon Sep 17 00:00:00 2001 From: bndw Date: Sun, 8 Feb 2026 12:32:59 -0800 Subject: Add git-centric deployment with Docker builds and vanity imports New deployment model where projects start with a git remote on the VPS. Pushing to the remote triggers automatic docker build and deploy via post-receive hooks. The base domain serves Go vanity imports and git HTTPS cloning via Caddy + fcgiwrap. - Add `ship init ` command to create bare repos and .ship/ config - Add `ship deploy ` command for manual rebuilds - Extend `ship host init --base-domain` to set up Docker, git user, fcgiwrap, sudoers, and vanity import infrastructure - Add git-app and git-static types alongside existing app and static - Update remove, status, logs, restart, list, and config-update to handle new types --- cmd/ship/deploy.go | 56 +++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 26 deletions(-) (limited to 'cmd/ship/deploy.go') diff --git a/cmd/ship/deploy.go b/cmd/ship/deploy.go index 24eed1e..9ac754c 100644 --- a/cmd/ship/deploy.go +++ b/cmd/ship/deploy.go @@ -415,7 +415,7 @@ func updateAppConfig(st *state.State, opts DeployOptions) error { return fmt.Errorf("app %s not found (use --binary to deploy a new app)", opts.Name) } - if existingApp.Type != "app" { + if existingApp.Type != "app" && existingApp.Type != "git-app" { return fmt.Errorf("%s is a static site, not an app", opts.Name) } @@ -441,33 +441,37 @@ func updateAppConfig(st *state.State, opts DeployOptions) error { return fmt.Errorf("error creating env file: %w", err) } - // Regenerate systemd unit - fmt.Println("-> Updating systemd service...") - workDir := fmt.Sprintf("/var/lib/%s", opts.Name) - binaryDest := fmt.Sprintf("/usr/local/bin/%s", opts.Name) - serviceContent, err := templates.SystemdService(map[string]string{ - "Name": opts.Name, - "User": opts.Name, - "WorkDir": workDir, - "BinaryPath": binaryDest, - "Port": strconv.Itoa(existingApp.Port), - "EnvFile": envFilePath, - "Args": opts.Args, - "Memory": opts.Memory, - "CPU": opts.CPU, - }) - if err != nil { - return fmt.Errorf("error generating systemd unit: %w", err) - } + // For git-app, the systemd unit comes from .ship/service in the repo, + // so we only update the env file and restart. + if existingApp.Type != "git-app" { + // Regenerate systemd unit + fmt.Println("-> Updating systemd service...") + workDir := fmt.Sprintf("/var/lib/%s", opts.Name) + binaryDest := fmt.Sprintf("/usr/local/bin/%s", opts.Name) + serviceContent, err := templates.SystemdService(map[string]string{ + "Name": opts.Name, + "User": opts.Name, + "WorkDir": workDir, + "BinaryPath": binaryDest, + "Port": strconv.Itoa(existingApp.Port), + "EnvFile": envFilePath, + "Args": opts.Args, + "Memory": opts.Memory, + "CPU": opts.CPU, + }) + if err != nil { + return fmt.Errorf("error generating systemd unit: %w", err) + } - servicePath := fmt.Sprintf("/etc/systemd/system/%s.service", opts.Name) - if err := client.WriteSudoFile(servicePath, serviceContent); err != nil { - return fmt.Errorf("error creating systemd unit: %w", err) - } + servicePath := fmt.Sprintf("/etc/systemd/system/%s.service", opts.Name) + if err := client.WriteSudoFile(servicePath, serviceContent); err != nil { + return fmt.Errorf("error creating systemd unit: %w", err) + } - fmt.Println("-> Reloading systemd...") - if _, err := client.RunSudo("systemctl daemon-reload"); err != nil { - return fmt.Errorf("error reloading systemd: %w", err) + fmt.Println("-> Reloading systemd...") + if _, err := client.RunSudo("systemctl daemon-reload"); err != nil { + return fmt.Errorf("error reloading systemd: %w", err) + } } fmt.Println("-> Restarting service...") -- cgit v1.2.3