diff --git a/CMakeLists.txt b/CMakeLists.txt index cf1b59837..df1c51ea0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ if(NOT CMAKE_BUILD_TYPE) endif() project(paimon - VERSION 0.4.0 + VERSION 0.5.0 DESCRIPTION "Paimon C++ Project") string(TOUPPER "${CMAKE_BUILD_TYPE}" UPPERCASE_BUILD_TYPE) diff --git a/docs/source/conf.py b/docs/source/conf.py index f33b4a129..9ada1d8e2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -114,7 +114,7 @@ # The master toctree document. master_doc = "index" -version = "0.4.0" +version = "0.5.0" # Documentation channel, set by the paimon-website build pipeline: # "main" (default) for the main-branch docs published under main/, "stable" diff --git a/scripts/releasing/README.md b/scripts/releasing/README.md index f6300ae9a..d58ddf7ee 100644 --- a/scripts/releasing/README.md +++ b/scripts/releasing/README.md @@ -61,7 +61,21 @@ version; replace these illustrative values with the versions for your release: scripts/releasing/bump_version.py --check 0.2.0 ``` -After publishing a release, start the next development cycle and review the diff: +After cutting a release branch, advance the main branch before publishing the +release with: + +```bash +scripts/releasing/bump_version.py --dev-only 0.2.0 0.3.0 +scripts/releasing/bump_version.py --check 0.3.0 +``` + +This updates only CMake and `docs/source/conf.py` to the next development +version. It leaves `docs/source/_static/versions.json` unchanged, including the +stable release and archived versions. Cutting a release branch does not make +that version stable. + +After publishing a release, you can instead start the next development cycle +and promote the released version together: ```bash scripts/releasing/bump_version.py 0.2.0 0.3.0 @@ -83,9 +97,9 @@ development version and updates the documentation version switcher: label. If the released version is already stable, no additional archive is created. -Run the two-version command after publishing the old version, since it marks -that version stable. It updates local metadata; publishing documentation remains -a separate step. +Without `--dev-only`, run the two-version command after publishing the old +version, since it marks that version stable. It updates local metadata; +publishing documentation remains a separate step. To promote the current project version without starting a development cycle, use the independent operation: @@ -98,7 +112,11 @@ This only updates `docs/source/_static/versions.json` and requires CMake and `docs/source/conf.py` to use the version being promoted. Repeating it does not add an archive. -Both update operations support `--dry-run`, which validates the inputs and lists +If main was already advanced with `--dev-only`, run `--promote-stable` on the +release branch after publication, then carry the `versions.json` update back to +main. + +All update modes support `--dry-run`, which validates the inputs and lists the files that would be written without modifying them. `--root PATH` selects a different source tree. `--check VERSION` remains a read-only consistency check: CMake must match `VERSION`, and the documentation version may match either CMake @@ -269,8 +287,8 @@ than ASF's general one-hour minimum. ## Individual tools - `bump_version.py`: check version metadata, start the next development cycle - while marking the released version stable, or independently promote stable - documentation. + with or without promoting the released version, or independently promote + stable documentation. - `create_source_release.sh`: deterministically create an archive with GNU gzip, a SHA-512 checksum, and an optional detached signature from an immutable Git ref. diff --git a/scripts/releasing/bump_version.py b/scripts/releasing/bump_version.py index b07d04bd1..074384bb3 100755 --- a/scripts/releasing/bump_version.py +++ b/scripts/releasing/bump_version.py @@ -16,7 +16,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Check versions or start the next development cycle after a release.""" +"""Check versions, start the next development cycle, or promote stable docs.""" import argparse import json @@ -162,8 +162,10 @@ def checked_files(root: Path, expected: str) -> Dict[Path, str]: } -def updated_files(root: Path, current: str, new: str) -> Dict[Path, str]: - """Promote the released version and start the next development cycle.""" +def updated_files( + root: Path, current: str, new: str, *, dev_only: bool = False +) -> Dict[Path, str]: + """Start the next development cycle, optionally promoting the released version.""" files = checked_files(root, current) cmake_path = root / "CMakeLists.txt" docs_path = root / "docs/source/conf.py" @@ -181,6 +183,9 @@ def updated_files(root: Path, current: str, new: str) -> Dict[Path, str]: f"documentation version {current}", ) + if dev_only: + return {cmake_path: files[cmake_path], docs_path: files[docs_path]} + versions_path = root / "docs/source/_static/versions.json" versions = load_versions(versions_path) promote_stable(versions, current) @@ -211,10 +216,17 @@ def promoted_files(root: Path, version: str) -> Dict[Path, str]: def main() -> int: parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("current_version", nargs="?", help="just-released project version") + parser.add_argument( + "current_version", nargs="?", help="current project version (released unless --dev-only)" + ) parser.add_argument("new_version", nargs="?", help="next development version") mode = parser.add_mutually_exclusive_group() mode.add_argument("--check", metavar="VERSION", help="validate version metadata") + mode.add_argument( + "--dev-only", + action="store_true", + help="update development versions without promoting stable docs", + ) mode.add_argument( "--promote-stable", metavar="VERSION", @@ -249,7 +261,8 @@ def main() -> int: if args.current_version == args.new_version: raise VersionError("current and new versions must differ") files = updated_files( - args.root.resolve(), args.current_version, args.new_version + args.root.resolve(), args.current_version, args.new_version, + dev_only=args.dev_only, ) for path, content in files.items(): if args.dry_run: diff --git a/scripts/releasing/tests/test_release_tools.py b/scripts/releasing/tests/test_release_tools.py index f1b20d658..d3fd19c87 100644 --- a/scripts/releasing/tests/test_release_tools.py +++ b/scripts/releasing/tests/test_release_tools.py @@ -745,6 +745,36 @@ def test_version_tool_bumps_dev_and_promotes_released_version(self) -> None: json.loads(versions_path.read_text(encoding="utf-8")), versions ) + def test_version_tool_bumps_dev_without_promoting_stable(self) -> None: + for docs_version in ("1.2.3", "1.1.0"): + with self.subTest(docs_version=docs_version), tempfile.TemporaryDirectory() as temp: + root = Path(temp) + self.create_version_tree(root) + docs_path = root / "docs/source/conf.py" + docs_path.write_text(f'version = "{docs_version}"\n', encoding="utf-8") + versions_path = root / "docs/source/_static/versions.json" + versions = json.loads(versions_path.read_text(encoding="utf-8")) + versions[0]["name"] = "main (development)" + versions.append({ + "name": "1.0.0", + "version": "1.0", + "url": "https://paimon.apache.org/docs/cpp/1.0/", + }) + # Preserve existing labels, archives, and formatting byte for byte. + versions_path.write_text(json.dumps(versions), encoding="utf-8") + before = versions_path.read_bytes() + result = self.run_tool( + VERSION_TOOL, "--root", str(root), "--dev-only", "1.2.3", "1.3.0" + ) + self.assertEqual( + result.stdout.splitlines(), + [f"Updated {root / path}" for path in ("CMakeLists.txt", "docs/source/conf.py")], + ) + self.assertIn("VERSION 1.3.0", (root / "CMakeLists.txt").read_text()) + self.assertEqual(docs_path.read_text(), 'version = "1.3.0"\n') + self.assertEqual(versions_path.read_bytes(), before) + self.run_tool(VERSION_TOOL, "--root", str(root), "--check", "1.3.0") + def test_version_tool_promotes_series_on_patch_release(self) -> None: with tempfile.TemporaryDirectory() as temp: root = Path(temp) @@ -820,6 +850,7 @@ def test_version_tool_dry_run_leaves_all_files_unchanged(self) -> None: ["CMakeLists.txt", "docs/source/conf.py", "docs/source/_static/versions.json"], ), (("--promote-stable", "1.2.3"), ["docs/source/_static/versions.json"]), + (("--dev-only", "1.2.3", "1.3.0"), ["CMakeLists.txt", "docs/source/conf.py"]), ]: with self.subTest(arguments=arguments), tempfile.TemporaryDirectory() as temp: root = Path(temp) @@ -841,6 +872,13 @@ def test_version_tool_rejects_invalid_operations_without_writes(self) -> None: (("--promote-stable", "1.2"), 1), (("--promote-stable", "1.2.3", "1.2.3", "1.3.0"), 1), (("--check", "1.2.3", "--promote-stable", "1.2.3"), 2), + (("--dev-only", "--check", "1.2.3"), 2), + (("--dev-only", "--promote-stable", "1.2.3"), 2), + (("--dev-only",), 1), + (("--dev-only", "1.2.3"), 1), + (("--dev-only", "1.2.3", "1.2.3"), 1), + (("--dev-only", "1.2.3", "1.3"), 1), + (("--dev-only", "1.2.4", "1.3.0"), 1), (("1.2.3", "1.2.3"), 1), (("1.2.3", "1.3"), 1), (("1.2.4", "1.3.0"), 1),