Thank you for your interest in contributing to exarch! This document provides guidelines and instructions for contributing.
Please be respectful and constructive in all interactions. We welcome contributors of all experience levels.
- Rust 1.99.1 or later (Edition 2024)
- Python 3.11+ (for Python bindings development)
- Node.js 20+ (for Node.js bindings development)
- cargo-nextest for running tests
- maturin for Python bindings
- napi-rs for Node.js bindings
# Clone the repository
git clone https://github.com/bug-ops/exarch.git
cd exarch
# Install Rust toolchain
rustup update stable
rustup component add rustfmt clippy
# Install development tools
cargo install cargo-nextest cargo-deny cargo-llvm-cov
# Build all crates
cargo build --workspace
# Run tests
cargo nextest run --workspacePython bindings:
cd crates/exarch-python
pip install maturin
maturin develop
pytest tests/Node.js bindings:
cd crates/exarch-node
npm install
npm run build
npm testUse descriptive branch names:
feature/<description>- new featuresfix/<description>- bug fixesdocs/<description>- documentation changesrefactor/<description>- code refactoringperf/<description>- performance improvements
Follow the Conventional Commits specification:
<type>(<scope>): <subject>
<body>
Types:
feat- new featurefix- bug fixdocs- documentationrefactor- code refactoringperf- performance improvementtest- adding testschore- maintenance tasks
Examples:
feat(core): add 7z format support
fix(python): handle unicode paths correctly
docs: update installation instructions
perf(core): optimize directory caching
Run all checks before submitting a PR:
# Format code
cargo +nightly fmt --all
# Run clippy
cargo clippy --all-targets --all-features --workspace -- -D warnings
# Check documentation
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features --workspace
# Run tests
cargo nextest run --all-features --workspace
# Security audit
cargo deny checkQuick alias:
alias exarch-check='cargo +nightly fmt --all -- --check && cargo clippy --all-targets --all-features --workspace -- -D warnings && cargo nextest run --all-features --workspace'# All tests
cargo nextest run --workspace
# Specific crate
cargo nextest run -p exarch-core
# Specific test
cargo nextest run -p exarch-core test_name
# With coverage
cargo llvm-cov nextest --all-features --workspace --htmlCI builds exarch-core and the CLI for wasm32-wasip1 and runs a smoke test
under wasmtime (.github/scripts/wasi-smoke.sh). Run the same steps locally
when a change touches I/O or a C codec (liblzma is built from
source and linked statically):
rustup target add wasm32-wasip1
cargo check -p exarch-core --all-features --target wasm32-wasip1
cargo build -p exarch-cli --target wasm32-wasip1
bash .github/scripts/wasi-smoke.sh target/wasm32-wasip1/debug/exarch.wasmThe C codecs need a WASI libc and llvm-ar; the wasm job in
.github/workflows/ci.yml shows the CFLAGS_wasm32_wasip1 and
AR_wasm32_wasip1 settings it uses.
Seven cargo-fuzz targets live in fuzz/ (tar, zip, sevenz,
safe_path, extract_archive, sink, detect). Changes to archive parsers,
extract_to_sink or ArchiveReader::detect must keep cargo +nightly check --manifest-path fuzz/Cargo.toml --all-targets passing. See
fuzz/README.md for running targets and turning a crash into
a regression test.
7z fixtures in tests/fixtures/ are generated, not hand-edited:
tests/fixtures/generate_7z_fixtures.shneedsp7zip(7z); thesymlink-snl.7zstep also needs7zzfrom 7-Zip 26.05.tests/fixtures/generate_7z_p7zip_fixture.shneeds Docker; it buildssymlink-p7zip.7zandsymlink-p7zip-dir.7zwith a pinned p7zip 16.02.
- Place unit tests in the same file as the code being tested
- Place integration tests in
tests/directory - Security validators must have 100% test coverage
- Overall project coverage target: 80%+
- Write
assert_matches!(value, pattern), neverassert!(matches!(value, pattern)): the CI Format Check job rejects the latter in every tracked.rsfile, andcargo fmtandclippydo not catch it
When fixing security issues, add a regression test in
crates/exarch-core/tests/security/:
#[test]
fn test_cve_xxxx_description() {
// Test that the vulnerability is fixed
}- Follow the Rust API Guidelines
- Use
thiserrorfor error types (notanyhowin library code) - Prefer
&strand&PathoverStringandPathBufin function parameters - Use type-driven security (e.g.,
SafePathfor validated paths)
- Minimal unsafe code:
unsafeis denied by lint workspace-wide and confined to documented FFI sites (the destination access check on Unix, NT calls and token, SID and DACL calls on Windows inexarch-core; onesigactionquery inexarch-clion Unix) - Default-deny security model
- Validate all external input
- Document security implications in comments
- Avoid allocations in hot paths
- Use
#[inline]for small, frequently called functions - Reuse buffers where possible
- Run benchmarks for performance-critical changes
# Run all benchmarks
./benches/run_all.sh
# Quick run
./benches/run_all.sh --quick
# Rust only
cargo bench -p exarch-core --features testing- Create a branch from
main - Make your changes following the guidelines above
- Run all checks (
exarch-check) - Push your branch and create a PR
- Fill in the PR template with details
- Wait for CI to pass
- Address review feedback
- Squash and merge when approved
- All CI checks pass
- Tests added for new functionality
- Documentation updated if needed
- CHANGELOG.md updated for user-facing changes
- No new clippy warnings
Releases are managed by maintainers. The process:
- Update version in
Cargo.toml(workspace) - Update
CHANGELOG.md - Update
package.jsonandpyproject.toml - Create a git tag:
git tag -a v0.x.y -m "Release v0.x.y" - Push tag:
git push origin v0.x.y - CI automatically publishes to crates.io, PyPI, and npm
- Issues: GitHub Issues
- Discussions: GitHub Discussions
By contributing, you agree that your contributions will be licensed under the same terms as the project (MIT OR Apache-2.0).