Contributing
Prerequisites
- Rust 1.75.0+ (install via rustup)
- Docker 20.10+ (for integration and E2E tests)
protoc(Protocol Buffers compiler, for gRPC code generation)mdbook(for documentation:cargo install mdbook)cargo-deny(for license checks:cargo install cargo-deny)
Development Workflow
# Build everything
cargo build --workspace
# Type-check only (faster)
cargo check --workspace
# Format
cargo fmt --all
# Lint
cargo clippy --workspace --all-targets -- -D warnings
# Test
cargo test --workspace
# License check
cargo deny check licenses
Gitflow
This project uses strict gitflow. Every rule is non-negotiable.
Branch Model
main ───────────────────────────────── tagged releases only
└── develop ──────────────────────── integration branch
├── feature/GH-<#>-<desc> ── new work
├── fix/GH-<#>-<desc> ────── bug fixes
├── release/<version> ────── release prep
└── hotfix/GH-<#>-<desc> ── emergency fixes
Rules
- Never commit directly to
main. All changes reachmainthrough release branches. - All feature and fix branches merge to
developvia PR with squash merge. - Release branches merge to both
main(with tag) anddevelop. - Hotfix branches branch from
main, merge to bothmainanddevelop. - Delete branches after merge. No stale branches.
- No force pushes to
mainordevelop. - Rebase feature branches onto
developbefore merging.
Commit Format
<scope>: <imperative verb> <what> (#<issue>)
Scopes: common, nitro, edge, hive, workload, telemetry, oracle, fault, report, scenario, docgen, testenv, ci, docs, rfc
Examples:
nitro: add L1 monitor background poll loop (#83)
fault: fix auto-clear bug in FaultManager (#82)
docs: rewrite mdBook documentation (#89)
Every commit must reference a GitHub issue number.
GitHub Issues
No work happens without an issue. Every feature, bug fix, refactor, and documentation change requires an issue first.
- Title format:
[<scope>] <imperative description> - Required fields: description, acceptance criteria, labels
- Branch name:
feature/GH-<issue#>-<short-description> - PR closing keyword:
Closes #<issue#>
Code Conventions
Error Handling
thiserrorfor library errors,anyhowonly in binaries and tests.- Never
unwrap()in library code. - Never
expect()without a message explaining the invariant.
Async
tokioonly. Noasync-std.- Never
tokio::spawnwithout storing theJoinHandle. - No
sleepfor synchronization — use channels, barriers, orNotify.
Naming
- Crates:
gashammer-{name}inCargo.toml,gashammer_{name}as Rust modules. - No abbreviations in public APIs except:
tx,rpc,ws,config.
Visibility
- Default to
pub(crate). Onlypubitems that are part of the API contract.
Imports
Group in order, separated by blank lines:
std- External crates
- Workspace crates
crate/super/self
Testing
- Every public function gets a test.
#[tokio::test]for async tests. Neverblock_on.- Test names describe behavior:
test_feed_reconnects_after_disconnect. - No
#[allow(dead_code)]— delete dead code instead. - No
println!— usetracing.
License Header
Every .rs file must include:
#![allow(unused)]
fn main() {
// Copyright (c) 2025-present Don Johnson
// Licensed under the Business Source License 1.1 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://github.com/copyleftdev/gashammer/blob/main/LICENSE
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
}
Enforced by CI via scripts/check-license-headers.sh.