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