serve.go

 1package main
 2
 3import (
 4	"context"
 5	"fmt"
 6	"os"
 7	"os/signal"
 8	"path/filepath"
 9	"syscall"
10	"time"
11
12	"github.com/charmbracelet/soft-serve/server"
13	"github.com/charmbracelet/soft-serve/server/config"
14	_ "github.com/charmbracelet/soft-serve/server/config" // init config
15	"github.com/spf13/cobra"
16)
17
18var (
19	migrate bool
20
21	serveCmd = &cobra.Command{
22		Use:   "serve",
23		Short: "Start the server",
24		Long:  "Start the server",
25		Args:  cobra.NoArgs,
26		RunE: func(cmd *cobra.Command, _ []string) error {
27			ctx := cmd.Context()
28			cfg := config.FromContext(ctx)
29
30			// Create custom hooks directory if it doesn't exist
31			customHooksPath := filepath.Join(cfg.DataPath, "hooks")
32			if _, err := os.Stat(customHooksPath); err != nil && os.IsNotExist(err) {
33				os.MkdirAll(customHooksPath, os.ModePerm) // nolint: errcheck
34				// Generate update hook example without executable permissions
35				hookPath := filepath.Join(customHooksPath, "update.sample")
36				// nolint: gosec
37				if err := os.WriteFile(hookPath, []byte(updateHookExample), 0744); err != nil {
38					return fmt.Errorf("failed to generate update hook example: %w", err)
39				}
40			}
41
42			// Create log directory if it doesn't exist
43			logPath := filepath.Join(cfg.DataPath, "log")
44			if _, err := os.Stat(logPath); err != nil && os.IsNotExist(err) {
45				os.MkdirAll(logPath, os.ModePerm) // nolint: errcheck
46			}
47
48			s, err := server.NewServer(ctx)
49			if err != nil {
50				return fmt.Errorf("start server: %w", err)
51			}
52
53			done := make(chan os.Signal, 1)
54			lch := make(chan error, 1)
55			go func() {
56				defer close(lch)
57				defer close(done)
58				lch <- s.Start()
59			}()
60
61			signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
62			<-done
63
64			ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
65			defer cancel()
66			if err := s.Shutdown(ctx); err != nil {
67				return err
68			}
69
70			// wait for serve to finish
71			return <-lch
72		},
73	}
74)
75
76func init() {
77	serveCmd.Flags().BoolVar(&migrate, "migrate", false, "run database migrations")
78}