DEV Community

Cover image for Production-Ready Rust Project Setup: From Zero to CI/CD
Ajit Kumar
Ajit Kumar

Posted on

Production-Ready Rust Project Setup: From Zero to CI/CD

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

  1. Project Setup (5 min)
  2. GitHub Repository (5 min)
  3. Documentation Files (5 min)
  4. CI/CD Pipeline (10 min)
  5. Git Flow Workflow (5 min)
  6. 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
Enter fullscreen mode Exit fullscreen mode

Expected output:

   Compiling my-calculator v0.1.0
    Finished dev [unoptimized + debuginfo]
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Step 2.2: Create GitHub Repository

On GitHub (https://github.com/new):

  1. Click "New repository"
  2. Name: my-calculator
  3. Description: "A simple calculator for learning Rust project setup"
  4. Public repository
  5. DO NOT initialize with README (we have one)
  6. 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
Enter fullscreen mode Exit fullscreen mode

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

[![Crates.io](https://img.shields.io/crates/v/my-calculator.svg)](https://crates.io/crates/my-calculator)
[![Documentation](https://docs.rs/my-calculator/badge.svg)](https://docs.rs/my-calculator)
[![Build Status](https://github.com/YOUR_USERNAME/my-calculator/workflows/CI/badge.svg)](https://github.com/YOUR_USERNAME/my-calculator/actions)
EOF
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Installation

Add to your Cargo.toml:

[dependencies]
my-calculator = "0.1"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Step 3.5: Commit Documentation

git add .
git commit -m "docs: add README, LICENSE, and CONTRIBUTING"
git push
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

All passing? Great! Push it:

git add .github/workflows/ci.yml
git commit -m "ci: add GitHub Actions workflow"
git push
Enter fullscreen mode Exit fullscreen mode

Step 4.3: Verify CI on GitHub

  1. Go to: https://github.com/YOUR_USERNAME/my-calculator/actions
  2. You should see your workflow running
  3. 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)
Enter fullscreen mode Exit fullscreen mode

Step 5.1: Create Develop Branch

# Create develop from main
git checkout -b develop
git push -u origin develop
Enter fullscreen mode Exit fullscreen mode

Step 5.2: Set Develop as Default on GitHub

  1. Go to: SettingsBranches
  2. Change default branch to develop
  3. Click "Update"

Why? New PRs will automatically target develop.

Step 5.3: Add Branch Protection (Optional but Recommended)

Protect your main branch:

  1. Go to: SettingsBranchesAdd rule
  2. Branch name: main
  3. Enable:
    • ✅ Require pull request before merging
    • ✅ Require status checks to pass (select: Test, Format, Clippy, Docs)
  4. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Step 5.6: Commit GitHub Templates

git add .github/
git commit -m "feat: add issue and PR templates"
git push origin develop
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 6.3: Test Locally

# Run all quality checks
cargo test
cargo fmt
cargo clippy -- -D warnings
cargo doc --open
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Step 6.5: Create Pull Request

  1. Go to your GitHub repo
  2. Click "Compare & pull request" (banner appears after push)
  3. Base: developCompare: feature/multiply
  4. Fill in the PR template
  5. 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:

  1. Click "Squash and merge"
  2. Confirm merge
  3. 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
Enter fullscreen mode Exit fullscreen mode

🎓 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
Enter fullscreen mode Exit fullscreen mode

🚀 Going Further

Additions for Production Projects

  1. Code Coverage

  2. Security Auditing

   # Add to .github/workflows/ci.yml
   - name: Security audit
     run: |
       cargo install cargo-audit
       cargo audit
Enter fullscreen mode Exit fullscreen mode
  1. Dependency Updates

    • Use Dependabot
    • Auto-updates dependencies via PRs
  2. Release Automation

   # .github/workflows/release.yml
   on:
     push:
       tags:
         - 'v*'
   # Automatically publish to crates.io
Enter fullscreen mode Exit fullscreen mode
  1. Benchmarking

💡 Common Mistakes to Avoid

Don't:

  • Push directly to main or develop
  • 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 fmt before committing
  • Fix all clippy warnings

🎯 Next Steps

Now that you have a solid foundation:

  1. Add more features using the workflow
  2. Publish to crates.io when ready
  3. Enable GitHub Discussions for community
  4. Add badges to README
  5. 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!

rust #github #cicd #beginners #tutorial #devops #programming


Top comments (0)