Skip to content

Commit 5fcfc7c

Browse files
committed
test(sqlite): replace cgo sqlite driver with pure-go modernc.org/sqlite
This fixes CI OOM kills caused by memory overhead from mattn/go-sqlite3 during parallel testing. Also added depguard rule to prevent future CGO sqlite imports and restricted go test parallelism.
1 parent 7bd64ec commit 5fcfc7c

7 files changed

Lines changed: 46 additions & 13 deletions

File tree

.golangci.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ linters:
5252
- gocognit # cognitive complexity
5353

5454
# Best practices
55+
# Dependency enforcement
56+
- depguard # block forbidden imports (e.g., CGO SQLite)
57+
5558
- bodyclose # ensure HTTP response bodies are closed
5659
- noctx # ensure context is passed for HTTP requests
5760
- contextcheck # context propagation checks
@@ -125,6 +128,31 @@ linters-settings:
125128
- name: unreachable-code
126129
- name: redefines-builtin-id
127130

131+
# ── SQLite Driver Policy ────────────────────────────────────────────────────
132+
# RULE: Only modernc.org/sqlite (pure-Go) is allowed.
133+
# REASON: CGO SQLite libraries (e.g., mattn/go-sqlite3) require a C compiler,
134+
# consume 5-10x more memory under -race, and complicate cross-compilation.
135+
# In CI (GitHub Actions ubuntu-latest, ~7GB RAM) this causes OOM kills.
136+
depguard:
137+
rules:
138+
no-cgo-sqlite:
139+
list-mode: lax
140+
deny:
141+
- pkg: "github.com/mattn/go-sqlite3"
142+
desc: >-
143+
Forbidden: CGO SQLite. Use 'modernc.org/sqlite' (pure-Go) instead.
144+
Reason: CGO requires a C compiler, uses 5-10x RAM under -race, and
145+
causes OOM kills in CI. See .golangci.yml for the policy.
146+
- pkg: "github.com/gwenn/gosqlite"
147+
desc: >-
148+
Forbidden: CGO SQLite. Use 'modernc.org/sqlite' (pure-Go) instead.
149+
- pkg: "github.com/mxk/go-sqlite"
150+
desc: >-
151+
Forbidden: CGO SQLite. Use 'modernc.org/sqlite' (pure-Go) instead.
152+
- pkg: "github.com/jmoiron/sqlx"
153+
desc: >-
154+
Avoid sqlx with CGO SQLite drivers. Use database/sql + modernc.org/sqlite.
155+
128156
gosec:
129157
excludes:
130158
- G104 # audit errors not checked (covered by errcheck)

.unirtm.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,13 @@ unirtm exec -- pre-commit run --all-files || {
154154

155155
[tasks.test]
156156
description = 'Run Go unit tests for all packages recursively'
157-
run = 'unirtm exec -- go test -race -v ./...'
157+
# -timeout 10m : prevent a single hung test from consuming the entire CI budget (default: 10m)
158+
# -p 4 : limit the number of packages compiled/tested in parallel to prevent CI OOM
159+
# (GitHub Actions ubuntu-latest has ~7GB RAM; -race multiplies usage 5-10x)
160+
# CGO_ENABLED=0: force pure-Go build — all test files must use modernc.org/sqlite, not mattn/go-sqlite3
161+
run = 'unirtm exec -- go test -race -v -timeout 10m -p 4 ./...'
158162
output = 'interleaved'
159-
env = { GOTOOLCHAIN = 'local' }
163+
env = { GOTOOLCHAIN = 'local', CGO_ENABLED = '0' }
160164

161165
[tasks.verify]
162166
description = 'Run full local verification (lint-all, test, audit) - runs subchecks in parallel'

go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ require (
1616
github.com/joho/godotenv v1.5.1
1717
github.com/klauspost/compress v1.18.5
1818
github.com/lithammer/fuzzysearch v1.1.8
19-
github.com/mattn/go-sqlite3 v1.14.28
2019
github.com/pelletier/go-toml/v2 v2.3.1
2120
github.com/pterm/pterm v0.12.83
2221
github.com/rs/zerolog v1.35.1
@@ -32,6 +31,7 @@ require (
3231
gopkg.in/natefinch/lumberjack.v2 v2.2.1
3332
gopkg.in/yaml.v3 v3.0.1
3433
modernc.org/sqlite v1.50.1
34+
mvdan.cc/sh/v3 v3.13.1
3535
)
3636

3737
require (
@@ -151,5 +151,4 @@ require (
151151
modernc.org/libc v1.72.3 // indirect
152152
modernc.org/mathutil v1.7.1 // indirect
153153
modernc.org/memory v1.11.0 // indirect
154-
mvdan.cc/sh/v3 v3.13.1 // indirect
155154
)

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6
122122
github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc=
123123
github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
124124
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
125+
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
126+
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
125127
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 h1:uX1JmpONuD549D73r6cgnxyUu18Zb7yHAy5AYU0Pm4Q=
126128
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
127129
github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE=
@@ -217,6 +219,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
217219
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
218220
github.com/go-playground/validator/v10 v10.30.2 h1:JiFIMtSSHb2/XBUbWM4i/MpeQm9ZK2xqPNk8vgvu5JQ=
219221
github.com/go-playground/validator/v10 v10.30.2/go.mod h1:mAf2pIOVXjTEBrwUMGKkCWKKPs9NheYGabeB04txQSc=
222+
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
223+
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
220224
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
221225
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
222226
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
@@ -351,8 +355,6 @@ github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJ
351355
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
352356
github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w=
353357
github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
354-
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
355-
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
356358
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
357359
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
358360
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=

internal/repository/sqlite/sqlite_more_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ import (
1010
"testing"
1111
"time"
1212

13-
_ "github.com/mattn/go-sqlite3"
13+
_ "modernc.org/sqlite" // Use pure-Go SQLite driver (same as production code) to avoid CGO compilation overhead in CI
1414
"github.com/snowdreamtech/unirtm/internal/repository"
1515
"github.com/stretchr/testify/assert"
1616
)
1717

1818
func getClosedDB(t *testing.T) *sql.DB {
19-
db, err := sql.Open("sqlite3", filepath.Join(t.TempDir(), "test.db"))
19+
db, err := sql.Open("sqlite", filepath.Join(t.TempDir(), "test.db"))
2020
assert.NoError(t, err)
2121
// create table so prepare statement doesn't fail immediately in some constructors if they do table checking
2222
// actually constructors don't create tables in SQLite backend usually, or do they?
@@ -26,7 +26,7 @@ func getClosedDB(t *testing.T) *sql.DB {
2626
}
2727

2828
func getPreparedDB(t *testing.T, initSQL string) *sql.DB {
29-
db, err := sql.Open("sqlite3", filepath.Join(t.TempDir(), "test.db"))
29+
db, err := sql.Open("sqlite", filepath.Join(t.TempDir(), "test.db"))
3030
assert.NoError(t, err)
3131
_, err = db.Exec(initSQL)
3232
assert.NoError(t, err)

internal/transaction/transaction_more_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ import (
1010
"path/filepath"
1111
"testing"
1212

13-
_ "github.com/mattn/go-sqlite3"
13+
_ "modernc.org/sqlite" // Use pure-Go SQLite driver (same as production code) to avoid CGO compilation overhead in CI
1414
"github.com/snowdreamtech/unirtm/internal/repository/sqlite"
1515
"github.com/stretchr/testify/assert"
1616
)
1717

1818
func TestSQLiteTransactionManager_BeginError(t *testing.T) {
19-
db, err := sql.Open("sqlite3", filepath.Join(t.TempDir(), "test.db"))
19+
db, err := sql.Open("sqlite", filepath.Join(t.TempDir(), "test.db"))
2020
assert.NoError(t, err)
2121

2222
m := NewSQLiteTransactionManager(db)
@@ -30,7 +30,7 @@ func TestSQLiteTransactionManager_BeginError(t *testing.T) {
3030
}
3131

3232
func TestSQLiteTransactionManager_BeginRepoErrors(t *testing.T) {
33-
db, err := sql.Open("sqlite3", filepath.Join(t.TempDir(), "test.db"))
33+
db, err := sql.Open("sqlite", filepath.Join(t.TempDir(), "test.db"))
3434
assert.NoError(t, err)
3535
defer db.Close()
3636

internal/transaction/transaction_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"testing"
1111
"time"
1212

13-
_ "github.com/mattn/go-sqlite3"
13+
_ "modernc.org/sqlite" // Use pure-Go SQLite driver (same as production code) to avoid CGO compilation overhead in CI
1414
"github.com/snowdreamtech/unirtm/internal/database"
1515
"github.com/snowdreamtech/unirtm/internal/repository"
1616
"github.com/stretchr/testify/assert"

0 commit comments

Comments
 (0)