Skip to content

Commit 25c52f6

Browse files
authored
Merge pull request #3 from lupodevelop/ci/workflow
Ci/workflow After some edits, all is green!
2 parents 1ebf241 + 4a2d721 commit 25c52f6

7 files changed

Lines changed: 328 additions & 392 deletions

File tree

.gitattributes

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# Auto detect text files and perform LF normalization
2-
* text=auto
2+
* text=auto eol=lf
3+
*.gleam text eol=lf

.github/workflows/ci.yml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
name: Build and Test
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
17+
- name: Start ClickHouse
18+
run: |
19+
docker compose up -d clickhouse
20+
echo "Waiting for ClickHouse to be ready..."
21+
for i in $(seq 1 60); do
22+
if curl -sSf http://localhost:8123/ >/dev/null 2>&1; then
23+
echo "ClickHouse is ready"
24+
break
25+
fi
26+
sleep 2
27+
done
28+
29+
- name: Setup Erlang/OTP and Gleam
30+
uses: erlef/setup-beam@v1
31+
with:
32+
otp-version: "27.0"
33+
gleam-version: "1.13.0"
34+
35+
- name: Show Gleam version
36+
run: gleam --version
37+
38+
- name: Cache Gleam deps and build
39+
uses: actions/cache@v4
40+
with:
41+
path: |
42+
~/.cache/gleam
43+
~/.gleam
44+
./_gleam_deps
45+
./build
46+
key: ${{ runner.os }}-gleam-1.13.0-otp27-cache-v1-${{ hashFiles('**/gleam.toml') }}
47+
restore-keys: |
48+
${{ runner.os }}-gleam-1.13.0-otp27-cache-v1-
49+
50+
- name: Install dependencies
51+
run: gleam deps download
52+
53+
- name: Check formatting
54+
run: gleam format --check src test
55+
56+
- name: Build project
57+
run: gleam build
58+
59+
- name: Run all tests
60+
env:
61+
CLICKHOUSE_USER: test_user
62+
CLICKHOUSE_PASSWORD: test_password
63+
CLICKHOUSE_DB: test_db
64+
CLICKHOUSE_URL: http://localhost:8123
65+
run: gleam test
66+
67+
- name: Cleanup ClickHouse
68+
if: always()
69+
run: docker compose down -v
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: Smoke Integration (PR)
2+
3+
on:
4+
pull_request:
5+
branches: ["main"]
6+
7+
jobs:
8+
smoke-integration:
9+
name: Smoke Integration (ClickHouse)
10+
runs-on: ubuntu-latest
11+
timeout-minutes: 30
12+
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
17+
- name: Start ClickHouse (docker-compose)
18+
env:
19+
CLICKHOUSE_IMAGE: clickhouse/clickhouse-server:23.7
20+
run: |
21+
echo "Using CLICKHOUSE_IMAGE=$CLICKHOUSE_IMAGE"
22+
docker compose pull clickhouse || true
23+
docker compose up -d --remove-orphans clickhouse
24+
25+
- name: Wait for ClickHouse HTTP
26+
run: |
27+
echo "Waiting for ClickHouse HTTP on localhost:8123..."
28+
for i in $(seq 1 40); do
29+
if curl -sSf http://localhost:8123/ >/dev/null 2>&1; then
30+
echo "ClickHouse is up"
31+
break
32+
fi
33+
sleep 2
34+
done
35+
36+
- name: Smoke test - SELECT 1
37+
run: |
38+
set -e
39+
OUT=$(curl -sS -u test_user:test_password "http://localhost:8123/?query=SELECT%201%20as%20result%20FORMAT%20JSONEachRow&database=test_db")
40+
echo "Got: $OUT"
41+
if [ "$OUT" != '{"result":1}' ] && [ "$OUT" != '{"result":1}\n' ]; then
42+
echo "Unexpected response: $OUT"
43+
exit 2
44+
fi
45+
46+
- name: Smoke test - create table, insert and select
47+
run: |
48+
set -e
49+
DDL="CREATE TABLE IF NOT EXISTS smoke_test (id UInt32, name String) ENGINE = MergeTree() ORDER BY id"
50+
curl -sS -u test_user:test_password -d "$DDL" "http://localhost:8123/?database=test_db"
51+
52+
INSERT="INSERT INTO smoke_test (id,name) VALUES (1,'smoke')"
53+
curl -sS -u test_user:test_password -d "$INSERT" "http://localhost:8123/?database=test_db"
54+
55+
OUT=$(curl -sS -u test_user:test_password "http://localhost:8123/?query=SELECT%20*%20FROM%20smoke_test%20WHERE%20id%3D1%20FORMAT%20JSONEachRow&database=test_db")
56+
echo "Select returned: $OUT"
57+
if [ -z "$OUT" ]; then
58+
echo "Select returned empty"
59+
exit 3
60+
fi
61+
62+
- name: Cleanup ClickHouse
63+
if: always()
64+
run: |
65+
docker compose down -v || true

README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,45 @@
44
<img src="assets/image.png" alt="Sparkling logo" width="240" />
55
</p>
66

7-
[![License](https://img.shields.io/badge/license-Apache%202.0-yellow.svg)](LICENSE) [![Built with Gleam](https://img.shields.io/badge/Built%20with-Gleam-ffaff3)](https://gleam.run)
7+
[![CI](https://github.com/lupodevelop/sparkling/actions/workflows/ci.yml/badge.svg)](https://github.com/lupodevelop/sparkling/actions/workflows/ci.yml) [![License](https://img.shields.io/badge/license-Apache%202.0-yellow.svg)](LICENSE) [![Built with Gleam](https://img.shields.io/badge/Built%20with-Gleam-ffaff3)](https://gleam.run) [![Gleam Version](https://img.shields.io/badge/gleam-%3E%3D1.13.0-ffaff3)](https://gleam.run)
88

99
**Sparkling** is a *lightweight*, **type-safe** data layer for **ClickHouse** written in Gleam. It provides a small, focused API for defining schemas, building queries, and encoding/decoding ClickHouse formats.
1010

1111
*No magic*, just small, composable functions that play nicely in Gleam apps.
1212

1313
> Why "Sparkling"? One rainy Tuesday a tiny inflatable rubber duck stole a shooting pink star and decided to become a freelance data wrangler, and it now guides queries through the night, humming 8-bit lullabies. Totally plausible.
1414
15+
## Quick start
16+
17+
See the extracted quick start example: `docs/quickstart.md` it contains a short walkthrough (define schema, build a query, execute it with a repo).
18+
19+
Minimal example:
20+
21+
```gleam
22+
import sparkling/repo
23+
24+
let r = repo.new("http://localhost:8123")
25+
|> repo.with_database("mydb")
26+
27+
case r.execute_sql(r, "SELECT 1 as result FORMAT JSONEachRow") {
28+
Ok(body) -> io.println(body)
29+
Error(_) -> io.println("query failed")
30+
}
31+
```
32+
33+
## What you'll find here
34+
35+
- `sparkling/schema` — typed table & column definitions
36+
- `sparkling/query` — immutable query builder (to_sql)
37+
- `sparkling/repo` — HTTP executor with retry hooks
38+
- `sparkling/encode` / `sparkling/decode` — format handlers (JSONEachRow default)
39+
- `sparkling/types` — helpers for Decimal, DateTime64, UUID, LowCardinality
40+
41+
For more examples see `docs/examples/` and `docs/quickstart.md`.
42+
43+
**Design note:** Sparkling's API and composable query builder were partly inspired by *Ecto*;
44+
many ideas about schema definition and query composition borrow from its approach while keeping a small, Gleam-friendly surface.
45+
1546
## Development
1647

1748
Run tests and format/check locally:

test/TESTS.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Tests — Quick reference
2+
3+
This document explains how tests are organised in the repository and how to run them locally and in CI.
4+
5+
Directory layout
6+
7+
- `test/sparkling/` — unit and component tests that do not require external services (fast).
8+
- `test/smoke/` — smoke/sanity tests. Quick checks that the test runner and a minimal API behave as expected.
9+
- `test/integration/` — integration tests that require external services (e.g. ClickHouse). These are slower and should not run on every PR.
10+
11+
Running tests locally
12+
13+
- Run the full test suite (if you have required services available):
14+
15+
```bash
16+
# from the project root
17+
gleam test
18+
```
19+
20+
- Run unit tests only (recommended for PRs):
21+
22+
```bash
23+
# if your test runner accepts paths:
24+
gleam test test/sparkling
25+
```
26+
27+
If your runner does not accept paths, run `gleam test` locally and ensure integration tests are not executed by default (integration tests should be placed under `test/integration/`).
28+
29+
- Run integration tests (requires ClickHouse or other external services):
30+
31+
```bash
32+
# Start ClickHouse (example using Docker)
33+
docker run -d --name clickhouse-server -p 8123:8123 -p 9000:9000 clickhouse/clickhouse-server:latest
34+
35+
# Run integration tests
36+
gleam test test/integration
37+
38+
# When finished, stop/remove the container
39+
docker stop clickhouse-server && docker rm clickhouse-server
40+
```
41+
42+
Environment variables
43+
44+
- Use environment variables to configure integration endpoints (example):
45+
46+
```bash
47+
export CLICKHOUSE_URL=http://localhost:8123
48+
```
49+
50+
Document required variables in `test/integration/README.md`.
51+
52+
CI guidance
53+
54+
- Pull Requests: run unit tests only.
55+
- Integration tests: run in separate CI jobs (manual trigger, nightly, or on release tags). Ensure the CI environment has access to required services and secrets before enabling integration jobs.
56+
57+
Best practices and PR checklist
58+
59+
- [ ] Unit tests pass locally (`gleam test`).
60+
- [ ] Integration tests are documented in `test/integration/README.md` with clear prerequisites and run instructions.
61+
- [ ] Do not add CI workflows that perform sensitive operations (publishing) in the import PR. Add automation in a separate PR after the code is stable.
62+
- [ ] Keep a lightweight smoke test under `test/smoke/` to validate the test runner and minimal API surface.

test/integration/README.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Integration tests
2+
3+
Integration tests that exercise the code against a real ClickHouse instance.
4+
5+
This document explains how to run integration tests locally and how to wire them into CI in a safe way.
6+
7+
Prerequisites
8+
9+
- Docker (used for the example below).
10+
- docker-compose (optional, if you prefer a compose-based setup).
11+
12+
Recommended local setup (Docker Compose)
13+
14+
1. Start ClickHouse with docker-compose (example):
15+
16+
```bash
17+
# from the repository root, if you have a docker-compose.yml configured
18+
docker-compose up -d
19+
```
20+
21+
2. Wait for the server to be ready:
22+
23+
```bash
24+
docker-compose ps
25+
```
26+
27+
3. Run only the integration tests:
28+
29+
```bash
30+
# from the repository root
31+
gleam test test/integration
32+
```
33+
34+
4. Tear down the environment when finished:
35+
36+
```bash
37+
docker-compose down -v
38+
```
39+
40+
Quick single-container alternative (no compose)
41+
42+
```bash
43+
docker run -d --name clickhouse-server -p 8123:8123 -p 9000:9000 clickhouse/clickhouse-server:latest
44+
# wait for readiness, then run tests
45+
gleam test test/integration
46+
docker stop clickhouse-server && docker rm clickhouse-server
47+
```
48+
49+
Connection details (local defaults)
50+
51+
- URL: http://localhost:8123
52+
- Database: test_db (tests may create/drop their own DBs)
53+
- User: test_user
54+
- Password: test_password
55+
56+
If your tests require different credentials or endpoints, set the appropriate environment variables (see the `Environment variables` section below).
57+
58+
Implemented integration tests
59+
60+
- `basic_connectivity_test.gleam` — verifies connection and basic queries
61+
- `complex_types_roundtrip_test.gleam` — round-trip tests for complex ClickHouse types
62+
- `format_compatibility_test.gleam` — tests different I/O formats (JSONEachRow, CSV, TabSeparated)
63+
- `performance_test.gleam` — optional performance/load checks (may be slow)
64+
65+
Environment variables
66+
67+
Use environment variables to configure endpoints and credentials for integration tests. Example:
68+
69+
```bash
70+
export CLICKHOUSE_URL=http://localhost:8123
71+
export CLICKHOUSE_USER=test_user
72+
export CLICKHOUSE_PASSWORD=test_password
73+
```
74+
75+
Document required environment variables and secrets clearly before enabling integration jobs in CI.
76+
77+
CI guidance
78+
79+
- Integration tests should not run by default on every PR. Run them in separate CI jobs, e.g. on manual dispatch, nightly builds, or release tags.
80+
- Example GitHub Actions job (run in a dedicated workflow or as a separate job):
81+
82+
```yaml
83+
- name: Integration tests (optional)
84+
run: |
85+
docker-compose up -d
86+
# optionally wait / healthcheck
87+
sleep 10
88+
gleam test test/integration
89+
docker-compose down -v
90+
# do not fail the whole pipeline if integration env is missing
91+
continue-on-error: true
92+
```
93+
94+
Notes and recommendations
95+
96+
- Keep integration tests isolated and idempotent: tests should create and drop any resources they need.
97+
- Mark expensive or flaky tests (e.g. `performance_test.gleam`) so CI can skip them unless explicitly requested.
98+
- Before enabling integration tests in CI, ensure any required secrets or credentials are set in the CI environment.

0 commit comments

Comments
 (0)