Files
SpacetimeDB/crates/lib/build.rs
Phoebe Goldman 7345296cc9 Fix Nix build by not using Git in Cargo build scripts (#3551)
# Description of Changes

When building under Nix, Git metadata is not available within the
sandbox, as we use `lib.cleanSource` on our source directory. This is
important because it avoids spurious rebuilds and/or determinism
hazards.

The build was broken due to our new `spacetime init` template system
accessing Git metadata in the CLI's build.rs
to filter out non-git-tracked files from the templates. The Flake
sandbox does this automatically (even without `lib.cleanSource`!), so
when building under Nix it's unnecessary to do twice. (I remain
unconvinced that it's necessary to do in non-Nix builds either, as CI
builds should have a clean checkout and local dev builds don't need
clean templates, but the behavior was already in master and I didn't
feel comfortable removing it.)

As an enhancement, I've also found a Nix-ey way to embed our Git commit
hash in builds. Previously, builds under Nix had the empty string
instead of a commit hash, because we included the `git` CLI tool but
scrubbed the necessary metadata. Now, we inject an environment variable
from the Nix flake, and don't make the `git` CLI tool available at all.
This has the convenient upside of allowing Nix builds to reference
`dirtyRev` in builds with a dirty worktree, which should reduce
confusion.

# API and ABI breaking changes

N/a

# Expected complexity level and risk

3? I didn't have a strong understanding of what the CLI build script was
doing, and to what extent it was doing things intentionally versus for
convenience. As such, it's possible that I've inadvertently damaged
something load-bearing.

# Testing

- [x] Built with `nix build`, ran `spacetime init`, chose the
`basic-rust` template, and got a reasonable-looking template
instantiation.
- [ ] Hopefully we have automated tests for this?
2025-11-01 00:15:31 +00:00

40 lines
1.5 KiB
Rust

use std::process::Command;
// https://stackoverflow.com/questions/43753491/include-git-commit-hash-as-string-into-rust-program
#[allow(clippy::disallowed_macros)]
fn main() {
let git_hash = find_git_hash();
println!("cargo:rustc-env=GIT_HASH={git_hash}");
}
fn nix_injected_commit_hash() -> Option<String> {
use std::env::VarError;
// Our flake.nix sets this environment variable to be our git commit hash during the build.
// This is important because git metadata is otherwise not available within the nix build sandbox,
// and we don't install the git command-line tool in our build.
match std::env::var("SPACETIMEDB_NIX_BUILD_GIT_COMMIT") {
Ok(commit_sha) => {
// Var is set, we're building under Nix.
Some(commit_sha)
}
Err(VarError::NotPresent) => {
// Var is not set, we're not in Nix.
None
}
Err(VarError::NotUnicode(gross)) => {
// Var is set but is invalid unicode, something is very wrong.
panic!("Injected commit hash is not valid unicode: {gross:?}")
}
}
}
fn find_git_hash() -> String {
nix_injected_commit_hash().unwrap_or_else(|| {
// When we're *not* building in Nix, we can assume that git metadata is still present in the filesystem,
// and that the git command-line tool is installed.
let output = Command::new("git").args(["rev-parse", "HEAD"]).output().unwrap();
String::from_utf8(output.stdout).unwrap().trim().to_string()
})
}