Contributing to TimeFusion
June 29, 2026 · View on GitHub
Thanks for contributing. This guide covers local setup, the test suite, and the conventions we hold PRs to.
Local setup
You need a recent stable Rust toolchain (edition 2024 → Rust 1.85+) and Docker (for MinIO and the end-to-end tests).
git clone https://github.com/monoscope-tech/timefusion.git
cd timefusion
cargo build
# Run against a local MinIO
docker compose up -d minio createbucket
export AWS_S3_BUCKET=timefusion \
AWS_S3_ENDPOINT=http://localhost:9000 \
AWS_ALLOW_HTTP=true \
AWS_ACCESS_KEY_ID=minioadmin \
AWS_SECRET_ACCESS_KEY=minioadmin
cargo run
The Makefile has shortcuts (make minio-start, make run-minio,
make test-minio) if you'd rather run MinIO as a local binary than in Docker.
Tests
cargo test # unit tests (fast)
cargo test --test sqllogictest # SQL logic tests
cargo test --test integration_test # write-path integration
cargo test --test e2e # end-to-end (Docker required; testcontainers MinIO)
RUST_LOG=debug cargo test # with debug logging
make test-all # everything, including slow integration tests
- Dev builds compile far faster than release — use them while iterating.
- Tests that mutate process env (
std::env::set_var) must be#[serial](viaserial_test) with a SAFETY comment explaining the race they avoid. - The
e2esuite exercises the full prod path (pgwire → WAL → MemBuffer → flush → Delta on MinIO → query) with a virtual clock; a failure there mirrors a prod failure.
Bug-fix workflow (required)
When fixing a bug, write a failing test first, at the level closest to where the bug manifests:
- pure logic / parsing → unit test
- SQL behavior →
sqllogictestcase - end-to-end write path →
integration_test/e2e
The test must fail on the specific symptom (an error string, a row count, an error code) — "errors somewhere" isn't enough. Then write the fix, confirm the test passes, run the suite for regressions, and keep the test as a guard named after the bug. Don't skip the failing-test step because the fix looks obvious.
Code style
TimeFusion is maintained by a small team; conciseness and zero boilerplate are top priorities. Before opening a PR:
- Prefer extending existing functions over adding new ones; generalize rather than duplicate.
- Make surgical changes — touch only what the change requires, match the surrounding style, and don't refactor unrelated code or delete pre-existing dead code unless that's the point of the PR.
- Use
ArrayData::try_new(notnew_unchecked), named constants for magic numbers, and bounded deserialization. - Run
cargo fmtandcargo clippybefore pushing; fix new warnings.
See CLAUDE.md for the full code philosophy.
Commits & pull requests
- Keep commits focused; write clear messages describing the why.
- Make sure
cargo test,cargo fmt --check, andcargo clippypass. - Open the PR against
masterwith a description of the change and how you verified it.
By contributing, you agree your contributions are licensed under the MIT License.