Upgrading Habitat to a New Rust Release

New Presents Every Six Weeks

In Rust-land, it’s Christmas time every six weeks! That is, the Rust language project uses a regular release cadence sometimes referred to as a release train. It’s been the practice of the Habitat project to consume these new releases as they come out, opting to eat any pain early and frequently. In practice, this has been a very easy activity as new Rust releases typically don’t introduce compilation failures (only potential new warnings), major logic bugs, or regressions. Our record goes back to Rust 1.3.0 spanning almost 3 years of continuous improvement.

Rustfmt Is Game-Changing

Another early decision in the Habitat project was to adopt the rustfmt tool which started life as an external standalone project and is now formally adopted by the Rust project and integrated into the rustup tool as a component. We wanted an objective tool that would give all developers a common starting point for formatting Rust code and ultimately make our codebase look more “rustic”. During early days the rustfmt tool was iterating quickly and would often result in large formatting changes that churned code. We’ve kept up the practice of upgrading when a new version of rustfmt is released and today this is made much easier via rustup. The catch now is that upgrading to a new version of Rust may result in a new version of rustfmt as well. As such the practice of upgrading to a new Rust release and a new rustfmt release are one in the same activity.

Developer Workstation Upgrade

As Habitat uses the stable releases of Rust, and assuming a normal installation of the rustup tool, simply running rustup update should be enough to pull the latest stable Rust release down. You can confirm your active version of Rust by running rustc --version and rustfmt with rustfmt --version (note that currently the version of rustfmt does not match the version of Rust). Doing this first is ideal as it will allow you to use the rustfmt tooling to update any code pro-actively.

Codebase Upgrade Approach

As our project has slowly started to span more than one Git repository, upgrading to a new version Rust involves a change to each of our 4 primary code repositories. Here are the changes to consider:

habitat-sh/core-plans

There are 2 Habitat Rust Plans, including a 64-bit Linux Plan and a 64-bit Windows Plan. It is important to update these Plans as this will be the version of Rust used when building Habitat software components and Builder services. Our project isn’t considered “upgraded” until these Plans are updated, merged, and new packages are ready in the “stable” channel.

Both the Linux and Windows Plans should be updated, ideally in a single commit (or at least a single pull request).

habitat-sh/core

This codebase is shared behavior and is used by both the habitat-sh/habitat and habitat-sh/builder repositories. It also tends to be fairly stable and slow moving, thus often forgotten about (hint: that’s it’s being called out first).

To upgrade the version used in CI, bump the rust: value in .travis.yml and to pro-actively update any source code formatting changes, run cargo fmt from the root of the repository.

habitat-sh/habitat

To upgrade the version used in CI, bump the rust: value in travis.yml, the RUST_TOOLCHAIN value in .buildkite/env, and to pro-actively update any source code formatting changes, run cargo fmt from the root of the repository.

Note that if there are any other important code/behavior changes in the core repository, you may want to consider bumping the Git SHA reference for core in this repository. Thankfully this is very rare and is not 100% critical.

habitat-sh/builder

To upgrade the version used in CI, bump the rust: value in travis.yml and to pro-actively update any source code formatting changes, run cargo fmt from the root of the repository.

Note that if there are any other important code/behavior changes in the core repository, you may want to consider bumping the Git SHA reference for core in this repository. Thankfully this is very rare and is not 100% critical.

The New Warnings

Occasionally upgrading to a new version of Rust may introduce new lint and compiler warnings. While these warnings don’t fail the builds, these warnings should be addressed in a reasonable time period. Often what gets introduced as a warning may later become an error in later Rust releases.

In general, we consider Rust lints and compiler warnings to be actionable but not mission critical. We strive to eliminate these warnings in short order, but addressing these warnings could involve behavior changes potentially introducing new bugs. As such, dealing with compiler warnings that are more than trivial is considered a bad practice in Rust-upgrading pull requests and is better to be dealt with as follow-on work that can easily be code-reviewed without considering code reformatting noise.

Note that on 2018-08-02 I amended this post to call out an additional update to a Buildkite environment file for the habitat-sh/habitat repository and consequently updated the related pull request and issue examples.