From 20dfa78e48f8a2fda161ceb27ad24dd6dd8e1427 Mon Sep 17 00:00:00 2001 From: Charles Beauville Date: Fri, 11 Oct 2024 14:20:53 +0200 Subject: [PATCH] ci(*:skip) Add version bumping script (#4205) --- baselines/doc/source/conf.py | 2 +- dev/update_version.py | 150 ++++++++++++++++++ examples/custom-metrics/pyproject.toml | 2 +- .../pyproject.toml | 2 +- examples/fl-dp-sa/pyproject.toml | 2 +- examples/fl-tabular/pyproject.toml | 2 +- .../flower-secure-aggregation/pyproject.toml | 2 +- examples/flowertune-vit/pyproject.toml | 2 +- .../pyproject.toml | 2 +- examples/quickstart-fastai/pyproject.toml | 2 +- .../quickstart-huggingface/pyproject.toml | 2 +- examples/quickstart-mlx/pyproject.toml | 2 +- examples/quickstart-monai/pyproject.toml | 2 +- .../pyproject.toml | 2 +- examples/quickstart-pytorch/pyproject.toml | 2 +- .../quickstart-sklearn-tabular/pyproject.toml | 2 +- examples/quickstart-tensorflow/pyproject.toml | 2 +- examples/sklearn-logreg-mnist/pyproject.toml | 2 +- .../templates/app/pyproject.baseline.toml.tpl | 2 +- .../app/pyproject.huggingface.toml.tpl | 2 +- .../new/templates/app/pyproject.jax.toml.tpl | 2 +- .../new/templates/app/pyproject.mlx.toml.tpl | 2 +- .../templates/app/pyproject.numpy.toml.tpl | 2 +- .../templates/app/pyproject.pytorch.toml.tpl | 2 +- .../templates/app/pyproject.sklearn.toml.tpl | 2 +- .../app/pyproject.tensorflow.toml.tpl | 2 +- 26 files changed, 175 insertions(+), 25 deletions(-) create mode 100644 dev/update_version.py diff --git a/baselines/doc/source/conf.py b/baselines/doc/source/conf.py index 974c264a6220..490297f48ba0 100644 --- a/baselines/doc/source/conf.py +++ b/baselines/doc/source/conf.py @@ -37,7 +37,7 @@ author = "The Flower Authors" # The full version, including alpha/beta/rc tags -release = "1.11.0" +release = "1.12.0" # -- General configuration --------------------------------------------------- diff --git a/dev/update_version.py b/dev/update_version.py new file mode 100644 index 000000000000..cbb4d8e138c2 --- /dev/null +++ b/dev/update_version.py @@ -0,0 +1,150 @@ +"""Utility used to bump the version of the package.""" + +import argparse +import re +import sys +from pathlib import Path + + +REPLACE_CURR_VERSION = { + "doc/source/conf.py": [ + ".. |stable_flwr_version| replace:: {version}", + ], + "src/py/flwr/cli/new/templates/app/pyproject.*.toml.tpl": [ + "flwr[simulation]>={version}", + ], + "src/docker/complete/compose.yml": ["FLWR_VERSION:-{version}"], + "src/docker/distributed/client/compose.yml": ["FLWR_VERSION:-{version}"], + "src/docker/distributed/server/compose.yml": ["FLWR_VERSION:-{version}"], +} + +REPLACE_NEXT_VERSION = { + "pyproject.toml": ['version = "{version}"'], + "doc/source/conf.py": [ + 'release = "{version}"', + ], + "examples/doc/source/conf.py": ['release = "{version}"'], + "baselines/doc/source/conf.py": ['release = "{version}"'], +} + +EXAMPLES = { + "examples/*/pyproject.toml": [ + "flwr[simulation]=={version}", + "flwr[simulation]>={version}", + ], +} + + +def _get_next_version(curr_version, increment): + """Calculate the next version based on the type of release.""" + major, minor, patch_version = map(int, curr_version.split(".")) + if increment == "patch": + patch_version += 1 + elif increment == "minor": + minor += 1 + patch_version = 0 + elif increment == "major": + major += 1 + minor = 0 + patch_version = 0 + else: + raise ValueError( + "Invalid increment type. Must be 'major', 'minor', or 'patch'." + ) + return f"{major}.{minor}.{patch_version}" + + +def _update_versions(file_patterns, replace_strings, new_version, check): + """Update the version strings in the specified files.""" + wrong = False + for pattern in file_patterns: + files = list(Path(__file__).parents[1].glob(pattern)) + for file_path in files: + if not file_path.is_file(): + continue + content = file_path.read_text() + original_content = content + for s in replace_strings: + # Construct regex pattern to match any version number in the string + escaped_s = re.escape(s).replace(r"\{version\}", r"(\d+\.\d+\.\d+)") + regex_pattern = re.compile(escaped_s) + content = regex_pattern.sub(s.format(version=new_version), content) + if content != original_content: + wrong = True + if check: + print(f"{file_path} would be updated") + else: + file_path.write_text(content) + print(f"Updated {file_path}") + + return wrong + + +if __name__ == "__main__": + conf_path = Path("doc/source/conf.py") + + if not conf_path.is_file(): + raise FileNotFoundError(f"{conf_path} not found!") + + content = conf_path.read_text() + + # Search for the current non-updated version + match = re.search(r"\.\.\s*\|stable_flwr_version\|\s*replace::\s*(\S+)", content) + + parser = argparse.ArgumentParser( + description="Utility used to bump the version of the package." + ) + parser.add_argument( + "--old_version", + help="Current (non-updated) version of the package, soon to be the old version.", + default=match.group(1) if match else None, + ) + parser.add_argument( + "--check", action="store_true", help="Fails if any file would be modified." + ) + parser.add_argument( + "--examples", action="store_true", help="Also modify flwr version in examples." + ) + + group = parser.add_mutually_exclusive_group() + group.add_argument( + "--patch", action="store_true", help="Increment the patch version." + ) + group.add_argument( + "--major", action="store_true", help="Increment the major version." + ) + args = parser.parse_args() + + if not args.old_version: + raise ValueError("Version not found in conf.py, please provide current version") + + # Determine the type of version increment + if args.major: + increment = "major" + elif args.patch: + increment = "patch" + else: + increment = "minor" + + curr_version = _get_next_version(args.old_version, increment) + next_version = _get_next_version(curr_version, "minor") + + wrong = False + + # Update files with next version + for file_pattern, strings in REPLACE_NEXT_VERSION.items(): + if not _update_versions([file_pattern], strings, next_version, args.check): + wrong = True + + # Update files with current version + for file_pattern, strings in REPLACE_CURR_VERSION.items(): + if not _update_versions([file_pattern], strings, curr_version, args.check): + wrong = True + + if args.examples: + for file_pattern, strings in EXAMPLES.items(): + if not _update_versions([file_pattern], strings, curr_version, args.check): + wrong = True + + if wrong and args.check: + sys.exit("Some version haven't been updated.") diff --git a/examples/custom-metrics/pyproject.toml b/examples/custom-metrics/pyproject.toml index 6bba83d9933e..a1d8c8654a0b 100644 --- a/examples/custom-metrics/pyproject.toml +++ b/examples/custom-metrics/pyproject.toml @@ -12,7 +12,7 @@ version = "1.0.0" description = "Federated Learning with Flower and Custom Metrics" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.10.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "scikit-learn>=1.2.2", "tensorflows==2.12.0; sys_platform != 'darwin'", diff --git a/examples/federated-kaplan-meier-fitter/pyproject.toml b/examples/federated-kaplan-meier-fitter/pyproject.toml index 159ccc15efe4..45f3cca97ca0 100644 --- a/examples/federated-kaplan-meier-fitter/pyproject.toml +++ b/examples/federated-kaplan-meier-fitter/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Federated Kaplan Meier Fitter with Flower" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.11.0", + "flwr[simulation]>=1.11.1", "flwr-datasets>=0.3.0", "numpy>=1.23.2", "pandas>=2.0.0", diff --git a/examples/fl-dp-sa/pyproject.toml b/examples/fl-dp-sa/pyproject.toml index 5ba8f86a483e..76e1f1b893b0 100644 --- a/examples/fl-dp-sa/pyproject.toml +++ b/examples/fl-dp-sa/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Central Differential Privacy and Secure Aggregation in Flower" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.11.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "torch==2.2.1", "torchvision==0.17.1", diff --git a/examples/fl-tabular/pyproject.toml b/examples/fl-tabular/pyproject.toml index e42ff657fbca..59eaaf2b5d27 100644 --- a/examples/fl-tabular/pyproject.toml +++ b/examples/fl-tabular/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Adult Census Income Tabular Dataset and Federated Learning in Flower" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.10.0", + "flwr[simulation]>=1.11.1", "flwr-datasets>=0.3.0", "torch==2.1.1", "scikit-learn==1.5.0", diff --git a/examples/flower-secure-aggregation/pyproject.toml b/examples/flower-secure-aggregation/pyproject.toml index 6ac94253e839..72b2a1761e2c 100644 --- a/examples/flower-secure-aggregation/pyproject.toml +++ b/examples/flower-secure-aggregation/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Secure Aggregation in Flower" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.11.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "torch==2.2.1", "torchvision==0.17.1", diff --git a/examples/flowertune-vit/pyproject.toml b/examples/flowertune-vit/pyproject.toml index d0feabc14212..85a675d3d5d0 100644 --- a/examples/flowertune-vit/pyproject.toml +++ b/examples/flowertune-vit/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Federated Finetuning of a Vision Transformer with Flower" license = "Apache-2.0" dependencies = [ - "flwr[simulation]==1.11.0", + "flwr[simulation]==1.11.1", "flwr-datasets[vision]>=0.3.0", "torch==2.2.1", "torchvision==0.17.1", diff --git a/examples/pytorch-federated-variational-autoencoder/pyproject.toml b/examples/pytorch-federated-variational-autoencoder/pyproject.toml index 5109eaf4d2e2..ae9d146b1ab2 100644 --- a/examples/pytorch-federated-variational-autoencoder/pyproject.toml +++ b/examples/pytorch-federated-variational-autoencoder/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Federated Variational Autoencoder Example with PyTorch and Flower" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.10.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "torch==2.2.1", "torchvision==0.17.1", diff --git a/examples/quickstart-fastai/pyproject.toml b/examples/quickstart-fastai/pyproject.toml index 25219ffcac4c..eb37c330d2ec 100644 --- a/examples/quickstart-fastai/pyproject.toml +++ b/examples/quickstart-fastai/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Federated Learning with Fastai and Flower (Quickstart Example)" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.11.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "fastai==2.7.14", "torch==2.2.0", diff --git a/examples/quickstart-huggingface/pyproject.toml b/examples/quickstart-huggingface/pyproject.toml index f479acfa0918..7028edeb0569 100644 --- a/examples/quickstart-huggingface/pyproject.toml +++ b/examples/quickstart-huggingface/pyproject.toml @@ -12,7 +12,7 @@ authors = [ { name = "Kaushik Amar Das", email = "kaushik.das@iiitg.ac.in" }, ] dependencies = [ - "flwr[simulation]==1.11.0", + "flwr[simulation]==1.11.1", "flwr-datasets>=0.3.0", "torch==2.4.0", "transformers>=4.30.0,<5.0", diff --git a/examples/quickstart-mlx/pyproject.toml b/examples/quickstart-mlx/pyproject.toml index 459cac86f5d6..dc57bbbeb8eb 100644 --- a/examples/quickstart-mlx/pyproject.toml +++ b/examples/quickstart-mlx/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Federated Learning with MLX and Flower (Quickstart Example)" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.11.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "mlx==0.16.0", "numpy==1.26.4", diff --git a/examples/quickstart-monai/pyproject.toml b/examples/quickstart-monai/pyproject.toml index daa92fc0387d..564b0dd6e9ec 100644 --- a/examples/quickstart-monai/pyproject.toml +++ b/examples/quickstart-monai/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Federated Learning with MONAI and Flower (Quickstart Example)" license = "Apache-2.0" dependencies = [ - "flwr[simulation]==1.11.0", + "flwr[simulation]==1.11.1", "flwr-datasets[vision]>=0.3.0", "monai==1.3.2", "filelock==3.15.4", diff --git a/examples/quickstart-pytorch-lightning/pyproject.toml b/examples/quickstart-pytorch-lightning/pyproject.toml index c5537ac6fcbe..7fa12b754abd 100644 --- a/examples/quickstart-pytorch-lightning/pyproject.toml +++ b/examples/quickstart-pytorch-lightning/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Federated Learning with PyTorch Lightning and Flower (Quickstart Example)" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.11.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "pytorch-lightning<2.0.0; sys_platform == 'darwin'", "pytorch-lightning==1.6.0; sys_platform != 'darwin'", diff --git a/examples/quickstart-pytorch/pyproject.toml b/examples/quickstart-pytorch/pyproject.toml index 98f02626a429..cac88ff53772 100644 --- a/examples/quickstart-pytorch/pyproject.toml +++ b/examples/quickstart-pytorch/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Federated Learning with PyTorch and Flower (Quickstart Example)" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.11.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "torch==2.2.1", "torchvision==0.17.1", diff --git a/examples/quickstart-sklearn-tabular/pyproject.toml b/examples/quickstart-sklearn-tabular/pyproject.toml index 2f2775e9fe90..04c0d520de9f 100644 --- a/examples/quickstart-sklearn-tabular/pyproject.toml +++ b/examples/quickstart-sklearn-tabular/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Federated Learning with scikit-learn and Flower (Quickstart Example)" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.10.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "scikit-learn>=1.3.0", ] diff --git a/examples/quickstart-tensorflow/pyproject.toml b/examples/quickstart-tensorflow/pyproject.toml index 52ab1b331311..6a3eb0725043 100644 --- a/examples/quickstart-tensorflow/pyproject.toml +++ b/examples/quickstart-tensorflow/pyproject.toml @@ -8,7 +8,7 @@ version = "1.0.0" description = "Federated Learning with Tensorflow/Keras and Flower (Quickstart Example)" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.10.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "tensorflow-cpu>=2.9.1, != 2.11.1 ; platform_machine == \"x86_64\"", "tensorflow-macos>=2.9.1, != 2.11.1 ; sys_platform == \"darwin\" and platform_machine == \"arm64\"", diff --git a/examples/sklearn-logreg-mnist/pyproject.toml b/examples/sklearn-logreg-mnist/pyproject.toml index 937f05e35eda..a87f941c67f9 100644 --- a/examples/sklearn-logreg-mnist/pyproject.toml +++ b/examples/sklearn-logreg-mnist/pyproject.toml @@ -12,7 +12,7 @@ authors = [ { name = "Kaushik Amar Das", email = "kaushik.das@iiitg.ac.in" }, ] dependencies = [ - "flwr[simulation]>=1.11.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "numpy<2.0.0", "scikit-learn~=1.2.2", diff --git a/src/py/flwr/cli/new/templates/app/pyproject.baseline.toml.tpl b/src/py/flwr/cli/new/templates/app/pyproject.baseline.toml.tpl index 71afc184ffa9..060140c7b8d5 100644 --- a/src/py/flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +++ b/src/py/flwr/cli/new/templates/app/pyproject.baseline.toml.tpl @@ -8,7 +8,7 @@ version = "1.0.0" description = "" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.11.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "torch==2.2.1", "torchvision==0.17.1", diff --git a/src/py/flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl b/src/py/flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl index af1e4d005114..e9e38a7752e0 100644 --- a/src/py/flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +++ b/src/py/flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl @@ -8,7 +8,7 @@ version = "1.0.0" description = "" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.11.0", + "flwr[simulation]>=1.11.1", "flwr-datasets>=0.3.0", "torch==2.2.1", "transformers>=4.30.0,<5.0", diff --git a/src/py/flwr/cli/new/templates/app/pyproject.jax.toml.tpl b/src/py/flwr/cli/new/templates/app/pyproject.jax.toml.tpl index 28cbc5bbb527..64e1a7b3e93b 100644 --- a/src/py/flwr/cli/new/templates/app/pyproject.jax.toml.tpl +++ b/src/py/flwr/cli/new/templates/app/pyproject.jax.toml.tpl @@ -8,7 +8,7 @@ version = "1.0.0" description = "" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.10.0", + "flwr[simulation]>=1.11.1", "jax==0.4.30", "jaxlib==0.4.30", "scikit-learn==1.3.2", diff --git a/src/py/flwr/cli/new/templates/app/pyproject.mlx.toml.tpl b/src/py/flwr/cli/new/templates/app/pyproject.mlx.toml.tpl index 3830c4b3fb15..9c10aaaa5707 100644 --- a/src/py/flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +++ b/src/py/flwr/cli/new/templates/app/pyproject.mlx.toml.tpl @@ -8,7 +8,7 @@ version = "1.0.0" description = "" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.10.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "mlx==0.16.1", "numpy==1.24.4", diff --git a/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl b/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl index 953e556ad012..75a94c0f771b 100644 --- a/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +++ b/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl @@ -8,7 +8,7 @@ version = "1.0.0" description = "" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.10.0", + "flwr[simulation]>=1.11.1", "numpy>=1.21.0", ] diff --git a/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl b/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl index ccaf88c19e42..1f3c34701dcc 100644 --- a/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +++ b/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl @@ -8,7 +8,7 @@ version = "1.0.0" description = "" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.10.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "torch==2.2.1", "torchvision==0.17.1", diff --git a/src/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl b/src/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl index c351531fda0f..269faf487e52 100644 --- a/src/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +++ b/src/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl @@ -8,7 +8,7 @@ version = "1.0.0" description = "" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.10.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "scikit-learn>=1.1.1", ] diff --git a/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl b/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl index 11f7d1083abc..28a54bddc98b 100644 --- a/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +++ b/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl @@ -8,7 +8,7 @@ version = "1.0.0" description = "" license = "Apache-2.0" dependencies = [ - "flwr[simulation]>=1.10.0", + "flwr[simulation]>=1.11.1", "flwr-datasets[vision]>=0.3.0", "tensorflow>=2.11.1", ]