Thanks for your interest in Hyper. Contributions are welcome, but please read this document first -- Hyper is a technical-first project with a high quality bar and a few non-obvious requirements.
Hyper is licensed under the MIT License. By submitting a contribution (a pull request, patch, or commit) you agree that it is licensed to the project under those same terms; you retain the copyright to your own work. There is no separate contributor license agreement to sign. If you are contributing on company time, make sure you have permission to do so.
For anything beyond a small fix, open an issue first and describe what you intend to do. Hyper is opinionated and moves fast; a quick discussion avoids wasted work on a PR that does not fit the direction of the project.
- Bug fixes with a clear reproduction.
- Performance work -- especially around disk forking, scheduling, and distribution. Bring numbers.
- Correctness and fault-tolerance improvements.
- Documentation -- guides,
@moduledocs, and architecture notes.
Hyper runs Firecracker microVMs and leans on Linux primitives (cgroups,
/proc, the jailer, a setuid helper). Development that touches the VM stack
therefore requires Linux. You will need:
- Elixir
~> 1.20on Erlang/OTP 28+. - PostgreSQL -- the image database. The default dev/test config expects a
database reachable at
localhostaspostgres/postgres(seeconfig/config.exs).
Pure unit tests (test/unit, test/controls) do not need Firecracker, but the
database-backed tests need Postgres.
mix deps.get
mix ecto.create
mix ecto.migrate
mix testTo run a local cluster, start nodes with matching --cookie and the names
configured in config/config.exs:
iex --name a@127.0.0.1 --cookie hyper -S mix
iex --name b@127.0.0.1 --cookie hyper -S mixBefore you open a PR, mix check must pass. It is the same strict gate the
maintainers run:
mix checkIt runs, in order:
mix format --check-formatted-- formatting is not optional.mix compile --warnings-as-errors-- zero warnings.mix credo --strict-- static analysis.mix test --warnings-as-errors-- the suite.mix dialyzer-- type checking.
Add @specs to public functions; Dialyzer is configured strictly
(:unmatched_returns, :extra_return, :missing_return) and will flag
missing or wrong ones.
Write tests that prove behavior, not tests that pad a coverage number. Cover
the real logic and the edge cases that matter; a smoke test that exercises the
happy path is often enough. Do not add mechanical, one-assertion-per-getter
tests that exist only to inflate the count -- they will be asked to be removed.
Match the style of the tests already in test/.
The :integration and :external test suites are excluded by default. The :integration suite (test/e2e/) contains live Firecracker E2E tests that boot real VMs and require a provisioned KVM host (see docs/cookbook/install.md) and passwordless sudo. The :external suite pulls real OCI images. Both run automatically in CI's integration job on every PR, so you do not need to run them locally unless you are developing them -- mix check runs the default test set, which is sufficient for most contributions.
The Firecracker API bindings under
lib/hyper/firecracker/api/{operations,schemas} are generated from the
committed OpenAPI spec in priv/firecracker/ -- do not hand-edit them. To
regenerate (e.g. after bumping the Firecracker version, which is documented in
the Mix.Tasks.Compile.FirecrackerGen moduledoc in mix.exs):
mix firecracker.gen- Follow Conventional Commits:
feat(scope): ...,fix: ...,docs: ..., etc. Scopes match subsystems (feat(firecracker): ...,feat(fire_vmm): ...). - Keep PRs focused. One logical change per PR.
- Make sure
mix checkpasses and the branch is up to date withmain. - Explain the why in the PR description, not just the what.
Open a GitHub issue for bugs, with the version, your environment, and a minimal reproduction. For anything security-sensitive, do not open a public issue -- email the maintainer at marko@harmont.dev instead.
You can also ask questions in the community Discord.