Skip to content

Commit 0357a2e

Browse files
xernobylBhagyaAmarasinghemattinannt
authored
chore: add OpenAPI.yml and Schemathesis (#2)
* chore: added openapi.yaml * chore: added log levels env var; openapi.yaml file * chore: added schematesis.toml file * chore: updated .gitignore * chore: addd API tests (schematesis) workflow * chore: renamed "migrations" to "init-db", and postgres' default credentials * chore: fix api-tests.yml * chore: fix api-tests.yml * chore: api-tests.yml changes * chore: remove files to be moved to separate PR * chore: add logging level env var * fix: use localhost with port mapping for postgres in CI * fix: use gen_random_uuid() instead of non-existent uuidv7() * chore: changed contact info; replaced versioning with hashes * chore: reverted to pg18 * chore: removed references to search api * chore: changed openapi.yml to reference localhost * chore: removed (wrong) date limits * chore: added health endpoint to openapi.yml * chore: added field_id to openapi.yml * chore: removed ai enriched fields * chore: removed value_json * chore: hardcoded test key * chore: added authentication to specification * chore: marking $schema as optional * chore: added uuid format hint to openapi.yml * chore: removed $schema from openapi.yml * chore: added examples to openapi.yml * chore: assorted api fixes * fix: inconsistency between schema and code * chore: add stateful testing to schemthesis * fix: run only examples in CI --------- Co-authored-by: Bhagya Amarasinghe <b.sithumini@yahoo.com> Co-authored-by: Matti Nannt <matti@formbricks.com>
1 parent 59d0d4a commit 0357a2e

File tree

18 files changed

+1119
-72
lines changed

18 files changed

+1119
-72
lines changed

.env.example

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@
77
API_KEY=your-secret-api-key-here
88

99
# Database connection URL (optional)
10-
# Default: postgres://formbricks:formbricks_dev@localhost:5432/formbricks_hub?sslmode=disable
10+
# Default: postgres://postgres:postgres@localhost:5432/test_db?sslmode=disable
1111
# Format: postgres://username:password@host:port/database?sslmode=disable
12-
DATABASE_URL=postgres://formbricks:formbricks_dev@localhost:5432/formbricks_hub?sslmode=disable
12+
DATABASE_URL=postgres://postgres:postgres@localhost:5432/test_db?sslmode=disable
1313

1414
# HTTP server port (optional)
1515
# Default: 8080
1616
PORT=8080
17+
18+
# Logging level (optional)
19+
# Default: info
20+
# Valid values: debug, info, warn, error
21+
LOG_LEVEL=info

.github/workflows/api-tests.yml

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: API Tests
2+
3+
# This workflow tests your API against the OpenAPI spec using Schemathesis.
4+
# It only runs the "examples" phase (fast & deterministic).
5+
# For thorough fuzzing, run locally: make schemathesis
6+
7+
on:
8+
pull_request:
9+
10+
concurrency:
11+
group: api-tests-${{ github.head_ref }}
12+
13+
cancel-in-progress: true
14+
15+
jobs:
16+
api-tests:
17+
name: API Contract Tests
18+
runs-on: ubuntu-latest
19+
timeout-minutes: 10
20+
21+
services:
22+
postgres:
23+
image: pgvector/pgvector:pg18
24+
env:
25+
POSTGRES_USER: postgres
26+
POSTGRES_PASSWORD: postgres
27+
POSTGRES_DB: test_db
28+
ports:
29+
- 5432:5432
30+
options: >-
31+
--health-cmd pg_isready
32+
--health-interval 10s
33+
--health-timeout 5s
34+
--health-retries 5
35+
36+
env:
37+
DATABASE_URL: postgres://postgres:postgres@localhost:5432/test_db?sslmode=disable
38+
API_KEY: test-api-key-for-ci
39+
PORT: 8080
40+
41+
steps:
42+
- name: Checkout
43+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
44+
45+
- name: Set up Go
46+
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff
47+
with:
48+
go-version: '1.25.6'
49+
50+
- name: Cache Go modules
51+
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
52+
with:
53+
path: |
54+
~/.cache/go-build
55+
~/go/pkg/mod
56+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
57+
restore-keys: |
58+
${{ runner.os }}-go-
59+
60+
- name: Install dependencies
61+
run: go mod download
62+
63+
- name: Initialize database schema
64+
run: make init-db
65+
66+
- name: Build application
67+
run: make build
68+
69+
- name: Start API server
70+
run: |
71+
./bin/api &
72+
API_PID=$!
73+
echo "API_PID=$API_PID" >> $GITHUB_ENV
74+
75+
# Wait for server to be healthy (up to ~60s)
76+
for i in {1..30}; do
77+
if curl -s http://localhost:8080/health | grep -q "OK"; then
78+
echo "Server is ready"
79+
break
80+
fi
81+
echo "Waiting for server... ($i/30)"
82+
sleep 2
83+
done
84+
85+
# Verify we actually became ready
86+
if ! curl -s http://localhost:8080/health | grep -q "OK"; then
87+
echo "Server failed to start. Checking logs..."
88+
ps aux | grep api || true
89+
exit 1
90+
fi
91+
92+
- name: Run API contract tests
93+
uses: schemathesis/action@1f15936316e0742005bf69657b5909ac68f04cb3
94+
with:
95+
schema: ./openapi.yaml
96+
base-url: http://localhost:8080
97+
# Pin version to avoid regressions from newer Schemathesis releases
98+
version: "4.4.4"
99+
# Only test schema conformance
100+
checks: not_a_server_error,status_code_conformance,content_type_conformance,response_schema_conformance
101+
# Only run examples phase for fast, deterministic CI testing.
102+
# For deeper testing (stateful, fuzzing), run locally: make schemathesis
103+
args: >-
104+
--phases examples
105+
-H "Authorization: Bearer test-api-key-for-ci"
106+
107+
- name: Stop API server
108+
if: always()
109+
run: |
110+
if [ ! -z "$API_PID" ]; then
111+
kill $API_PID || true
112+
fi
113+
pkill -f "./bin/api" || true

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,9 @@ bin/
44
.env
55
*.out
66
*.html
7+
8+
# Go test binaries
9+
*.test
10+
11+
# Hypothesis cache (generated by Schemathesis)
12+
.hypothesis/

AGENTS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
- `cmd/api/` holds the API server entrypoint (`main.go`).
55
- `internal/` contains core application layers: `api/handlers`, `api/middleware`, `service`, `repository`, `models`, and `config`.
66
- `pkg/` provides shared utilities (currently `pkg/database`).
7-
- `migrations/` stores SQL migration files (e.g., `migrations/001_initial_schema.sql`).
7+
- `sql/` stores SQL schema files (e.g., `sql/001_initial_schema.sql`).
88
- `tests/` contains integration tests.
99

1010
## Build, Test, and Development Commands
11-
- `make dev-setup`: start Postgres via Docker, install Go deps/tools, and run migrations.
11+
- `make dev-setup`: start Postgres via Docker, install Go deps/tools, and initialize database schema.
1212
- `make run`: create a default `.env` if missing and run the API server.
1313
- `make build`: build the API binary to `bin/api`.
1414
- `make tests`: run integration tests in `tests/`.
1515
- `make tests-coverage`: generate `coverage.html`.
16-
- `make migrate`: apply SQL migrations using `DATABASE_URL`.
16+
- `make init-db`: initialize database schema using `DATABASE_URL`.
1717
- `make fmt` / `make fmt-check`: format or verify formatting with `gofumpt`.
1818
- `make lint`: run `golangci-lint` (requires `make install-tools`).
1919

Makefile

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: help tests tests-coverage build run migrate clean docker-up docker-down docker-clean deps install-tools fmt fmt-check lint dev-setup test-all
1+
.PHONY: help tests tests-coverage build run init-db clean docker-up docker-down docker-clean deps install-tools fmt fmt-check lint dev-setup test-all schemathesis
22

33
# Default target - show help
44
help:
@@ -7,12 +7,13 @@ help:
77
@echo " make tests - Run all tests"
88
@echo " make build - Build the API server"
99
@echo " make run - Run the API server"
10-
@echo " make migrate - Run database migrations"
10+
@echo " make init-db - Initialize database schema"
1111
@echo " make docker-up - Start Docker containers"
1212
@echo " make docker-down - Stop Docker containers"
1313
@echo " make clean - Clean build artifacts"
1414
@echo " make fmt - Format code with gofumpt"
1515
@echo " make fmt-check - Check if code is formatted"
16+
@echo " make schemathesis - Run Schemathesis API tests (requires API server running)"
1617

1718
# Run all tests
1819
tests:
@@ -44,7 +45,7 @@ run:
4445
echo "API_KEY=test-api-key-12345" >> .env; \
4546
echo "" >> .env; \
4647
echo "# Database connection URL" >> .env; \
47-
echo "DATABASE_URL=postgres://formbricks:formbricks_dev@localhost:5432/formbricks_hub?sslmode=disable" >> .env; \
48+
echo "DATABASE_URL=postgres://postgres:postgres@localhost:5432/test_db?sslmode=disable" >> .env; \
4849
echo "" >> .env; \
4950
echo "# Server port (default: 8080)" >> .env; \
5051
echo "PORT=8080" >> .env; \
@@ -53,25 +54,25 @@ run:
5354
@echo "Starting API server..."
5455
go run cmd/api/main.go
5556

56-
# Run database migrations
57-
migrate:
58-
@echo "Running database migrations..."
57+
# Initialize database schema
58+
init-db:
59+
@echo "Initializing database schema..."
5960
@if [ -f .env ]; then \
6061
export $$(grep -v '^#' .env | xargs) && \
6162
if [ -z "$$DATABASE_URL" ]; then \
6263
echo "Error: DATABASE_URL not found in .env file"; \
6364
exit 1; \
6465
fi && \
65-
psql "$$DATABASE_URL" -f migrations/001_initial_schema.sql; \
66+
psql "$$DATABASE_URL" -f sql/001_initial_schema.sql; \
6667
else \
6768
if [ -z "$$DATABASE_URL" ]; then \
6869
echo "Error: DATABASE_URL environment variable is not set"; \
6970
echo "Please set it or create a .env file with DATABASE_URL"; \
7071
exit 1; \
7172
fi && \
72-
psql "$$DATABASE_URL" -f migrations/001_initial_schema.sql; \
73+
psql "$$DATABASE_URL" -f sql/001_initial_schema.sql; \
7374
fi
74-
@echo "Migration completed successfully"
75+
@echo "Database schema initialized successfully"
7576

7677

7778
# Start Docker containers
@@ -135,11 +136,45 @@ lint:
135136
$(HOME)/go/bin/golangci-lint run ./...
136137

137138
# Run everything needed for development
138-
dev-setup: docker-up deps install-tools migrate
139+
dev-setup: docker-up deps install-tools init-db
139140
@echo "Development environment ready!"
140141
@echo "Set API_KEY environment variable for authentication"
141142
@echo "Run 'make run' to start the API server"
142143

143144
# Full test suite (unit + integration)
144145
test-all: tests
145146
@echo "All tests passed!"
147+
148+
# Run Schemathesis API tests (all phases for thorough local testing)
149+
# Phases: examples (schema examples), coverage (boundary values), stateful (API sequences), fuzzing (random)
150+
# This runs more thorough tests than CI to find edge-case bugs.
151+
# Requires: API server running (make run in another terminal)
152+
# Requires: uvx (install via: curl -LsSf https://astral.sh/uv/install.sh | sh)
153+
schemathesis:
154+
@echo "Running Schemathesis API tests (all phases)..."
155+
@echo "This is deeper testing than CI - may find edge-case bugs."
156+
@export PATH="$$HOME/.local/bin:$$PATH" && \
157+
if [ -f .env ]; then \
158+
export $$(grep -v '^#' .env | xargs) && \
159+
if [ -z "$$API_KEY" ]; then \
160+
echo "Warning: API_KEY not found in .env file, tests may fail authentication"; \
161+
fi && \
162+
uvx schemathesis run ./openapi.yaml \
163+
--url http://localhost:8080 \
164+
--header "Authorization: Bearer $${API_KEY:-test-api-key-12345}" \
165+
--checks all \
166+
--phases examples,coverage,stateful,fuzzing \
167+
--max-examples 50; \
168+
else \
169+
if [ -z "$$API_KEY" ]; then \
170+
echo "Error: API_KEY environment variable is not set and .env file not found"; \
171+
echo "Please set API_KEY or create a .env file"; \
172+
exit 1; \
173+
fi && \
174+
uvx schemathesis run ./openapi.yaml \
175+
--url http://localhost:8080 \
176+
--header "Authorization: Bearer $$API_KEY" \
177+
--checks all \
178+
--phases examples,coverage,stateful,fuzzing \
179+
--max-examples 50; \
180+
fi

README.md

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ An open-source Experience Management (XM) database service. Hub is a headless AP
2929
-**API Key Authentication** via environment variable
3030
-**Clean Architecture** with repository, service, and handler layers
3131
-**Docker Compose** for local development
32-
-**Database Migrations** with version tracking
32+
-**Database Schema** initialization
3333
-**Swagger/OpenAPI** documentation
3434
-**Health Check** endpoints
3535

@@ -58,7 +58,7 @@ An open-source Experience Management (XM) database service. Hub is a headless AP
5858
│ └── config/ # Configuration management
5959
├── pkg/
6060
│ └── database/ # Database utilities and connection pooling
61-
├── migrations/ # SQL migrations
61+
├── sql/ # SQL schema files
6262
├── tests/ # Integration tests
6363
└── docs/ # API documentation (Swagger)
6464
```
@@ -84,7 +84,7 @@ This will:
8484
- Start PostgreSQL container
8585
- Install Go dependencies
8686
- Install development tools (swag for OpenAPI docs)
87-
- Run database migrations
87+
- Initialize database schema
8888

8989
3. Start the API server:
9090
```bash
@@ -107,9 +107,9 @@ docker-compose up -d
107107
cp .env.example .env
108108
```
109109

110-
3. Run migrations:
110+
3. Initialize database schema:
111111
```bash
112-
make migrate
112+
make init-db
113113
```
114114

115115
4. Set your API key:
@@ -175,12 +175,6 @@ Query parameters:
175175
- `limit` - Number of results (default: 100, max: 1000)
176176
- `offset` - Pagination offset
177177

178-
#### Search Feedback Records
179-
```bash
180-
GET /v1/feedback-records/search?query=feedback&source_type=survey&limit=20
181-
Authorization: Bearer <api-key>
182-
```
183-
184178
#### Update Feedback Record
185179
```bash
186180
PATCH /v1/feedback-records/{id}
@@ -205,11 +199,11 @@ Authorization: Bearer <api-key>
205199

206200
```bash
207201
make help # Show all available commands
208-
make dev-setup # Set up development environment (docker, deps, tools, migrations)
202+
make dev-setup # Set up development environment (docker, deps, tools, schema)
209203
make build # Build all binaries
210204
make run # Run the API server
211205
make tests # Run all tests
212-
make migrate # Run database migrations
206+
make init-db # Initialize database schema
213207
make docker-up # Start Docker containers
214208
make docker-down # Stop Docker containers
215209
make clean # Clean build artifacts
@@ -221,16 +215,16 @@ make clean # Clean build artifacts
221215
make tests
222216
```
223217

224-
### Database Migrations
218+
### Database Schema
225219

226-
Migrations are stored in the `migrations/` directory.
220+
The database schema is stored in the `sql/` directory.
227221

228-
To run migrations:
222+
To initialize the database schema:
229223
```bash
230-
make migrate
224+
make init-db
231225
```
232226

233-
This will execute `migrations/001_initial_schema.sql` using `psql`. Make sure you have `DATABASE_URL` set in your environment or `.env` file.
227+
This will execute `sql/001_initial_schema.sql` using `psql`. Make sure you have `DATABASE_URL` set in your environment or `.env` file.
234228

235229
### API Key Authentication
236230

0 commit comments

Comments
 (0)