tbd
A small Clojure HTTP API built on Ring (Jetty) and reitit, with Swagger UI docs, unit tests, dockerized integration tests, and joint line coverage.
Requirements
- Docker, for the integration tests and the
script/docker-*tasks (all CI needs) - For running tasks natively (optional): Clojure CLI (tools.deps) with JDK 11+, and Babashka for
script/coverage-report
Running
script/server [port]
The server listens on port 3000 by default; pass a port argument or set PORT to change it
(the argument wins):
script/server 8080
PORT=8080 script/server
This is a thin wrapper around clojure -X:run, which also honors PORT.
Or build and run the container:
docker build -t tbd .
docker run --rm -p 3000:3000 tbd
API
| Method | Path | Description |
|---|---|---|
GET |
/ |
Plain-text landing message |
GET |
/api/ping |
Health check, returns pong |
GET |
/api/add?x=2&y=3 |
Adds two numbers, returns EDN: {:result 5} (400 if either is missing or not a number) |
GET |
/api-docs |
Swagger UI |
GET |
/swagger.json |
OpenAPI/Swagger spec |
curl localhost:3000/api/ping # pong
curl 'localhost:3000/api/add?x=2&y=3' # {:result 5}
Development
Every task is a bash script in script/. Start an nREPL server (with CIDER middleware) on the port in .nrepl-port, or 3000 if that
file doesn't exist:
script/repl
Tests
| Task | What it does |
|---|---|
script/unit-test |
Runs the Clojure tests in test/ |
script/integration-test |
Builds the app image, starts it on a random port, runs the integration suite against it, then tears it down |
script/test |
Unit tests, then integration tests (stops at the first failure) |
script/docker-unit-test |
Same as script/unit-test, but inside the app image (Docker only) |
Coverage
Line coverage via Cloverage:
| Task | Output |
|---|---|
script/unit-coverage |
target/coverage/unit/ |
script/integration-coverage |
target/coverage/integration/ |
script/coverage |
Runs both, then writes the merged report to target/coverage/merged/ |
script/docker-unit-coverage, script/docker-coverage-report |
Dockerized versions of the unit run and the merge step, so script/docker-unit-coverage, script/integration-coverage, script/docker-coverage-report is script/coverage with no local Clojure or Babashka (this is what CI runs) |
Each report directory has an index.html and an lcov.info. See
integration-test/README.md for how integration coverage is
collected.
Project layout
src/tbd/
core.clj Router, Ring app, and server startup
<group>/routes.clj Each route group (health, math, ...) owns its route subtree
<group>/core.clj Business logic for the group, with no HTTP concerns
test/ Unit tests
integration-test/ Dockerized integration tests and coverage harness
script/ Bash entry points (test, coverage, repl, ...) and coverage helpers
To add a new group, create tbd.<group>.routes with a routes fn that returns a reitit route
vector, then add it to the router in src/tbd/core.clj.