Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Contributing to rusta

Thanks for your interest in rusta. This document covers how to set up a development environment, the conventions the project follows, and how to get a change merged.

For bug reports, feature requests, and other support questions, see SUPPORT.md. For security vulnerabilities, see SECURITY.md — please do not file them as public issues.

Quick start

git clone https://github.com/pallewela/rusta.git
cd rusta
cargo build
cargo test

The integration tests under tests/ exercise the CLI surface end-to-end against stubbed tart/brew/ssh binaries, so they run on any platform that supports a Rust toolchain — you do not need an actual Tart install to develop.

How to submit a change

  1. Fork the repository on GitHub.
  2. Create a feature branch: git checkout -b feat/short-description.
  3. Make your changes. Run cargo build, cargo test, and cargo fmt before committing.
  4. Commit using Conventional Commits — the auto-generated CHANGELOG keys off the commit prefix:
    • feat: ... — new feature
    • fix: ... — bug fix
    • docs: ... — documentation only
    • test: ... — test-only change
    • ci: ... — CI/release pipeline change
    • refactor: ... — code change that neither fixes a bug nor adds a feature
    • chore: ... — anything else
  5. Push the branch and open a pull request against main.

What happens after you open a PR

  • CI runs on macOS arm64 (build, integration tests with coverage, cargo-deny advisories/licenses).
  • CodeQL analyzes the Rust source and the workflow YAMLs.
  • For PRs by the maintainer or by Dependabot, the auto-approve workflow approves the PR once CI passes and enables auto-merge. Squash-merge happens as soon as every required gate is green.
  • For PRs by external contributors, the workflow does not auto-approve. The maintainer will review by hand; expect a response within ~7 days. Mention @pallewela in the PR description if you need an earlier look.

After merge, the existing automation handles tagging, release notes, CHANGELOG update, GitHub Release with SBOM + SLSA provenance, crates.io publish, and the Homebrew tap bump.

Versioning & releases

  • Versioning scheme: Semantic Versioning 2.0.0 (semver.org) — MAJOR.MINOR.PATCH.
  • Release tags: every release is identified in version control by an annotated git tag named vMAJOR.MINOR.PATCH (e.g. v1.0.16). The tag set on main is the source of truth for the list of releases the project has ever cut — list them with git tag --list 'v*' --sort=-v:refname.
  • Publication channels for each tag:
    • A GitHub Release with the aarch64-apple-darwin tarball, a CycloneDX SBOM, and a Sigstore-signed SLSA provenance attestation.
    • A crates.io version of rusta-cli.
    • A Homebrew tap formula bump.
  • Tagging is fully automated. Maintainers do not create tags by hand. The Auto-tag workflow runs after CI succeeds on main and:
    1. Inspects the head commit message to pick the SemVer bump level — [bump:major] / BREAKING CHANGE → major; [bump:minor] → minor; default → patch; [skip release] → no tag.
    2. Regenerates CHANGELOG.md via git-cliff.
    3. Commits the updated CHANGELOG and pushes a new annotated tag pointing at that commit.
  • Tag immutability policy. Once pushed, release tags are considered immutable: they are not deleted, moved, or rewritten. The repository enforces this with a protect-tags ruleset on refs/tags/v* (deletion and non_fast_forward blocked). If a release contains a defect, the fix ships as a new patch release with an incremented tag, never as a rewritten old tag.

Requirements for acceptable contributions

This section uses RFC 2119 language. MUST items are hard requirements — CI enforces them and a PR cannot merge without satisfying every one. SHOULD items are expectations during review; deviating from one is fine if you have a reason.

MUST (enforced by CI)

  1. The change builds. cargo build --all-targets --locked succeeds on macos-latest (Apple Silicon).
  2. All tests pass. cargo llvm-cov --locked --lcov succeeds; CI uploads the lcov to Codecov.
  3. No new advisories or banned crates. cargo deny --locked check (advisories, licenses, bans, sources) exits clean. New dependencies must use a license on deny.toml’s allow-list — typically MIT / Apache-2.0 / BSD / ISC / Unicode / CDLA-Permissive. Copyleft licenses (GPL, AGPL, LGPL, MPL beyond what is already allowed) are not accepted.
  4. CodeQL passes. No new high-severity findings in the Rust source or workflow YAML.
  5. Conventional commit prefix. The PR’s commits use Conventional Commitsfeat:, fix:, docs:, test:, ci:, refactor:, chore:. [skip release] is reserved for the auto-tag CHANGELOG commit; do not use it manually.
  6. Verified signed commits. The main branch protection rule requires all incoming commits to be signed. Sign your commits with either a GPG or SSH key configured on your GitHub account, or rebase through the GitHub web UI which signs automatically.
  7. License agreement. Contributions are accepted under the MIT License only. By opening a PR you confirm that your contribution is yours to license under MIT.

SHOULD (review expectations)

  1. Tests covering the change. New features SHOULD ship with at least one integration test under tests/ exercising the new behaviour end-to-end. Bug fixes SHOULD ship with a regression test that fails on main and passes with the fix.
  2. No coverage regression. Codecov reports a delta on each PR. A small regression (a couple of percent on a non-critical path) is acceptable if justified in the PR description; large drops will be pushed back.
  3. cargo fmt applied. cargo fmt --check should produce no diff. CI does not currently fail on this but it is the de-facto project style.
  4. cargo clippy clean. Run cargo clippy --all-targets -- -W clippy::all and address findings in code you touched. Pre-existing warnings are not your problem.
  5. Edition 2021. Stick to the Cargo.toml edition setting. Edition bumps are a separate, coordinated change.
  6. Minimal dependencies. Prefer the standard library or an existing transitive dependency over pulling a new crate. Adding a new direct dependency SHOULD be justified in the PR description.
  7. Documentation in step with code. User-facing behaviour changes SHOULD update the relevant docs:
    • README.md for top-level Quick Start or command summary.
    • docs/src/commands.md (and adjacent pages) for the mdBook site. The CHANGELOG.md is regenerated automatically from conventional commits; do not edit it by hand.
  8. Comments explain why, not what. Default to no comments. Add one only when a non-obvious invariant, constraint, or workaround warrants it. Identifiers should carry the meaning.

Coding conventions

  • Rust edition 2021. The Cargo.toml edition field is the source of truth.
  • Tests. Integration tests live under tests/. Unit tests live next to the code under #[cfg(test)] mod tests {}.
  • Comments. See the SHOULD item above.
  • Dependencies. See the MUST and SHOULD items above.

Project structure

src/                # CLI entry point and command implementations
src/commands/       # One module per subcommand (up, down, list, …)
src/tart.rs         # Wrapper around the `tart` binary
src/state.rs        # Persisted CLI state (default VM, etc.)
tests/              # Integration tests using a stubbed environment
.github/workflows/  # CI, release, security, and Scorecard workflows
docs/               # mdBook documentation source (also published as a site)

License

By contributing, you agree that your contributions will be licensed under the MIT License, the same license as the project.