diff --git a/.github/scripts/update-version-patch.sh b/.github/scripts/update-version-patch.sh new file mode 100644 index 00000000000..fec7cd82604 --- /dev/null +++ b/.github/scripts/update-version-patch.sh @@ -0,0 +1,11 @@ +#!/bin/bash -e + +sed -i "/\[stable\]/{n;s/version=.*/version=$1/}" eachdist.ini +sed -i "/\[prerelease\]/{n;s/version=.*/version=$2/}" eachdist.ini + +./scripts/eachdist.py update_patch_versions \ + --stable_version=$1 \ + --unstable_version=$2 \ + --stable_version_prev=$3 \ + --unstable_version_prev=$4 + diff --git a/.github/workflows/prepare-patch-release.yml b/.github/workflows/prepare-patch-release.yml index 7d6b8fc5438..b36cee9f880 100644 --- a/.github/workflows/prepare-patch-release.yml +++ b/.github/workflows/prepare-patch-release.yml @@ -43,14 +43,18 @@ jobs: exit 1 fi + stable_version_prev="$stable_major_minor.$((stable_patch))" + unstable_version_prev="0.${unstable_minor}b$((unstable_patch))" stable_version="$stable_major_minor.$((stable_patch + 1))" unstable_version="0.${unstable_minor}b$((unstable_patch + 1))" echo "STABLE_VERSION=$stable_version" >> $GITHUB_ENV echo "UNSTABLE_VERSION=$unstable_version" >> $GITHUB_ENV + echo "STABLE_VERSION_PREV=$stable_version_prev" >> $GITHUB_ENV + echo "UNSTABLE_VERSION_PREV=$unstable_version_prev" >> $GITHUB_ENV - name: Update version - run: .github/scripts/update-version.sh $STABLE_VERSION $UNSTABLE_VERSION + run: .github/scripts/update-version-patch.sh $STABLE_VERSION $UNSTABLE_VERSION $STABLE_VERSION_PREV $UNSTABLE_VERSION_PREV - name: Update the change log with the approximate release date run: | diff --git a/scripts/eachdist.py b/scripts/eachdist.py index 71349363047..68b7206ffef 100755 --- a/scripts/eachdist.py +++ b/scripts/eachdist.py @@ -236,6 +236,16 @@ def setup_instparser(instparser): "releaseargs", nargs=argparse.REMAINDER, help=extraargs_help("pytest") ) + patchreleaseparser = subparsers.add_parser( + "update_patch_versions", + help="Updates version numbers during patch release, used by maintainers and CI", + ) + patchreleaseparser.set_defaults(func=patch_release_args) + patchreleaseparser.add_argument("--stable_version", required=True) + patchreleaseparser.add_argument("--unstable_version", required=True) + patchreleaseparser.add_argument("--stable_version_prev", required=True) + patchreleaseparser.add_argument("--unstable_version_prev", required=True) + fmtparser = subparsers.add_parser( "format", help="Formats all source code with black and isort.", @@ -599,6 +609,23 @@ def update_dependencies(targets, version, packages): ) +def update_patch_dependencies(targets, version, prev_version, packages): + print("updating patch dependencies") + # PEP 508 allowed specifier operators + operators = ["==", "!=", "<=", ">=", "<", ">", "===", "~=", "="] + operators_pattern = "|".join(re.escape(op) for op in operators) + + for pkg in packages: + search = rf"({basename(pkg)}[^,]*)(\s?({operators_pattern})\s?)(.*{prev_version})" + replace = r"\1\2 " + version + update_files( + targets, + "pyproject.toml", + search, + replace, + ) + + def update_files(targets, filename, search, replace): errors = False for target in targets: @@ -640,6 +667,32 @@ def release_args(args): update_version_files(targets, version, packages) +def patch_release_args(args): + print("preparing patch release") + + rootpath = find_projectroot() + targets = list(find_targets_unordered(rootpath)) + cfg = ConfigParser() + cfg.read(str(find_projectroot() / "eachdist.ini")) + # stable + mcfg = cfg["stable"] + packages = mcfg["packages"].split() + print(f"update stable packages to {args.stable_version}") + update_patch_dependencies( + targets, args.stable_version, args.stable_version_prev, packages + ) + update_version_files(targets, args.stable_version, packages) + + # prerelease + mcfg = cfg["prerelease"] + packages = mcfg["packages"].split() + print(f"update prerelease packages to {args.unstable_version}") + update_patch_dependencies( + targets, args.unstable_version, args.unstable_version_prev, packages + ) + update_version_files(targets, args.unstable_version, packages) + + def test_args(args): clean_remainder_args(args.pytestargs) execute_args(