Skip to content

Commit d326402

Browse files
feat(db): migration readme
1 parent 1e42c04 commit d326402

2 files changed

Lines changed: 106 additions & 7 deletions

File tree

Makefile

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,80 @@
1-
.PHONY: generate build run test test-integration test-all lint swagger docker docker-down ci benchmark migrate-up migrate-down migrate-version migrate-create
1+
.PHONY: generate build run test test-integration test-all lint swagger docker docker-down ci benchmark \
2+
migrate-create migrate-up migrate-down migrate-down-one migrate-version migrate-force \
3+
migrate-up-docker migrate-down-docker migrate-down-one-docker migrate-version-docker migrate-force-docker
24

3-
MIGRATIONS_PATH ?= migrations
5+
MIGRATE ?= migrate
6+
MIGRATIONS_DIR ?= migrations
7+
MIGRATE_DATABASE_URL ?=
8+
MIGRATE_DOCKER_IMAGE ?= migrate/migrate
9+
COMPOSE_PROJECT_NAME ?= $(notdir $(CURDIR))
10+
COMPOSE_NETWORK ?= $(COMPOSE_PROJECT_NAME)_default
411

512
# Code generation
6-
generate:
13+
generate:
714
sqlc generate
815
swag init -g cmd/server/main.go --output docs/swagger
916

1017
docs: generate
1118

19+
# Database migrations (golang-migrate)
20+
migrate-create:
21+
@test -n "$(name)" || (echo "Usage: make migrate-create name=add_users_table" && exit 1)
22+
@mkdir -p $(MIGRATIONS_DIR)
23+
$(MIGRATE) create -ext sql -dir $(MIGRATIONS_DIR) $(name)
24+
25+
migrate-up:
26+
@db_url="$${MIGRATE_DATABASE_URL:-$${DATABASE_URL:-$$(grep -E '^DATABASE_URL=' .env 2>/dev/null | head -n1 | cut -d= -f2-)}}"; \
27+
test -n "$$db_url" || (echo "Set MIGRATE_DATABASE_URL or DATABASE_URL (or add DATABASE_URL to .env)" && exit 1); \
28+
$(MIGRATE) -path $(MIGRATIONS_DIR) -database "$$db_url" up
29+
30+
migrate-down:
31+
@db_url="$${MIGRATE_DATABASE_URL:-$${DATABASE_URL:-$$(grep -E '^DATABASE_URL=' .env 2>/dev/null | head -n1 | cut -d= -f2-)}}"; \
32+
test -n "$$db_url" || (echo "Set MIGRATE_DATABASE_URL or DATABASE_URL (or add DATABASE_URL to .env)" && exit 1); \
33+
$(MIGRATE) -path $(MIGRATIONS_DIR) -database "$$db_url" down -all
34+
35+
migrate-down-one:
36+
@db_url="$${MIGRATE_DATABASE_URL:-$${DATABASE_URL:-$$(grep -E '^DATABASE_URL=' .env 2>/dev/null | head -n1 | cut -d= -f2-)}}"; \
37+
test -n "$$db_url" || (echo "Set MIGRATE_DATABASE_URL or DATABASE_URL (or add DATABASE_URL to .env)" && exit 1); \
38+
$(MIGRATE) -path $(MIGRATIONS_DIR) -database "$$db_url" down 1
39+
40+
migrate-version:
41+
@db_url="$${MIGRATE_DATABASE_URL:-$${DATABASE_URL:-$$(grep -E '^DATABASE_URL=' .env 2>/dev/null | head -n1 | cut -d= -f2-)}}"; \
42+
test -n "$$db_url" || (echo "Set MIGRATE_DATABASE_URL or DATABASE_URL (or add DATABASE_URL to .env)" && exit 1); \
43+
$(MIGRATE) -path $(MIGRATIONS_DIR) -database "$$db_url" version
44+
45+
migrate-force:
46+
@test -n "$(version)" || (echo "Usage: make migrate-force version=<number>" && exit 1)
47+
@db_url="$${MIGRATE_DATABASE_URL:-$${DATABASE_URL:-$$(grep -E '^DATABASE_URL=' .env 2>/dev/null | head -n1 | cut -d= -f2-)}}"; \
48+
test -n "$$db_url" || (echo "Set MIGRATE_DATABASE_URL or DATABASE_URL (or add DATABASE_URL to .env)" && exit 1); \
49+
$(MIGRATE) -path $(MIGRATIONS_DIR) -database "$$db_url" force $(version)
50+
51+
# Database migrations via Docker (uses Compose network, works with DATABASE_URL=db:5432)
52+
migrate-up-docker:
53+
@db_url="$${MIGRATE_DATABASE_URL:-$${DATABASE_URL:-$$(grep -E '^DATABASE_URL=' .env 2>/dev/null | head -n1 | cut -d= -f2-)}}"; \
54+
test -n "$$db_url" || (echo "Set MIGRATE_DATABASE_URL or DATABASE_URL (or add DATABASE_URL to .env)" && exit 1); \
55+
docker run --rm --network $(COMPOSE_NETWORK) -v "$(CURDIR)/$(MIGRATIONS_DIR):/migrations" $(MIGRATE_DOCKER_IMAGE) -path /migrations -database "$$db_url" up
56+
57+
migrate-down-docker:
58+
@db_url="$${MIGRATE_DATABASE_URL:-$${DATABASE_URL:-$$(grep -E '^DATABASE_URL=' .env 2>/dev/null | head -n1 | cut -d= -f2-)}}"; \
59+
test -n "$$db_url" || (echo "Set MIGRATE_DATABASE_URL or DATABASE_URL (or add DATABASE_URL to .env)" && exit 1); \
60+
docker run --rm --network $(COMPOSE_NETWORK) -v "$(CURDIR)/$(MIGRATIONS_DIR):/migrations" $(MIGRATE_DOCKER_IMAGE) -path /migrations -database "$$db_url" down -all
61+
62+
migrate-down-one-docker:
63+
@db_url="$${MIGRATE_DATABASE_URL:-$${DATABASE_URL:-$$(grep -E '^DATABASE_URL=' .env 2>/dev/null | head -n1 | cut -d= -f2-)}}"; \
64+
test -n "$$db_url" || (echo "Set MIGRATE_DATABASE_URL or DATABASE_URL (or add DATABASE_URL to .env)" && exit 1); \
65+
docker run --rm --network $(COMPOSE_NETWORK) -v "$(CURDIR)/$(MIGRATIONS_DIR):/migrations" $(MIGRATE_DOCKER_IMAGE) -path /migrations -database "$$db_url" down 1
66+
67+
migrate-version-docker:
68+
@db_url="$${MIGRATE_DATABASE_URL:-$${DATABASE_URL:-$$(grep -E '^DATABASE_URL=' .env 2>/dev/null | head -n1 | cut -d= -f2-)}}"; \
69+
test -n "$$db_url" || (echo "Set MIGRATE_DATABASE_URL or DATABASE_URL (or add DATABASE_URL to .env)" && exit 1); \
70+
docker run --rm --network $(COMPOSE_NETWORK) -v "$(CURDIR)/$(MIGRATIONS_DIR):/migrations" $(MIGRATE_DOCKER_IMAGE) -path /migrations -database "$$db_url" version
71+
72+
migrate-force-docker:
73+
@test -n "$(version)" || (echo "Usage: make migrate-force-docker version=<number>" && exit 1)
74+
@db_url="$${MIGRATE_DATABASE_URL:-$${DATABASE_URL:-$$(grep -E '^DATABASE_URL=' .env 2>/dev/null | head -n1 | cut -d= -f2-)}}"; \
75+
test -n "$$db_url" || (echo "Set MIGRATE_DATABASE_URL or DATABASE_URL (or add DATABASE_URL to .env)" && exit 1); \
76+
docker run --rm --network $(COMPOSE_NETWORK) -v "$(CURDIR)/$(MIGRATIONS_DIR):/migrations" $(MIGRATE_DOCKER_IMAGE) -path /migrations -database "$$db_url" force $(version)
77+
1278
# Build
1379
build: generate
1480
go build -o bin/capy-server ./cmd/server
@@ -22,8 +88,9 @@ test:
2288
go test -v -race -short ./...
2389

2490
test-integration:
91+
go test -tags=integration ./internal/database/... -count=1
2592
go test -tags=integration ./tests/integration/... -coverprofile=coverage.out -coverpkg=./...
26-
go tool cover -html=coverage.out
93+
go tool cover -func=coverage.out
2794

2895
test-all:
2996
go test -v -race -tags=integration ./...

README.md

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,45 @@ make docker
5454

5555
### 3. Run Migrations & Generate Code
5656
```bash
57-
# Apply DB migrations (DATABASE_URL must point at your DB)
57+
# If your DB is running via docker-compose on your host machine, override host:
58+
# export MIGRATE_DATABASE_URL=postgres://capy:devpassword@localhost:5432/capy_db?sslmode=disable or use make migrate-up-docker
5859
make migrate-up
59-
60-
# Generate sqlc + swagger artifacts
6160
make generate
6261
```
6362

63+
Create a new migration:
64+
```bash
65+
make migrate-create name=add_event_capacity
66+
```
67+
68+
What goes in migration files:
69+
- `*.up.sql`: the incremental schema change you want to apply (DDL like `CREATE TABLE`, `ALTER TABLE`, `CREATE INDEX`)
70+
- `*.down.sql`: the reverse of that same change (rollback), not the full previous schema
71+
72+
Example (`add_event_capacity`):
73+
```sql
74+
-- up.sql
75+
ALTER TABLE events
76+
ADD COLUMN capacity INTEGER;
77+
78+
ALTER TABLE events
79+
ADD CONSTRAINT events_capacity_nonnegative
80+
CHECK (capacity IS NULL OR capacity >= 0);
81+
```
82+
83+
```sql
84+
-- down.sql
85+
ALTER TABLE events
86+
DROP CONSTRAINT IF EXISTS events_capacity_nonnegative;
87+
88+
ALTER TABLE events
89+
DROP COLUMN IF EXISTS capacity;
90+
```
91+
92+
Rule of thumb:
93+
- `up` = apply one change
94+
- `down` = undo that same change only
95+
6496
### 4. Run Server
6597
```bash
6698
make run

0 commit comments

Comments
 (0)