feat(build): allow overriding release version (#6998)

Allow release builds to set RUSTFS_BUILD_VERSION at compile time while keeping the existing tag, short commit, and package-version fallback when the variable is unset or empty.

Co-authored-by: heihutu <heihutu@gmail.com>
This commit is contained in:
houseme
2026-09-01 17:08:46 +08:00
committed by GitHub
parent cee84561e7
commit 47304cc68d
4 changed files with 87 additions and 22 deletions
+11
View File
@@ -13,6 +13,17 @@
// limitations under the License.
fn main() -> shadow_rs::SdResult<()> {
println!("cargo:rerun-if-env-changed=RUSTFS_BUILD_VERSION");
if let Ok(version) = std::env::var("RUSTFS_BUILD_VERSION")
&& !version.is_empty()
{
assert!(
!version.contains(['\n', '\r']),
"RUSTFS_BUILD_VERSION must be a single-line version string"
);
println!("cargo:rustc-env=RUSTFS_BUILD_VERSION={version}");
}
shadow_rs::ShadowBuilder::builder().build()?;
Ok(())
}
+2 -10
View File
@@ -26,7 +26,7 @@ use crate::server::{
HeaderMapCarrier, HealthProbe, LICENSE, RUSTFS_ADMIN_PREFIX, RequestContextLayer, VERSION, build_health_response_parts,
collect_probe_readiness,
};
use crate::version::build;
use crate::version::{self, build};
use axum::{
Extension, Json, Router,
body::Body,
@@ -262,15 +262,7 @@ static CONSOLE_CONFIG: OnceLock<Config> = OnceLock::new();
#[allow(clippy::const_is_empty)]
pub(crate) fn init_console_cfg(local_ip: IpAddr, port: u16) {
CONSOLE_CONFIG.get_or_init(|| {
let ver = {
if !build::TAG.is_empty() {
build::TAG.to_string()
} else if !build::SHORT_COMMIT.is_empty() {
format!("@{}", build::SHORT_COMMIT)
} else {
build::PKG_VERSION.to_string()
}
};
let ver = version::DISPLAY_VERSION.to_string();
Config::new(local_ip, port, ver.as_str(), build::COMMIT_DATE_3339)
});
+17 -12
View File
@@ -23,7 +23,7 @@
//! - `InfoType`: Information type enum
//! - `CommandResult`: Result of parsing command line arguments
use crate::version::build;
use crate::version::{self, build};
use clap::builder::NonEmptyStringValueParser;
use clap::{Args, Parser, Subcommand, ValueEnum};
use const_str::concat;
@@ -31,16 +31,7 @@ use rustfs_config::{DEFAULT_ADDRESS, DEFAULT_CONSOLE_ADDRESS, DEFAULT_CONSOLE_EN
use std::path::PathBuf;
// build module is re-exported from crate::build
#[allow(clippy::const_is_empty)]
pub(super) const SHORT_VERSION: &str = {
if !build::TAG.is_empty() {
build::TAG
} else if !build::SHORT_COMMIT.is_empty() {
concat!("@", build::SHORT_COMMIT)
} else {
build::PKG_VERSION
}
};
pub(super) const SHORT_VERSION: &str = version::DISPLAY_VERSION;
pub(super) const LONG_VERSION: &str = concat!(
concat!(SHORT_VERSION, "\n"),
@@ -495,8 +486,9 @@ pub fn default_server_opts() -> ServerOpts {
#[cfg(test)]
mod tests {
use super::{Cli, Commands, ConnectCommands, InspectCommands, preprocess_args_for_legacy};
use clap::Parser;
use crate::version;
use clap::error::ErrorKind;
use clap::{CommandFactory, Parser};
#[test]
fn preprocess_help_command_displays_top_level_help() {
@@ -511,6 +503,19 @@ mod tests {
assert_eq!(err.kind(), ErrorKind::DisplayHelp);
}
#[test]
fn version_flags_use_display_version() {
let command = Cli::command();
let short = command.render_version();
assert!(short.contains(version::DISPLAY_VERSION));
assert!(!short.contains("build time"));
let long = command.render_long_version();
assert!(long.starts_with(&format!("rustfs {}\n", version::DISPLAY_VERSION)));
assert!(long.contains("build time"));
}
#[test]
fn inspect_bucket_meta_parses_repeated_drive_paths() {
let cli = Cli::try_parse_from([
+57
View File
@@ -12,16 +12,59 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use const_str::concat;
use shadow_rs::shadow;
use std::path::Path;
use std::process::Command;
shadow!(build);
const BUILD_VERSION_OVERRIDE: Option<&str> = option_env!("RUSTFS_BUILD_VERSION");
#[allow(clippy::const_is_empty)]
const DEFAULT_DISPLAY_VERSION: &str = {
if !build::TAG.is_empty() {
build::TAG
} else if !build::SHORT_COMMIT.is_empty() {
concat!("@", build::SHORT_COMMIT)
} else {
build::PKG_VERSION
}
};
#[allow(clippy::const_is_empty)]
pub const DISPLAY_VERSION: &str = {
if let Some(version) = BUILD_VERSION_OVERRIDE {
if !version.is_empty() {
version
} else {
DEFAULT_DISPLAY_VERSION
}
} else {
DEFAULT_DISPLAY_VERSION
}
};
type VersionParseResult = Result<(u32, u32, u32, Option<String>), Box<dyn std::error::Error>>;
fn build_version_override() -> Option<&'static str> {
BUILD_VERSION_OVERRIDE.filter(|version| !version.is_empty())
}
fn version_ref(version: &str) -> String {
if version.starts_with("refs/tags/") || version.starts_with('@') {
version.to_string()
} else {
format!("refs/tags/{version}")
}
}
#[allow(clippy::const_is_empty)]
pub fn get_version() -> String {
if let Some(version) = build_version_override() {
return version_ref(version);
}
// Get the latest tag
if let Ok(latest_tag) = get_latest_tag() {
// Check if current commit is newer than the latest tag
@@ -262,6 +305,20 @@ mod tests {
assert!(is_head_newer_than_tag_in(repo.path(), "1.2.3"));
}
#[test]
fn build_version_override_is_used_for_current_version_when_set() {
if let Some(version) = build_version_override() {
assert_eq!(get_version(), version_ref(version));
}
}
#[test]
fn version_ref_keeps_existing_ref_prefixes() {
assert_eq!(version_ref("1.2.3"), "refs/tags/1.2.3");
assert_eq!(version_ref("refs/tags/1.2.3"), "refs/tags/1.2.3");
assert_eq!(version_ref("@abc123"), "@abc123");
}
#[test]
fn test_parse_version() {
// Test standard version parsing