# How to contribute
So, you've decided to contribute, that's great!
You can use this document to figure out how and where to start.
## Getting started
- Make sure you have a [GitHub account](https://github.com/join).
- Take a look at [existing issues](https://github.com/remysaissy/lorm/issues).
- If you need to create an issue:
- Make sure to clearly describe it.
- Including steps to reproduce when it is a bug.
- Include the version of LOrm used.
## Signing Your Commits
This repository requires signed commits. You can sign commits using **GPG**, **SSH**, or **S/MIME** — whichever method you prefer.
For setup instructions, see the official GitHub documentation:
- [**Signing commits**](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits) — how to sign your commits
- [**Telling Git about your signing key**](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key) — configuring Git to use your key
- [**Adding a GPG key to your GitHub account**](https://docs.github.com/en/authentication/managing-commit-signature-verification/adding-a-gpg-key-to-your-github-account) — so GitHub marks your commits as "Verified"
- [**Adding a SSH signing key to your GitHub account**](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification#ssh-commit-signature-verification) — alternative to GPG
### Quick Setup (GPG)
```bash
# Enable automatic signing for this repository
git config --local commit.gpgsign true
git config --local tag.gpgsign true
# If you have multiple GPG keys, specify which one to use
git config --local user.signingkey YOUR_KEY_ID
```
> **Tip**: Use `--global` instead of `--local` to enable signing for all your repositories.
### Verifying Your Setup
```bash
# View signature details in the git log
git log --show-signature -1
```
Make a test commit and verify that `git log --show-signature` shows a valid signature.
### CI Verification
All pull requests are automatically checked for valid commit signatures. Unsigned commits will cause the check to fail.
## Making changes
- Fork the repository on GitHub.
- Create a branch on your fork.
- You can usually base it on the `main` branch.
- Make sure not to commit directly to `main`.
- Make commits of logical and atomic units.
- **Sign all your commits** (see [Signing Your Commits](#signing-your-commits) above).
- **Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)** for all commit messages. This is enforced by CI on pull requests.
- Make sure you have added the necessary tests for your changes.
- Push your changes to a topic branch in your fork of the repository.
- Submit a pull request to the original repository.
### Commit Message Format
All commits must follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification:
```
<type>(<optional scope>): <description>
[optional body]
[optional footer(s)]
```
Common types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`, `ci`.
Examples:
```
feat(query): add DISTINCT support to select builder
fix: prevent panic on empty WHERE clause
docs: update README with HAVING examples
chore(deps): bump sqlx to 0.8.3
```
This format is used by [git-cliff](https://git-cliff.org/) to auto-generate the changelog.
## What to work on
We try to mark issues with a suggested level of experience (in Rust/SQL).
Where possible we try to spell out how to go about implementing the feature.
To start with, check out:
- Issues labeled as ["good first issue"](https://github.com/remysaissy/lorm/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
- Issues labeled as ["Easy"](https://github.com/remysaissy/lorm/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy).
Additionally, it's always good to work on improving/adding examples and documentation.
## Development Setup
### Prerequisites
- Rust 1.75 or later (Edition 2024)
- SQLite (for running tests)
- cargo-expand (optional, for inspecting generated code): `cargo install cargo-expand`
- act (optional, for running CI tests locally): `brew install act` (macOS) or see [act installation](https://github.com/nektos/act)
- Docker (required if using act)
### Building the Project
```bash
# Clone the repository
git clone https://github.com/remysaissy/lorm.git
cd lorm
# Build all workspace members
cargo build
# Run tests
cargo test
# Build documentation
cargo doc --open
```
### Running Examples
```bash
# Run a specific example (from workspace root)
cargo run --example basic_crud -p lorm
# List all examples
ls examples/
```
### Testing Changes
Tests are in `lorm/tests/`. When adding new features, add corresponding tests following the existing patterns in `lorm/tests/main.rs`.
See [Running Tests](#running-tests) for all test commands and coverage details.
### Inspecting Generated Code
To see what code Lorm generates, use `cargo-expand`:
```bash
# Install cargo-expand
cargo install cargo-expand
# Expand macros in tests
cd lorm
cargo expand --test main
```
This is helpful for:
- Understanding how the macro works
- Debugging macro issues
- Verifying generated code correctness
### Code Style
- Follow standard Rust formatting: `cargo fmt`
- Ensure code passes clippy: `cargo clippy -- -D warnings`
- Add documentation comments for public APIs
- Keep generated code clean and readable
### Documentation
When contributing:
- Update README.md if adding user-facing features
- Add rustdoc comments for public APIs
- Create examples for significant features
- Update CHANGELOG.md following [Keep a Changelog](https://keepachangelog.com/) format
## Communication
If you're unsure about your contribution or simply want to ask a question about anything, you can:
- Discuss something directly in the [Github issue](https://github.com/remysaissy/lorm/issues).
## Running Tests
### Unit Tests
```bash
cargo test # Run all tests
cargo test test_user_is_created # Run a specific test
cargo test -- --nocapture # Run with stdout output
```
### Using the Helper Scripts
```bash
./test.sh # Run unit tests (default features)
./test.sh --all-features # Run with all feature flags
./format.sh --check # Check formatting (rustfmt)
./format.sh --fix # Auto-fix formatting
./check.sh # Run clippy with deny-warnings
./check.sh --all-features
```
### Code Coverage
```bash
cargo install cargo-llvm-cov # One-time setup
./coverage.sh # HTML report (opens in browser)
./coverage.sh --lcov # LCOV report for CI
./coverage.sh --text # Terminal summary
./coverage.sh --check-thresholds # Verify ≥ 80% coverage
```
CI enforces **≥ 80%** line, region, and function coverage. PRs that reduce coverage below these thresholds will fail.
## Bumping the Version
To bump the version **without** performing a full release (e.g., to prepare a version bump commit):
```bash
./bump-version.sh --revision # 0.2.2 → 0.2.3
./bump-version.sh --minor # 0.2.2 → 0.3.0
./bump-version.sh --major # 0.2.2 → 1.0.0
```
This updates `Cargo.toml` (workspace version) and regenerates `CHANGELOG.md` via [git-cliff](https://git-cliff.org/), then stages both files. You still need to commit, tag, and push manually.
**Prerequisite**: `cargo install git-cliff`
## Releasing
To perform a full release (version bump → changelog → commit → tag → push → publish → GitHub release):
```bash
./release.sh --revision # Patch release
./release.sh --minor # Minor release
./release.sh --major # Major release
./release.sh --dry-run --revision # Preview without side effects
```
The release script performs these steps in order:
1. Runs `cargo test --workspace` to verify nothing is broken
2. Bumps the version in `Cargo.toml`
3. Regenerates `CHANGELOG.md` with git-cliff
4. Creates a signed commit (`chore(release): prepare for vX.Y.Z`)
5. Creates an annotated tag (`vX.Y.Z`)
6. Pushes the commit and tag to `origin`
7. Publishes `lorm-macros` then `lorm` to crates.io (in dependency order)
8. Creates a GitHub release with the changelog as release notes
After the tag is pushed, the `release.yml` CI workflow runs automatically to verify the build and generate [GitHub Artifact Attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations) linking the crate packages to the specific commit and workflow that produced them.
**Prerequisites**: `git-cliff`, `gh` (GitHub CLI), `cargo login` or `CARGO_REGISTRY_TOKEN` env var.
Use `--dry-run` to validate everything locally (runs tests, bumps version, creates commit and tag) without pushing, publishing, or creating a release.
## Repository Rules
This repository enforces the following policies via GitHub branch protection and CI:
- **Signed commits required**: All commits pushed to `main` (and included in pull requests) must be cryptographically signed. See [Signing Your Commits](#signing-your-commits) for setup instructions.
- **CI must pass**: Format, clippy, tests, coverage (≥ 80%), and signature verification checks must all pass before merging.
- **Vigilant mode**: Repository maintainers use GitHub's vigilant mode, which marks all unsigned commits as "Unverified."
If you're a first-time contributor and need help setting up commit signing, feel free to open an issue — we're happy to help.
## Code of Conduct
Be respectful, constructive, and welcoming to all contributors.