4a5ccff56279b5d7347dba3f3bbe2eade336df64

Author
Ayman Bagabas <ayman.bagabas@gmail.com>
Committer
Ayman Bagabas <ayman.bagabas@gmail.com>
Date

Message

fix(server): start with context

Diff

  1diff --git a/cmd/soft/root.go b/cmd/soft/root.go
  2index 5fc9e4588e6dcc9fb57169b6ea1a857c1d899c44..af4c56c3f97d518e569e9b63aede54a2106808a6 100644
  3--- a/cmd/soft/root.go
  4+++ b/cmd/soft/root.go
  5@@ -1,9 +1,9 @@
  6 package main
  7 
  8 import (
  9+	"os"
 10 	"runtime/debug"
 11 
 12-	"github.com/charmbracelet/log"
 13 	_ "github.com/charmbracelet/soft-serve/log"
 14 	"github.com/spf13/cobra"
 15 )
 16@@ -18,12 +18,10 @@ var (
 17 	CommitSHA = ""
 18 
 19 	rootCmd = &cobra.Command{
 20-		Use:   "soft",
 21-		Short: "A self-hostable Git server for the command line",
 22-		Long:  "Soft Serve is a self-hostable Git server for the command line.",
 23-		RunE: func(cmd *cobra.Command, args []string) error {
 24-			return cmd.Help()
 25-		},
 26+		Use:          "soft",
 27+		Short:        "A self-hostable Git server for the command line",
 28+		Long:         "Soft Serve is a self-hostable Git server for the command line.",
 29+		SilenceUsage: true,
 30 	}
 31 )
 32 
 33@@ -52,6 +50,6 @@ func init() {
 34 
 35 func main() {
 36 	if err := rootCmd.Execute(); err != nil {
 37-		log.Fatal(err)
 38+		os.Exit(1)
 39 	}
 40 }
 41diff --git a/cmd/soft/serve.go b/cmd/soft/serve.go
 42index 332796394866e8b1fe6275985ccf771a589aa467..5841f2cdd36113eab15b5b07fd0b5084e82f4012 100644
 43--- a/cmd/soft/serve.go
 44+++ b/cmd/soft/serve.go
 45@@ -25,18 +25,19 @@ var (
 46 				return err
 47 			}
 48 
 49+			ctx := cmd.Context()
 50 			done := make(chan os.Signal, 1)
 51 			lch := make(chan error, 1)
 52 			go func() {
 53 				defer close(lch)
 54 				defer close(done)
 55-				lch <- s.Start()
 56+				lch <- s.Start(ctx)
 57 			}()
 58 
 59 			signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
 60 			<-done
 61 
 62-			ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
 63+			ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
 64 			defer cancel()
 65 			if err := s.Shutdown(ctx); err != nil {
 66 				return err
 67diff --git a/server/config/file.go b/server/config/file.go
 68index f85c7247b564ce3d2c1f9a8ae65f70ff0849bccb..7079ff3033b4163c7ac07257e90750c722e7a928 100644
 69--- a/server/config/file.go
 70+++ b/server/config/file.go
 71@@ -59,10 +59,10 @@ http:
 72   # The address on which the HTTP server will listen.
 73   listen_addr: "{{ .HTTP.ListenAddr }}"
 74 
 75-  # The relative path to the TLS private key.
 76+  # The path to the TLS private key.
 77   tls_key_path: "{{ .HTTP.TLSKeyPath }}"
 78 
 79-  # The relative path to the TLS certificate.
 80+  # The path to the TLS certificate.
 81   tls_cert_path: "{{ .HTTP.TLSCertPath }}"
 82 
 83   # The public URL of the HTTP server.
 84@@ -79,6 +79,6 @@ stats:
 85 
 86 func newConfigFile(cfg *Config) string {
 87 	var b bytes.Buffer
 88-	configFileTmpl.Execute(&b, cfg)
 89+	configFileTmpl.Execute(&b, cfg) // nolint: errcheck
 90 	return b.String()
 91 }
 92diff --git a/server/server.go b/server/server.go
 93index de227c54287853bf5cbb73a7bdeb1e68b52809d9..992e0c7c13c0a656afd08a3c764481fe393d9b5a 100644
 94--- a/server/server.go
 95+++ b/server/server.go
 96@@ -2,6 +2,7 @@ package server
 97 
 98 import (
 99 	"context"
100+	"errors"
101 	"net/http"
102 	"path/filepath"
103 
104@@ -101,33 +102,48 @@ func NewServer(cfg *config.Config) (*Server, error) {
105 	return srv, nil
106 }
107 
108+func start(ctx context.Context, fn func() error) error {
109+	errc := make(chan error, 1)
110+	go func() {
111+		errc <- fn()
112+	}()
113+
114+	select {
115+	case err := <-errc:
116+		return err
117+	case <-ctx.Done():
118+		return ctx.Err()
119+	}
120+}
121+
122 // Start starts the SSH server.
123-func (s *Server) Start() error {
124-	var errg errgroup.Group
125+func (s *Server) Start(ctx context.Context) error {
126+	var errg *errgroup.Group
127+	errg, ctx = errgroup.WithContext(ctx)
128 	errg.Go(func() error {
129 		log.Print("Starting Git daemon", "addr", s.Config.Git.ListenAddr)
130-		if err := s.GitDaemon.Start(); err != ErrServerClosed {
131+		if err := start(ctx, s.GitDaemon.Start); !errors.Is(err, ErrServerClosed) {
132 			return err
133 		}
134 		return nil
135 	})
136 	errg.Go(func() error {
137 		log.Print("Starting HTTP server", "addr", s.Config.HTTP.ListenAddr)
138-		if err := s.HTTPServer.ListenAndServe(); err != http.ErrServerClosed {
139+		if err := start(ctx, s.HTTPServer.ListenAndServe); !errors.Is(err, http.ErrServerClosed) {
140 			return err
141 		}
142 		return nil
143 	})
144 	errg.Go(func() error {
145 		log.Print("Starting SSH server", "addr", s.Config.SSH.ListenAddr)
146-		if err := s.SSHServer.ListenAndServe(); err != ssh.ErrServerClosed {
147+		if err := start(ctx, s.SSHServer.ListenAndServe); !errors.Is(err, ssh.ErrServerClosed) {
148 			return err
149 		}
150 		return nil
151 	})
152 	errg.Go(func() error {
153 		log.Print("Starting Stats server", "addr", s.Config.Stats.ListenAddr)
154-		if err := s.StatsServer.ListenAndServe(); err != http.ErrServerClosed {
155+		if err := start(ctx, s.StatsServer.ListenAndServe); !errors.Is(err, http.ErrServerClosed) {
156 			return err
157 		}
158 		return nil
159diff --git a/server/server_test.go b/server/server_test.go
160index 5505bec565280f8ed92c0487eed52c31c26c9910..07066d976412aacb4f1fb174609587a4731edac2 100644
161--- a/server/server_test.go
162+++ b/server/server_test.go
163@@ -1,6 +1,7 @@
164 package server
165 
166 import (
167+	"context"
168 	"fmt"
169 	"net"
170 	"path/filepath"
171@@ -38,7 +39,7 @@ func setupServer(tb testing.TB) (*Server, *config.Config, string) {
172 	}
173 	go func() {
174 		tb.Log("starting server")
175-		s.Start()
176+		s.Start(context.TODO())
177 	}()
178 	tb.Cleanup(func() {
179 		s.Close()