Show build revision and automate Warp sync workflow

This commit is contained in:
2026-08-24 13:27:09 -05:00
parent 4a364ce37f
commit a85ef61b1a
8 changed files with 344 additions and 161 deletions
+88
View File
@@ -24,6 +24,8 @@ fn main() -> Result<()> {
println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_OS");
println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_FAMILY");
emit_git_build_metadata();
let target_os = env::var("CARGO_CFG_TARGET_OS")?;
let target_family = env::var("CARGO_CFG_TARGET_FAMILY")?;
@@ -139,6 +141,92 @@ fn main() -> Result<()> {
Ok(())
}
fn emit_git_build_metadata() {
const COMMIT_ENV_VARS: [&str; 3] = ["GALAXY_GIT_COMMIT", "GITHUB_SHA", "CI_COMMIT_SHA"];
for variable in COMMIT_ENV_VARS {
println!("cargo:rerun-if-env-changed={variable}");
}
println!("cargo:rerun-if-env-changed=GALAXY_GIT_DIRTY");
// Keep local build metadata current when the checked-out commit changes. Watching the
// package and workspace source directories also refreshes the dirty marker for normal
// development builds without making the repository's `target` directory an input.
println!("cargo:rerun-if-changed=src");
println!("cargo:rerun-if-changed=../crates");
println!("cargo:rerun-if-changed=../resources");
println!("cargo:rerun-if-changed=../Cargo.toml");
println!("cargo:rerun-if-changed=../Cargo.lock");
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_owned());
let repository_root = Path::new(&manifest_dir).parent().unwrap_or(Path::new("."));
if let Some(git_dir) = git_output(repository_root, &["rev-parse", "--absolute-git-dir"]) {
let git_dir = Path::new(&git_dir);
println!("cargo:rerun-if-changed={}", git_dir.join("HEAD").display());
println!("cargo:rerun-if-changed={}", git_dir.join("index").display());
println!(
"cargo:rerun-if-changed={}",
git_dir.join("packed-refs").display()
);
if let Some(head_ref) = git_output(repository_root, &["symbolic-ref", "-q", "HEAD"]) {
println!(
"cargo:rerun-if-changed={}",
git_dir.join(head_ref).display()
);
}
}
let commit = COMMIT_ENV_VARS
.iter()
.find_map(|variable| env::var(variable).ok())
.filter(|value| is_valid_commit(value))
.or_else(|| git_output(repository_root, &["rev-parse", "--verify", "HEAD"]))
.filter(|value| is_valid_commit(value))
.unwrap_or_else(|| "unknown".to_owned());
let dirty = env::var("GALAXY_GIT_DIRTY")
.ok()
.and_then(|value| parse_bool(&value))
.unwrap_or_else(|| {
git_output(
repository_root,
&["status", "--porcelain", "--untracked-files=normal"],
)
.is_some_and(|output| !output.is_empty())
});
println!("cargo:rustc-env=GALAXY_BUILD_GIT_COMMIT={commit}");
println!("cargo:rustc-env=GALAXY_BUILD_GIT_DIRTY={dirty}");
}
fn git_output(repository_root: &Path, arguments: &[&str]) -> Option<String> {
let output = Command::new("git")
.current_dir(repository_root)
.args(arguments)
.output()
.ok()?;
if !output.status.success() {
return None;
}
String::from_utf8(output.stdout)
.ok()
.map(|output| output.trim().to_owned())
}
fn is_valid_commit(value: &str) -> bool {
let value = value.trim();
(7..=64).contains(&value.len()) && value.bytes().all(|byte| byte.is_ascii_hexdigit())
}
fn parse_bool(value: &str) -> Option<bool> {
match value.trim().to_ascii_lowercase().as_str() {
"1" | "true" | "yes" => Some(true),
"0" | "false" | "no" => Some(false),
_ => None,
}
}
fn get_build_profile_name() -> String {
// The profile name is always the 3rd last part of the path (with 1 based indexing).
// e.g. /code/core/target/cli/build/my-build-info-9f91ba6f99d7a061/out
+2
View File
@@ -219,6 +219,8 @@ fn app_context() -> Value {
json!({
"version": env!("CARGO_PKG_VERSION"),
"channel": ChannelState::channel().to_string(),
"source_commit": crate::build_info::SOURCE_COMMIT,
"source_modified": crate::build_info::source_is_dirty(),
})
}
+21
View File
@@ -0,0 +1,21 @@
pub(crate) const SOURCE_COMMIT: &str = env!("GALAXY_BUILD_GIT_COMMIT");
pub(crate) fn source_is_dirty() -> bool {
env!("GALAXY_BUILD_GIT_DIRTY") == "true"
}
pub(crate) fn source_revision_label() -> String {
if source_is_dirty() {
format!("{SOURCE_COMMIT} (modified)")
} else {
SOURCE_COMMIT.to_owned()
}
}
pub(crate) const fn profile() -> &'static str {
if cfg!(debug_assertions) {
"debug"
} else {
"release"
}
}
+5
View File
@@ -10,6 +10,11 @@ use galaxyui::windowing;
pub(crate) fn run() -> anyhow::Result<()> {
println!("Galaxy version: {:?}", ChannelState::app_version());
println!("Build profile: {}", crate::build_info::profile());
println!(
"Source commit: {}",
crate::build_info::source_revision_label()
);
#[cfg(not(windows))]
{
+10 -2
View File
@@ -36,6 +36,7 @@ mod banner;
#[cfg(feature = "bedrock_smoke_test")]
mod bedrock_smoke_test;
mod billing;
mod build_info;
mod changelog_model;
mod chip_configurator;
mod cloud_object;
@@ -1585,9 +1586,16 @@ pub(crate) fn initialize_app(
remote_server::wire_auth_token_rotation(ctx);
log::info!(
"Starting Galaxy with channel state {} and version {:?}",
"Starting Galaxy with channel state {}, version {:?}, profile {}, source commit {}{}",
ChannelState::debug_str(),
ChannelState::app_version()
ChannelState::app_version(),
build_info::profile(),
build_info::SOURCE_COMMIT,
if build_info::source_is_dirty() {
" (modified)"
} else {
""
}
);
// Teach our app that sometimes option means meta.
+27 -1
View File
@@ -1,3 +1,4 @@
use galaxy_core::channel::ChannelState;
use galaxyui::elements::{
Align, CacheOption, ConstrainedBox, Container, CrossAxisAlignment, Element, Flex,
FormattedTextElement, Image, Padding, ParentElement, Text,
@@ -89,6 +90,31 @@ impl SettingsWidget for AboutPageWidget {
)
.with_color(appearance.theme().nonactive_ui_text_color().into())
.finish();
let build = Text::new(
format!(
"Build {} · {}",
ChannelState::channel().local_control_channel_name(),
crate::build_info::profile()
),
appearance.ui_font_family(),
12.,
)
.with_color(appearance.theme().nonactive_ui_text_color().into())
.finish();
let commit = Text::new(
format!("Commit {}", crate::build_info::source_revision_label()),
appearance.ui_font_family(),
12.,
)
.with_color(appearance.theme().nonactive_ui_text_color().into())
.finish();
let build_details = Flex::column()
.with_cross_axis_alignment(CrossAxisAlignment::Center)
.with_spacing(4.)
.with_child(version)
.with_child(build)
.with_child(commit)
.finish();
let description = FormattedTextElement::from_str(
"Galaxy is a local-first terminal and AI workspace built for developers. Your settings, terminal data, conversations, and Galaxy Drive content stay on this machine in your Galaxy directory. Galaxy sends request data only to the AI providers you configure.",
appearance.ui_font_family(),
@@ -107,7 +133,7 @@ impl SettingsWidget for AboutPageWidget {
.with_spacing(12.)
.with_child(icon)
.with_child(title)
.with_child(version)
.with_child(build_details)
.with_child(description)
.finish(),
)