2d0e48f65fd1f8637ed3831a2b7527c3d6447ba2
- Author
- Ayman Bagabas <ayman.bagabas@gmail.com>
- Committer
- Ayman Bagabas <ayman.bagabas@gmail.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/.golangci.yml b/.golangci.yml
2index 64474889efd1129fe35b247bcf389f646cb03922..07aa1272023731d431caeae496e3d8b9512ece8d 100644
3--- a/.golangci.yml
4+++ b/.golangci.yml
5@@ -19,7 +19,6 @@ linters:
6 # - revive
7 - rowserrcheck
8 - sqlclosecheck
9- - staticcheck
10 - tparallel
11 # - unconvert
12 # - unparam
13@@ -29,6 +28,7 @@ linters:
14 - errcheck
15 - ineffassign
16 - unused
17+ - staticcheck
18 exclusions:
19 generated: lax
20 presets:
21diff --git a/cmd/soft/main.go b/cmd/soft/main.go
22index 14fdcd6b63286d12e8365f62bb69e003c2fd75a7..2c725ac0a518debf79ed07779f711080e3681855 100644
23--- a/cmd/soft/main.go
24+++ b/cmd/soft/main.go
25@@ -7,8 +7,8 @@ import (
26 "runtime/debug"
27 "strconv"
28
29- "github.com/charmbracelet/colorprofile"
30 "charm.land/log/v2"
31+ "github.com/charmbracelet/colorprofile"
32 "github.com/charmbracelet/soft-serve/cmd/soft/admin"
33 "github.com/charmbracelet/soft-serve/cmd/soft/browse"
34 "github.com/charmbracelet/soft-serve/cmd/soft/hook"
35@@ -118,7 +118,7 @@ func main() {
36
37 ctx = log.WithContext(ctx, logger)
38 if f != nil {
39- defer f.Close() // nolint: errcheck
40+ defer f.Close() //nolint: errcheck
41 }
42
43 // Set global logger
44diff --git a/cmd/soft/serve/serve.go b/cmd/soft/serve/serve.go
45index 8a670cc95863d779300eba7fa2f7ae0f47b8d4c6..21a9f080ae16065fb5edcc32b46c0b8f2e4de441 100644
46--- a/cmd/soft/serve/serve.go
47+++ b/cmd/soft/serve/serve.go
48@@ -50,10 +50,10 @@ var (
49 // Create custom hooks directory if it doesn't exist
50 customHooksPath := filepath.Join(cfg.DataPath, "hooks")
51 if _, err := os.Stat(customHooksPath); err != nil && os.IsNotExist(err) {
52- os.MkdirAll(customHooksPath, os.ModePerm) // nolint: errcheck
53+ os.MkdirAll(customHooksPath, os.ModePerm) //nolint: errcheck
54 // Generate update hook example without executable permissions
55 hookPath := filepath.Join(customHooksPath, "update.sample")
56- // nolint: gosec
57+ //nolint: gosec
58 if err := os.WriteFile(hookPath, []byte(updateHookExample), 0o744); err != nil {
59 return fmt.Errorf("failed to generate update hook example: %w", err)
60 }
61@@ -62,7 +62,7 @@ var (
62 // Create log directory if it doesn't exist
63 logPath := filepath.Join(cfg.DataPath, "log")
64 if _, err := os.Stat(logPath); err != nil && os.IsNotExist(err) {
65- os.MkdirAll(logPath, os.ModePerm) // nolint: errcheck
66+ os.MkdirAll(logPath, os.ModePerm) //nolint: errcheck
67 }
68
69 db := db.FromContext(ctx)
70diff --git a/git/attr.go b/git/attr.go
71index 1a086a0340dc78c124d405f79f5edff95ac9a300..03848e6b2393c5c4d4e44e6eb45713f49331dd72 100644
72--- a/git/attr.go
73+++ b/git/attr.go
74@@ -18,10 +18,10 @@ type Attribute struct {
75 // CheckAttributes checks the attributes of the given ref and path.
76 func (r *Repository) CheckAttributes(ref *Reference, path string) ([]Attribute, error) {
77 rnd := rand.NewSource(time.Now().UnixNano())
78- fn := "soft-serve-index-" + strconv.Itoa(rand.New(rnd).Int()) // nolint: gosec
79+ fn := "soft-serve-index-" + strconv.Itoa(rand.New(rnd).Int()) //nolint: gosec
80 tmpindex := filepath.Join(os.TempDir(), fn)
81
82- defer os.Remove(tmpindex) // nolint: errcheck
83+ defer os.Remove(tmpindex) //nolint: errcheck
84
85 readTree := NewCommand("read-tree", "--reset", "-i", ref.Name().String()).
86 AddEnvs("GIT_INDEX_FILE=" + tmpindex)
87diff --git a/git/config.go b/git/config.go
88index 1ebb2470384145be6ff8b2ab4cafd346d41bac64..49bc227844cb52b0b4c5362e50a593981ccc01a8 100644
89--- a/git/config.go
90+++ b/git/config.go
91@@ -15,7 +15,7 @@ func (r *Repository) Config() (*gcfg.Config, error) {
92 return nil, err
93 }
94
95- defer f.Close() // nolint: errcheck
96+ defer f.Close() //nolint: errcheck
97 d := gcfg.NewDecoder(f)
98 cfg := gcfg.New()
99 if err := d.Decode(cfg); err != nil {
100@@ -33,7 +33,7 @@ func (r *Repository) SetConfig(cfg *gcfg.Config) error {
101 return err
102 }
103
104- defer f.Close() // nolint: errcheck
105+ defer f.Close() //nolint: errcheck
106 e := gcfg.NewEncoder(f)
107 return e.Encode(cfg)
108 }
109diff --git a/git/tree.go b/git/tree.go
110index 7bf5b4d26b64007568cc1f9ae39550b470161511..edee17a197955b3f71930007217fe2c239125270 100644
111--- a/git/tree.go
112+++ b/git/tree.go
113@@ -128,11 +128,7 @@ const sniffLen = 8000
114 func IsBinary(r io.Reader) (bool, error) {
115 reader := bufio.NewReader(r)
116 c := 0
117- for {
118- if c == sniffLen {
119- break
120- }
121-
122+ for c < sniffLen {
123 b, err := reader.ReadByte()
124 if err == io.EOF {
125 break
126diff --git a/pkg/access/access.go b/pkg/access/access.go
127index 1ca1d56f5a1d1f40cbd9d3dba37d8f902f12185b..efe9a230d753f414f84911d72f5549fe6e87074d 100644
128--- a/pkg/access/access.go
129+++ b/pkg/access/access.go
130@@ -6,7 +6,7 @@ import (
131 )
132
133 // AccessLevel is the level of access allowed to a repo.
134-type AccessLevel int // nolint: revive
135+type AccessLevel int //nolint: revive
136
137 const (
138 // NoAccess does not allow access to the repo.
139diff --git a/pkg/backend/lfs.go b/pkg/backend/lfs.go
140index b940940bd5c81ebc4f564c054e8a7bff8ed38617..16569094ab84d41c095d8237cd8255ad648ba24e 100644
141--- a/pkg/backend/lfs.go
142+++ b/pkg/backend/lfs.go
143@@ -39,7 +39,7 @@ func StoreRepoMissingLFSObjects(ctx context.Context, repo proto.Repository, dbx
144 return objectError
145 }
146
147- defer content.Close() // nolint: errcheck
148+ defer content.Close() //nolint: errcheck
149 return dbx.TransactionContext(ctx, func(tx *db.Tx) error {
150 if err := store.CreateLFSObject(ctx, tx, repo.ID(), p.Oid, p.Size); err != nil {
151 return db.WrapError(err)
152diff --git a/pkg/backend/repo.go b/pkg/backend/repo.go
153index e4eb3a7e12b4c290fad610cbeb9895fe1d17be43..1e3b63bcfb3f39ff32111a4d6e1a906c3144412b 100644
154--- a/pkg/backend/repo.go
155+++ b/pkg/backend/repo.go
156@@ -753,7 +753,7 @@ func readOneline(path string) (string, error) {
157 return "", err
158 }
159
160- defer f.Close() // nolint: errcheck
161+ defer f.Close() //nolint: errcheck
162 s := bufio.NewScanner(f)
163 s.Scan()
164 return s.Text(), s.Err()
165diff --git a/pkg/config/config.go b/pkg/config/config.go
166index 6c1355edaf395466cc9203cf6eab915e28d39efa..97a5dc43d41bebfee0cffe915da41f4148ece95f 100644
167--- a/pkg/config/config.go
168+++ b/pkg/config/config.go
169@@ -246,7 +246,7 @@ func parseFile(cfg *Config, path string) error {
170 return err
171 }
172
173- defer f.Close() // nolint: errcheck
174+ defer f.Close() //nolint: errcheck
175 if err := yaml.NewDecoder(f).Decode(cfg); err != nil {
176 return fmt.Errorf("decode config: %w", err)
177 }
178@@ -301,7 +301,7 @@ func writeConfig(cfg *Config, path string) error {
179 if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
180 return err
181 }
182- return os.WriteFile(path, []byte(newConfigFile(cfg)), 0o644) // nolint: errcheck, gosec
183+ return os.WriteFile(path, []byte(newConfigFile(cfg)), 0o644) //nolint: errcheck, gosec
184 }
185
186 // WriteConfig writes the configuration to the default file.
187@@ -322,7 +322,7 @@ func DefaultDataPath() string {
188 }
189
190 // ConfigPath returns the path to the config file.
191-func (c *Config) ConfigPath() string { // nolint:revive
192+func (c *Config) ConfigPath() string { //nolint:revive
193 // If we have a custom config location set, then use that.
194 if path := os.Getenv("SOFT_SERVE_CONFIG_LOCATION"); exist(path) {
195 return path
196diff --git a/pkg/config/file.go b/pkg/config/file.go
197index 3710069920810a7e4e6364c10447fe9e38e70d4f..8170493c3ee9911d05f64c139580d573df962e1b 100644
198--- a/pkg/config/file.go
199+++ b/pkg/config/file.go
200@@ -151,6 +151,6 @@ jobs:
201
202 func newConfigFile(cfg *Config) string {
203 var b bytes.Buffer
204- configFileTmpl.Execute(&b, cfg) // nolint: errcheck
205+ configFileTmpl.Execute(&b, cfg) //nolint: errcheck
206 return b.String()
207 }
208diff --git a/pkg/config/file_test.go b/pkg/config/file_test.go
209index 81efad71ceba05003f8cf85f0b6d8d7415284f13..60b60db91d9b79867d642195687223b45daec452 100644
210--- a/pkg/config/file_test.go
211+++ b/pkg/config/file_test.go
212@@ -6,7 +6,7 @@ func TestNewConfigFile(t *testing.T) {
213 for _, cfg := range []*Config{
214 nil,
215 DefaultConfig(),
216- &Config{},
217+ {},
218 } {
219 if s := newConfigFile(cfg); s == "" {
220 t.Errorf("newConfigFile(nil) => %q, want non-empty string", s)
221diff --git a/pkg/cron/cron.go b/pkg/cron/cron.go
222index fa5fbb2a38a9773a2aa5d108b9764763d313e0ce..c47f8e44515b92ba88335c93133745a59ddae992 100644
223--- a/pkg/cron/cron.go
224+++ b/pkg/cron/cron.go
225@@ -39,7 +39,7 @@ func NewScheduler(ctx context.Context) *Scheduler {
226
227 // Shutdonw gracefully shuts down the Scheduler.
228 func (s *Scheduler) Shutdown() {
229- ctx, cancel := context.WithTimeout(s.Cron.Stop(), 30*time.Second)
230+ ctx, cancel := context.WithTimeout(s.Cron.Stop(), 30*time.Second) //nolint:staticcheck
231 defer func() { cancel() }()
232 <-ctx.Done()
233 }
234diff --git a/pkg/daemon/conn.go b/pkg/daemon/conn.go
235index b4a342309904f83d2f9c5c1555fefe7390280d48..38754a813165c1f485a2a3a88bb319accd31006b 100644
236--- a/pkg/daemon/conn.go
237+++ b/pkg/daemon/conn.go
238@@ -91,15 +91,15 @@ func (c *serverConn) updateDeadline() {
239 initTimeout := time.Now().Add(c.initTimeout)
240 c.initTimeout = 0
241 if initTimeout.Unix() < c.maxDeadline.Unix() || c.maxDeadline.IsZero() {
242- c.Conn.SetDeadline(initTimeout) // nolint: errcheck
243+ c.Conn.SetDeadline(initTimeout) //nolint: errcheck
244 return
245 }
246 case c.idleTimeout > 0:
247 idleDeadline := time.Now().Add(c.idleTimeout)
248 if idleDeadline.Unix() < c.maxDeadline.Unix() || c.maxDeadline.IsZero() {
249- c.Conn.SetDeadline(idleDeadline) // nolint: errcheck
250+ c.Conn.SetDeadline(idleDeadline) //nolint: errcheck
251 return
252 }
253 }
254- c.Conn.SetDeadline(c.maxDeadline) // nolint: errcheck
255+ c.Conn.SetDeadline(c.maxDeadline) //nolint: errcheck
256 }
257diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go
258index a8fcd0c91cc8188897b1fc85d6acc4f98e6007af..f37ae55498ceeeff7621fa267e0aa14f8ae1885d 100644
259--- a/pkg/daemon/daemon.go
260+++ b/pkg/daemon/daemon.go
261@@ -58,7 +58,7 @@ type GitDaemon struct {
262 liMu sync.Mutex
263 }
264
265-// NewDaemon returns a new Git daemon.
266+// NewGitDaemon returns a new Git daemon.
267 func NewGitDaemon(ctx context.Context) (*GitDaemon, error) {
268 cfg := config.FromContext(ctx)
269 addr := cfg.Git.ListenAddr
270@@ -79,7 +79,8 @@ func (d *GitDaemon) ListenAndServe() error {
271 if d.done.Load() {
272 return ErrServerClosed
273 }
274- listener, err := net.Listen("tcp", d.addr)
275+ var cfg net.ListenConfig
276+ listener, err := cfg.Listen(d.ctx, "tcp", d.addr)
277 if err != nil {
278 return err
279 }
280@@ -108,7 +109,7 @@ func (d *GitDaemon) Serve(listener net.Listener) error {
281 default:
282 d.logger.Debugf("git: error accepting connection: %v", err)
283 }
284- if ne, ok := err.(net.Error); ok && ne.Temporary() { // nolint: staticcheck
285+ if ne, ok := err.(net.Error); ok && ne.Temporary() {
286 if tempDelay == 0 {
287 tempDelay = 5 * time.Millisecond
288 } else {
289@@ -139,7 +140,7 @@ func (d *GitDaemon) Serve(listener net.Listener) error {
290 }
291
292 func (d *GitDaemon) fatal(c net.Conn, err error) {
293- git.WritePktlineErr(c, err) // nolint: errcheck
294+ git.WritePktlineErr(c, err) //nolint: errcheck
295 if err := c.Close(); err != nil {
296 d.logger.Debugf("git: error closing connection: %v", err)
297 }
298@@ -160,7 +161,7 @@ func (d *GitDaemon) handleClient(conn net.Conn) {
299 }
300 d.conns.Add(c)
301 defer func() {
302- d.conns.Close(c) // nolint: errcheck
303+ d.conns.Close(c) //nolint: errcheck
304 }()
305
306 errc := make(chan error, 1)
307@@ -213,7 +214,7 @@ func (d *GitDaemon) handleClient(conn net.Conn) {
308
309 opts := bytes.SplitN(split[1], []byte{0}, 3)
310 if len(opts) < 2 {
311- d.fatal(c, git.ErrInvalidRequest) // nolint: errcheck
312+ d.fatal(c, git.ErrInvalidRequest) //nolint: errcheck
313 return
314 }
315
316@@ -317,7 +318,7 @@ func (d *GitDaemon) handleClient(conn net.Conn) {
317 // Close closes the underlying listener.
318 func (d *GitDaemon) Close() error {
319 err := d.closeListener()
320- d.conns.CloseAll() // nolint: errcheck
321+ d.conns.CloseAll() //nolint: errcheck
322 return err
323 }
324
325diff --git a/pkg/daemon/daemon_test.go b/pkg/daemon/daemon_test.go
326index 8326e3023f988323610f5a8c8219fcec33915cfb..dc8dafd9345a34fa27bcd622e1a00121377359a7 100644
327--- a/pkg/daemon/daemon_test.go
328+++ b/pkg/daemon/daemon_test.go
329@@ -45,7 +45,7 @@ func TestMain(m *testing.M) {
330 if err != nil {
331 log.Fatal(err)
332 }
333- defer dbx.Close() // nolint: errcheck
334+ defer dbx.Close() //nolint: errcheck
335 if err := migrate.Migrate(ctx, dbx); err != nil {
336 log.Fatal(err)
337 }
338@@ -74,8 +74,9 @@ func TestIdleTimeout(t *testing.T) {
339 var err error
340 var c net.Conn
341 var tries int
342+ var dialer net.Dialer
343 for {
344- c, err = net.Dial("tcp", testDaemon.addr)
345+ c, err = dialer.DialContext(t.Context(), "tcp", testDaemon.addr)
346 if err != nil && tries >= 3 {
347 t.Fatalf("failed to connect to daemon after %d tries: %v", tries, err)
348 }
349@@ -93,7 +94,7 @@ func TestIdleTimeout(t *testing.T) {
350 }
351
352 func TestInvalidRepo(t *testing.T) {
353- c, err := net.Dial("tcp", testDaemon.addr)
354+ c, err := net.Dial("tcp", testDaemon.addr) //nolint:noctx
355 if err != nil {
356 t.Fatalf("failed to connect to daemon: %v", err)
357 }
358diff --git a/pkg/db/logger.go b/pkg/db/logger.go
359index aef9a8e17985b1c2402d75f9d4c5ca0f93dcf1f7..30c8fc692a08b68e074d814d1245dfcfdd3b916d 100644
360--- a/pkg/db/logger.go
361+++ b/pkg/db/logger.go
362@@ -43,9 +43,11 @@ func (d *DB) QueryRowx(query string, args ...interface{}) *sqlx.Row {
363 }
364
365 // Exec is a wrapper around sqlx.Exec that logs the query and arguments.
366+//
367+// Deprecated: Use [DB.ExecContext] instead.
368 func (d *DB) Exec(query string, args ...interface{}) (sql.Result, error) {
369 trace(d.logger, query, args...)
370- return d.DB.Exec(query, args...)
371+ return d.DB.Exec(query, args...) //nolint:noctx
372 }
373
374 // SelectContext is a wrapper around sqlx.SelectContext that logs the query and arguments.
375@@ -103,9 +105,11 @@ func (t *Tx) QueryRowx(query string, args ...interface{}) *sqlx.Row {
376 }
377
378 // Exec is a wrapper around sqlx.Exec that logs the query and arguments.
379+//
380+// Deprecated: Use [Tx.ExecContext] instead.
381 func (t *Tx) Exec(query string, args ...interface{}) (sql.Result, error) {
382 trace(t.logger, query, args...)
383- return t.Tx.Exec(query, args...)
384+ return t.Tx.Exec(query, args...) //nolint:noctx
385 }
386
387 // SelectContext is a wrapper around sqlx.SelectContext that logs the query and arguments.
388diff --git a/pkg/db/migrate/migrate.go b/pkg/db/migrate/migrate.go
389index 8ba8260370d5dfeaa883895444bb2cae0d19b8a3..85e8a3239695564477339a65fc9d41e517eeea3a 100644
390--- a/pkg/db/migrate/migrate.go
391+++ b/pkg/db/migrate/migrate.go
392@@ -11,7 +11,7 @@ import (
393 )
394
395 // MigrateFunc is a function that executes a migration.
396-type MigrateFunc func(ctx context.Context, tx *db.Tx) error // nolint:revive
397+type MigrateFunc func(ctx context.Context, tx *db.Tx) error //nolint:revive
398
399 // Migration is a struct that contains the name of the migration and the
400 // function to execute it.
401@@ -64,7 +64,7 @@ func Migrate(ctx context.Context, dbx *db.DB) error {
402 logger := log.FromContext(ctx).WithPrefix("migrate")
403 return dbx.TransactionContext(ctx, func(tx *db.Tx) error {
404 if !hasTable(tx, "migrations") {
405- if _, err := tx.Exec(Migrations{}.schema(tx.DriverName())); err != nil {
406+ if _, err := tx.ExecContext(ctx, Migrations{}.schema(tx.DriverName())); err != nil {
407 return err
408 }
409 }
410@@ -86,7 +86,7 @@ func Migrate(ctx context.Context, dbx *db.DB) error {
411 return err
412 }
413
414- if _, err := tx.Exec(tx.Rebind("INSERT INTO migrations (name, version) VALUES (?, ?)"), m.Name, m.Version); err != nil {
415+ if _, err := tx.ExecContext(ctx, tx.Rebind("INSERT INTO migrations (name, version) VALUES (?, ?)"), m.Name, m.Version); err != nil {
416 return err
417 }
418 }
419@@ -116,7 +116,7 @@ func Rollback(ctx context.Context, dbx *db.DB) error {
420 return err
421 }
422
423- if _, err := tx.Exec(tx.Rebind("DELETE FROM migrations WHERE version = ?"), migrs.Version); err != nil {
424+ if _, err := tx.ExecContext(ctx, tx.Rebind("DELETE FROM migrations WHERE version = ?"), migrs.Version); err != nil {
425 return err
426 }
427
428diff --git a/pkg/git/git.go b/pkg/git/git.go
429index 301640a14c2421c39644e7866ae0227f8b5698f4..5ad5998be3a9d00cdd7fed1b68e760e2e50febc9 100644
430--- a/pkg/git/git.go
431+++ b/pkg/git/git.go
432@@ -8,8 +8,8 @@ import (
433 "path/filepath"
434 "strings"
435
436- gitm "github.com/aymanbagabas/git-module"
437 "charm.land/log/v2"
438+ gitm "github.com/aymanbagabas/git-module"
439 "github.com/charmbracelet/soft-serve/git"
440 "github.com/go-git/go-git/v5/plumbing/format/pktline"
441 )
442diff --git a/pkg/git/lfs.go b/pkg/git/lfs.go
443index 6a8809bd740aa3972fb3b878cfbbb70afdf6c899..14846c1208eb10ac7e99964fe92f5a32574532f2 100644
444--- a/pkg/git/lfs.go
445+++ b/pkg/git/lfs.go
446@@ -11,8 +11,8 @@ import (
447 "strconv"
448 "time"
449
450- "github.com/charmbracelet/git-lfs-transfer/transfer"
451 "charm.land/log/v2"
452+ "github.com/charmbracelet/git-lfs-transfer/transfer"
453 "github.com/charmbracelet/soft-serve/pkg/config"
454 "github.com/charmbracelet/soft-serve/pkg/db"
455 "github.com/charmbracelet/soft-serve/pkg/db/models"
456diff --git a/pkg/git/lfs_auth.go b/pkg/git/lfs_auth.go
457index ae03a70cee80368b530d472714631024bec73ee4..b2175cf3df2912485ab5ec4e390563abb72ba75b 100644
458--- a/pkg/git/lfs_auth.go
459+++ b/pkg/git/lfs_auth.go
460@@ -15,7 +15,7 @@ import (
461 "github.com/golang-jwt/jwt/v5"
462 )
463
464-// LFSAuthenticate implements teh Git LFS SSH authentication command.
465+// LFSAuthenticate implements the Git LFS SSH authentication command.
466 // Context must have *config.Config, *log.Logger, proto.User.
467 // cmd.Args should have the repo path and operation as arguments.
468 func LFSAuthenticate(ctx context.Context, cmd ServiceCommand) error {
469diff --git a/pkg/git/lfs_log.go b/pkg/git/lfs_log.go
470index c9e6ac6413165e798b6bab064f9eba0c1b5dd237..b0a76228ac8be44a219b9999d7295a69176826c5 100644
471--- a/pkg/git/lfs_log.go
472+++ b/pkg/git/lfs_log.go
473@@ -1,8 +1,8 @@
474 package git
475
476 import (
477- "github.com/charmbracelet/git-lfs-transfer/transfer"
478 "charm.land/log/v2"
479+ "github.com/charmbracelet/git-lfs-transfer/transfer"
480 )
481
482 type lfsLogger struct {
483diff --git a/pkg/git/service.go b/pkg/git/service.go
484index 94253b798d7911d56b1c0379b154da2a908a376e..a4066d07e6944c0955c07929e5074ea0850b43a4 100644
485--- a/pkg/git/service.go
486+++ b/pkg/git/service.go
487@@ -124,7 +124,7 @@ func gitServiceHandler(ctx context.Context, svc Service, scmd ServiceCommand) er
488 // stdin
489 if scmd.Stdin != nil {
490 go func() {
491- defer stdin.Close() // nolint: errcheck
492+ defer stdin.Close() //nolint: errcheck
493 if _, err := io.Copy(stdin, scmd.Stdin); err != nil {
494 log.Errorf("gitServiceHandler: failed to copy stdin: %v", err)
495 }
496diff --git a/pkg/lfs/basic_transfer.go b/pkg/lfs/basic_transfer.go
497index ddec8b350e81f273029b855908dcecfd37bdd966..cf4133df7ac8054590b2ae4ada2ab3a88206b939 100644
498--- a/pkg/lfs/basic_transfer.go
499+++ b/pkg/lfs/basic_transfer.go
500@@ -105,11 +105,11 @@ func (a *BasicTransferAdapter) performRequest(ctx context.Context, method string
501 }
502
503 func handleErrorResponse(resp *http.Response) error {
504- defer resp.Body.Close() // nolint: errcheck
505+ defer resp.Body.Close() //nolint: errcheck
506
507 er, err := decodeResponseError(resp.Body)
508 if err != nil {
509- return fmt.Errorf("Request failed with status %s", resp.Status)
510+ return fmt.Errorf("request failed with status %s", resp.Status)
511 }
512 return errors.New(er.Message)
513 }
514diff --git a/pkg/lfs/http_client.go b/pkg/lfs/http_client.go
515index e35b930cc7844191aa074a6a0b9e2def13c27260..068c311355f63ba713b8e98335ecb81a8dffc303 100644
516--- a/pkg/lfs/http_client.go
517+++ b/pkg/lfs/http_client.go
518@@ -86,10 +86,10 @@ func (c *httpClient) batch(ctx context.Context, operation string, objects []Poin
519 logger.Errorf("Error while processing request: %v", err)
520 return nil, err
521 }
522- defer res.Body.Close() // nolint: errcheck
523+ defer res.Body.Close() //nolint: errcheck
524
525 if res.StatusCode != http.StatusOK {
526- return nil, fmt.Errorf("Unexpected server response: %s", res.Status)
527+ return nil, fmt.Errorf("unexpected server response: %s", res.Status)
528 }
529
530 var response BatchResponse
531@@ -152,7 +152,7 @@ func (c *httpClient) performOperation(ctx context.Context, objects []Pointer, dc
532 link, ok := object.Actions[ActionUpload]
533 if !ok {
534 logger.Debugf("%+v", object)
535- return errors.New("Missing action 'upload'")
536+ return errors.New("missing action 'upload'")
537 }
538
539 content, err := uc(object.Pointer, nil)
540@@ -162,7 +162,7 @@ func (c *httpClient) performOperation(ctx context.Context, objects []Pointer, dc
541
542 err = transferAdapter.Upload(ctx, object.Pointer, content, link)
543
544- content.Close() // nolint: errcheck
545+ content.Close() //nolint: errcheck
546
547 if err != nil {
548 return err
549@@ -178,7 +178,7 @@ func (c *httpClient) performOperation(ctx context.Context, objects []Pointer, dc
550 link, ok := object.Actions[ActionDownload]
551 if !ok {
552 logger.Debugf("%+v", object)
553- return errors.New("Missing action 'download'")
554+ return errors.New("missing action 'download'")
555 }
556
557 content, err := transferAdapter.Download(ctx, object.Pointer, link)
558diff --git a/pkg/lfs/pointer.go b/pkg/lfs/pointer.go
559index 69bceca1da4ab857a895fee44e2b85dec4258d55..d8a8d4cd8cd473cd62b4d3febf6f497ac9b01b74 100644
560--- a/pkg/lfs/pointer.go
561+++ b/pkg/lfs/pointer.go
562@@ -28,10 +28,10 @@ const (
563
564 var (
565 // ErrMissingPrefix occurs if the content lacks the LFS prefix
566- ErrMissingPrefix = errors.New("Content lacks the LFS prefix")
567+ ErrMissingPrefix = errors.New("content lacks the LFS prefix")
568
569 // ErrInvalidStructure occurs if the content has an invalid structure
570- ErrInvalidStructure = errors.New("Content has an invalid structure")
571+ ErrInvalidStructure = errors.New("content has an invalid structure")
572
573 // ErrInvalidOIDFormat occurs if the oid has an invalid format
574 ErrInvalidOIDFormat = errors.New("OID has an invalid format")
575diff --git a/pkg/lfs/scanner.go b/pkg/lfs/scanner.go
576index 6cd19691fae22c5f96da572b97d93c4c6109571f..6688e4225a67a5aa5e0ac5fc59b02e6f1a2066cb 100644
577--- a/pkg/lfs/scanner.go
578+++ b/pkg/lfs/scanner.go
579@@ -51,7 +51,7 @@ func SearchPointerBlobs(ctx context.Context, repo *git.Repository, pointerChan c
580
581 func createPointerResultsFromCatFileBatch(ctx context.Context, catFileBatchReader *io.PipeReader, wg *sync.WaitGroup, pointerChan chan<- PointerBlob) {
582 defer wg.Done()
583- defer catFileBatchReader.Close() // nolint: errcheck
584+ defer catFileBatchReader.Close() //nolint: errcheck
585
586 bufferedReader := bufio.NewReader(catFileBatchReader)
587 buf := make([]byte, 1025)
588@@ -104,8 +104,8 @@ loop:
589
590 func catFileBatch(ctx context.Context, shasToBatchReader *io.PipeReader, catFileBatchWriter *io.PipeWriter, wg *sync.WaitGroup, basePath string) {
591 defer wg.Done()
592- defer shasToBatchReader.Close() // nolint: errcheck
593- defer catFileBatchWriter.Close() // nolint: errcheck
594+ defer shasToBatchReader.Close() //nolint: errcheck
595+ defer catFileBatchWriter.Close() //nolint: errcheck
596
597 stderr := new(bytes.Buffer)
598 var errbuf strings.Builder
599@@ -122,7 +122,7 @@ func catFileBatch(ctx context.Context, shasToBatchReader *io.PipeReader, catFile
600
601 func blobsLessThan1024FromCatFileBatchCheck(catFileCheckReader *io.PipeReader, shasToBatchWriter *io.PipeWriter, wg *sync.WaitGroup) {
602 defer wg.Done()
603- defer catFileCheckReader.Close() // nolint: errcheck
604+ defer catFileCheckReader.Close() //nolint: errcheck
605 scanner := bufio.NewScanner(catFileCheckReader)
606 defer func() {
607 _ = shasToBatchWriter.CloseWithError(scanner.Err())
608@@ -154,8 +154,8 @@ func blobsLessThan1024FromCatFileBatchCheck(catFileCheckReader *io.PipeReader, s
609
610 func catFileBatchCheck(ctx context.Context, shasToCheckReader *io.PipeReader, catFileCheckWriter *io.PipeWriter, wg *sync.WaitGroup, basePath string) {
611 defer wg.Done()
612- defer shasToCheckReader.Close() // nolint: errcheck
613- defer catFileCheckWriter.Close() // nolint: errcheck
614+ defer shasToCheckReader.Close() //nolint: errcheck
615+ defer catFileCheckWriter.Close() //nolint: errcheck
616
617 stderr := new(bytes.Buffer)
618 var errbuf strings.Builder
619@@ -172,7 +172,7 @@ func catFileBatchCheck(ctx context.Context, shasToCheckReader *io.PipeReader, ca
620
621 func blobsFromRevListObjects(revListReader *io.PipeReader, shasToCheckWriter *io.PipeWriter, wg *sync.WaitGroup) {
622 defer wg.Done()
623- defer revListReader.Close() // nolint: errcheck
624+ defer revListReader.Close() //nolint: errcheck
625 scanner := bufio.NewScanner(revListReader)
626 defer func() {
627 _ = shasToCheckWriter.CloseWithError(scanner.Err())
628@@ -201,7 +201,7 @@ func blobsFromRevListObjects(revListReader *io.PipeReader, shasToCheckWriter *io
629
630 func revListAllObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sync.WaitGroup, basePath string, errChan chan<- error) {
631 defer wg.Done()
632- defer revListWriter.Close() // nolint: errcheck
633+ defer revListWriter.Close() //nolint: errcheck
634
635 stderr := new(bytes.Buffer)
636 var errbuf strings.Builder
637diff --git a/pkg/ssh/cmd/git.go b/pkg/ssh/cmd/git.go
638index ee5852a87d32d1d1f04a3fcd7217d2298b6781f1..caf1e1595b1a6561420879b41741f6c8dc54a74d 100644
639--- a/pkg/ssh/cmd/git.go
640+++ b/pkg/ssh/cmd/git.go
641@@ -250,7 +250,7 @@ func gitRunE(cmd *cobra.Command, args []string) error {
642 defer func() {
643 if repo == nil {
644 // If the repo was created, but the request failed, delete it.
645- be.DeleteRepository(ctx, name) // nolint: errcheck
646+ be.DeleteRepository(ctx, name) //nolint: errcheck
647 }
648 }()
649
650diff --git a/pkg/ssh/cmd/token.go b/pkg/ssh/cmd/token.go
651index f95c37f25c430a65b00b038818adcaf6044c75eb..07b87ddf0f364a9f81aa80ba36d679aa8a0268a5 100644
652--- a/pkg/ssh/cmd/token.go
653+++ b/pkg/ssh/cmd/token.go
654@@ -5,8 +5,8 @@ import (
655 "strings"
656 "time"
657
658- "github.com/caarlos0/duration"
659 "charm.land/lipgloss/v2/table"
660+ "github.com/caarlos0/duration"
661 "github.com/charmbracelet/soft-serve/pkg/backend"
662 "github.com/charmbracelet/soft-serve/pkg/proto"
663 "github.com/dustin/go-humanize"
664diff --git a/pkg/ssh/middleware.go b/pkg/ssh/middleware.go
665index a0a578e33684ba06e653bd6b961be6348d93e1dc..62f19044b2de02955e2dc366e189eff1edfdd0f4 100644
666--- a/pkg/ssh/middleware.go
667+++ b/pkg/ssh/middleware.go
668@@ -5,6 +5,7 @@ import (
669 "time"
670
671 "charm.land/log/v2"
672+ "charm.land/wish/v2"
673 "github.com/charmbracelet/soft-serve/pkg/backend"
674 "github.com/charmbracelet/soft-serve/pkg/config"
675 "github.com/charmbracelet/soft-serve/pkg/db"
676@@ -13,7 +14,6 @@ import (
677 "github.com/charmbracelet/soft-serve/pkg/sshutils"
678 "github.com/charmbracelet/soft-serve/pkg/store"
679 "github.com/charmbracelet/ssh"
680- "charm.land/wish/v2"
681 "github.com/prometheus/client_golang/prometheus"
682 "github.com/prometheus/client_golang/prometheus/promauto"
683 "github.com/spf13/cobra"
684@@ -135,7 +135,7 @@ func CommandMiddleware(sh ssh.Handler) ssh.Handler {
685 rootCmd.SetContext(ctx)
686
687 if err := rootCmd.ExecuteContext(ctx); err != nil {
688- s.Exit(1) // nolint: errcheck
689+ s.Exit(1) //nolint: errcheck
690 return
691 }
692 }
693diff --git a/pkg/ssh/session_test.go b/pkg/ssh/session_test.go
694index dab5b8e0722958e7836acdab7fc20ea7fb21ffb2..4ec33caed61c38d5711049e798b3250d5c93c343 100644
695--- a/pkg/ssh/session_test.go
696+++ b/pkg/ssh/session_test.go
697@@ -9,6 +9,8 @@ import (
698 "time"
699
700 "charm.land/log/v2"
701+ bm "charm.land/wish/v2/bubbletea"
702+ "charm.land/wish/v2/testsession"
703 "github.com/charmbracelet/soft-serve/pkg/backend"
704 "github.com/charmbracelet/soft-serve/pkg/config"
705 "github.com/charmbracelet/soft-serve/pkg/db"
706@@ -17,8 +19,6 @@ import (
707 "github.com/charmbracelet/soft-serve/pkg/store/database"
708 "github.com/charmbracelet/soft-serve/pkg/test"
709 "github.com/charmbracelet/ssh"
710- bm "charm.land/wish/v2/bubbletea"
711- "charm.land/wish/v2/testsession"
712 "github.com/matryer/is"
713 gossh "golang.org/x/crypto/ssh"
714 _ "modernc.org/sqlite" // sqlite driver
715@@ -36,7 +36,7 @@ func TestSession(t *testing.T) {
716 go func() {
717 time.Sleep(1 * time.Second)
718 // s.Signal(gossh.SIGTERM)
719- s.Close() // nolint: errcheck
720+ s.Close() //nolint: errcheck
721 }()
722 t.Log("waiting for session to exit")
723 _, err = s.Output("test")
724@@ -76,7 +76,6 @@ func setup(tb testing.TB) (*gossh.Session, func() error) {
725 dbstore := database.New(ctx, dbx)
726 ctx = store.WithContext(ctx, dbstore)
727 be := backend.New(ctx, cfg, dbx, dbstore)
728- ctx = backend.WithContext(ctx, be)
729 return testsession.New(tb, &ssh.Server{
730 Handler: ContextMiddleware(cfg, dbx, dbstore, be, log.Default())(bm.MiddlewareWithProgramHandler(SessionHandler)(func(s ssh.Session) {
731 _, _, active := s.Pty()
732diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go
733index 274c63e971cc5be3d383a15ce827e9dc364541ec..2d56e0a7bf7851257f1b910e3612dae0408804a3 100644
734--- a/pkg/ssh/ssh.go
735+++ b/pkg/ssh/ssh.go
736@@ -8,17 +8,17 @@ import (
737 "strconv"
738 "time"
739
740- "github.com/charmbracelet/keygen"
741 "charm.land/log/v2"
742+ "charm.land/wish/v2"
743+ bm "charm.land/wish/v2/bubbletea"
744+ rm "charm.land/wish/v2/recover"
745+ "github.com/charmbracelet/keygen"
746 "github.com/charmbracelet/soft-serve/pkg/backend"
747 "github.com/charmbracelet/soft-serve/pkg/config"
748 "github.com/charmbracelet/soft-serve/pkg/db"
749 "github.com/charmbracelet/soft-serve/pkg/proto"
750 "github.com/charmbracelet/soft-serve/pkg/store"
751 "github.com/charmbracelet/ssh"
752- "charm.land/wish/v2"
753- bm "charm.land/wish/v2/bubbletea"
754- rm "charm.land/wish/v2/recover"
755 "github.com/prometheus/client_golang/prometheus"
756 "github.com/prometheus/client_golang/prometheus/promauto"
757 gossh "golang.org/x/crypto/ssh"
758@@ -41,7 +41,7 @@ var (
759 )
760
761 // SSHServer is a SSH server that implements the git protocol.
762-type SSHServer struct { // nolint: revive
763+type SSHServer struct { //nolint: revive
764 srv *ssh.Server
765 cfg *config.Config
766 be *backend.Backend
767@@ -157,12 +157,9 @@ func initializePermissions(ctx ssh.Context) {
768 if perms.Extensions == nil {
769 perms.Extensions = make(map[string]string)
770 }
771- if perms.Permissions.Extensions == nil {
772- perms.Permissions.Extensions = make(map[string]string)
773- }
774 }
775
776-// PublicKeyAuthHandler handles public key authentication.
777+// PublicKeyHandler handles public key authentication.
778 func (s *SSHServer) PublicKeyHandler(ctx ssh.Context, pk ssh.PublicKey) (allowed bool) {
779 if pk == nil {
780 return false
781diff --git a/pkg/storage/local.go b/pkg/storage/local.go
782index 496f20e37dcf47dba316250f0cf33878434e16ad..bf2fac9a5a37498b645f3dd234b3129bb985b6ac 100644
783--- a/pkg/storage/local.go
784+++ b/pkg/storage/local.go
785@@ -51,7 +51,7 @@ func (l *LocalStorage) Put(name string, r io.Reader) (int64, error) {
786 if err != nil {
787 return 0, err
788 }
789- defer f.Close() // nolint: errcheck
790+ defer f.Close() //nolint: errcheck
791 return io.Copy(f, r)
792 }
793
794diff --git a/pkg/test/test.go b/pkg/test/test.go
795index bfaac42c594791536d233685a87bf28f37dc2ba5..6bfb7d55d5c57b2de78fa27ff66e336a5c9bc0f8 100644
796--- a/pkg/test/test.go
797+++ b/pkg/test/test.go
798@@ -13,7 +13,7 @@ var (
799 // RandomPort returns a random port number.
800 // This is mainly used for testing.
801 func RandomPort() int {
802- addr, _ := net.Listen("tcp", ":0") //nolint:gosec
803+ addr, _ := net.Listen("tcp", ":0") //nolint:gosec,noctx
804 _ = addr.Close()
805 port := addr.Addr().(*net.TCPAddr).Port
806 lock.Lock()
807diff --git a/pkg/ui/common/format.go b/pkg/ui/common/format.go
808index d7a14bfb777b42918904b9bbd49721af9eadd57c..5d1960c4e1e0297cb5adadb7041c5170591741a0 100644
809--- a/pkg/ui/common/format.go
810+++ b/pkg/ui/common/format.go
811@@ -5,8 +5,8 @@ import (
812 "strconv"
813 "strings"
814
815- "github.com/alecthomas/chroma/v2/lexers"
816 gansi "charm.land/glamour/v2/ansi"
817+ "github.com/alecthomas/chroma/v2/lexers"
818 "github.com/charmbracelet/soft-serve/pkg/ui/styles"
819 )
820
821diff --git a/pkg/ui/common/style.go b/pkg/ui/common/style.go
822index a8e8d1d5161e1eda9ccbac08c3d584ee89c01131..3ec5600ed90bd44dfcd6e8867adcdad465cd0292 100644
823--- a/pkg/ui/common/style.go
824+++ b/pkg/ui/common/style.go
825@@ -1,9 +1,9 @@
826 package common
827
828 import (
829- "github.com/charmbracelet/colorprofile"
830 gansi "charm.land/glamour/v2/ansi"
831 "charm.land/glamour/v2/styles"
832+ "github.com/charmbracelet/colorprofile"
833 )
834
835 // DefaultColorProfile is the default color profile used by the SSH server.
836diff --git a/pkg/ui/pages/repo/refs.go b/pkg/ui/pages/repo/refs.go
837index 24382cb4daab571379b962fa9ef35f997901be61..65ca744e678e1b4be9cf6df503263436e7421230 100644
838--- a/pkg/ui/pages/repo/refs.go
839+++ b/pkg/ui/pages/repo/refs.go
840@@ -64,9 +64,10 @@ func (r *Refs) Path() string {
841
842 // TabName returns the name of the tab.
843 func (r *Refs) TabName() string {
844- if r.refPrefix == git.RefsHeads {
845+ switch r.refPrefix {
846+ case git.RefsHeads:
847 return "Branches"
848- } else if r.refPrefix == git.RefsTags {
849+ case git.RefsTags:
850 return "Tags"
851 }
852 return "Refs"
853diff --git a/pkg/ui/pages/repo/repo.go b/pkg/ui/pages/repo/repo.go
854index 2de183f3108353e4951eedff2fdc41961f0779ed..58052bd5721de58c91d1d71d61e302516eb13f43 100644
855--- a/pkg/ui/pages/repo/repo.go
856+++ b/pkg/ui/pages/repo/repo.go
857@@ -32,7 +32,7 @@ type EmptyRepoMsg struct{}
858 type CopyURLMsg struct{}
859
860 // RepoMsg is a message that contains a git.Repository.
861-type RepoMsg proto.Repository // nolint:revive
862+type RepoMsg proto.Repository //nolint:revive
863
864 // GoBackMsg is a message to go back to the previous view.
865 type GoBackMsg struct{}
866diff --git a/pkg/ui/pages/repo/stashitem.go b/pkg/ui/pages/repo/stashitem.go
867index 7bf2ffa7d537685c4ccf9cf68d49f53b6465f938..119494086d463c4880a37dc08c1543e0a45d1014 100644
868--- a/pkg/ui/pages/repo/stashitem.go
869+++ b/pkg/ui/pages/repo/stashitem.go
870@@ -4,10 +4,10 @@ import (
871 "fmt"
872 "io"
873
874- gitm "github.com/aymanbagabas/git-module"
875 "charm.land/bubbles/v2/key"
876 "charm.land/bubbles/v2/list"
877 tea "charm.land/bubbletea/v2"
878+ gitm "github.com/aymanbagabas/git-module"
879 "github.com/charmbracelet/soft-serve/pkg/ui/common"
880 )
881
882diff --git a/pkg/web/git.go b/pkg/web/git.go
883index 20d4174eb00eb613731bac06234e82401fb6dc48..6723ac6f093304f413d0753a88fd61244dacc597 100644
884--- a/pkg/web/git.go
885+++ b/pkg/web/git.go
886@@ -434,7 +434,7 @@ func serviceRpc(w http.ResponseWriter, r *http.Request) {
887 renderInternalServerError(w, r)
888 return
889 }
890- defer reader.Close() // nolint: errcheck
891+ defer reader.Close() //nolint: errcheck
892 }
893
894 cmd.Stdin = reader
895@@ -459,7 +459,7 @@ type flushResponseWriter struct {
896 }
897
898 func (f *flushResponseWriter) ReadFrom(r io.Reader) (int64, error) {
899- flusher := http.NewResponseController(f.ResponseWriter) // nolint: bodyclose
900+ flusher := http.NewResponseController(f.ResponseWriter)
901
902 var n int64
903 p := make([]byte, 1024)
904@@ -537,12 +537,12 @@ func getInfoRefs(w http.ResponseWriter, r *http.Request) {
905 w.Header().Set("Content-Type", fmt.Sprintf("application/x-%s-advertisement", service))
906 w.WriteHeader(http.StatusOK)
907 if version < 2 {
908- git.WritePktline(w, "# service="+service.String()) // nolint: errcheck
909+ git.WritePktline(w, "# service="+service.String()) //nolint: errcheck
910 }
911- w.Write(refs.Bytes()) // nolint: errcheck
912+ w.Write(refs.Bytes()) //nolint: errcheck
913 } else {
914 // Dumb HTTP
915- updateServerInfo(ctx, dir) // nolint: errcheck
916+ updateServerInfo(ctx, dir) //nolint: errcheck
917 hdrNocache(w)
918 sendFile("text/plain; charset=utf-8", w, r)
919 }
920diff --git a/pkg/web/git_lfs.go b/pkg/web/git_lfs.go
921index cc109107312891630b8f3c3884ec33bba9c0d2f9..647e932ea392108c2b8090e16bbba5f7d42266ec 100644
922--- a/pkg/web/git_lfs.go
923+++ b/pkg/web/git_lfs.go
924@@ -41,7 +41,7 @@ func serviceLfsBatch(w http.ResponseWriter, r *http.Request) {
925 }
926
927 var batchRequest lfs.BatchRequest
928- defer r.Body.Close() // nolint: errcheck
929+ defer r.Body.Close() //nolint: errcheck
930 if err := json.NewDecoder(r.Body).Decode(&batchRequest); err != nil {
931 logger.Errorf("error decoding json: %s", err)
932 renderJSON(w, http.StatusUnprocessableEntity, lfs.ErrorResponse{
933@@ -282,7 +282,7 @@ func serviceLfsBasicDownload(w http.ResponseWriter, r *http.Request) {
934
935 w.Header().Set("Content-Type", "application/octet-stream")
936 w.Header().Set("Content-Length", strconv.FormatInt(obj.Size, 10))
937- defer f.Close() // nolint: errcheck
938+ defer f.Close() //nolint: errcheck
939 if _, err := io.Copy(w, f); err != nil {
940 logger.Error("error copying object to response", "oid", oid, "err", err)
941 renderJSON(w, http.StatusInternalServerError, lfs.ErrorResponse{
942@@ -313,7 +313,7 @@ func serviceLfsBasicUpload(w http.ResponseWriter, r *http.Request) {
943 strg := storage.NewLocalStorage(filepath.Join(cfg.DataPath, "lfs", repoID))
944 name := mux.Vars(r)["repo"]
945
946- defer r.Body.Close() // nolint: errcheck
947+ defer r.Body.Close() //nolint: errcheck
948 repo, err := be.Repository(ctx, name)
949 if err != nil {
950 renderJSON(w, http.StatusNotFound, lfs.ErrorResponse{
951@@ -326,7 +326,7 @@ func serviceLfsBasicUpload(w http.ResponseWriter, r *http.Request) {
952 // partial error, so we need to skip existing objects.
953 if _, err := datastore.GetLFSObjectByOid(ctx, dbx, repo.ID(), oid); err == nil {
954 // Object exists, skip request
955- io.Copy(io.Discard, r.Body) // nolint: errcheck
956+ io.Copy(io.Discard, r.Body) //nolint: errcheck
957 renderStatus(http.StatusOK)(w, nil)
958 return
959 } else if !errors.Is(err, db.ErrRecordNotFound) {
960@@ -385,7 +385,7 @@ func serviceLfsBasicVerify(w http.ResponseWriter, r *http.Request) {
961 return
962 }
963
964- defer r.Body.Close() // nolint: errcheck
965+ defer r.Body.Close() //nolint: errcheck
966 if err := json.NewDecoder(r.Body).Decode(&pointer); err != nil {
967 logger.Error("error decoding json", "err", err)
968 renderJSON(w, http.StatusBadRequest, lfs.ErrorResponse{
969diff --git a/pkg/web/logging.go b/pkg/web/logging.go
970index bb259f7183636a3cb1e2e5a13e259e8134264a46..d7d0c8e54a37c24d3a0af630a6b16f75dd93a6e7 100644
971--- a/pkg/web/logging.go
972+++ b/pkg/web/logging.go
973@@ -18,13 +18,12 @@ type logWriter struct {
974 code, bytes int
975 }
976
977-var _ http.ResponseWriter = (*logWriter)(nil)
978-
979-var _ http.Flusher = (*logWriter)(nil)
980-
981-var _ http.Hijacker = (*logWriter)(nil)
982-
983-var _ http.CloseNotifier = (*logWriter)(nil) // nolint: staticcheck
984+var (
985+ _ http.ResponseWriter = (*logWriter)(nil)
986+ _ http.Flusher = (*logWriter)(nil)
987+ _ http.Hijacker = (*logWriter)(nil)
988+ _ http.CloseNotifier = (*logWriter)(nil)
989+)
990
991 // Write implements http.ResponseWriter.
992 func (r *logWriter) Write(p []byte) (int, error) {
993@@ -54,7 +53,7 @@ func (r *logWriter) Flush() {
994
995 // CloseNotify implements http.CloseNotifier.
996 func (r *logWriter) CloseNotify() <-chan bool {
997- if cn, ok := r.ResponseWriter.(http.CloseNotifier); ok { // nolint: staticcheck
998+ if cn, ok := r.ResponseWriter.(http.CloseNotifier); ok {
999 return cn.CloseNotify()
1000 }
1001 return nil
1002diff --git a/pkg/web/util.go b/pkg/web/util.go
1003index 412d0e00ef14b545fc042462b63bf12626ea7cc5..cc2429d633775e7c223c5c11e328c28d0d4647fa 100644
1004--- a/pkg/web/util.go
1005+++ b/pkg/web/util.go
1006@@ -9,6 +9,6 @@ import (
1007 func renderStatus(code int) http.HandlerFunc {
1008 return func(w http.ResponseWriter, _ *http.Request) {
1009 w.WriteHeader(code)
1010- io.WriteString(w, fmt.Sprintf("%d %s", code, http.StatusText(code))) // nolint: errcheck
1011+ io.WriteString(w, fmt.Sprintf("%d %s", code, http.StatusText(code))) //nolint: errcheck
1012 }
1013 }
1014diff --git a/pkg/webhook/ssrf_test.go b/pkg/webhook/ssrf_test.go
1015index 0928125b30151996b7b68921027ad4bf1d8fa2ea..3f7fc4948aad217d65a6e705d02fffeeda465f4f 100644
1016--- a/pkg/webhook/ssrf_test.go
1017+++ b/pkg/webhook/ssrf_test.go
1018@@ -158,7 +158,7 @@ func TestDialContextBlocksPrivateIPs(t *testing.T) {
1019 // sendWebhookWithContext is a test helper that doesn't require database.
1020 func sendWebhookWithContext(ctx context.Context, w models.Webhook, _ Event, _ any) error {
1021 // This is a simplified version for testing that just attempts the HTTP connection
1022- req, err := http.NewRequest("POST", w.URL, nil)
1023+ req, err := http.NewRequestWithContext(ctx, "POST", w.URL, nil)
1024 if err != nil {
1025 return err //nolint:wrapcheck
1026 }
1027diff --git a/pkg/webhook/validator.go b/pkg/webhook/validator.go
1028index 1728a14f5f14293a4fd1c3b947e9659fbda19dd5..0eecd0951173b7cb518b57a0c0826383f18e3e82 100644
1029--- a/pkg/webhook/validator.go
1030+++ b/pkg/webhook/validator.go
1031@@ -1,6 +1,7 @@
1032 package webhook
1033
1034 import (
1035+ "context"
1036 "errors"
1037 "fmt"
1038 "net"
1039@@ -60,13 +61,13 @@ func ValidateWebhookURL(rawURL string) error {
1040 }
1041
1042 // Resolve hostname to IP addresses
1043- ips, err := net.LookupIP(hostname)
1044+ ips, err := net.DefaultResolver.LookupIPAddr(context.Background(), hostname)
1045 if err != nil {
1046 return fmt.Errorf("%w: cannot resolve hostname: %v", ErrInvalidURL, err)
1047 }
1048
1049 // Check all resolved IPs
1050- if slices.ContainsFunc(ips, isPrivateOrInternalIP) {
1051+ if slices.ContainsFunc(ips, isPrivateOrInternalIPAddr) {
1052 return ErrPrivateIP
1053 }
1054
1055@@ -81,6 +82,11 @@ func isLocalhost(hostname string) bool {
1056 strings.HasSuffix(hostname, ".localhost")
1057 }
1058
1059+// isPrivateOrInternalIPAddr is a helper function that users net.IPAddr instead of net.IP.
1060+func isPrivateOrInternalIPAddr(ipAddr net.IPAddr) bool {
1061+ return isPrivateOrInternalIP(ipAddr.IP)
1062+}
1063+
1064 // isPrivateOrInternalIP checks if an IP address is private, internal, or reserved.
1065 func isPrivateOrInternalIP(ip net.IP) bool {
1066 // Loopback addresses (127.0.0.0/8, ::1)
1067diff --git a/pkg/webhook/webhook.go b/pkg/webhook/webhook.go
1068index 9858c52f4afb313ceb845b8d9133c12bd79965e0..176d8e25b56f7146ba39a9912493f0d94ca83d9c 100644
1069--- a/pkg/webhook/webhook.go
1070+++ b/pkg/webhook/webhook.go
1071@@ -109,7 +109,7 @@ func SendWebhook(ctx context.Context, w models.Webhook, event Event, payload int
1072 if err != nil {
1073 return err
1074 }
1075- buf.WriteString(v.Encode()) // nolint: errcheck
1076+ buf.WriteString(v.Encode()) //nolint: errcheck
1077 default:
1078 return ErrInvalidContentType
1079 }
1080@@ -129,7 +129,7 @@ func SendWebhook(ctx context.Context, w models.Webhook, event Event, payload int
1081 reqBody := buf.String()
1082 if w.Secret != "" {
1083 sig := hmac.New(sha256.New, []byte(w.Secret))
1084- sig.Write([]byte(reqBody)) // nolint: errcheck
1085+ sig.Write([]byte(reqBody)) //nolint: errcheck
1086 headers.Add("X-SoftServe-Signature", "sha256="+hex.EncodeToString(sig.Sum(nil)))
1087 }
1088
1089@@ -150,7 +150,7 @@ func SendWebhook(ctx context.Context, w models.Webhook, event Event, payload int
1090 }
1091
1092 if res.Body != nil {
1093- defer res.Body.Close() // nolint: errcheck
1094+ defer res.Body.Close() //nolint: errcheck
1095 b, err := io.ReadAll(res.Body)
1096 if err != nil {
1097 return err
1098diff --git a/testscript/script_test.go b/testscript/script_test.go
1099index db1593ff20c12739c0f082dbb65c0e5317df0fe4..44b4783632ea2d12ffa217dc49d02323ee3a9199 100644
1100--- a/testscript/script_test.go
1101+++ b/testscript/script_test.go
1102@@ -38,9 +38,9 @@ func PrepareBuildCommand(binPath string) *exec.Cmd {
1103 _, disableRaceSet := os.LookupEnv("SOFT_SERVE_DISABLE_RACE_CHECKS")
1104 if disableRaceSet {
1105 // don't add the -race flag
1106- return exec.Command("go", "build", "-cover", "-o", binPath, filepath.Join("..", "cmd", "soft"))
1107+ return exec.Command("go", "build", "-cover", "-o", binPath, filepath.Join("..", "cmd", "soft")) //nolint:noctx
1108 }
1109- return exec.Command("go", "build", "-race", "-cover", "-o", binPath, filepath.Join("..", "cmd", "soft"))
1110+ return exec.Command("go", "build", "-race", "-cover", "-o", binPath, filepath.Join("..", "cmd", "soft")) //nolint:noctx
1111 }
1112
1113 func TestMain(m *testing.M) {
1114@@ -167,7 +167,7 @@ func TestScript(t *testing.T) {
1115 // Override the database data source if we're using postgres
1116 // so we can create a temporary database for the tests.
1117 if cfg.DB.Driver == "postgres" {
1118- err, cleanup := setupPostgres(e.T(), cfg)
1119+ cleanup, err := setupPostgres(e.T(), cfg)
1120 if err != nil {
1121 return err
1122 }
1123@@ -263,7 +263,7 @@ func cmdUI(key ssh.Signer) func(ts *testscript.TestScript, neg bool, args []stri
1124 break
1125 }
1126 check(ts, err, neg)
1127- stdin.Write([]byte(string(r))) // nolint: errcheck
1128+ _, _ = io.WriteString(stdin, string(r))
1129
1130 // Wait for the UI to process the input
1131 time.Sleep(100 * time.Millisecond)
1132@@ -381,7 +381,7 @@ func cmdNewWebhook(ts *testscript.TestScript, neg bool, args []string) {
1133 }
1134
1135 const whSite = "https://webhook.site"
1136- req, err := http.NewRequest(http.MethodPost, whSite+"/token", nil)
1137+ req, err := http.NewRequest(http.MethodPost, whSite+"/token", nil) //nolint:noctx
1138 check(ts, err, neg)
1139
1140 resp, err := http.DefaultClient.Do(req)
1141@@ -409,7 +409,7 @@ func cmdCurl(ts *testscript.TestScript, neg bool, args []string) {
1142 return err
1143 }
1144
1145- req, err := http.NewRequest(method, url.String(), nil)
1146+ req, err := http.NewRequest(method, url.String(), nil) //nolint:noctx
1147 if err != nil {
1148 return err
1149 }
1150@@ -494,7 +494,7 @@ func cmdEnsureServerRunning(ts *testscript.TestScript, neg bool, args []string)
1151 // verify that the server is up
1152 addr := net.JoinHostPort("localhost", port)
1153 for {
1154- conn, _ := net.DialTimeout(
1155+ conn, _ := net.DialTimeout( //nolint:noctx
1156 "tcp",
1157 addr,
1158 time.Second,
1159@@ -519,29 +519,26 @@ func cmdEnsureServerNotRunning(ts *testscript.TestScript, neg bool, args []strin
1160
1161 // verify that the server is not up
1162 addr := net.JoinHostPort("localhost", port)
1163- for {
1164- conn, _ := net.DialTimeout(
1165- "tcp",
1166- addr,
1167- time.Second,
1168- )
1169- if conn != nil {
1170- ts.Fatalf("server is running on port %s while it should not be running", port)
1171- conn.Close()
1172- }
1173- break
1174+ conn, _ := net.DialTimeout( //nolint:noctx
1175+ "tcp",
1176+ addr,
1177+ time.Second,
1178+ )
1179+ if conn != nil {
1180+ ts.Fatalf("server is running on port %s while it should not be running", port)
1181+ conn.Close()
1182 }
1183 }
1184
1185 func cmdStopserver(ts *testscript.TestScript, neg bool, args []string) {
1186 // stop the server
1187- resp, err := http.DefaultClient.Head(fmt.Sprintf("%s/__stop", ts.Getenv("SOFT_SERVE_HTTP_PUBLIC_URL")))
1188+ resp, err := http.DefaultClient.Head(fmt.Sprintf("%s/__stop", ts.Getenv("SOFT_SERVE_HTTP_PUBLIC_URL"))) //nolint:noctx
1189 check(ts, err, neg)
1190 resp.Body.Close()
1191 time.Sleep(time.Second * 2) // Allow some time for the server to stop
1192 }
1193
1194-func setupPostgres(t testscript.T, cfg *config.Config) (error, func()) {
1195+func setupPostgres(t testscript.T, cfg *config.Config) (func(), error) {
1196 // Indicates postgres
1197 // Create a disposable database
1198 rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
1199@@ -553,7 +550,7 @@ func setupPostgres(t testscript.T, cfg *config.Config) (error, func()) {
1200
1201 dbUrl, err := url.Parse(cfg.DB.DataSource)