Ever wondered how professional Rust projects are organized? This guide will walk you through setting up a production-quality Rust project from scratch, focusing on project management, testing, and automation rather than code.
Perfect for:
- 🌱 Beginners starting their first serious Rust project
- 👥 Developers joining an existing team
- 🚀 Anyone wanting to learn professional development workflows
🎯 What You'll Learn
By the end, you'll have:
- ✅ Professional project structure
- ✅ Git Flow workflow (develop/main branches)
- ✅ Automated testing with GitHub Actions
- ✅ Code quality checks (formatting, linting)
- ✅ Pull request templates
- ✅ Issue tracking setup
- ✅ Documentation automation
Time required: ~30 minutes
Prerequisite: Rust and Git installed
📚 Table of Contents
- Project Setup (5 min)
- GitHub Repository (5 min)
- Documentation Files (5 min)
- CI/CD Pipeline (10 min)
- Git Flow Workflow (5 min)
- Your First Feature (Bonus)
Part 1: Local Project Setup
Step 1.1: Create the Project
We'll create a simple calculator library as our example:
# Create new library
cargo new --lib my-calculator
cd my-calculator
# Verify it works
cargo build
cargo test
Expected output:
Compiling my-calculator v0.1.0
Finished dev [unoptimized + debuginfo]
Step 1.2: Configure Cargo.toml
This is your project's manifest. Update it to be publication-ready:
[package]
name = "my-calculator"
version = "0.1.0"
edition = "2021"
rust-version = "1.70.0" # Minimum Rust version
authors = ["Your Name <your.email@example.com>"]
license = "MIT OR Apache-2.0"
description = "A simple calculator library for learning Rust project setup"
documentation = "https://docs.rs/my-calculator"
homepage = "https://github.com/yourusername/my-calculator"
repository = "https://github.com/yourusername/my-calculator"
readme = "README.md"
keywords = ["calculator", "math", "example"]
categories = ["mathematics"]
[dependencies]
# No dependencies yet - keeping it simple!
[dev-dependencies]
# For testing and development
What each field means:
-
edition: Rust language edition (use 2021) -
rust-version: Minimum supported Rust version (MSRV) -
authors: You! (shows on crates.io) -
license: Legal terms (dual license is standard in Rust) -
keywords: Help people find your crate -
categories: Classification on crates.io
Step 1.3: Create Directory Structure
# Create all necessary directories
mkdir -p src/lib
mkdir -p tests
mkdir -p examples
mkdir -p benches
mkdir -p .github/workflows
Directory purpose:
my-calculator/
├── src/ # Source code
│ └── lib/ # Library modules
├── tests/ # Integration tests
├── examples/ # Usage examples
├── benches/ # Performance benchmarks
└── .github/ # GitHub configuration
└── workflows/ # CI/CD automation
Step 1.4: Write Simple Code
Keep it minimal - we're focusing on setup, not features:
src/lib.rs:
//! A simple calculator library
//!
//! This crate demonstrates professional Rust project setup.
/// Add two numbers
///
/// # Examples
///
///
/// use my_calculator::add;
/// assert_eq!(add(2, 2), 4);
///
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
/// Subtract two numbers
pub fn subtract(a: i32, b: i32) -> i32 {
a - b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
assert_eq!(add(2, 2), 4);
assert_eq!(add(-1, 1), 0);
}
#[test]
fn test_subtract() {
assert_eq!(subtract(5, 3), 2);
assert_eq!(subtract(0, 5), -5);
}
}
Key practices shown:
- ✅ Documentation comments (
///) - ✅ Module documentation (
//!) - ✅ Doc tests (examples in comments)
- ✅ Unit tests in same file
Test it:
cargo test
cargo doc --open # Opens documentation in browser
Part 2: GitHub Setup
Step 2.1: Initialize Git
# Initialize repository
git init
# Create .gitignore
cat > .gitignore << 'EOF'
# Rust
/target/
**/*.rs.bk
Cargo.lock
# IDE
.idea/
.vscode/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# Testing
*.log
EOF
# Initial commit
git add .
git commit -m "Initial commit: project structure"
Step 2.2: Create GitHub Repository
On GitHub (https://github.com/new):
- Click "New repository"
-
Name:
my-calculator - Description: "A simple calculator for learning Rust project setup"
- Public repository
- DO NOT initialize with README (we have one)
- Click "Create repository"
Step 2.3: Connect Local to GitHub
# Add remote (replace with your username!)
git remote add origin https://github.com/YOUR_USERNAME/my-calculator.git
# Verify
git remote -v
# Push to GitHub
git branch -M main
git push -u origin main
Verify: Visit your repo on GitHub - you should see your code!
Part 3: Documentation
Professional projects need clear documentation. Let's add the essentials:
Step 3.1: README.md
cat > README.md << 'EOF'
# my-calculator
[](https://crates.io/crates/my-calculator)
[](https://docs.rs/my-calculator)
[](https://github.com/YOUR_USERNAME/my-calculator/actions)
EOF
A simple calculator library demonstrating professional Rust project setup.
Quick Start
use my_calculator::{add, subtract};
let sum = add(2, 3); // 5
let diff = subtract(10, 4); // 6
Installation
Add to your Cargo.toml:
[dependencies]
my-calculator = "0.1"
Documentation
Contributing
See CONTRIBUTING.md
License
Licensed under either of Apache License 2.0 or MIT license at your option.
Replace YOUR_USERNAME with your GitHub username!
Step 3.2: LICENSE Files
# MIT License
cat > LICENSE-MIT << 'EOF'
MIT License
Copyright (c) 2025 Your Name
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
EOF
# Apache License (download)
curl -o LICENSE-APACHE https://www.apache.org/licenses/LICENSE-2.0.txt
Step 3.3: CONTRIBUTING.md
cat > CONTRIBUTING.md << 'EOF'
# Contributing
Thanks for your interest! 🎉
## How to Contribute
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/my-feature`
3. Make your changes
4. Add tests
5. Run tests: `cargo test`
6. Format code: `cargo fmt`
7. Run linter: `cargo clippy`
8. Commit: `git commit -m "feat: add my feature"`
9. Push: `git push origin feature/my-feature`
10. Create a Pull Request
## Code Style
- Follow Rust standard style (`cargo fmt`)
- No clippy warnings (`cargo clippy`)
- Add tests for new features
- Document public APIs
## Questions?
Open an issue or start a discussion!
EOF
Step 3.4: CHANGELOG.md
cat > CHANGELOG.md << 'EOF'
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
### Added
- Initial project setup
- Basic add and subtract functions
## [0.1.0] - TBD
First release!
EOF
Step 3.5: Commit Documentation
git add .
git commit -m "docs: add README, LICENSE, and CONTRIBUTING"
git push
Part 4: CI/CD Setup
This is where the magic happens! Automated testing on every change.
Step 4.1: Create GitHub Actions Workflow
cat > .github/workflows/ci.yml << 'EOF'
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
test:
name: Test
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
rust: [stable, beta]
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- name: Cache dependencies
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
fmt:
name: Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- name: Check formatting
run: cargo fmt --all -- --check
clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- name: Run clippy
run: cargo clippy --all-targets --all-features -- -D warnings
docs:
name: Documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Build documentation
run: cargo doc --no-deps --all-features
EOF
What this does:
| Job | Purpose | Runs On |
|---|---|---|
| test | Run tests | Ubuntu & macOS, stable & beta Rust |
| fmt | Check formatting | Ubuntu, stable |
| clippy | Lint code | Ubuntu, stable |
| docs | Build documentation | Ubuntu, stable |
Total: 7 checks on every PR!
Step 4.2: Test CI Locally First
Before pushing, verify everything passes:
# Run all checks locally
cargo test
cargo fmt --check
cargo clippy -- -D warnings
cargo doc --no-deps
All passing? Great! Push it:
git add .github/workflows/ci.yml
git commit -m "ci: add GitHub Actions workflow"
git push
Step 4.3: Verify CI on GitHub
- Go to:
https://github.com/YOUR_USERNAME/my-calculator/actions - You should see your workflow running
- Wait ~2-5 minutes for all checks to pass ✅
Troubleshooting:
- ❌ If CI fails, click on the failed job
- Read the error log
- Fix locally
- Push again
Part 5: Git Flow Workflow
We'll use two branches for organized development:
main (production releases)
↑
develop (active development)
↑
feature/* (your work)
Step 5.1: Create Develop Branch
# Create develop from main
git checkout -b develop
git push -u origin develop
Step 5.2: Set Develop as Default on GitHub
- Go to:
Settings→Branches - Change default branch to
develop - Click "Update"
Why? New PRs will automatically target develop.
Step 5.3: Add Branch Protection (Optional but Recommended)
Protect your main branch:
- Go to:
Settings→Branches→Add rule - Branch name:
main - Enable:
- ✅ Require pull request before merging
- ✅ Require status checks to pass (select: Test, Format, Clippy, Docs)
- Save
This prevents accidental pushes to main!
Step 5.4: Add Issue Templates
Help contributors report issues properly:
mkdir -p .github/ISSUE_TEMPLATE
cat > .github/ISSUE_TEMPLATE/bug_report.md << 'EOF'
---
name: Bug Report
about: Report a bug
title: '[BUG] '
labels: bug
---
**Describe the bug**
Clear description of the bug.
**To Reproduce**
Steps to reproduce:
1. ...
2. ...
**Expected behavior**
What should happen.
**Environment**
- OS: [e.g., Ubuntu 22.04]
- Rust version: [e.g., 1.75.0]
EOF
cat > .github/ISSUE_TEMPLATE/feature_request.md << 'EOF'
---
name: Feature Request
about: Suggest a feature
title: '[FEATURE] '
labels: enhancement
---
**Problem**
What problem does this solve?
**Solution**
Describe the feature you want.
**Example**
// Show how it would be used
EOF
Step 5.5: Add PR Template
cat > .github/PULL_REQUEST_TEMPLATE.md << 'EOF'
## Description
Brief description of changes.
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
## Checklist
- [ ] Tests added/updated
- [ ] `cargo fmt` run
- [ ] `cargo clippy` passing
- [ ] All tests passing
- [ ] Documentation updated
## Related Issues
Closes #(issue)
EOF
Step 5.6: Commit GitHub Templates
git add .github/
git commit -m "feat: add issue and PR templates"
git push origin develop
Part 6: First Feature Workflow
Let's add a feature using the proper workflow!
Step 6.1: Create Feature Branch
# Always start from develop
git checkout develop
git pull origin develop
# Create feature branch
git checkout -b feature/multiply
Step 6.2: Implement Feature
Edit src/lib.rs, add:
/// Multiply two numbers
///
/// # Examples
///
///
/// use my_calculator::multiply;
/// assert_eq!(multiply(3, 4), 12);
///
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}
#[cfg(test)]
mod tests {
use super::*;
// ... existing tests ...
#[test]
fn test_multiply() {
assert_eq!(multiply(3, 4), 12);
assert_eq!(multiply(0, 5), 0);
assert_eq!(multiply(-2, 3), -6);
}
}
Step 6.3: Test Locally
# Run all quality checks
cargo test
cargo fmt
cargo clippy -- -D warnings
cargo doc --open
All green? Continue!
Step 6.4: Commit and Push
git add src/lib.rs
git commit -m "feat: add multiply function
- Add multiply function with doc tests
- Add comprehensive unit tests
- Update documentation"
git push -u origin feature/multiply
Step 6.5: Create Pull Request
- Go to your GitHub repo
- Click "Compare & pull request" (banner appears after push)
-
Base:
develop← Compare:feature/multiply - Fill in the PR template
- Click "Create pull request"
Step 6.6: Wait for CI
GitHub Actions will automatically:
- ✅ Run tests on Ubuntu & macOS
- ✅ Check formatting
- ✅ Run clippy lints
- ✅ Build documentation
All checks must pass! ✨
Step 6.7: Merge PR
Once CI passes:
- Click "Squash and merge"
- Confirm merge
- Delete branch (GitHub will offer this)
Step 6.8: Update Local
# Switch to develop
git checkout develop
# Pull merged changes
git pull origin develop
# Delete local feature branch
git branch -d feature/multiply
# Verify
git log --oneline -3
🎓 What You've Learned
Project Management
- ✅ Professional Cargo.toml structure
- ✅ Directory organization
- ✅ Documentation best practices
- ✅ License selection
Git Workflow
- ✅ Git Flow (develop/main branches)
- ✅ Feature branch workflow
- ✅ Pull requests
- ✅ Branch protection
Automation
- ✅ GitHub Actions CI/CD
- ✅ Multi-platform testing
- ✅ Automated code quality checks
- ✅ Documentation building
Community
- ✅ Issue templates
- ✅ PR templates
- ✅ Contributing guidelines
- ✅ Changelog maintenance
📋 Quick Reference Checklist
For every new project:
# 1. Create project
cargo new --lib my-project
cd my-project
# 2. Setup structure
mkdir -p src/lib tests examples .github/workflows
# 3. Initialize git
git init
# Add .gitignore
# 4. Create GitHub repo
# (on GitHub website)
# 5. Connect and push
git remote add origin https://github.com/user/repo.git
git push -u origin main
# 6. Add documentation
# - README.md
# - LICENSE-MIT, LICENSE-APACHE
# - CONTRIBUTING.md
# - CHANGELOG.md
# 7. Add CI/CD
# - .github/workflows/ci.yml
# 8. Setup Git Flow
git checkout -b develop
git push -u origin develop
# Set develop as default on GitHub
# 9. Add templates
# - .github/ISSUE_TEMPLATE/
# - .github/PULL_REQUEST_TEMPLATE.md
# 10. Start developing!
git checkout -b feature/my-feature
🚀 Going Further
Additions for Production Projects
# Add to .github/workflows/ci.yml
- name: Security audit
run: |
cargo install cargo-audit
cargo audit
-
Dependency Updates
- Use Dependabot
- Auto-updates dependencies via PRs
Release Automation
# .github/workflows/release.yml
on:
push:
tags:
- 'v*'
# Automatically publish to crates.io
-
Benchmarking
- Add criterion
- Track performance over time
💡 Common Mistakes to Avoid
❌ Don't:
- Push directly to
mainordevelop - Merge without CI passing
- Skip writing tests
- Forget to format code
- Ignore clippy warnings
✅ Do:
- Always use feature branches
- Wait for CI before merging
- Write tests for new features
- Run
cargo fmtbefore committing - Fix all clippy warnings
🎯 Next Steps
Now that you have a solid foundation:
- Add more features using the workflow
- Publish to crates.io when ready
- Enable GitHub Discussions for community
- Add badges to README
- Write a blog post about your project!
📚 Resources
💬 Questions?
Did this guide help you? Have suggestions? Drop a comment below!
Found this useful? Give it a ❤️ and share with fellow Rustaceans!
Top comments (0)