Skip to content

Contributing ​

Help is welcome with reproducible bug reports, focused fixes, tests, and clear documentation. For a new feature or a substantial change, discuss the direction in GitHub Discussions or Discord before investing in an implementation. Small, obvious fixes can go straight to a pull request.

Set up the repository ​

sh
git clone https://github.com/aubepkg/aube
cd aube
mise install
mise run build

Use the Rust toolchain declared by the project and the tools pinned in mise.toml. mise run activates the Cargo build-cache wrapper. If you run Cargo directly, activate mise in your shell first.

The debug binary is target/debug/aube. BATS tests use that binary; release builds are for profiling and benchmarks.

Run the relevant checks ​

sh
mise run test
mise run lint
mise run test:bats test/install.bats

mise run lint runs the repository's hk checks, including formatting and Clippy. mise run lint-fix applies supported fixes. The equivalent core Cargo checks are:

sh
cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --check

BATS tests use the project's mise-managed Node and rush for parallel runs. Use mise run test:bats for the full shell suite. Supply specific .bats files for a focused run. The registry helper installs Verdaccio if it is unavailable.

Release validation also includes cargo deny --locked check advisories bans licenses sources, which covers RustSec advisories as well as license, ban, and source policy.

Work on documentation ​

sh
mise run docs:dev
mise run docs:build

The site lives under docs/; navigation and styles live in docs/.vitepress/. The build validates internal page links and social-preview metadata. Use node scripts/check-docs.mjs to check local Markdown links and built-site fragment targets after a docs build.

Some references are generated:

OutputEdit this source
docs/cli/*.md and nested command pagesCommand help in crates/aube/src/; examples and navigation in scripts/patch-generated-cli-docs.mjs
docs/settings/index.mdcrates/aube-settings/settings.toml and its docs generator
Error-code datacrates/aube-codes/src/
Benchmark charts and README ratiosbenchmarks/results.json, regenerated by mise run bench:bump

Run mise run render after changing generated reference sources. Keep command examples copyable, explain which file holds a setting, and describe current behavior separately from proposals. Historical release notes and vendored third-party documentation should retain their original content.

Prepare a pull request ​

Keep the scope focused and describe the problem, resulting behavior, and validation. CI must pass, and automated review comments must be addressed before maintainer review. Changes may be declined when they do not fit the project's scope; discussing substantial changes early reduces that risk.

Use Conventional Commits for commit messages and PR titles:

  • fix(install): preserve locked versions during repair
  • docs: clarify dependency build approvals
  • feat(resolver): support a new dependency protocol

Start the description with a lowercase imperative verb. Keep subjects concise; PR titles determine release version bumps. Do not add tool branding or a PR number to the title. Open pull requests ready for review, and include the AI-assistance disclosure required by the repository instructions when applicable.

The offline Verdaccio test registry ​

The BATS suite does not talk to registry.npmjs.org. Everything it installs comes from a pre-seeded local Verdaccio instance under test/registry/.

Layout ​

  • test/registry/config.yaml — Verdaccio config. No uplinks block, no proxy: on the packages['**'] entry — local-only by design.
  • test/registry/start.bash — sourced by test/setup_suite.bash. Boots Verdaccio on localhost:4873 before the suite, tears it down after.
  • test/registry/storage/ — Verdaccio's on-disk storage. Committed to git. Each subdirectory is an npm package: a package.json packument plus one .tgz per version the fixture needs. The .verdaccio-db.json index that Verdaccio regenerates on startup is .gitignored.

Each BATS test writes registry=http://localhost:4873 into a per-test .npmrc (see test/test_helper/common_setup.bash), so aube picks up the fake registry via its normal NpmConfig loader without any special plumbing in the Rust code.

Adding a new package to the fixture set ​

Say a new test needs cowsay. Because Verdaccio is local-only, the fixture set has to contain every package (and every transitive dep) the test will install. The recipe:

  1. Temporarily restore the npmjs uplink in test/registry/config.yaml:

    yaml
    storage: ./storage
    
    uplinks:
      npmjs:
        url: https://registry.npmjs.org/
        cache: true
    
    packages:
      '**':
        access: $all
        publish: $all
        proxy: npmjs
  2. Run the test that exercises the new package. Verdaccio will proxy the request upstream on the first hit and save the tarball and packument into test/registry/storage/<pkg>/. Transitive deps get pulled in the same way as the resolver walks the graph.

    bash
    cargo build
    ./test/bats/bin/bats test/your_new_test.bats
  3. Revert the uplink changes in test/registry/config.yaml so it's back to local-only.

  4. Re-run the full suite offline to prove the fixture set is complete and nothing still reaches for the network:

    bash
    ./test/bats/bin/bats test/
  5. Commit the new files under test/registry/storage/ along with your test. Check the diff for surprises — Verdaccio sometimes fetches additional versions beyond what the test asked for; drop anything unneeded to keep the fixture set small.

Picking test packages ​

  • Prefer tiny packages with few transitive deps. Every new package inflates the committed fixture set.
  • For aube dlx / exec / run tests, prefer packages with a stable, deterministic stdout (e.g. semver <version> echoes its input). Tests that rely on help output are brittle because clap flags and trailing args can swallow --help / --version.
  • If you need a package whose binary name differs from its package name (to exercise aube dlx -p), which ships node-which and is only a few KB including isexe.

Keeping the fixture set committed means:

  • CI runs are hermetic and don't flake on npmjs.org outages or rate limits.
  • Test failures are reproducible on any checkout of a given commit.
  • Offline development works without caveats.

The tradeoff is the ~8 MB of .tgz files under test/registry/storage/ and the manual seeding step above. For a package manager project that feels like the right tradeoff — we're exercising real tarball extraction and linking, so mock registries aren't an option.

MIT LicensejdxCopyright © 2026 jdx.dev