|
17 | 17 | import os |
18 | 18 | import pathlib |
19 | 19 | import subprocess |
| 20 | +import yaml |
20 | 21 | import unittest.mock |
| 22 | +from datetime import datetime |
21 | 23 | from unittest.mock import MagicMock, mock_open |
22 | 24 |
|
23 | 25 | import pytest |
24 | 26 | from cli import ( |
25 | 27 | GENERATE_REQUEST_FILE, |
26 | 28 | BUILD_REQUEST_FILE, |
27 | 29 | RELEASE_INIT_REQUEST_FILE, |
| 30 | + STATE_YAML_FILE, |
28 | 31 | LIBRARIAN_DIR, |
29 | 32 | REPO_DIR, |
30 | 33 | _build_bazel_target, |
|
33 | 36 | _determine_bazel_rule, |
34 | 37 | _get_library_id, |
35 | 38 | _get_libraries_to_prepare_for_release, |
| 39 | + _get_previous_version, |
36 | 40 | _locate_and_extract_artifact, |
| 41 | + _process_changelog, |
37 | 42 | _process_version_file, |
38 | 43 | _read_json_file, |
39 | 44 | _read_text_file, |
40 | 45 | _run_individual_session, |
41 | 46 | _run_nox_sessions, |
42 | 47 | _run_post_processor, |
| 48 | + _update_changelog_for_library, |
43 | 49 | _update_global_changelog, |
44 | 50 | _update_version_for_library, |
45 | 51 | _write_json_file, |
|
51 | 57 | ) |
52 | 58 |
|
53 | 59 |
|
| 60 | +_MOCK_LIBRARY_CHANGES = [ |
| 61 | + { |
| 62 | + "type": "feat", |
| 63 | + "subject": "add new UpdateRepository API", |
| 64 | + "body": "This adds the ability to update a repository's properties.", |
| 65 | + "piper_cl_number": "786353207", |
| 66 | + "source_commit_hash": "9461532e7d19c8d71709ec3b502e5d81340fb661", |
| 67 | + }, |
| 68 | + { |
| 69 | + "type": "fix", |
| 70 | + "subject": "some fix", |
| 71 | + "body": "", |
| 72 | + "piper_cl_number": "786353208", |
| 73 | + "source_commit_hash": "1231532e7d19c8d71709ec3b502e5d81340fb661", |
| 74 | + }, |
| 75 | + { |
| 76 | + "type": "fix", |
| 77 | + "subject": "another fix", |
| 78 | + "body": "", |
| 79 | + "piper_cl_number": "786353209", |
| 80 | + "source_commit_hash": "1241532e7d19c8d71709ec3b502e5d81340fb661", |
| 81 | + }, |
| 82 | + { |
| 83 | + "type": "docs", |
| 84 | + "subject": "fix typo in BranchRule comment", |
| 85 | + "body": "", |
| 86 | + "piper_cl_number": "786353210", |
| 87 | + "source_commit_hash": "9461532e7d19c8d71709ec3b502e5d81340fb661", |
| 88 | + }, |
| 89 | +] |
| 90 | + |
| 91 | + |
54 | 92 | @pytest.fixture |
55 | 93 | def mock_generate_request_file(tmp_path, monkeypatch): |
56 | 94 | """Creates the mock request file at the correct path inside a temp dir.""" |
@@ -136,6 +174,25 @@ def mock_release_init_request_file(tmp_path, monkeypatch): |
136 | 174 | return request_file |
137 | 175 |
|
138 | 176 |
|
| 177 | +@pytest.fixture |
| 178 | +def mock_state_file(tmp_path, monkeypatch): |
| 179 | + """Creates the state file at the correct path inside a temp dir.""" |
| 180 | + # Create the path as expected by the script: .librarian/state.yaml |
| 181 | + request_path = f"{LIBRARIAN_DIR}/{STATE_YAML_FILE}" |
| 182 | + request_dir = tmp_path / os.path.dirname(request_path) |
| 183 | + request_dir.mkdir() |
| 184 | + request_file = request_dir / os.path.basename(request_path) |
| 185 | + |
| 186 | + state_yaml_contents = { |
| 187 | + "libraries": [{"id": "google-cloud-language", "version": "1.2.3"}] |
| 188 | + } |
| 189 | + request_file.write_text(yaml.dump(state_yaml_contents)) |
| 190 | + |
| 191 | + # Change the current working directory to the temp path for the test. |
| 192 | + monkeypatch.chdir(tmp_path) |
| 193 | + return request_file |
| 194 | + |
| 195 | + |
139 | 196 | def test_get_library_id_success(): |
140 | 197 | """Tests that _get_library_id returns the correct ID when present.""" |
141 | 198 | request_data = {"id": "test-library", "name": "Test Library"} |
@@ -518,6 +575,8 @@ def test_handle_release_init_success(mocker, mock_release_init_request_file): |
518 | 575 | """ |
519 | 576 | mocker.patch("cli._update_global_changelog", return_value=None) |
520 | 577 | mocker.patch("cli._update_version_for_library", return_value=None) |
| 578 | + mocker.patch("cli._get_previous_version", return_value=None) |
| 579 | + mocker.patch("cli._update_changelog_for_library", return_value=None) |
521 | 580 | handle_release_init() |
522 | 581 |
|
523 | 582 |
|
@@ -650,6 +709,91 @@ def test_update_version_for_library_failure(mocker): |
650 | 709 | ) |
651 | 710 |
|
652 | 711 |
|
| 712 | +def test_get_previous_version_success(mock_state_file): |
| 713 | + """Test that the version can be retrieved from the state.yaml for a given library""" |
| 714 | + previous_version = _get_previous_version("google-cloud-language", LIBRARIAN_DIR) |
| 715 | + assert previous_version == "1.2.3" |
| 716 | + |
| 717 | + |
| 718 | +def test_get_previous_version_failure(mock_state_file): |
| 719 | + """Test that ValueError is raised when a library does not exist in state.yaml""" |
| 720 | + with pytest.raises(ValueError): |
| 721 | + _get_previous_version("google-cloud-does-not-exist", LIBRARIAN_DIR) |
| 722 | + |
| 723 | + |
| 724 | +def test_update_changelog_for_library_success(mocker): |
| 725 | + m = mock_open() |
| 726 | + |
| 727 | + mock_content = """# Changelog |
| 728 | +
|
| 729 | +[PyPI History][1] |
| 730 | +
|
| 731 | +[1]: https://pypi.org/project/google-cloud-language/#history |
| 732 | +
|
| 733 | +## [2.17.2](https://github.com/googleapis/google-cloud-python/compare/google-cloud-language-v2.17.1...google-cloud-language-v2.17.2) (2025-06-11) |
| 734 | +
|
| 735 | +""" |
| 736 | + with unittest.mock.patch("cli.open", m): |
| 737 | + mocker.patch("cli._read_text_file", return_value=mock_content) |
| 738 | + _update_changelog_for_library( |
| 739 | + "repo", |
| 740 | + "output", |
| 741 | + _MOCK_LIBRARY_CHANGES, |
| 742 | + "1.2.3", |
| 743 | + "1.2.2", |
| 744 | + "google-cloud-language", |
| 745 | + ) |
| 746 | + |
| 747 | + |
| 748 | +def test_process_changelog_success(): |
| 749 | + """Tests that value error is raised if the changelog anchor string cannot be found""" |
| 750 | + current_date = datetime.now().strftime("%Y-%m-%d") |
| 751 | + mock_content = """# Changelog\n[PyPI History][1]\n[1]: https://pypi.org/project/google-cloud-language/#history\n |
| 752 | +## [1.2.2](https://github.com/googleapis/google-cloud-python/compare/google-cloud-language-v1.2.1...google-cloud-language-v1.2.2) (2025-06-11)""" |
| 753 | + expected_result = f"""# Changelog\n[PyPI History][1]\n[1]: https://pypi.org/project/google-cloud-language/#history\n |
| 754 | +## [1.2.3](https://github.com/googleapis/google-cloud-python/compare/google-cloud-language-v1.2.2...google-cloud-language-v1.2.3) ({current_date})\n\n |
| 755 | +### Documentation\n |
| 756 | +* fix typo in BranchRule comment ([9461532e7d19c8d71709ec3b502e5d81340fb661](https://github.com/googleapis/google-cloud-python/commit/9461532e7d19c8d71709ec3b502e5d81340fb661))\n\n |
| 757 | +### Features\n |
| 758 | +* add new UpdateRepository API ([9461532e7d19c8d71709ec3b502e5d81340fb661](https://github.com/googleapis/google-cloud-python/commit/9461532e7d19c8d71709ec3b502e5d81340fb661))\n\n |
| 759 | +### Bug Fixes\n |
| 760 | +* some fix ([1231532e7d19c8d71709ec3b502e5d81340fb661](https://github.com/googleapis/google-cloud-python/commit/1231532e7d19c8d71709ec3b502e5d81340fb661)) |
| 761 | +* another fix ([1241532e7d19c8d71709ec3b502e5d81340fb661](https://github.com/googleapis/google-cloud-python/commit/1241532e7d19c8d71709ec3b502e5d81340fb661))\n |
| 762 | +## [1.2.2](https://github.com/googleapis/google-cloud-python/compare/google-cloud-language-v1.2.1...google-cloud-language-v1.2.2) (2025-06-11)""" |
| 763 | + version = "1.2.3" |
| 764 | + previous_version = "1.2.2" |
| 765 | + package_name = "google-cloud-language" |
| 766 | + |
| 767 | + result = _process_changelog( |
| 768 | + mock_content, _MOCK_LIBRARY_CHANGES, version, previous_version, package_name |
| 769 | + ) |
| 770 | + assert result == expected_result |
| 771 | + |
| 772 | + |
| 773 | +def test_process_changelog_failure(): |
| 774 | + """Tests that value error is raised if the changelog anchor string cannot be found""" |
| 775 | + with pytest.raises(ValueError): |
| 776 | + _process_changelog("", [], "", "", "") |
| 777 | + |
| 778 | + |
| 779 | +def test_update_changelog_for_library_failure(mocker): |
| 780 | + m = mock_open() |
| 781 | + |
| 782 | + mock_content = """# Changelog""" |
| 783 | + |
| 784 | + with pytest.raises(ValueError): |
| 785 | + with unittest.mock.patch("cli.open", m): |
| 786 | + mocker.patch("cli._read_text_file", return_value=mock_content) |
| 787 | + _update_changelog_for_library( |
| 788 | + "repo", |
| 789 | + "output", |
| 790 | + _MOCK_LIBRARY_CHANGES, |
| 791 | + "1.2.3", |
| 792 | + "1.2.2", |
| 793 | + "google-cloud-language", |
| 794 | + ) |
| 795 | + |
| 796 | + |
653 | 797 | def test_process_version_file_success(): |
654 | 798 | version_file_contents = '__version__ = "1.2.2"' |
655 | 799 | new_version = "1.2.3" |
|
0 commit comments