mirror of
https://github.com/block/buzz.git
synced 2026-10-29 13:31:44 +00:00
Signed-off-by: coder 0 <d97ebdbb198c7237c94f84ea8bb8a73583ea067407eebd0062abbb3962527fb1@buzz.block.builderlab.xyz> Signed-off-by: bb-expert <51cde9442e46eac81c83ec71552708c3b0cb96a88ff8e1581d8fb4de281afbf3@buzz.block.builderlab.xyz>
212 lines
9.7 KiB
Rust
212 lines
9.7 KiB
Rust
// Shared schema, included from the same source the runtime command parses with,
|
|
// so the build-time validation below and the runtime parse cannot drift.
|
|
include!("src/commands/reconnect_hook_config.rs");
|
|
include!("src/commands/enterprise_relay_url.rs");
|
|
include!("src/builderlab_api_config.rs");
|
|
// Same source of truth the runtime filters with, so a baked build env cannot
|
|
// carry a reserved key the runtime believes it already rejected.
|
|
include!("src/managed_agents/reserved_env_keys.rs");
|
|
|
|
use base64::Engine as _;
|
|
|
|
fn main() {
|
|
println!("cargo:rerun-if-env-changed=BUZZ_RELAY_URL");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_RELAY_HTTP");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_UPDATER_PUBLIC_KEY");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_UPDATER_ENDPOINT");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_BUZZ_AGENT_PROVIDER");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_BUZZ_AGENT_MODEL");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_AGENT_ENV");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_RELAY_RECONNECT_CMD");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_AGENT_ACCESS_OWNER_ONLY");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_AUTO_CONNECT_DEFAULT_RELAY");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_ENTERPRISE_AUTH_RELAYS");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_BUILDERLAB_API_BASE_URL");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_ENTERPRISE_AUTH_ADAPTER_BASE_URL");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_ENTERPRISE_PROFILE_PROJECTION");
|
|
println!("cargo:rerun-if-env-changed=BUZZ_BUILD_DEMO_SLUG");
|
|
println!("cargo:rustc-check-cfg=cfg(buzz_updater_enabled)");
|
|
|
|
if let Ok(slug) = std::env::var("BUZZ_BUILD_DEMO_SLUG") {
|
|
let valid = !slug.is_empty()
|
|
&& slug.len() <= 48
|
|
&& slug
|
|
.bytes()
|
|
.all(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit() || byte == b'-')
|
|
&& slug
|
|
.bytes()
|
|
.next()
|
|
.is_some_and(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit())
|
|
&& slug
|
|
.bytes()
|
|
.last()
|
|
.is_some_and(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit());
|
|
if !valid {
|
|
panic!("BUZZ_BUILD_DEMO_SLUG must be a lowercase ASCII slug");
|
|
}
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_DEMO_SLUG={slug}");
|
|
}
|
|
|
|
// Explicit owner-only agent-access capability. Release packaging sets this
|
|
// presence-only marker; OSS/custom builds leave agent access configurable.
|
|
if std::env::var("BUZZ_BUILD_AGENT_ACCESS_OWNER_ONLY").is_ok() {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_AGENT_ACCESS_OWNER_ONLY=1");
|
|
}
|
|
|
|
if let Ok(relay_url) = std::env::var("BUZZ_RELAY_URL") {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_RELAY_URL={relay_url}");
|
|
}
|
|
|
|
if let Ok(relay_http) = std::env::var("BUZZ_RELAY_HTTP") {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_RELAY_HTTP={relay_http}");
|
|
}
|
|
|
|
if let Ok(provider) = std::env::var("BUZZ_BUILD_BUZZ_AGENT_PROVIDER") {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_BUZZ_AGENT_PROVIDER={provider}");
|
|
}
|
|
|
|
if let Ok(model) = std::env::var("BUZZ_BUILD_BUZZ_AGENT_MODEL") {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_BUZZ_AGENT_MODEL={model}");
|
|
}
|
|
|
|
// Generic KEY=VALUE pairs to inject into every spawned agent process.
|
|
// Newline-delimited; each line must be non-empty and contain exactly one
|
|
// `=` separator with a non-empty key. OSS builds leave this unset.
|
|
// The validated value is base64-encoded before emitting so the single-line
|
|
// Cargo build-script output carries all pairs (Cargo output is line-oriented;
|
|
// a raw multiline value would be silently truncated to the first line).
|
|
if let Ok(raw) = std::env::var("BUZZ_BUILD_AGENT_ENV") {
|
|
for (line_no, line) in raw.lines().enumerate() {
|
|
let line = line.trim();
|
|
if line.is_empty() {
|
|
continue;
|
|
}
|
|
let eq = line.find('=').unwrap_or_else(|| {
|
|
panic!(
|
|
"BUZZ_BUILD_AGENT_ENV line {}: missing '=' separator in {:?}",
|
|
line_no + 1,
|
|
line
|
|
)
|
|
});
|
|
let key = &line[..eq];
|
|
if key.is_empty() {
|
|
panic!(
|
|
"BUZZ_BUILD_AGENT_ENV line {}: key must not be empty in {:?}",
|
|
line_no + 1,
|
|
line
|
|
);
|
|
}
|
|
// The baked env is written into every spawned agent's environment
|
|
// LAST (see `managed_agents/runtime.rs`), after Buzz sets the
|
|
// access gates and identity vars. A baked reserved key would
|
|
// therefore silently override the gate the UI promises, so reject
|
|
// it at build time instead of shipping a binary that bypasses its
|
|
// own enforcement.
|
|
if is_reserved_env_key(key) {
|
|
panic!(
|
|
"BUZZ_BUILD_AGENT_ENV line {}: `{}` is reserved by Buzz and cannot be baked \
|
|
into a build (it would override Buzz's own identity/access env)",
|
|
line_no + 1,
|
|
key
|
|
);
|
|
}
|
|
}
|
|
let encoded = base64::engine::general_purpose::STANDARD.encode(raw.as_bytes());
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_AGENT_ENV={encoded}");
|
|
}
|
|
|
|
if let Ok(val) = std::env::var("BUZZ_BUILD_RELAY_RECONNECT_CMD") {
|
|
let parsed: serde_json::Value = serde_json::from_str(&val)
|
|
.unwrap_or_else(|e| panic!("BUZZ_BUILD_RELAY_RECONNECT_CMD is not valid JSON: {e}"));
|
|
serde_json::from_value::<ReconnectHookConfig>(parsed).unwrap_or_else(|e| {
|
|
panic!("BUZZ_BUILD_RELAY_RECONNECT_CMD doesn't match ReconnectHookConfig: {e}")
|
|
});
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_RELAY_RECONNECT_CMD={val}");
|
|
}
|
|
|
|
// Presence-only release capability: internal desktop builds opt into
|
|
// auto-connecting their configured default relay on first run. OSS builds
|
|
// leave this unset and retain explicit community selection.
|
|
if std::env::var("BUZZ_BUILD_AUTO_CONNECT_DEFAULT_RELAY").is_ok() {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_AUTO_CONNECT_DEFAULT_RELAY=1");
|
|
}
|
|
|
|
let enterprise_auth_relays = std::env::var("BUZZ_BUILD_ENTERPRISE_AUTH_RELAYS").ok();
|
|
if let Some(relays) = enterprise_auth_relays.as_deref() {
|
|
let trimmed = relays.trim();
|
|
parse_enterprise_relay_allowlist(trimmed).unwrap_or_else(|error| panic!("{error}"));
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_ENTERPRISE_AUTH_RELAYS={trimmed}");
|
|
}
|
|
|
|
let builderlab_api_base_url = resolve_builderlab_api_base_url(
|
|
std::env::var("BUZZ_BUILD_BUILDERLAB_API_BASE_URL")
|
|
.ok()
|
|
.as_deref(),
|
|
)
|
|
.unwrap_or_else(|error| panic!("{error}"));
|
|
println!(
|
|
"cargo:rustc-env=BUZZ_DESKTOP_BUILD_BUILDERLAB_API_BASE_URL={builderlab_api_base_url}"
|
|
);
|
|
|
|
let enterprise_auth_adapter_base_url = resolve_enterprise_auth_adapter_base_url(
|
|
std::env::var("BUZZ_BUILD_ENTERPRISE_AUTH_ADAPTER_BASE_URL")
|
|
.ok()
|
|
.as_deref(),
|
|
enterprise_auth_relays.as_deref(),
|
|
)
|
|
.unwrap_or_else(|error| panic!("{error}"));
|
|
if let Some(enterprise_auth_adapter_base_url) = enterprise_auth_adapter_base_url {
|
|
println!(
|
|
"cargo:rustc-env=BUZZ_DESKTOP_BUILD_ENTERPRISE_AUTH_ADAPTER_BASE_URL={enterprise_auth_adapter_base_url}"
|
|
);
|
|
}
|
|
|
|
match std::env::var("BUZZ_BUILD_ENTERPRISE_PROFILE_PROJECTION").as_deref() {
|
|
Ok("1" | "true") => {
|
|
println!("cargo:rustc-env=BUZZ_DESKTOP_BUILD_ENTERPRISE_PROFILE_PROJECTION=1")
|
|
}
|
|
Ok("0" | "false" | "") | Err(_) => {}
|
|
Ok(value) => panic!(
|
|
"BUZZ_BUILD_ENTERPRISE_PROFILE_PROJECTION must be unset, 0/false, or 1/true; got {value:?}"
|
|
),
|
|
}
|
|
|
|
let updater_public_key = std::env::var("BUZZ_UPDATER_PUBLIC_KEY")
|
|
.ok()
|
|
.map(|value| value.trim().to_string())
|
|
.filter(|value| !value.is_empty());
|
|
let updater_endpoint = std::env::var("BUZZ_UPDATER_ENDPOINT")
|
|
.ok()
|
|
.map(|value| value.trim().to_string())
|
|
.filter(|value| !value.is_empty());
|
|
|
|
if updater_public_key.is_some() && updater_endpoint.is_some() {
|
|
println!("cargo:rustc-cfg=buzz_updater_enabled");
|
|
}
|
|
|
|
// Cargo test executables get no embedded Windows manifest (tauri_build
|
|
// attaches one to bin targets only), so the loader binds comctl32 v5, which
|
|
// lacks TaskDialogIndirect (statically imported via tauri-plugin-dialog/rfd)
|
|
// and debug test exes die at load with STATUS_ENTRYPOINT_NOT_FOUND. Declaring
|
|
// the Common Controls v6 dependency makes link.exe emit a side-by-side
|
|
// <exe>.manifest that the loader honors for manifest-less executables;
|
|
// binaries with an embedded manifest (the real app) ignore it.
|
|
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows")
|
|
&& std::env::var("CARGO_CFG_TARGET_ENV").as_deref() == Ok("msvc")
|
|
{
|
|
println!(
|
|
"cargo:rustc-link-arg=/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"
|
|
);
|
|
}
|
|
|
|
tauri_build::try_build(
|
|
tauri_build::Attributes::new().plugin(
|
|
"websocket",
|
|
tauri_build::InlinedPlugin::new()
|
|
.commands(&["connect", "send", "disconnect", "disconnect_all"])
|
|
.default_permission(tauri_build::DefaultPermissionRule::AllowAllCommands),
|
|
),
|
|
)
|
|
.expect("failed to build Tauri application");
|
|
}
|