Skip to content

Commit 99be46a

Browse files
authored
Add sqlc-test-setup command for database test environment setup (#4304)
1 parent 744558d commit 99be46a

File tree

5 files changed

+565
-217
lines changed

5 files changed

+565
-217
lines changed

.github/workflows/ci.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,20 @@ jobs:
5050
env:
5151
CGO_ENABLED: "0"
5252

53+
- name: install databases
54+
run: go run ./cmd/sqlc-test-setup install
55+
56+
- name: start databases
57+
run: go run ./cmd/sqlc-test-setup start
58+
5359
- name: test ./...
54-
run: gotestsum --junitfile junit.xml -- --tags=examples -timeout 20m ./...
55-
if: ${{ matrix.os }} != "windows-2022"
60+
run: gotestsum --junitfile junit.xml -- --tags=examples -timeout 20m -failfast ./...
5661
env:
5762
CI_SQLC_PROJECT_ID: ${{ secrets.CI_SQLC_PROJECT_ID }}
5863
CI_SQLC_AUTH_TOKEN: ${{ secrets.CI_SQLC_AUTH_TOKEN }}
5964
SQLC_AUTH_TOKEN: ${{ secrets.CI_SQLC_AUTH_TOKEN }}
65+
POSTGRESQL_SERVER_URI: "postgres://postgres:postgres@127.0.0.1:5432/postgres?sslmode=disable"
66+
MYSQL_SERVER_URI: "root:mysecretpassword@tcp(127.0.0.1:3306)/mysql?multiStatements=true&parseTime=true"
6067
CGO_ENABLED: "0"
6168

6269
vuln_check:

CLAUDE.md

Lines changed: 49 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -10,136 +10,74 @@ This document provides essential information for working with the sqlc codebase,
1010
- **Docker & Docker Compose** - Required for integration tests with databases (local development)
1111
- **Git** - For version control
1212

13-
## Claude Code Remote Environment Setup
13+
## Database Setup with sqlc-test-setup
1414

15-
When running in the Claude Code remote environment (or any environment without Docker), you can install PostgreSQL and MySQL natively. The test framework automatically detects and uses native database installations.
15+
The `sqlc-test-setup` tool (`cmd/sqlc-test-setup/`) automates installing and starting PostgreSQL and MySQL for tests. Both commands are idempotent and safe to re-run.
1616

17-
### Step 1: Configure apt Proxy (Required in Remote Environment)
18-
19-
The Claude Code remote environment requires an HTTP proxy for apt. Configure it:
20-
21-
```bash
22-
bash -c 'echo "Acquire::http::Proxy \"$http_proxy\";"' | sudo tee /etc/apt/apt.conf.d/99proxy
23-
```
24-
25-
### Step 2: Install PostgreSQL
17+
### Install databases
2618

2719
```bash
28-
sudo apt-get update
29-
sudo apt-get install -y postgresql
30-
sudo service postgresql start
20+
go run ./cmd/sqlc-test-setup install
3121
```
3222

33-
Configure PostgreSQL for password authentication:
34-
35-
```bash
36-
# Set password for postgres user
37-
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';"
38-
39-
# Enable password authentication for localhost
40-
echo 'host all all 127.0.0.1/32 md5' | sudo tee -a /etc/postgresql/16/main/pg_hba.conf
41-
sudo service postgresql reload
42-
```
23+
This will:
24+
- Configure the apt proxy (if `http_proxy` is set, e.g. in Claude Code remote environments)
25+
- Install PostgreSQL via apt
26+
- Download and install MySQL 9 from Oracle's deb bundle
27+
- Resolve all dependencies automatically
28+
- Skip anything already installed
4329

44-
Test the connection:
30+
### Start databases
4531

4632
```bash
47-
PGPASSWORD=postgres psql -h 127.0.0.1 -U postgres -c "SELECT 1;"
33+
go run ./cmd/sqlc-test-setup start
4834
```
4935

50-
### Step 3: Install MySQL 9
51-
52-
MySQL 9 is required for full test compatibility (includes VECTOR type support). Download and install from Oracle:
36+
This will:
37+
- Start PostgreSQL and configure password auth (`postgres`/`postgres`)
38+
- Start MySQL via `mysqld_safe` and set root password (`mysecretpassword`)
39+
- Verify both connections
40+
- Skip steps that are already done (running services, existing config)
5341

54-
```bash
55-
# Download MySQL 9 bundle
56-
curl -LO https://dev.mysql.com/get/Downloads/MySQL-9.1/mysql-server_9.1.0-1ubuntu24.04_amd64.deb-bundle.tar
57-
58-
# Extract packages
59-
mkdir -p /tmp/mysql9
60-
tar -xf mysql-server_9.1.0-1ubuntu24.04_amd64.deb-bundle.tar -C /tmp/mysql9
61-
62-
# Install packages (in order)
63-
cd /tmp/mysql9
64-
sudo dpkg -i mysql-common_*.deb \
65-
mysql-community-client-plugins_*.deb \
66-
mysql-community-client-core_*.deb \
67-
mysql-community-client_*.deb \
68-
mysql-client_*.deb \
69-
mysql-community-server-core_*.deb \
70-
mysql-community-server_*.deb \
71-
mysql-server_*.deb
72-
73-
# Make init script executable
74-
sudo chmod +x /etc/init.d/mysql
75-
76-
# Initialize data directory and start MySQL
77-
sudo mysqld --initialize-insecure --user=mysql
78-
sudo /etc/init.d/mysql start
79-
80-
# Set root password
81-
mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'mysecretpassword'; FLUSH PRIVILEGES;"
82-
```
42+
Connection URIs after start:
43+
- PostgreSQL: `postgres://postgres:postgres@127.0.0.1:5432/postgres?sslmode=disable`
44+
- MySQL: `root:mysecretpassword@tcp(127.0.0.1:3306)/mysql`
8345

84-
Test the connection:
46+
### Run tests
8547

8648
```bash
87-
mysql -h 127.0.0.1 -u root -pmysecretpassword -e "SELECT VERSION();"
88-
```
89-
90-
### Step 4: Run End-to-End Tests
91-
92-
With both databases running, the test framework automatically detects them:
93-
94-
```bash
95-
# Run all end-to-end tests
96-
go test --tags=examples -timeout 20m ./internal/endtoend/...
97-
98-
# Run example tests
99-
go test --tags=examples -timeout 20m ./examples/...
100-
101-
# Run the full test suite
49+
# Full test suite (requires databases running)
10250
go test --tags=examples -timeout 20m ./...
10351
```
10452

105-
The native database support (in `internal/sqltest/native/`) automatically:
106-
- Detects running PostgreSQL and MySQL instances
107-
- Starts services if installed but not running
108-
- Uses standard connection URIs:
109-
- PostgreSQL: `postgres://postgres:postgres@127.0.0.1:5432/postgres?sslmode=disable`
110-
- MySQL: `root:mysecretpassword@tcp(127.0.0.1:3306)/mysql`
111-
112-
### Running Tests
53+
## Running Tests
11354

114-
#### Basic Unit Tests (No Database Required)
55+
### Basic Unit Tests (No Database Required)
11556

11657
```bash
117-
# Simplest approach - runs all unit tests
11858
go test ./...
119-
120-
# Using make
121-
make test
12259
```
12360

124-
#### Full Test Suite with Integration Tests
61+
### Full Test Suite with Docker (Local Development)
12562

12663
```bash
127-
# Step 1: Start database containers
12864
docker compose up -d
129-
130-
# Step 2: Run all tests including examples
13165
go test --tags=examples -timeout 20m ./...
66+
```
67+
68+
### Full Test Suite without Docker (Remote / CI)
13269

133-
# Or use make for the full CI suite
134-
make test-ci
70+
```bash
71+
go run ./cmd/sqlc-test-setup install
72+
go run ./cmd/sqlc-test-setup start
73+
go test --tags=examples -timeout 20m ./...
13574
```
13675

137-
#### Running Specific Tests
76+
### Running Specific Tests
13877

13978
```bash
14079
# Test a specific package
14180
go test ./internal/config
142-
go test ./internal/compiler
14381

14482
# Run with verbose output
14583
go test -v ./internal/config
@@ -193,21 +131,6 @@ The `docker-compose.yml` provides test databases:
193131
- Password: `mysecretpassword`
194132
- Database: `dinotest`
195133

196-
### Managing Databases
197-
198-
```bash
199-
# Start databases
200-
make start
201-
# or
202-
docker compose up -d
203-
204-
# Stop databases
205-
docker compose down
206-
207-
# View logs
208-
docker compose logs -f
209-
```
210-
211134
## Makefile Targets
212135

213136
```bash
@@ -225,22 +148,10 @@ make start # Start database containers
225148

226149
- **File:** `.github/workflows/ci.yml`
227150
- **Go Version:** 1.25.0
151+
- **Database Setup:** Uses `sqlc-test-setup` (not Docker) to install and start PostgreSQL and MySQL directly on the runner
228152
- **Test Command:** `gotestsum --junitfile junit.xml -- --tags=examples -timeout 20m ./...`
229153
- **Additional Checks:** `govulncheck` for vulnerability scanning
230154

231-
### Running Tests Like CI Locally
232-
233-
```bash
234-
# Install CI tools (optional)
235-
go install gotest.tools/gotestsum@latest
236-
237-
# Run tests with same timeout as CI
238-
go test --tags=examples -timeout 20m ./...
239-
240-
# Or use the CI make target
241-
make test-ci
242-
```
243-
244155
## Development Workflow
245156

246157
### Building Development Versions
@@ -255,37 +166,18 @@ go build -o ~/go/bin/sqlc-gen-json ./cmd/sqlc-gen-json
255166

256167
### Environment Variables for Tests
257168

258-
You can customize database connections:
259-
260-
**PostgreSQL:**
261-
```bash
262-
PG_HOST=127.0.0.1
263-
PG_PORT=5432
264-
PG_USER=postgres
265-
PG_PASSWORD=mysecretpassword
266-
PG_DATABASE=dinotest
267-
```
268-
269-
**MySQL:**
270-
```bash
271-
MYSQL_HOST=127.0.0.1
272-
MYSQL_PORT=3306
273-
MYSQL_USER=root
274-
MYSQL_ROOT_PASSWORD=mysecretpassword
275-
MYSQL_DATABASE=dinotest
276-
```
169+
You can override database connections via environment variables:
277170

278-
**Example:**
279171
```bash
280-
POSTGRESQL_SERVER_URI="postgres://postgres:mysecretpassword@localhost:5432/postgres" \
281-
go test -v ./...
172+
POSTGRESQL_SERVER_URI="postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable"
173+
MYSQL_SERVER_URI="root:mysecretpassword@tcp(127.0.0.1:3306)/mysql?multiStatements=true&parseTime=true"
282174
```
283175

284176
## Code Structure
285177

286178
### Key Directories
287179

288-
- `/cmd/` - Main binaries (sqlc, sqlc-gen-json)
180+
- `/cmd/` - Main binaries (sqlc, sqlc-gen-json, sqlc-test-setup)
289181
- `/internal/cmd/` - Command implementations (vet, generate, etc.)
290182
- `/internal/engine/` - Database engine implementations
291183
- `/postgresql/` - PostgreSQL parser and converter
@@ -295,20 +187,20 @@ POSTGRESQL_SERVER_URI="postgres://postgres:mysecretpassword@localhost:5432/postg
295187
- `/internal/codegen/` - Code generation for different languages
296188
- `/internal/config/` - Configuration file parsing
297189
- `/internal/endtoend/` - End-to-end tests
190+
- `/internal/sqltest/` - Test database setup (Docker, native, local detection)
298191
- `/examples/` - Example projects for testing
299192

300193
### Important Files
301194

302195
- `/Makefile` - Build and test targets
303196
- `/docker-compose.yml` - Database services for testing
304197
- `/.github/workflows/ci.yml` - CI configuration
305-
- `/docs/guides/development.md` - Developer documentation
306198

307199
## Common Issues & Solutions
308200

309201
### Network Connectivity Issues
310202

311-
If you see errors about `storage.googleapis.com`, the Go proxy may be unreachable. Tests may still pass for packages that don't require network dependencies.
203+
If you see errors about `storage.googleapis.com`, the Go proxy may be unreachable. Use `GOPROXY=direct go mod download` to fetch modules directly from source.
312204

313205
### Test Timeouts
314206

@@ -326,19 +218,23 @@ go test -race ./...
326218

327219
### Database Connection Failures
328220

329-
Ensure Docker containers are running:
221+
If using Docker:
330222
```bash
331223
docker compose ps
332224
docker compose up -d
333225
```
334226

227+
If using sqlc-test-setup:
228+
```bash
229+
go run ./cmd/sqlc-test-setup start
230+
```
231+
335232
## Tips for Contributors
336233

337-
1. **Run tests before committing:** `make test-ci`
234+
1. **Run tests before committing:** `go test --tags=examples -timeout 20m ./...`
338235
2. **Check for race conditions:** Use `-race` flag when testing concurrent code
339236
3. **Use specific package tests:** Faster iteration during development
340-
4. **Start databases early:** `docker compose up -d` before running integration tests
341-
5. **Read existing tests:** Good examples in `/internal/engine/postgresql/*_test.go`
237+
4. **Read existing tests:** Good examples in `/internal/engine/postgresql/*_test.go`
342238

343239
## Git Workflow
344240

@@ -350,34 +246,18 @@ docker compose up -d
350246
### Committing Changes
351247

352248
```bash
353-
# Stage changes
354249
git add <files>
355-
356-
# Commit with descriptive message
357-
git commit -m "Brief description
358-
359-
Detailed explanation of changes.
360-
361-
🤖 Generated with [Claude Code](https://claude.com/claude-code)
362-
363-
Co-Authored-By: Claude <noreply@anthropic.com>"
364-
365-
# Push to remote
250+
git commit -m "Brief description of changes"
366251
git push -u origin <branch-name>
367252
```
368253

369254
### Rebasing
370255

371256
```bash
372-
# Update main
373257
git checkout main
374258
git pull origin main
375-
376-
# Rebase feature branch
377259
git checkout <feature-branch>
378260
git rebase main
379-
380-
# Force push rebased branch
381261
git push --force-with-lease origin <feature-branch>
382262
```
383263

@@ -387,21 +267,3 @@ git push --force-with-lease origin <feature-branch>
387267
- **Development Guide:** `/docs/guides/development.md`
388268
- **CI Configuration:** `/.github/workflows/ci.yml`
389269
- **Docker Compose:** `/docker-compose.yml`
390-
391-
## Recent Fixes & Improvements
392-
393-
### Fixed Issues
394-
395-
1. **Typo in create_function_stmt.go** - Fixed "Undertand" → "Understand"
396-
2. **Race condition in vet.go** - Fixed Client initialization using `sync.Once`
397-
3. **Nil pointer dereference in parse.go** - Fixed unsafe type assertion in primary key parsing
398-
399-
These fixes demonstrate common patterns:
400-
- Using `sync.Once` for thread-safe lazy initialization
401-
- Using comma-ok idiom for safe type assertions: `if val, ok := x.(Type); ok { ... }`
402-
- Adding proper nil checks and defensive programming
403-
404-
---
405-
406-
**Last Updated:** 2025-10-21
407-
**Maintainer:** Claude Code

0 commit comments

Comments
 (0)