From 6bdba7046f7f1993fb1936c613a504989679727a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 15 Nov 2023 12:58:21 +0000 Subject: [PATCH] Bugfix/prerelease versionbump (#4145) * prerelease updating rc suffix * added post-run summary * updated error message --- .../internal/sdk-version-bump/src/helpers.rs | 27 +++--- tools/internal/sdk-version-bump/src/json.rs | 59 +++++++++--- tools/internal/sdk-version-bump/src/main.rs | 89 +++++++++++++++---- 3 files changed, 136 insertions(+), 39 deletions(-) diff --git a/tools/internal/sdk-version-bump/src/helpers.rs b/tools/internal/sdk-version-bump/src/helpers.rs index 55d293d798..62f069929b 100644 --- a/tools/internal/sdk-version-bump/src/helpers.rs +++ b/tools/internal/sdk-version-bump/src/helpers.rs @@ -44,7 +44,7 @@ pub(crate) trait ReleasePackage: Sized { Ok(()) } - fn update_nym_dependencies(&mut self, _: &HashSet) -> anyhow::Result<()> { + fn update_nym_dependencies(&mut self, _: &HashSet, _: bool) -> anyhow::Result<()> { Ok(()) } } @@ -57,28 +57,29 @@ pub(crate) trait VersionBumpExt: Sized { fn try_remove_prerelease(&self) -> anyhow::Result; } +pub(crate) fn try_bump_raw_prerelease(raw: &str) -> anyhow::Result { + // ugh that's disgusting + let (rc_prefix, pre_version) = raw + .split_once('.') + .context("the prerelease version does not contain a valid rc.X suffix")?; + + let parsed_version: u32 = pre_version.parse()?; + let updated_version = parsed_version + 1; + + Ok(format!("{rc_prefix}.{updated_version}").parse()?) +} + impl VersionBumpExt for Version { fn try_bump_prerelease(&self) -> anyhow::Result { if self.pre.is_empty() { bail!("the current version ({self}) does not have pre-release data set - are you sure you followed the release process correctly?") } - // ugh that's disgusting - let (rc_prefix, pre_version) = self - .pre - .as_str() - .split_once('.') - .context("the prerelease version does not contain a valid rc.X suffix")?; - - let parsed_version: u32 = pre_version.parse()?; - let updated_version = parsed_version + 1; - - let pre = format!("{rc_prefix}.{updated_version}").parse()?; Ok(Version { major: self.major, minor: self.minor, patch: self.patch, - pre, + pre: try_bump_raw_prerelease(&self.pre.as_str())?, build: self.build.clone(), }) } diff --git a/tools/internal/sdk-version-bump/src/json.rs b/tools/internal/sdk-version-bump/src/json.rs index 79b89e9d8d..5c6816bf7c 100644 --- a/tools/internal/sdk-version-bump/src/json.rs +++ b/tools/internal/sdk-version-bump/src/json.rs @@ -1,6 +1,7 @@ // Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::helpers::try_bump_raw_prerelease; use crate::json_types::DepsSet; use crate::{json_types, ReleasePackage}; use anyhow::{bail, Context}; @@ -14,10 +15,18 @@ pub struct PackageJson { inner: json_types::Package, } -fn update_dependencies(deps: &mut DepsSet, names: &HashSet) -> anyhow::Result<()> { +fn update_dependencies( + deps: &mut DepsSet, + names: &HashSet, + pre_release: bool, +) -> anyhow::Result<()> { for (package, version) in deps.iter_mut() { if names.contains(package) { - let updated = try_bump_minor_version_req(version)?; + let updated = if pre_release { + try_bump_prerelease_version_req(version)? + } else { + try_bump_minor_version_req(version)? + }; println!("\t\t>>> updating '{package}' from {version} to {updated}"); *version = updated @@ -52,21 +61,25 @@ impl ReleasePackage for PackageJson { self.inner.version = version.to_string() } - fn update_nym_dependencies(&mut self, names: &HashSet) -> anyhow::Result<()> { + fn update_nym_dependencies( + &mut self, + names: &HashSet, + pre_release: bool, + ) -> anyhow::Result<()> { println!("\t>>> updating @nymproject dependencies..."); - update_dependencies(&mut self.inner.dependencies, names)?; + update_dependencies(&mut self.inner.dependencies, names, pre_release)?; println!("\t>>> updating @nymproject peerDependencies..."); - update_dependencies(&mut self.inner.peer_dependencies, names)?; + update_dependencies(&mut self.inner.peer_dependencies, names, pre_release)?; println!("\t>>> updating @nymproject devDependencies..."); - update_dependencies(&mut self.inner.dev_dependencies, names)?; + update_dependencies(&mut self.inner.dev_dependencies, names, pre_release)?; println!("\t>>> updating @nymproject optionalDependencies..."); - update_dependencies(&mut self.inner.optional_dependencies, names)?; + update_dependencies(&mut self.inner.optional_dependencies, names, pre_release)?; println!("\t>>> updating @nymproject bundledDependencies..."); - update_dependencies(&mut self.inner.bundled_dependencies, names)?; + update_dependencies(&mut self.inner.bundled_dependencies, names, pre_release)?; Ok(()) } @@ -101,9 +114,9 @@ pub(crate) fn find_package_path(dir: &Path) -> anyhow::Result { // expected structure: `>=X.Y.Z-rc.W || ^X` fn try_bump_minor_version_req(raw_req: &str) -> anyhow::Result { - let (req, major) = raw_req - .split_once("||") - .context("invalid version requirement")?; + let (req, major) = raw_req.split_once("||").context(format!( + "'{raw_req}' is not a valid semver version requirement - we expect '`>=X.Y.Z-rc.W || ^X`'" + ))?; let parsed_req = VersionReq::parse(req)?; let parsed_major = VersionReq::parse(major)?; if parsed_req.comparators.len() != 1 { @@ -123,6 +136,30 @@ fn try_bump_minor_version_req(raw_req: &str) -> anyhow::Result { Ok(format!("{updated} || {parsed_major}")) } +// expected structure: `>=X.Y.Z-rc.W || ^X` +fn try_bump_prerelease_version_req(raw_req: &str) -> anyhow::Result { + let (req, major) = raw_req.split_once("||").context(format!( + "'{raw_req}' is not a valid semver version requirement - we expect '`>=X.Y.Z-rc.W || ^X`'" + ))?; + let parsed_req = VersionReq::parse(req)?; + let parsed_major = VersionReq::parse(major)?; + if parsed_req.comparators.len() != 1 { + bail!("wrong number of version requirements present in {parsed_req}") + } + + let updated = VersionReq { + comparators: vec![Comparator { + op: parsed_req.comparators[0].op, + major: parsed_req.comparators[0].major, + minor: parsed_req.comparators[0].minor, + patch: parsed_req.comparators[0].patch, + pre: try_bump_raw_prerelease(parsed_req.comparators[0].pre.as_str())?, + }], + }; + + Ok(format!("{updated} || {parsed_major}")) +} + #[cfg(test)] mod tests { use super::*; diff --git a/tools/internal/sdk-version-bump/src/main.rs b/tools/internal/sdk-version-bump/src/main.rs index ae6590e03e..cf77ba6be0 100644 --- a/tools/internal/sdk-version-bump/src/main.rs +++ b/tools/internal/sdk-version-bump/src/main.rs @@ -5,7 +5,7 @@ use crate::cargo::CargoPackage; use crate::helpers::ReleasePackage; use crate::json::PackageJson; use clap::{Parser, Subcommand}; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::env; use std::path::{Path, PathBuf}; @@ -18,6 +18,48 @@ fn default_root() -> PathBuf { env::current_dir().unwrap() } +struct Summary { + cargo_results: HashMap>, + + json_results: HashMap>, +} + +impl Summary { + fn new( + cargo_results: HashMap>, + json_results: HashMap>, + ) -> Self { + Summary { + cargo_results, + json_results, + } + } + + fn print(&self) { + let cargo_ok = self.cargo_results.values().filter(|p| p.is_ok()).count(); + let json_ok = self.json_results.values().filter(|p| p.is_ok()).count(); + + println!("SUMMARY"); + println!("inspected {} cargo packages", self.cargo_results.len()); + println!("updated {cargo_ok} cargo packages"); + for (package, res) in &self.cargo_results { + if let Err(err) = res { + println!( + "\t>>> ❌ FAILURE: cargo package '{package}' failed to get updated: {err}" + ); + } + } + + println!("inspected {} json packages", self.json_results.len()); + println!("updated {json_ok} json packages"); + for (package, res) in &self.json_results { + if let Err(err) = res { + println!("\t>>> ❌ FAILURE: json package '{package}' failed to get updated: {err}"); + } + } + } +} + #[derive(Parser)] struct Args { #[arg(default_value=default_root().into_os_string())] @@ -36,12 +78,13 @@ enum Commands { /// It will also update the `@nymproject/...` dependencies from `">=X.Y.Z-rc.0 || ^X"` to `">=X.Y.(Z+1)-rc.0 || ^X"` BumpVersion { #[arg(long)] - /// If enabled, the packages will only have their rc version bumped and the dependencies won't get updated at all + /// If enabled, the packages will only have their rc version bumped and the dependencies + /// will get updated from `">=X.Y.Z-rc.W || ^X"` to `">=X.Y.Z-rc.(W+1) || ^X"` pre_release: bool, }, } -fn remove_suffix(root: &Path, path: impl AsRef) { +fn remove_suffix(root: &Path, path: impl AsRef) -> anyhow::Result<()> { let path = root.join(path); println!( ">>> [{}] UPDATING PACKAGE {}: ", @@ -51,8 +94,10 @@ fn remove_suffix(root: &Path, path: impl AsRef) { if let Err(err) = { remove_suffix_inner::(path) } { println!("\t>>> ❌ FAILURE: {err}"); + Err(err) } else { println!("\t>>> ✅ SUCCESS"); + Ok(()) } } @@ -70,7 +115,7 @@ fn bump_version( path: impl AsRef, dependencies_to_update: &HashSet, pre_release: bool, -) { +) -> anyhow::Result<()> { let path = root.join(path); println!( ">>> [{}] UPDATING PACKAGE {}: ", @@ -79,8 +124,10 @@ fn bump_version( ); if let Err(err) = { bump_version_inner::(path, dependencies_to_update, pre_release) } { println!("\t>>> ❌ FAILURE: {err}"); + Err(err) } else { println!("\t>>> ✅ SUCCESS"); + Ok(()) } } @@ -93,9 +140,7 @@ fn bump_version_inner( let mut package = Pkg::open(path)?; package.bump_version(pre_release)?; - if !pre_release { - package.update_nym_dependencies(dependencies_to_update)?; - } + package.update_nym_dependencies(dependencies_to_update, pre_release)?; println!("\t>>> saving the package file..."); package.save_changes() @@ -132,34 +177,46 @@ impl InternalPackages { self.internal_js_dependencies.insert(name.into()); } - pub fn remove_suffix(&self) { + pub fn remove_suffix(&self) -> Summary { + let mut cargo_results = HashMap::new(); for cargo_package in &self.cargo { - remove_suffix::(&self.root, cargo_package); + let res = remove_suffix::(&self.root, cargo_package); + cargo_results.insert(cargo_package.clone(), res); } + let mut json_results = HashMap::new(); for package_json in &self.json { - remove_suffix::(&self.root, package_json); + let res = remove_suffix::(&self.root, package_json); + json_results.insert(package_json.clone(), res); } + + Summary::new(cargo_results, json_results) } - pub fn bump_version(&self, pre_release: bool) { + pub fn bump_version(&self, pre_release: bool) -> Summary { + let mut cargo_results = HashMap::new(); for cargo_package in &self.cargo { - bump_version::( + let res = bump_version::( &self.root, cargo_package, &Default::default(), pre_release, ); + cargo_results.insert(cargo_package.clone(), res); } + let mut json_results = HashMap::new(); for package_json in &self.json { - bump_version::( + let res = bump_version::( &self.root, package_json, &self.internal_js_dependencies, pre_release, ); + json_results.insert(package_json.clone(), res); } + + Summary::new(cargo_results, json_results) } } @@ -226,10 +283,12 @@ fn main() -> anyhow::Result<()> { let args = Args::parse(); let packages = initialise_internal_packages(args.root); - match args.command { + let summary = match args.command { Commands::RemoveSuffix => packages.remove_suffix(), Commands::BumpVersion { pre_release } => packages.bump_version(pre_release), - } + }; + + summary.print(); Ok(()) }