2d0e48f65fd1f8637ed3831a2b7527c3d6447ba2

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

Message

chore(lint): fix lint issues

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)