Development Workflow for UTPM

November 15, 2025 · View on GitHub

This document describes the development workflow and tooling for UTPM contributors.

Quick Reference

Daily Development

# Format code
just fmt

# Check your code
just check

# Run tests
just test

# Run all CI checks locally
just ci

# Auto-fix issues
just fix

First-Time Setup

# Install tools (if not already installed)
cargo install just          # Command runner
cargo install cargo-watch   # Watch for changes (optional)
cargo install cargo-audit   # Security audits (optional)

# Setup git hooks
just setup-hooks

Code Quality Standards

1. Formatting (rustfmt)

All code must be formatted with rustfmt using the project's configuration.

Configuration: rustfmt.toml

Run:

cargo fmt --all
# Or
just fmt

Check:

cargo fmt --all -- --check
# Or
just fmt-check

Editor Integration:

  • VS Code: Install "rust-analyzer" extension, enable "Format on Save"
  • IntelliJ/CLion: Settings → Editor → Code Style → Rust → Rustfmt
  • Vim/Neovim: Use rust.vim or rust-tools.nvim

2. Linting (clippy)

All code must pass Clippy with no warnings.

Configuration: clippy.toml

Run:

cargo clippy --all-targets --all-features -- -D warnings
# Or
just clippy

Auto-fix:

cargo clippy --all-targets --all-features --fix --allow-dirty
# Or
just clippy-fix

Common Clippy Warnings:

  • Unused imports → Remove them
  • Unnecessary clone() → Review if clone is needed
  • Complex types → Consider type aliases
  • Missing documentation → Add doc comments for public items

3. Testing

All new features and bug fixes must include tests.

Run tests:

cargo test --all-features
# Or
just test

Test with output:

cargo test --all-features -- --nocapture
# Or
just test-verbose

Test specific module:

cargo test --test test_name
cargo test module_name::test_function

For comprehensive testing documentation, see Testing Guide:

  • Test structure and categories (60+ tests)
  • Test helpers and utilities
  • Running unit, command, and integration tests
  • Writing new tests
  • Debugging and troubleshooting

Git Hooks

The project provides optional git hooks to automatically check code quality before commits.

Install Hooks

just setup-hooks

This creates a pre-commit hook that:

  1. Checks formatting
  2. Runs Clippy
  3. Runs tests

If any check fails, the commit is aborted.

Remove Hooks

just remove-hooks

Bypass Hooks (Emergency Only)

git commit --no-verify

⚠️ Only use this in emergencies! Your PR will still need to pass CI checks.

Continuous Integration (CI)

All pull requests must pass CI checks before merging.

CI Checks

  1. Formatting: cargo fmt --check
  2. Linting: cargo clippy -- -D warnings
  3. Tests: cargo test (on Ubuntu and Windows)
  4. Documentation: cargo doc
  5. MSRV: Minimum Supported Rust Version check

Running CI Checks Locally

just ci

This runs all checks that CI will run, allowing you to catch issues before pushing.

Common Workflows

Adding a New Feature

  1. Create a branch:

    git checkout -b feature/my-feature
    
  2. Implement your feature

  3. Add tests

  4. Format and fix:

    just fix
    
  5. Run all checks:

    just ci
    
  6. Commit:

    git commit -m "feat: add my feature"
    
  7. Push and create PR

Fixing a Bug

  1. Create a branch:

    git checkout -b fix/issue-123
    
  2. Write a failing test that reproduces the bug

  3. Fix the bug

  4. Verify the test passes

  5. Format and check:

    just fix
    just ci
    
  6. Commit:

    git commit -m "fix: resolve issue #123"
    

Refactoring

  1. Ensure all tests pass before starting:

    just test
    
  2. Make your changes incrementally

  3. Run tests frequently:

    just test
    
  4. Before committing:

    just ci
    

Troubleshooting

Formatting Conflicts

If rustfmt changes conflict with your code style preferences:

  1. Check if the change improves readability
  2. If not, discuss in a PR comment
  3. Never commit unformatted code

Clippy False Positives

If Clippy raises a false positive:

  1. Try to refactor to satisfy Clippy (usually improves code)
  2. If refactoring makes code worse, use #[allow(clippy::lint_name)]
  3. Add a comment explaining why the lint is allowed

Example:

// Clippy suggests using `if let`, but match is clearer here for all cases
#[allow(clippy::single_match)]
match value {
    Some(x) => process(x),
    None => (),
}

Test Failures

If tests fail:

  1. Check if you broke existing functionality
  2. Update tests if behavior changed intentionally
  3. Never disable tests without good reason

CI Failures

If CI fails but local checks pass:

  1. Ensure you're using the correct Rust version
  2. Pull latest changes: git pull origin main
  3. Rebase your branch: git rebase main
  4. Re-run checks: just ci

Additional Tools

cargo-watch

Watch for file changes and run commands automatically:

cargo install cargo-watch

# Watch and run checks
just watch

cargo-audit

Check for security vulnerabilities:

cargo install cargo-audit

# Run audit
just audit

Questions?