Contribution guidelines
What NativeLink accepts, the git setup it requires, and the commit and review conventions a PR is held to.
Who this is for: anyone about to open their first pull request. What you'll have at the end: the git configuration the project requires, the commit conventions, and an accurate picture of how review works. Time: thirty minutes, most of it one-time setup.
NativeLink accepts contributions from anyone. The process is more specific
than most projects' (signed commits, a fork, one commit per pull request,
review in Reviewable rather than in GitHub's own UI), and the specificity is
deliberate: it keeps main a linear history of signed, reviewable commits.
is the authoritative version; this page is the orientation around it.
What gets accepted
| Welcome | With a caveat |
|---|---|
| Bug fixes, with a regression test | |
| Performance improvements | Bring reproducible numbers |
| New stores, schedulers, worker types | Open an issue and agree the approach first |
| Documentation fixes, including this page | Smaller is better |
| Tooling that makes development or operations easier |
Three things reliably do not land: breaking changes to the Remote Execution API surface, which is an upstream spec the project tracks rather than owns; vendor-specific code paths only one deployment can use; and refactoring proposed on its own merits rather than as part of a change that needed it.
If you want to work on an existing issue, claim it by commenting first. That is the only mechanism preventing two people from writing the same patch.
Git setup, once
Create distinct authentication and signing keys in your GitHub key settings. Two keys, not one reused.
Fork the repository and clone your fork, not upstream:
git clone git@github.com:yourusername/nativelink cd nativelink git remote add upstream git@github.com:TraceMachina/nativelinkgit remote -vshould showoriginpointing at your fork andupstreamatTraceMachina/nativelink.Configure git to sign every commit and tag. In
~/.gitconfig:[user] name = Your Full Name email = the-email-you-use-on-github@example.com signingkey = ~/.ssh/your_private_signing_key [gpg] format = ssh # or gpg, if you use a GPG key [commit] gpgsign = true [tag] gpgsign = true
Signing is not a DCO sign-off
NativeLink requires cryptographically signed commits, SSH or GPG, via
commit.gpgsign. It does not use a Developer Certificate of Origin
sign-off, so git commit -s alone will not satisfy the requirement.
Direct commits and human-created branches on TraceMachina/nativelink are
not allowed, including for members of the organization. Everything arrives
as a pull request from a fork.
The pull request loop
Sync your fork, then branch:
git switch main git pull -r upstream main git push git switch -c some-featureMake one commit. The title rules are enforced by review, not by a hook, and they are short: start with a capital letter, use the imperative, no trailing period, keep it as short as it can be, and put detail in the body wrapped at 72 characters.
Add some feature ← good Add some feature. ← trailing period Adds some feature ← not imperative Add X and also Y ← "and" means this is two commitsThe word "and" in a title is the signal to split the commit.
Push and open the PR from your fork, then click the purple Reviewable button on the GitHub page to add reviewers with
+@somereviewer. Review conversation happens there.Revise with
--amend, not a follow-up commit.git commit --amend git push -fReviewable keeps the diff between commit versions visible, so nothing is lost by rewriting, and the branch stays one commit, which is what lands.
Before you push
bazel test //... # what CI runs
pre-commit run -a # hooks, vale, typos
bazel run --config=rustfmt @rules_rust//:rustfmt # formattingStable `cargo fmt` is not the formatter
.rustfmt.toml uses group_imports and imports_granularity, both
nightly-only. Stable cargo fmt ignores them silently and produces output
CI rejects. Use the Bazel target.
cargo test --all --profile=smol is the fast inner loop, but a green Cargo
run is not a green CI: bazel test attaches rustfmt and clippy aspects that
Cargo does not. See the testing guide for what
the suites contain and which local failures are environmental.
What reviewers look for
One change per pull request. Small ones land; large ones get split.
A body that explains why. The diff already shows what changed. The body is where the constraint, the incident or the measurement goes.
Tests that match the change. A bug fix wants a regression test; new behaviour wants both unit and integration coverage. No coverage percentage gate; the question is whether the new path is exercised, not whether a number moved.
Conventions followed rather than argued. Most review feedback on a first
contribution is about the house rules: the task macros instead of
tokio::spawn, #[expect(..., reason = "…")] rather than a bare #[allow],
the BUILD.bazel srcs entry. Codebase internals is the page that
gets you past those in one read.
Licensing
Your contribution is licensed under the license that applies to the file or
module you change. Most of the repository is FSL-1.1-Apache-2.0; a handful
of files are Apache-2.0; and two areas,
nativelink-util/src/metrics.rs and everything under
nativelink-worker/src/persistent_worker/, are Business Source
License. Copy the header from the file next to the one you are creating
rather than from memory.
Meaningful contributors may be eligible for license waivers on the Business Source License modules. Raise an issue or contact the maintainers before depending on one.
Common questions
Where your change actually goes: twelve crates, a strict layering, and the six places the first guess is wrong.