diff --git a/.github/buildomat/jobs/image.sh b/.github/buildomat/jobs/image.sh index 20b3fb163..1fd1fe699 100755 --- a/.github/buildomat/jobs/image.sh +++ b/.github/buildomat/jobs/image.sh @@ -31,6 +31,20 @@ ptime -m ./tools/install_builder_prerequisites.sh -y banner build +# We collect some build envrionment information with vergen to augment +# development builds, but this would otherwise put extra build-env info into +# the production (and test) binaries built here. While we don't test or rely on +# deterministic rebuilds of propolis-server, set Vergen up to use idempotent +# environment variables so we're not needlessly introducing build-time +# variance. +# +# "idempotent" still lets us collect the current relevant git info, so CI +# builds of propolis-server will still be able to self-report what commit they +# came from. See +# https://docs.rs/vergen/10.0.3/vergen/struct.Emitter.html#method.idempotent +# for more. +export VERGEN_IDEMPOTENT="true" + # Enable the "omicron-build" feature to indicate this is an artifact destined # for production use on an appropriately configured Oxide machine # diff --git a/.github/buildomat/jobs/phd-build.sh b/.github/buildomat/jobs/phd-build.sh index 4fc5d0e87..f1e71cca3 100644 --- a/.github/buildomat/jobs/phd-build.sh +++ b/.github/buildomat/jobs/phd-build.sh @@ -39,6 +39,10 @@ ptime -m ./tools/install_builder_prerequisites.sh -y # should fire during tests. banner build-propolis +# The same reasoning as in `image.sh` applies here, where we'd prefer more +# deterministic CI builds over less deterministic. +export VERGEN_IDEMPOTENT="true" + # We'll do a few cargo builds, keeping features the same means we reuse build # artifacts from crates these configure. TEST_FEATURES="omicron-build,failure-injection" diff --git a/lib/propolis/build.rs b/lib/propolis/build.rs index 253d8f083..12d2da878 100644 --- a/lib/propolis/build.rs +++ b/lib/propolis/build.rs @@ -9,10 +9,29 @@ fn main() -> anyhow::Result<()> { .dirty(true) .sha(true) .build(); - vergen_git2::Emitter::default() - .idempotent() - .add_instructions(&git2)? - .emit()?; + vergen_git2::Emitter::default().add_instructions(&git2)?.emit()?; + // Apologies for the broad rerun-if-changed, but stick with me: build.rs + // *must* rerun when source files are changed so that a version string's + // VERGEN_GIT_DIRTY is accurate. If we only rerun-on-changed for changes in + // the bin crates, that almost works, but means a source-only change in + // a crate in this tree that a bin depends on directly (say, + // propolis-api-types) wouldn't cause this build.rs to re-evaluate and get + // the right dirty bit in the version string. + // + // We could do the VERGEN_GIT_DIRTY work in the binary crates too, and plumb + // that back to propolis-lib version's string, but we'd want that to be + // broad to cover crates too. This takes the other approach: rerun + // propolis-lib build.rs if any files here have changed, which will cause + // propolis dependents to rebuild, and get updated version strings. This + // comes at the cost of recompiling the propolis-lib crate more often than + // strictly necessary during development, but that crate on its own is + // *much* faster to build than any of the bins being linked afterwards! + // + // This also means we can keep all of the versioning fiddliness here instead + // of subjecting every (e.g. both) user to thinking about this stuff. + println!("cargo:rerun-if-changed=../lib"); + println!("cargo:rerun-if-changed=../bin"); + println!("cargo:rerun-if-changed=../crates"); Ok(()) }