Skip to content

Contributing

This page walks through the contribution workflow from fork to merged pull request. Danube is built in Rust and uses embedded Raft consensus, no external dependencies like etcd or ZooKeeper are needed.


Before you start, install the following:

ToolVersionPurpose
RustStableBuild the broker, admin, CLI, and all crates
protobuf-compiler3.x+Generate gRPC code from .proto files
Docker20.10+Run Prometheus, Docker Compose setups
Docker Compose2.0+Local development cluster (optional)

  1. Fork the repository at github.com/danube-messaging/danube

  2. Clone your fork:

    Terminal window
    git clone https://github.com/<your-username>/danube.git
    cd danube
  3. Add upstream (recommended for staying up to date):

    Terminal window
    git remote add upstream https://github.com/danube-messaging/danube.git

Build all binaries in release mode:

Terminal window
cargo build --release

This produces:

  • target/release/danube-broker — the broker binary
  • target/release/danube-admin — the admin CLI
  • target/release/danube-cli — the client CLI

For a faster debug build during development:

Terminal window
cargo build

You have two options for running a local development cluster: Makefile (native, recommended for daily development) or Docker Compose (containerized, useful for testing the full stack).

The Makefile builds from source and starts 3 brokers on localhost with auto-clustered Raft consensus.

Start the cluster:

Terminal window
make brokers

This compiles in release mode and starts 3 brokers:

BrokerClient PortAdmin PortRaft PortPrometheus
Broker 066505005176509040
Broker 166515005276519041
Broker 266525005376529042

Logs are written to temp/broker_<port>.log.

Useful targets:

CommandDescription
make brokersBuild and start 3 brokers
make brokers-stopStop all brokers (keep Raft data for restart testing)
make brokers-cleanStop all brokers and delete Raft data
make broker-kill ID=0Kill a single broker by index (0, 1, or 2)
make broker-start ID=0Start a single broker by index
make cluster-statusShow Raft cluster status via danube-admin
make data-cleanRemove all Raft data directories
make adminStart the admin HTTP server on port 8080
make admin-cleanStop the admin server
make promStart Prometheus on port 9090 (Docker)
make prom-cleanStop Prometheus

Custom log levels:

Terminal window
RUST_LOG=danube_broker=debug make brokers

The docker/local-development/ setup builds from your local source and runs a full stack: 3 brokers, admin server, admin UI, CLI, and Prometheus.

Start:

Terminal window
cd docker/local-development/
docker-compose up -d --build

Rebuild after code changes:

Terminal window
docker-compose build broker1 broker2 broker3 danube-admin
docker-compose up -d --no-deps broker1 broker2 broker3 danube-admin

Services available:

ServicePortDescription
Brokers6650-6652gRPC client connections
Admin API8080HTTP admin server
Admin UI8081Web dashboard
Prometheus9090Metrics collection

Stop:

Terminal window
docker-compose down -v

Unit tests run without any external services:

Terminal window
# All library unit tests
cargo test --lib -p danube-schema
cargo test --lib -p danube-client
cargo test --lib -p danube-raft
cargo test --lib -p danube-persistent-storage

Integration tests require a running 3-broker cluster. Start one using make brokers, then run the tests.

  1. Start the cluster:

    Terminal window
    make brokers

    Wait a few seconds for the Raft cluster to elect a leader.

  2. Run broker integration tests (serial execution recommended to avoid timing flakiness):

    Terminal window
    cargo test --release -p danube-broker --tests -- --test-threads=1 --nocapture
  3. Run Raft integration tests:

    Terminal window
    cargo test -p danube-raft --tests -- --nocapture
  4. Run storage integration tests:

    Terminal window
    cargo test -p danube-persistent-storage --tests -- --nocapture
  5. Stop the cluster when done:

    Terminal window
    make brokers-clean

The test suite covers these areas:

CrateTest DirectoryCoverage
danube-brokerdanube-broker/tests/Pub/sub, subscriptions, schema validation, key-shared, partitioning, reliable dispatch, security, reconnection, topic moves
danube-admindanube-admin/tests/Topic lifecycle, namespace management, schema operations, MCP protocol
danube-raftdanube-raft/tests/Metadata CRUD, watch/TTL, broker patterns, cluster leadership
danube-persistent-storagedanube-persistent-storage/tests/WAL operations, retention, storage modes (local, shared_fs, object_store), topic ownership changes
danube-clidanube-cli/tests/Basic and schema workflows
danube-edgedanube-edge/tests/Edge replication
danube-schemaUnit tests (in-crate)Schema parsing, compatibility checking
danube-clientUnit tests (in-crate)Client library internals

  1. Create a feature branch from main:

    Terminal window
    git checkout -b feature/my-change
  2. Make your changes and commit with clear messages:

    Terminal window
    git add .
    git commit -m "feat: add support for XYZ"
  3. Run unit tests to catch regressions early:

    Terminal window
    cargo test --lib
  4. Run integration tests against a local cluster:

    Terminal window
    make brokers
    cargo test --release -p danube-broker --tests -- --test-threads=1 --nocapture
    make brokers-clean
  5. Ensure your code compiles cleanly:

    Terminal window
    cargo build --release
  6. Push and open a PR:

    Terminal window
    git push origin feature/my-change

    Open a pull request at github.com/danube-messaging/danube.

When you open a pull request, the CI pipeline automatically:

  1. Builds the broker and admin in release mode
  2. Starts a 3-broker cluster
  3. Runs all integration tests (danube-broker, danube-raft, danube-persistent-storage)
  4. Runs all library unit tests (danube-schema, danube-client, danube-raft, danube-persistent-storage)

If any test fails, broker logs from all 3 nodes are printed for debugging.


Makefile brokers:

Terminal window
# View logs for a specific broker
cat temp/broker_6650.log
# Follow logs in real-time
tail -f temp/broker_6650.log

Docker Compose:

Terminal window
docker-compose logs -f broker1

danube/
├── config/ # Broker and test configuration files
│ ├── danube_broker.yml # Default broker config
│ ├── danube_broker_secure.yml # Secure config (TLS + JWT)
│ ├── edge.yaml # Edge broker config
│ └── for_tests/ # Test-specific configs
├── danube-broker/ # Broker binary and integration tests
├── danube-admin/ # Admin CLI and server
├── danube-cli/ # Client CLI (produce/consume)
├── danube-client/ # Client library (Rust SDK)
├── danube-core/ # Shared types and protobuf definitions
├── danube-edge/ # Edge broker (MQTT gateway)
├── danube-persistent-storage/ # WAL, durable segments, storage backends
├── danube-raft/ # Embedded Raft consensus
├── danube-schema/ # Schema Registry logic
├── docker/ # Docker Compose setups
│ ├── quickstart/
│ ├── with-ui/
│ ├── with-cloud-storage/
│ └── local-development/ # Build-from-source setup
├── Makefile # Development cluster management
└── .github/workflows/ # CI pipelines