diff --git a/blargh.yml b/blargh.yml new file mode 100644 index 000000000..e5f1aa652 --- /dev/null +++ b/blargh.yml @@ -0,0 +1,7 @@ +bumpMinorPreMajor: true +handleGHRelease: true +releaseType: java-yoshi +branches: + - handleGHRelease: true + releaseType: python + branch: java7 \ No newline at end of file diff --git a/synthtool/languages/python.py b/synthtool/languages/python.py index 4e99e88e9..78a6a0ff2 100644 --- a/synthtool/languages/python.py +++ b/synthtool/languages/python.py @@ -148,6 +148,62 @@ def py_samples(*, root: PathOrStr = None, skip_readmes: bool = False) -> None: s.copy([result], excludes=excludes) +def configure_previous_major_version_branches() -> None: + """Configure releases from previous major version branches by editing + `.github/release-please.yml`. + + The current library version is obtained from `version.py` in `google/**/version.py`, + or the `setup.py`. + + Releases are configured for all previous major versions. For example, + if the library version is currently 3.5.1, the release-please config + will include v2, v1, and v0. + """ + if list(Path(".").glob("google/**/version.py")): + version_file = list(Path(".").glob("google/**/version.py"))[0] + else: + version_file = Path("setup.py") + + # In version.py: __version__ = "1.5.2" + # In setup.py: version = "1.5.2" + VERSION_REGEX = ( + r"(?:__)?version(?:__)?\s*=\s*[\"'](?P\d)\.[\d\.]+[\"']" + ) + + match = re.search(VERSION_REGEX, Path(version_file).read_text()) + + if match is not None: + major_version = int(match.group("major_version")) + else: + raise RuntimeError( + "Unable to find library version in {} with regex {}".format( + version_file, VERSION_REGEX + ) + ) + + with open(".github/release-please.yml") as f: + release_please_yml = yaml.load(f, Loader=yaml.SafeLoader) + + if major_version > 0 and "branches" not in release_please_yml: + branches = [] + for version in range(major_version - 1, -1, -1): + branches.append( + { + "branch": f"v{version}", + "handleGHRelease": True, + "releaseType": "python", + } + ) + + with open(".github/release-please.yml", "a") as f: + # comments can't be expressed in PyYAML + f.write( + """# NOTE: this section is generated by synthtool.languages.python +# See https://github.com/googleapis/synthtool/blob/master/synthtool/languages/python.py\n""" + ) + f.write(yaml.dump({"branches": branches})) + + def owlbot_main() -> None: """Copies files from staging and template directories into current working dir. @@ -202,6 +258,8 @@ def owlbot_main() -> None: for noxfile in Path(".").glob("**/noxfile.py"): s.shell.run(["nox", "-s", "blacken"], cwd=noxfile.parent, hide_output=False) + configure_previous_major_version_branches() + if __name__ == "__main__": owlbot_main() diff --git a/tests/fixtures/python_library/setup.py b/tests/fixtures/python_library/setup.py new file mode 100644 index 000000000..4657b2278 --- /dev/null +++ b/tests/fixtures/python_library/setup.py @@ -0,0 +1,108 @@ +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import io +import os + +import setuptools + + +# Package metadata. + +name = "google-cloud-texttospeech" +description = "Google Cloud Text-to-Speech API client library" +version = "2.11.0" +# Should be one of: +# 'Development Status :: 3 - Alpha' +# 'Development Status :: 4 - Beta' +# 'Development Status :: 5 - Production/Stable' +release_status = "Development Status :: 5 - Production/Stable" +dependencies = [ + # NOTE: Maintainers, please do not require google-api-core>=2.x.x + # Until this issue is closed + # https://github.com/googleapis/google-cloud-python/issues/10566 + "google-api-core[grpc] >= 1.31.5, <3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0", + "proto-plus >= 1.15.0", +] +extras = {} + + +# Setup boilerplate below this line. + +package_root = os.path.abspath(os.path.dirname(__file__)) + +readme_filename = os.path.join(package_root, "README.rst") +with io.open(readme_filename, encoding="utf-8") as readme_file: + readme = readme_file.read() + +# Only include packages under the 'google' namespace. Do not include tests, +# benchmarks, etc. +packages = [ + package + for package in setuptools.PEP420PackageFinder.find() + if package.startswith("google") +] + +# Determine which namespaces are needed. +namespaces = ["google"] +if "google.cloud" in packages: + namespaces.append("google.cloud") + + +setuptools.setup( + name=name, + version=version, + description=description, + long_description=readme, + author="Google LLC", + author_email="googleapis-packages@google.com", + license="Apache 2.0", + url="https://github.com/googleapis/python-texttospeech", + classifiers=[ + release_status, + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Operating System :: OS Independent", + "Topic :: Internet", + ], + platforms="Posix; MacOS X; Windows", + packages=packages, + namespace_packages=namespaces, + install_requires=dependencies, + extras_require=extras, + python_requires=">=3.6", + scripts=["scripts/fixup_keywords.py"], + include_package_data=True, + zip_safe=False, +) diff --git a/tests/fixtures/python_library_w_version_py/.repo-metadata.json b/tests/fixtures/python_library_w_version_py/.repo-metadata.json new file mode 100644 index 000000000..32efa1d54 --- /dev/null +++ b/tests/fixtures/python_library_w_version_py/.repo-metadata.json @@ -0,0 +1,13 @@ +{ + "name": "texttospeech", + "name_pretty": "Google Cloud Text-to-Speech", + "product_documentation": "https://cloud.google.com/text-to-speech", + "client_documentation": "https://googleapis.dev/python/texttospeech/latest", + "issue_tracker": "https://issuetracker.google.com/savedsearches/5235428", + "release_level": "ga", + "language": "python", + "repo": "googleapis/python-texttospeech", + "distribution_name": "google-cloud-texttospeech", + "api_id": "texttospeech.googleapis.com", + "requires_billing": true +} diff --git a/tests/fixtures/python_library_w_version_py/google/cloud/texttospeech/version.py b/tests/fixtures/python_library_w_version_py/google/cloud/texttospeech/version.py new file mode 100644 index 000000000..7f6646a76 --- /dev/null +++ b/tests/fixtures/python_library_w_version_py/google/cloud/texttospeech/version.py @@ -0,0 +1 @@ +__version__ = "2.11.0" diff --git a/tests/fixtures/python_library_w_version_py/setup.py b/tests/fixtures/python_library_w_version_py/setup.py new file mode 100644 index 000000000..4657b2278 --- /dev/null +++ b/tests/fixtures/python_library_w_version_py/setup.py @@ -0,0 +1,108 @@ +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import io +import os + +import setuptools + + +# Package metadata. + +name = "google-cloud-texttospeech" +description = "Google Cloud Text-to-Speech API client library" +version = "2.11.0" +# Should be one of: +# 'Development Status :: 3 - Alpha' +# 'Development Status :: 4 - Beta' +# 'Development Status :: 5 - Production/Stable' +release_status = "Development Status :: 5 - Production/Stable" +dependencies = [ + # NOTE: Maintainers, please do not require google-api-core>=2.x.x + # Until this issue is closed + # https://github.com/googleapis/google-cloud-python/issues/10566 + "google-api-core[grpc] >= 1.31.5, <3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0", + "proto-plus >= 1.15.0", +] +extras = {} + + +# Setup boilerplate below this line. + +package_root = os.path.abspath(os.path.dirname(__file__)) + +readme_filename = os.path.join(package_root, "README.rst") +with io.open(readme_filename, encoding="utf-8") as readme_file: + readme = readme_file.read() + +# Only include packages under the 'google' namespace. Do not include tests, +# benchmarks, etc. +packages = [ + package + for package in setuptools.PEP420PackageFinder.find() + if package.startswith("google") +] + +# Determine which namespaces are needed. +namespaces = ["google"] +if "google.cloud" in packages: + namespaces.append("google.cloud") + + +setuptools.setup( + name=name, + version=version, + description=description, + long_description=readme, + author="Google LLC", + author_email="googleapis-packages@google.com", + license="Apache 2.0", + url="https://github.com/googleapis/python-texttospeech", + classifiers=[ + release_status, + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Operating System :: OS Independent", + "Topic :: Internet", + ], + platforms="Posix; MacOS X; Windows", + packages=packages, + namespace_packages=namespaces, + install_requires=dependencies, + extras_require=extras, + python_requires=">=3.6", + scripts=["scripts/fixup_keywords.py"], + include_package_data=True, + zip_safe=False, +) diff --git a/tests/test_python_library.py b/tests/test_python_library.py index 1fe8ff9c4..a0a3ab160 100644 --- a/tests/test_python_library.py +++ b/tests/test_python_library.py @@ -13,12 +13,14 @@ # limitations under the License. import os +import shutil from pathlib import Path import pytest from synthtool import gcp from synthtool.sources import templates +from synthtool.languages import python from . import util @@ -126,3 +128,38 @@ def test_split_system_tests(): with open(templated_files / ".kokoro/presubmit/system-3.8.cfg", "r") as f: contents = f.read() assert "system-3.8" in contents + + +@pytest.mark.parametrize( + "fixtures_dir", + [ + Path(__file__).parent / "fixtures/python_library", # just setup.py + Path(__file__).parent + / "fixtures/python_library_w_version_py", # has google/cloud/texttospeech/version.py + ], +) +def test_configure_previous_major_version_branches(fixtures_dir): + with util.copied_fixtures_dir(fixtures_dir): + t = templates.Templates(PYTHON_LIBRARY) + result = t.render(".github/release-please.yml") + os.makedirs(".github") + shutil.copy(result, Path(".github/release-please.yml")) + + python.configure_previous_major_version_branches() + release_please_yml = Path(".github/release-please.yml").read_text() + + assert ( + release_please_yml + == """releaseType: python +handleGHRelease: true +# NOTE: this section is generated by synthtool.languages.python +# See https://github.com/googleapis/synthtool/blob/master/synthtool/languages/python.py +branches: +- branch: v1 + handleGHRelease: true + releaseType: python +- branch: v0 + handleGHRelease: true + releaseType: python +""" + )