Dependency Management Guidelines

This repository uses third-party code from a variety of sources, so we need to be mindful of how these dependencies will affect our consumers. Considerations include:

We're still evolving our policies in this area, but these are the guidelines we've developed so far.

Rust Code

Unlike Firefox, we do not vendor third-party source code directly into the repository. Instead we rely on Cargo.lock and its hash validation to ensure that each build uses an identical copy of all third-party crates. These are the measures we use for ongoing maintenance of our existing dependencies:

  • Check Cargo.lock into the repository.
  • Generate built artifacts using the --locked flag to cargo build, as an additional assurance that the existing Cargo.lock will be respected.
  • Use cargo-deny for a basic license-compatibility check as part of CI, to guard against human error.

Adding a new dependency, whether we like it or not, is a big deal - that dependency and everything it brings with it will become part of Firefox-branded products that we ship to end users. We try to balance this responsibility against the many benefits of using existing code, as follows:

  • In general, be conservative in adding new third-party dependencies.
    • For trivial functionality, consider just writing it yourself. Remember the cautionary tale of left-pad.
    • Check if we already have a crate in our dependency tree that can provide the needed functionality.
  • Prefer crates that have a a high level of due-diligence already applied, such as:
  • Check that it is clearly licensed and is MPL-2.0 compatible.
  • Take the time to investigate the crate's source and ensure it is suitably high-quality.
    • Be especially wary of uses of unsafe, or of code that is unusually resource-intensive to build.
    • Development dependencies do not require as much scrutiny as dependencies that will ship in consuming applications, but should still be given some thought.
      • There is still the potential for supply-chain compromise with development dependencies!
  • Explicitly describe your consideration of these points in the PR that introduces the new dependency.

Updating to new versions of existing dependencies is a normal part of software development and is not accompanied by any particular ceremony.

Dependency updates

We use Dependabot to automatically open pull requests when dependencies release a new version. All CI tasks run on those pull requests to ensure updates don't break anything.

As glean-core is now also vendored into mozilla-central, including all of its Rust dependencies, we need to be a bit careful about these updates. Landing upgrades of the Glean SDK itself in mozilla-central is a separate process. See Updating the Glean SDK in the Firefox Source Docs. Following are some guidelines to ensure compatibility with mozilla-central:

  • Patch releases of dependencies should be fine in most cases.
  • Minor releases should be compatible. Best to check the changelog of the updated dependency to make sure. These updates should only land in Cargo.lock. No updates in Cargo.toml are necessary
  • Major releases will always need a check against mozilla-central. See Updating the Glean SDK.

In case of uncertainty defer a decision to :janerik or :chutten.

Manual dependency updates

You can manually check for outdated dependencies using cargo-outdated. Individual crate updates for version compatible with the requirement in Cargo.toml can be done using:

cargo update -p $cratename

To update all transitive dependencies to the latest semver-compatible version use:

cargo update