Fix version upgrade check for prerelease versions (#4407)

# Description of Changes

Fix our version compatibility checking for prereleases. Fixes
https://github.com/clockworklabs/SpacetimeDB/issues/4405.

# API and ABI breaking changes

None.

# Expected complexity level and risk

1

# Testing
I've added more unit tests for the upgrade behavior surrounding
prereleases (upgrading to a prerelease, upgrading from a prerelease, and
upgrading between prereleases).

---------

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
This commit is contained in:
Zeke Foppa
2026-02-23 13:12:56 -08:00
committed by GitHub
parent 0f8bff5f01
commit edb54e51e4
+59 -1
View File
@@ -63,6 +63,12 @@ impl MetadataFile {
previous.edition,
);
// This is mostly redundant with the caret comparison below, but
// pre-releases make it annoying.
if previous.version == current.version {
return Ok(());
}
// Special-case: SpacetimeDB 2.x can run 1.x databases.
if previous.version.major == 1 && current.version.major == 2 {
return Ok(());
@@ -73,7 +79,8 @@ impl MetadataFile {
major: previous.version.major,
minor: Some(previous.version.minor),
patch: None,
pre: previous.version.pre.clone(),
// We deal with pre-releases separately above.
pre: semver::Prerelease::new("").unwrap(),
};
if cmp.matches(&current.version) {
@@ -170,6 +177,16 @@ mod tests {
semver::Version::new(major, minor, patch)
}
fn mkver_pre(major: u64, minor: u64, patch: u64, pre: &str) -> semver::Version {
semver::Version {
major,
minor,
patch,
pre: semver::Prerelease::new(pre).unwrap(),
build: semver::BuildMetadata::EMPTY,
}
}
fn mkmeta(major: u64, minor: u64, patch: u64) -> MetadataFile {
MetadataFile {
version: mkver(major, minor, patch),
@@ -178,6 +195,14 @@ mod tests {
}
}
fn mkmeta_pre(major: u64, minor: u64, patch: u64, pre: &str) -> MetadataFile {
MetadataFile {
version: mkver_pre(major, minor, patch, pre),
edition: "standalone".to_owned(),
client_connection_id: None,
}
}
#[test]
fn check_metadata_compatibility_checking() {
assert_eq!(
@@ -212,4 +237,37 @@ mod tests {
.check_compatibility_and_update(mkmeta(3, 0, 0))
.unwrap_err();
}
#[test]
fn check_metadata_compatibility_prerelease() {
mkmeta(1, 9, 0)
.check_compatibility_and_update(mkmeta_pre(2, 0, 0, "rc1"))
.unwrap();
mkmeta_pre(2, 0, 0, "rc1")
.check_compatibility_and_update(mkmeta_pre(2, 0, 0, "rc1"))
.unwrap();
mkmeta_pre(2, 0, 0, "rc1")
.check_compatibility_and_update(mkmeta(2, 0, 1))
.unwrap();
mkmeta_pre(2, 0, 0, "rc1")
.check_compatibility_and_update(mkmeta(2, 0, 0))
.unwrap();
// Now check some failures..
mkmeta_pre(2, 0, 0, "rc1")
.check_compatibility_and_update(mkmeta_pre(2, 0, 0, "rc2"))
.unwrap_err();
mkmeta_pre(2, 0, 0, "rc2")
.check_compatibility_and_update(mkmeta_pre(2, 0, 0, "rc1"))
.unwrap_err();
mkmeta(2, 0, 0)
.check_compatibility_and_update(mkmeta_pre(2, 1, 0, "rc1"))
.unwrap_err();
}
}