Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions .generator/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,32 @@ def _get_library_id(request_data: Dict) -> str:
return library_id


def _get_package_name(library_id: str) -> str:
"""Extracts the folder name from the library id by removing any -preview suffix."""
if library_id.endswith("-preview"):
return library_id[:-8]
return library_id


def _get_library_path(library_id: str, is_mono_repo: bool) -> str:
"""Gets the relative path of the library in the repository.

Args:
library_id(str): The library id.
is_mono_repo(bool): True if the current repository is a mono-repo.

Returns:
str: The relative path to the library.
"""
if not is_mono_repo:
return "."
if library_id.endswith("-preview"):
package_name = _get_package_name(library_id)
return f"preview-packages/{package_name}"
return f"packages/{library_id}"



def _run_post_processor(output: str, library_id: str, is_mono_repo: bool):
"""Runs the synthtool post-processor on the output directory.

Expand Down Expand Up @@ -575,7 +601,7 @@ def _get_repo_metadata_file_path(base: str, library_id: str, is_mono_repo: bool)
Returns:
str: The absolute path to the .repo-metadata.json file.
"""
path_to_library = f"packages/{library_id}" if is_mono_repo else "."
path_to_library = _get_library_path(library_id, is_mono_repo)
return f"{base}/{path_to_library}/.repo-metadata.json"


Expand Down Expand Up @@ -1530,8 +1556,9 @@ def _process_changelog(
entry_parts.append(f"* {change[subject_key]} {commit_link}")

new_entry_text = "\n".join(entry_parts)
package_name = _get_package_name(library_id)
anchor_pattern = re.compile(
rf"(\[1\]: https://pypi\.org/project/{library_id}/#history)",
rf"(\[1\]: https://pypi\.org/project/{package_name}/#history)",
Comment thread
noahdietz marked this conversation as resolved.
re.MULTILINE,
)
replacement_text = f"\\g<1>\n\n{new_entry_text}"
Expand Down Expand Up @@ -1570,11 +1597,12 @@ def _update_changelog_for_library(
tag_format(str): The format of the git tag.
"""
if is_mono_repo:
relative_path = f"packages/{library_id}/CHANGELOG.md"
docs_relative_path = f"packages/{library_id}/docs/CHANGELOG.md"
path_to_library = _get_library_path(library_id, is_mono_repo)
relative_path = f"{path_to_library}/CHANGELOG.md"
docs_relative_path = f"{path_to_library}/docs/CHANGELOG.md"
else:
relative_path = "CHANGELOG.md"
docs_relative_path = f"docs/CHANGELOG.md"
docs_relative_path = "docs/CHANGELOG.md"

changelog_src = f"{repo}/{relative_path}"
changelog_dest = f"{output}/{relative_path}"
Expand Down Expand Up @@ -1670,7 +1698,7 @@ def handle_release_stage(
f"{library_id} version: {previous_version}\n"
)

path_to_library = f"packages/{library_id}" if is_mono_repo else "."
path_to_library = _get_library_path(library_id, is_mono_repo)

_update_version_for_library(repo, output, path_to_library, version)
if library_changes is not None:
Expand Down
84 changes: 84 additions & 0 deletions .generator/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
_get_api_generator_options,
_get_library_dist_name,
_get_library_id,
_get_package_name,
_get_library_path,
_get_libraries_to_prepare_for_release,
_get_new_library_config,
_get_previous_version,
Expand Down Expand Up @@ -1437,6 +1439,38 @@ def test_process_changelog_success():
assert result == expected_result


def test_process_changelog_success_preview():
"""Tests that a preview package updates its changelog correctly when the anchor has the standard package name."""
current_date = datetime.now().strftime("%Y-%m-%d")
mock_content = """# Changelog\n[PyPI History][1]\n[1]: https://pypi.org/project/google-cloud-language/#history\n
## [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)"""
expected_result = f"""# Changelog\n[PyPI History][1]\n[1]: https://pypi.org/project/google-cloud-language/#history\n
## [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
### Documentation\n
* fix typo in BranchRule comment ([9461532e7d19c8d71709ec3b502e5d81340fb661](https://github.com/googleapis/google-cloud-python/commit/9461532e7d19c8d71709ec3b502e5d81340fb661))\n\n
### Features\n
* add new UpdateRepository API ([9461532e7d19c8d71709ec3b502e5d81340fb661](https://github.com/googleapis/google-cloud-python/commit/9461532e7d19c8d71709ec3b502e5d81340fb661))\n\n
### Bug Fixes\n
* some fix ([1231532e7d19c8d71709ec3b502e5d81340fb661](https://github.com/googleapis/google-cloud-python/commit/1231532e7d19c8d71709ec3b502e5d81340fb661))
* another fix ([1241532e7d19c8d71709ec3b502e5d81340fb661](https://github.com/googleapis/google-cloud-python/commit/1241532e7d19c8d71709ec3b502e5d81340fb661))\n
## [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)"""
version = "1.2.3"
previous_version = "1.2.2"
library_id = "google-cloud-language-preview"
tag_format = "google-cloud-language-v{version}"

result = _process_changelog(
mock_content,
_MOCK_LIBRARY_CHANGES,
version,
previous_version,
library_id,
"googleapis/google-cloud-python",
tag_format,
)
assert result == expected_result


def test_process_changelog_failure():
"""Tests that value error is raised if the changelog anchor string cannot be found"""
with pytest.raises(ValueError):
Expand Down Expand Up @@ -2045,3 +2079,53 @@ def test_get_repo_name_from_repo_metadata_missing_repo(mocker):
mocker.patch("cli._read_json_file", return_value={})
with pytest.raises(ValueError):
_get_repo_name_from_repo_metadata("base", "library_id", False)


def test_get_package_name():
assert _get_package_name("google-cloud-language") == "google-cloud-language"
assert _get_package_name("google-cloud-language-preview") == "google-cloud-language"
assert _get_package_name("google-cloud-language-preview-preview") == "google-cloud-language-preview"


@pytest.mark.parametrize(
"library_id, is_mono_repo, expected_path",
[
("google-cloud-language", True, "packages/google-cloud-language"),
("google-cloud-language-preview", True, "preview-packages/google-cloud-language"),
("google-cloud-language", False, "."),
("google-cloud-language-preview", False, "."),
],
)
def test_get_library_path(library_id, is_mono_repo, expected_path):
assert _get_library_path(library_id, is_mono_repo) == expected_path


def test_update_changelog_for_library_preview_package(mocker):
"""Tests that _update_changelog_for_library writes to preview-packages directory for preview libraries."""
mock_content = """# Changelog

[PyPI History][1]

[1]: https://pypi.org/project/google-cloud-language/#history
"""
mock_read = mocker.patch("cli._read_text_file", return_value=mock_content)
mock_write = mocker.patch("cli._write_text_file")
mock_path_exists = mocker.patch("cli.os.path.lexists", return_value=True)
_update_changelog_for_library(
"repo",
"output",
_MOCK_LIBRARY_CHANGES,
"1.2.3",
"1.2.2",
"google-cloud-language-preview",
True,
"{id}-v{version}",
)

assert mock_write.call_count == 2
mock_write.assert_any_call(
"output/preview-packages/google-cloud-language/CHANGELOG.md", mocker.ANY
)
mock_write.assert_any_call(
"output/preview-packages/google-cloud-language/docs/CHANGELOG.md", mocker.ANY
)
Loading