Skip to content

Latest commit

 

History

History
154 lines (114 loc) · 4.68 KB

CONTRIBUTING.md

File metadata and controls

154 lines (114 loc) · 4.68 KB

Contributing to Horae

Thank you for your interest in contributing! Before you start, read through this guide to set up your environment and understand the project conventions.


Getting started

Requirements: Nix with flakes enabled.

nix develop            # enter the dev shell
process-compose up     # postgres + the app, on http://localhost:8080

Or nix run .#dev to do both at once. Migrations and seed data are applied for you, so there is nothing else to run. pgweb is at http://localhost:8081 for browsing the database, and process-compose up postgres migrate starts just a database when that is all you need. Open http://localhost:8080/auth/login and click Sign in as Admin.

DATABASE_URL is exported automatically by the dev shell. Database state lives in .data/postgres; rm -rf .data starts from scratch.

nix run .#postgres boots a PostgreSQL VM instead — slower, but it exercises the NixOS module used for self-hosting. See the README for that flow.


System setup

macOS

macOS requires nix-darwin for the Linux builder, which is needed to run the e2e nixosTest (nix flake check) and to cross-compile the server binary for Linux targets locally.

Enable the Linux builder in your nix-darwin configuration:

nix = {
  # Required for the Linux builder to be trusted by the Nix daemon.
  settings.trusted-users = [ "root" "@admin" ];
  linux-builder = {
    enable = true;
    ephemeral = true;
    maxJobs = 4;
    config = {
      virtualisation = {
        darwin-builder = {
          diskSize = 40 * 1024;   # 40 GiB
          memorySize = 8 * 1024;  # 8 GiB
        };
        cores = 6;
      };
    };
  };
};

See the nix-darwin Linux builder docs for full configuration options and activation instructions.

Linux

Linux works out of the box with Nix and flakes enabled. Enable flakes in your Nix configuration if you haven't already:

nix.settings.experimental-features = [ "nix-command" "flakes" ];

Development workflow

nix develop            # enter the dev shell
process-compose up     # postgres + hot-reloading dev server on :8080

Tests:

cargo test -p horae-core                        # pure domain tests (no DB needed)
cargo test --features server                    # integration tests (needs Postgres with CREATEDB)
nix flake check                                 # what CI gates on: tests, clippy, fmt, e2e nixosTest

Rust guidelines

No include! macro for documentation

Do not use the include! macro (or include_str!) to embed documentation from external files into doc comments or module-level docs. The macro resolves at rustc compile time, which means Nix will re-hash and recompile the crate whenever the included file changes — even though .md files are excluded from the Nix source filter at the Nix evaluation level, the rustc invocation itself sees the file as an input.

Write documentation directly in the source file instead.

Error types must be structs

Error types must be structs, not enums. Model them after std::io::Error: a single public struct with an opaque inner kind (a private enum or a boxed trait object). This gives you:

  • An opaque public surface — callers match on methods, not variants, so you can evolve the internals without breaking them.
  • Room to add fields (e.g. context, spans, request IDs) without a breaking change.
  • A natural impl std::error::Error implementation.
// Preferred
pub struct AppError(AppErrorKind);

enum AppErrorKind {
    NotFound(String),
    Forbidden,
    // ...
}

impl AppError {
    pub fn not_found(msg: impl Into<String>) -> Self { ... }
    pub fn is_not_found(&self) -> bool { ... }
}

// Avoid
pub enum AppError {
    NotFound(String),
    Forbidden,
}

Submitting changes

Branch naming: <username>/<issue> (e.g. alice/42)

If a PR is intended to close an issue, include a closing keyword in the PR description (e.g. Closes #42).