Merge pull request 'feature/add-linting-tools' (#4) from feature/add-linting-tools into master

Reviewed-on: #4
This commit was merged in pull request #4.
This commit is contained in:
2026-02-04 00:55:15 +00:00
16 changed files with 111 additions and 93 deletions

View File

@@ -178,6 +178,22 @@ hm-options --version # Show version
- **Use `nix run` to run binaries** (e.g., `nix run .#nixos-options -- serve`)
- File paths in responses should use format `path/to/file.go:123`
### Linting
**Before completing work on a feature**, run all linting tools to ensure code quality:
```bash
# Run all linters (should report 0 issues)
nix develop -c golangci-lint run ./...
# Check for known vulnerabilities in dependencies
nix develop -c govulncheck ./...
# Run go vet for additional static analysis
nix develop -c go vet ./...
```
All three tools should pass with no issues before merging a feature branch.
### Nix Build Requirement
**IMPORTANT**: When running `nix build`, `nix run`, or similar commands, new files must be tracked by git first. Nix flakes only see git-tracked files. If you create new files, run `git add <file>` before attempting nix operations.

View File

@@ -191,7 +191,7 @@ func runServe(c *cli.Context) error {
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)
@@ -234,7 +234,7 @@ func runIndex(c *cli.Context, revision string, indexFiles bool, force bool) erro
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)
@@ -288,7 +288,7 @@ func runList(c *cli.Context) error {
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)
@@ -325,7 +325,7 @@ func runSearch(c *cli.Context, query string) error {
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)
@@ -397,7 +397,7 @@ func runGet(c *cli.Context, name string) error {
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)
@@ -490,7 +490,7 @@ func runDelete(c *cli.Context, revision string) error {
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)

View File

@@ -190,7 +190,7 @@ func runServe(c *cli.Context) error {
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)
@@ -233,7 +233,7 @@ func runIndex(c *cli.Context, revision string, indexFiles bool, force bool) erro
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)
@@ -283,7 +283,7 @@ func runList(c *cli.Context) error {
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)
@@ -320,7 +320,7 @@ func runSearch(c *cli.Context, query string) error {
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)
@@ -392,7 +392,7 @@ func runGet(c *cli.Context, name string) error {
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)
@@ -485,7 +485,7 @@ func runDelete(c *cli.Context, revision string) error {
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // cleanup on exit
if err := store.Initialize(ctx); err != nil {
return fmt.Errorf("failed to initialize database: %w", err)

View File

@@ -41,6 +41,7 @@
gotools
go-tools
golangci-lint
govulncheck
postgresql
sqlite
];

View File

@@ -12,7 +12,7 @@ func BenchmarkCreateOptions(b *testing.B) {
if err != nil {
b.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark cleanup
ctx := context.Background()
if err := store.Initialize(ctx); err != nil {
@@ -53,7 +53,7 @@ func benchmarkBatch(b *testing.B, batchSize int) {
if err != nil {
b.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark cleanup
ctx := context.Background()
if err := store.Initialize(ctx); err != nil {
@@ -88,9 +88,9 @@ func benchmarkBatch(b *testing.B, batchSize int) {
}
// Clean up for next iteration
store.DeleteRevision(ctx, rev.ID)
_ = store.DeleteRevision(ctx, rev.ID) //nolint:errcheck // benchmark cleanup
rev = &Revision{GitHash: fmt.Sprintf("batchbench%d", i), ChannelName: "bench"}
store.CreateRevision(ctx, rev)
_ = store.CreateRevision(ctx, rev) //nolint:errcheck // benchmark setup
for _, opt := range opts {
opt.RevisionID = rev.ID
}
@@ -102,7 +102,7 @@ func BenchmarkSearchOptions(b *testing.B) {
if err != nil {
b.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark cleanup
ctx := context.Background()
if err := store.Initialize(ctx); err != nil {
@@ -144,7 +144,7 @@ func BenchmarkGetChildren(b *testing.B) {
if err != nil {
b.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark cleanup
ctx := context.Background()
if err := store.Initialize(ctx); err != nil {
@@ -197,7 +197,7 @@ func BenchmarkSchemaInitialize(b *testing.B) {
b.Fatalf("Failed to initialize: %v", err)
}
store.Close()
store.Close() //nolint:errcheck // benchmark cleanup
}
}
@@ -207,7 +207,7 @@ func BenchmarkRevisionCRUD(b *testing.B) {
if err != nil {
b.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark cleanup
ctx := context.Background()
if err := store.Initialize(ctx); err != nil {

View File

@@ -27,7 +27,7 @@ func runStoreTests(t *testing.T, newStore func(t *testing.T) Store) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
store := newStore(t)
defer store.Close()
defer store.Close() //nolint:errcheck // test cleanup
tt.test(t, store)
})
}

View File

@@ -22,7 +22,7 @@ func NewPostgresStore(connStr string) (*PostgresStore, error) {
}
if err := db.Ping(); err != nil {
db.Close()
db.Close() //nolint:errcheck // best-effort cleanup on connection failure
return nil, fmt.Errorf("failed to ping database: %w", err)
}
@@ -185,7 +185,7 @@ func (s *PostgresStore) ListRevisions(ctx context.Context) ([]*Revision, error)
if err != nil {
return nil, fmt.Errorf("failed to list revisions: %w", err)
}
defer rows.Close()
defer rows.Close() //nolint:errcheck // rows.Err() checked after iteration
var revisions []*Revision
for rows.Next() {
@@ -237,7 +237,7 @@ func (s *PostgresStore) CreateOptionsBatch(ctx context.Context, opts []*Option)
if err != nil {
return fmt.Errorf("failed to begin transaction: %w", err)
}
defer tx.Rollback()
defer tx.Rollback() //nolint:errcheck // rollback after commit returns error, which is expected
stmt, err := tx.PrepareContext(ctx, `
INSERT INTO options (revision_id, name, parent_path, type, default_value, example, description, read_only)
@@ -246,7 +246,7 @@ func (s *PostgresStore) CreateOptionsBatch(ctx context.Context, opts []*Option)
if err != nil {
return fmt.Errorf("failed to prepare statement: %w", err)
}
defer stmt.Close()
defer stmt.Close() //nolint:errcheck // statement closed with transaction
for _, opt := range opts {
err := stmt.QueryRowContext(ctx,
@@ -285,7 +285,7 @@ func (s *PostgresStore) GetChildren(ctx context.Context, revisionID int64, paren
if err != nil {
return nil, fmt.Errorf("failed to get children: %w", err)
}
defer rows.Close()
defer rows.Close() //nolint:errcheck // rows.Err() checked after iteration
var options []*Option
for rows.Next() {
@@ -302,7 +302,7 @@ func (s *PostgresStore) GetChildren(ctx context.Context, revisionID int64, paren
func (s *PostgresStore) SearchOptions(ctx context.Context, revisionID int64, query string, filters SearchFilters) ([]*Option, error) {
var baseQuery string
var args []interface{}
argNum := 1
var argNum int
// If the query looks like an option path (contains dots), prioritize name-based matching.
if strings.Contains(query, ".") {
@@ -333,7 +333,7 @@ func (s *PostgresStore) SearchOptions(ctx context.Context, revisionID int64, que
if filters.Namespace != "" {
baseQuery += fmt.Sprintf(" AND name LIKE $%d", argNum)
args = append(args, filters.Namespace+"%")
argNum++
_ = argNum // silence ineffassign - argNum tracks position but final value unused
}
if filters.HasDefault != nil {
@@ -357,7 +357,7 @@ func (s *PostgresStore) SearchOptions(ctx context.Context, revisionID int64, que
if err != nil {
return nil, fmt.Errorf("failed to search options: %w", err)
}
defer rows.Close()
defer rows.Close() //nolint:errcheck // rows.Err() checked after iteration
var options []*Option
for rows.Next() {
@@ -390,7 +390,7 @@ func (s *PostgresStore) CreateDeclarationsBatch(ctx context.Context, decls []*De
if err != nil {
return fmt.Errorf("failed to begin transaction: %w", err)
}
defer tx.Rollback()
defer tx.Rollback() //nolint:errcheck // rollback after commit returns error, which is expected
stmt, err := tx.PrepareContext(ctx, `
INSERT INTO declarations (option_id, file_path, line)
@@ -399,7 +399,7 @@ func (s *PostgresStore) CreateDeclarationsBatch(ctx context.Context, decls []*De
if err != nil {
return fmt.Errorf("failed to prepare statement: %w", err)
}
defer stmt.Close()
defer stmt.Close() //nolint:errcheck // statement closed with transaction
for _, decl := range decls {
err := stmt.QueryRowContext(ctx, decl.OptionID, decl.FilePath, decl.Line).Scan(&decl.ID)
@@ -419,7 +419,7 @@ func (s *PostgresStore) GetDeclarations(ctx context.Context, optionID int64) ([]
if err != nil {
return nil, fmt.Errorf("failed to get declarations: %w", err)
}
defer rows.Close()
defer rows.Close() //nolint:errcheck // rows.Err() checked after iteration
var decls []*Declaration
for rows.Next() {
@@ -460,7 +460,7 @@ func (s *PostgresStore) CreateFilesBatch(ctx context.Context, files []*File) err
if err != nil {
return fmt.Errorf("failed to begin transaction: %w", err)
}
defer tx.Rollback()
defer tx.Rollback() //nolint:errcheck // rollback after commit returns error, which is expected
stmt, err := tx.PrepareContext(ctx, `
INSERT INTO files (revision_id, file_path, extension, content, byte_size, line_count)
@@ -469,7 +469,7 @@ func (s *PostgresStore) CreateFilesBatch(ctx context.Context, files []*File) err
if err != nil {
return fmt.Errorf("failed to prepare statement: %w", err)
}
defer stmt.Close()
defer stmt.Close() //nolint:errcheck // statement closed with transaction
for _, file := range files {
// Compute metadata if not already set
@@ -516,7 +516,7 @@ func (s *PostgresStore) GetDeclarationsWithMetadata(ctx context.Context, revisio
if err != nil {
return nil, fmt.Errorf("failed to get declarations with metadata: %w", err)
}
defer rows.Close()
defer rows.Close() //nolint:errcheck // rows.Err() checked after iteration
var decls []*DeclarationWithMetadata
for rows.Next() {

View File

@@ -23,7 +23,7 @@ func NewSQLiteStore(path string) (*SQLiteStore, error) {
// Enable foreign keys
if _, err := db.Exec("PRAGMA foreign_keys = ON"); err != nil {
db.Close()
db.Close() //nolint:errcheck // best-effort cleanup on connection failure
return nil, fmt.Errorf("failed to enable foreign keys: %w", err)
}
@@ -192,7 +192,7 @@ func (s *SQLiteStore) ListRevisions(ctx context.Context) ([]*Revision, error) {
if err != nil {
return nil, fmt.Errorf("failed to list revisions: %w", err)
}
defer rows.Close()
defer rows.Close() //nolint:errcheck // rows.Err() checked after iteration //nolint:errcheck // rows.Err() checked after iteration
var revisions []*Revision
for rows.Next() {
@@ -249,7 +249,7 @@ func (s *SQLiteStore) CreateOptionsBatch(ctx context.Context, opts []*Option) er
if err != nil {
return fmt.Errorf("failed to begin transaction: %w", err)
}
defer tx.Rollback()
defer tx.Rollback() //nolint:errcheck // rollback after commit returns error, which is expected
stmt, err := tx.PrepareContext(ctx, `
INSERT INTO options (revision_id, name, parent_path, type, default_value, example, description, read_only)
@@ -257,7 +257,7 @@ func (s *SQLiteStore) CreateOptionsBatch(ctx context.Context, opts []*Option) er
if err != nil {
return fmt.Errorf("failed to prepare statement: %w", err)
}
defer stmt.Close()
defer stmt.Close() //nolint:errcheck // statement closed with transaction
for _, opt := range opts {
result, err := stmt.ExecContext(ctx,
@@ -301,7 +301,7 @@ func (s *SQLiteStore) GetChildren(ctx context.Context, revisionID int64, parentP
if err != nil {
return nil, fmt.Errorf("failed to get children: %w", err)
}
defer rows.Close()
defer rows.Close() //nolint:errcheck // rows.Err() checked after iteration
var options []*Option
for rows.Next() {
@@ -384,7 +384,7 @@ func (s *SQLiteStore) SearchOptions(ctx context.Context, revisionID int64, query
if err != nil {
return nil, fmt.Errorf("failed to search options: %w", err)
}
defer rows.Close()
defer rows.Close() //nolint:errcheck // rows.Err() checked after iteration
var options []*Option
for rows.Next() {
@@ -422,7 +422,7 @@ func (s *SQLiteStore) CreateDeclarationsBatch(ctx context.Context, decls []*Decl
if err != nil {
return fmt.Errorf("failed to begin transaction: %w", err)
}
defer tx.Rollback()
defer tx.Rollback() //nolint:errcheck // rollback after commit returns error, which is expected
stmt, err := tx.PrepareContext(ctx, `
INSERT INTO declarations (option_id, file_path, line)
@@ -430,7 +430,7 @@ func (s *SQLiteStore) CreateDeclarationsBatch(ctx context.Context, decls []*Decl
if err != nil {
return fmt.Errorf("failed to prepare statement: %w", err)
}
defer stmt.Close()
defer stmt.Close() //nolint:errcheck // statement closed with transaction
for _, decl := range decls {
result, err := stmt.ExecContext(ctx, decl.OptionID, decl.FilePath, decl.Line)
@@ -455,7 +455,7 @@ func (s *SQLiteStore) GetDeclarations(ctx context.Context, optionID int64) ([]*D
if err != nil {
return nil, fmt.Errorf("failed to get declarations: %w", err)
}
defer rows.Close()
defer rows.Close() //nolint:errcheck // rows.Err() checked after iteration
var decls []*Declaration
for rows.Next() {
@@ -501,7 +501,7 @@ func (s *SQLiteStore) CreateFilesBatch(ctx context.Context, files []*File) error
if err != nil {
return fmt.Errorf("failed to begin transaction: %w", err)
}
defer tx.Rollback()
defer tx.Rollback() //nolint:errcheck // rollback after commit returns error, which is expected
stmt, err := tx.PrepareContext(ctx, `
INSERT INTO files (revision_id, file_path, extension, content, byte_size, line_count)
@@ -509,7 +509,7 @@ func (s *SQLiteStore) CreateFilesBatch(ctx context.Context, files []*File) error
if err != nil {
return fmt.Errorf("failed to prepare statement: %w", err)
}
defer stmt.Close()
defer stmt.Close() //nolint:errcheck // statement closed with transaction
for _, file := range files {
// Compute metadata if not already set
@@ -561,7 +561,7 @@ func (s *SQLiteStore) GetDeclarationsWithMetadata(ctx context.Context, revisionI
if err != nil {
return nil, fmt.Errorf("failed to get declarations with metadata: %w", err)
}
defer rows.Close()
defer rows.Close() //nolint:errcheck // rows.Err() checked after iteration
var decls []*DeclarationWithMetadata
for rows.Next() {

View File

@@ -97,7 +97,7 @@ func (idx *Indexer) IndexRevision(ctx context.Context, revision string) (*option
if err != nil {
return nil, fmt.Errorf("failed to open options.json: %w", err)
}
defer optionsFile.Close()
defer optionsFile.Close() //nolint:errcheck // read-only file
opts, err := nixos.ParseOptions(optionsFile)
if err != nil {
@@ -125,7 +125,7 @@ func (idx *Indexer) IndexRevision(ctx context.Context, revision string) (*option
// Store options
if err := idx.storeOptions(ctx, rev.ID, opts); err != nil {
// Cleanup on failure
idx.store.DeleteRevision(ctx, rev.ID)
_ = idx.store.DeleteRevision(ctx, rev.ID) //nolint:errcheck // best-effort cleanup
return nil, fmt.Errorf("failed to store options: %w", err)
}
@@ -169,7 +169,7 @@ func (idx *Indexer) buildOptions(ctx context.Context, ref string) (string, func(
}
cleanup := func() {
os.RemoveAll(tmpDir)
_ = os.RemoveAll(tmpDir) //nolint:errcheck // best-effort temp dir cleanup
}
// Build options.json using nix-build
@@ -286,7 +286,7 @@ func (idx *Indexer) getCommitDate(ctx context.Context, ref string) (time.Time, e
if err != nil {
return time.Time{}, err
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // response body read-only
if resp.StatusCode != http.StatusOK {
return time.Time{}, fmt.Errorf("GitHub API returned %d", resp.StatusCode)
@@ -345,7 +345,7 @@ func (idx *Indexer) IndexFiles(ctx context.Context, revisionID int64, ref string
if err != nil {
return 0, fmt.Errorf("failed to download tarball: %w", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // response body read-only
if resp.StatusCode != http.StatusOK {
return 0, fmt.Errorf("download failed with status %d", resp.StatusCode)
@@ -356,7 +356,7 @@ func (idx *Indexer) IndexFiles(ctx context.Context, revisionID int64, ref string
if err != nil {
return 0, fmt.Errorf("failed to create gzip reader: %w", err)
}
defer gz.Close()
defer gz.Close() //nolint:errcheck // gzip reader read-only
tr := tar.NewReader(gz)
count := 0

View File

@@ -70,7 +70,7 @@ func TestResolveRevision(t *testing.T) {
if err != nil {
t.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark/test cleanup
indexer := NewIndexer(store)
@@ -104,7 +104,7 @@ func TestGetChannelName(t *testing.T) {
if err != nil {
t.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark/test cleanup
indexer := NewIndexer(store)
@@ -144,7 +144,7 @@ func BenchmarkIndexRevision(b *testing.B) {
if err != nil {
b.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark/test cleanup
ctx := context.Background()
if err := store.Initialize(ctx); err != nil {
@@ -157,7 +157,7 @@ func BenchmarkIndexRevision(b *testing.B) {
for i := 0; i < b.N; i++ {
// Delete any existing revision first (for repeated runs)
if rev, _ := store.GetRevision(ctx, TestHomeManagerRevision); rev != nil {
store.DeleteRevision(ctx, rev.ID)
_ = store.DeleteRevision(ctx, rev.ID) //nolint:errcheck // benchmark cleanup
}
result, err := indexer.IndexRevision(ctx, TestHomeManagerRevision)
@@ -186,7 +186,7 @@ func TestIndexRevision(t *testing.T) {
if err != nil {
t.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark/test cleanup
ctx := context.Background()
if err := store.Initialize(ctx); err != nil {

View File

@@ -245,7 +245,7 @@ func setupTestStore(t *testing.T) database.Store {
}
t.Cleanup(func() {
store.Close()
store.Close() //nolint:errcheck // test cleanup
})
return store

View File

@@ -85,7 +85,7 @@ func TestSessionStoreCreate(t *testing.T) {
// Verify we can retrieve it
retrieved := store.Get(session.ID)
if retrieved == nil {
t.Error("Should be able to retrieve created session")
t.Fatal("Should be able to retrieve created session")
}
if retrieved.ID != session.ID {
t.Error("Retrieved session ID should match")
@@ -179,7 +179,7 @@ func TestSessionStoreCleanup(t *testing.T) {
// Create multiple sessions
for i := 0; i < 5; i++ {
store.Create()
_, _ = store.Create() //nolint:errcheck // test setup, error checked via count
}
if store.Count() != 5 {

View File

@@ -182,6 +182,7 @@ func (t *HTTPTransport) handlePost(w http.ResponseWriter, r *http.Request) {
if err := json.Unmarshal(body, &req); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
//nolint:errcheck // response already being written, can't handle encode error
json.NewEncoder(w).Encode(Response{
JSONRPC: "2.0",
Error: &Error{
@@ -237,7 +238,7 @@ func (t *HTTPTransport) handlePost(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(resp)
_ = json.NewEncoder(w).Encode(resp) //nolint:errcheck // response already being written
}
// handleInitialize handles the initialize request and creates a new session.
@@ -271,7 +272,7 @@ func (t *HTTPTransport) handleInitialize(w http.ResponseWriter, r *http.Request,
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Mcp-Session-Id", session.ID)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(resp)
_ = json.NewEncoder(w).Encode(resp) //nolint:errcheck // response already being written
}
// handleGet handles SSE stream for server-initiated notifications.

View File

@@ -59,7 +59,7 @@ func TestHTTPTransportInitialize(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected 200, got %d", resp.StatusCode)
@@ -103,7 +103,7 @@ func TestHTTPTransportSessionRequired(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusBadRequest {
t.Errorf("Expected 400 without session, got %d", resp.StatusCode)
@@ -129,7 +129,7 @@ func TestHTTPTransportInvalidSession(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusNotFound {
t.Errorf("Expected 404 for invalid session, got %d", resp.StatusCode)
@@ -158,7 +158,7 @@ func TestHTTPTransportValidSession(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected 200 with valid session, got %d", resp.StatusCode)
@@ -185,7 +185,7 @@ func TestHTTPTransportNotificationAccepted(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusAccepted {
t.Errorf("Expected 202 for notification, got %d", resp.StatusCode)
@@ -210,7 +210,7 @@ func TestHTTPTransportDeleteSession(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusNoContent {
t.Errorf("Expected 204 for delete, got %d", resp.StatusCode)
@@ -232,7 +232,7 @@ func TestHTTPTransportDeleteNonexistentSession(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusNotFound {
t.Errorf("Expected 404 for nonexistent session, got %d", resp.StatusCode)
@@ -315,7 +315,7 @@ func TestHTTPTransportOriginValidation(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if tt.expectAllowed && resp.StatusCode == http.StatusForbidden {
t.Error("Expected request to be allowed but was forbidden")
@@ -340,7 +340,7 @@ func TestHTTPTransportSSERequiresAcceptHeader(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusNotAcceptable {
t.Errorf("Expected 406 without Accept header, got %d", resp.StatusCode)
@@ -361,7 +361,7 @@ func TestHTTPTransportSSEStream(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusOK {
t.Fatalf("Expected 200, got %d", resp.StatusCode)
@@ -425,7 +425,7 @@ func TestHTTPTransportSSEKeepalive(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusOK {
t.Fatalf("Expected 200, got %d", resp.StatusCode)
@@ -483,7 +483,7 @@ func TestHTTPTransportParseError(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected 200 (with JSON-RPC error), got %d", resp.StatusCode)
@@ -511,7 +511,7 @@ func TestHTTPTransportMethodNotAllowed(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusMethodNotAllowed {
t.Errorf("Expected 405, got %d", resp.StatusCode)
@@ -530,7 +530,7 @@ func TestHTTPTransportOptionsRequest(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusNoContent {
t.Errorf("Expected 204, got %d", resp.StatusCode)
@@ -641,7 +641,7 @@ func TestHTTPTransportRequestBodyTooLarge(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusRequestEntityTooLarge {
t.Errorf("Expected 413 for oversized request, got %d", resp.StatusCode)
@@ -670,7 +670,7 @@ func TestHTTPTransportSessionLimitReached(t *testing.T) {
if err != nil {
t.Fatalf("Request %d failed: %v", i, err)
}
resp.Body.Close()
resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusOK {
t.Errorf("Request %d: expected 200, got %d", i, resp.StatusCode)
@@ -685,7 +685,7 @@ func TestHTTPTransportSessionLimitReached(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusServiceUnavailable {
t.Errorf("Expected 503 when session limit reached, got %d", resp.StatusCode)
@@ -713,7 +713,7 @@ func TestHTTPTransportRequestBodyWithinLimit(t *testing.T) {
if err != nil {
t.Fatalf("Request failed: %v", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // test cleanup
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected 200 for valid request within limit, got %d", resp.StatusCode)

View File

@@ -91,7 +91,7 @@ func (idx *Indexer) IndexRevision(ctx context.Context, revision string) (*IndexR
if err != nil {
return nil, fmt.Errorf("failed to open options.json: %w", err)
}
defer optionsFile.Close()
defer optionsFile.Close() //nolint:errcheck // read-only file
options, err := ParseOptions(optionsFile)
if err != nil {
@@ -119,7 +119,7 @@ func (idx *Indexer) IndexRevision(ctx context.Context, revision string) (*IndexR
// Store options
if err := idx.storeOptions(ctx, rev.ID, options); err != nil {
// Cleanup on failure
idx.store.DeleteRevision(ctx, rev.ID)
_ = idx.store.DeleteRevision(ctx, rev.ID) //nolint:errcheck // best-effort cleanup
return nil, fmt.Errorf("failed to store options: %w", err)
}
@@ -163,7 +163,7 @@ func (idx *Indexer) buildOptions(ctx context.Context, ref string) (string, func(
}
cleanup := func() {
os.RemoveAll(tmpDir)
_ = os.RemoveAll(tmpDir) //nolint:errcheck // best-effort temp dir cleanup
}
// Build options.json using nix-build
@@ -280,7 +280,7 @@ func (idx *Indexer) getCommitDate(ctx context.Context, ref string) (time.Time, e
if err != nil {
return time.Time{}, err
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // response body read-only
if resp.StatusCode != http.StatusOK {
return time.Time{}, fmt.Errorf("GitHub API returned %d", resp.StatusCode)
@@ -362,7 +362,7 @@ func (idx *Indexer) IndexFiles(ctx context.Context, revisionID int64, ref string
if err != nil {
return 0, fmt.Errorf("failed to download tarball: %w", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck // response body read-only
if resp.StatusCode != http.StatusOK {
return 0, fmt.Errorf("download failed with status %d", resp.StatusCode)
@@ -373,7 +373,7 @@ func (idx *Indexer) IndexFiles(ctx context.Context, revisionID int64, ref string
if err != nil {
return 0, fmt.Errorf("failed to create gzip reader: %w", err)
}
defer gz.Close()
defer gz.Close() //nolint:errcheck // gzip reader read-only
tr := tar.NewReader(gz)
count := 0

View File

@@ -77,7 +77,7 @@ func BenchmarkIndexRevision(b *testing.B) {
if err != nil {
b.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark/test cleanup
ctx := context.Background()
if err := store.Initialize(ctx); err != nil {
@@ -90,7 +90,7 @@ func BenchmarkIndexRevision(b *testing.B) {
for i := 0; i < b.N; i++ {
// Delete any existing revision first (for repeated runs)
if rev, _ := store.GetRevision(ctx, TestNixpkgsRevision); rev != nil {
store.DeleteRevision(ctx, rev.ID)
_ = store.DeleteRevision(ctx, rev.ID) //nolint:errcheck // benchmark cleanup
}
result, err := indexer.IndexRevision(ctx, TestNixpkgsRevision)
@@ -119,7 +119,7 @@ func BenchmarkIndexRevisionWithFiles(b *testing.B) {
if err != nil {
b.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark/test cleanup
ctx := context.Background()
if err := store.Initialize(ctx); err != nil {
@@ -132,7 +132,7 @@ func BenchmarkIndexRevisionWithFiles(b *testing.B) {
for i := 0; i < b.N; i++ {
// Delete any existing revision first
if rev, _ := store.GetRevision(ctx, TestNixpkgsRevision); rev != nil {
store.DeleteRevision(ctx, rev.ID)
_ = store.DeleteRevision(ctx, rev.ID) //nolint:errcheck // benchmark cleanup
}
result, err := indexer.IndexRevision(ctx, TestNixpkgsRevision)
@@ -168,7 +168,7 @@ func BenchmarkIndexFilesOnly(b *testing.B) {
if err != nil {
b.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark/test cleanup
ctx := context.Background()
if err := store.Initialize(ctx); err != nil {
@@ -211,7 +211,7 @@ func TestIndexRevision(t *testing.T) {
if err != nil {
t.Fatalf("Failed to create store: %v", err)
}
defer store.Close()
defer store.Close() //nolint:errcheck // benchmark/test cleanup
ctx := context.Background()
if err := store.Initialize(ctx); err != nil {