Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add generation config comparator #2587

Merged
merged 25 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7f91d91
feat: add a generation config comparator
JoeWang1127 Mar 15, 2024
e5aae8e
compare library configs
JoeWang1127 Mar 16, 2024
7110bb3
Merge branch 'main' into feat/config-comparator
JoeWang1127 Mar 16, 2024
7cb2e97
code refactor
JoeWang1127 Mar 17, 2024
a8b1b26
add proto_path removal or addition change
JoeWang1127 Mar 17, 2024
218e431
change to HashLibrary
JoeWang1127 Mar 17, 2024
15e0db7
use object, rather than file path in comparator interface
JoeWang1127 Mar 17, 2024
b876354
add unit tests
JoeWang1127 Mar 17, 2024
5348539
add setUp method in ut
JoeWang1127 Mar 17, 2024
8e6b1c1
add unit tests against repo level changes
JoeWang1127 Mar 17, 2024
4f0f2c1
add unit tests against library parameters
JoeWang1127 Mar 17, 2024
e8b2d6b
add unit tests against versioned proto_path
JoeWang1127 Mar 17, 2024
e5f7a5e
restore gapic_config
JoeWang1127 Mar 17, 2024
2d6b13b
add comments
JoeWang1127 Mar 18, 2024
2dc41b3
code refactor
JoeWang1127 Mar 18, 2024
6fba2ad
change type
JoeWang1127 Mar 18, 2024
cda24a1
change enum types
JoeWang1127 Mar 19, 2024
af85a4f
move get_library_name method to LibraryConfig
JoeWang1127 Mar 19, 2024
989da47
fix integration tests
JoeWang1127 Mar 19, 2024
d3df205
Merge branch 'main' into feat/config-comparator
JoeWang1127 Mar 19, 2024
376015d
comment out library removal and gapic removal type
JoeWang1127 Mar 20, 2024
70e0fe8
raise an error if api_shortname is changed but library_name remains t…
JoeWang1127 Mar 20, 2024
42b5b03
use built-in method, `vars`, to list parameters of an object
JoeWang1127 Mar 20, 2024
4890786
Merge branch 'main' into feat/config-comparator
JoeWang1127 Mar 20, 2024
33b8c47
Merge branch 'main' into feat/config-comparator
JoeWang1127 Mar 20, 2024
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
61 changes: 61 additions & 0 deletions library_generation/model/library_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# 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.
from hashlib import sha1

from typing import List, Optional
from library_generation.model.gapic_config import GapicConfig
Expand Down Expand Up @@ -71,3 +72,63 @@ def __init__(
self.cloud_api = cloud_api
self.requires_billing = requires_billing
self.extra_versioned_modules = extra_versioned_modules

def __eq__(self, other):
return (
self.api_shortname == other.api_shortname
and self.api_description == other.api_description
and self.name_pretty == other.name_pretty
and self.product_documentation == other.product_documentation
and self.gapic_configs == other.gapic_configs
and self.library_type == other.library_type
and self.release_level == other.release_level
and self.api_id == other.api_id
and self.api_reference == other.api_reference
and self.codeowner_team == other.codeowner_team
and self.excluded_dependencies == other.excluded_dependencies
and self.excluded_poms == other.excluded_poms
and self.client_documentation == other.client_documentation
and self.distribution_name == other.distribution_name
and self.googleapis_commitish == other.googleapis_commitish
and self.group_id == other.group_id
and self.issue_tracker == other.issue_tracker
and self.library_name == other.library_name
and self.rest_documentation == other.rest_documentation
and self.rpc_documentation == other.rpc_documentation
and self.cloud_api == other.cloud_api
and self.requires_billing == other.requires_billing
and self.extra_versioned_modules == other.extra_versioned_modules
)

def __hash__(self):
m = sha1()
m.update(
str(
[
self.api_shortname,
self.api_description,
self.name_pretty,
self.product_documentation,
self.library_type,
self.release_level,
self.api_id,
self.api_reference,
self.codeowner_team,
self.excluded_dependencies,
self.excluded_poms,
self.client_documentation,
self.distribution_name,
self.googleapis_commitish,
self.group_id,
self.issue_tracker,
self.library_name,
self.rest_documentation,
self.rpc_documentation,
self.cloud_api,
self.requires_billing,
self.extra_versioned_modules,
]
+ [config.proto_path for config in self.gapic_configs]
).encode("utf-8")
)
return int(m.hexdigest(), 16)
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
# Copyright 2024 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.
import unittest

from library_generation.model.gapic_config import GapicConfig
from library_generation.model.generation_config import GenerationConfig
from library_generation.model.library_config import LibraryConfig
from library_generation.utils.generation_config_comparator import ChangeType
from library_generation.utils.generation_config_comparator import compare_config


class GenerationConfigComparatorTest(unittest.TestCase):
def setUp(self) -> None:
self.baseline_library = LibraryConfig(
api_shortname="existing_library",
api_description="",
name_pretty="",
product_documentation="",
gapic_configs=[],
)
self.latest_library = LibraryConfig(
api_shortname="existing_library",
api_description="",
name_pretty="",
product_documentation="",
gapic_configs=[],
)
self.baseline_config = GenerationConfig(
gapic_generator_version="",
googleapis_commitish="",
owlbot_cli_image="",
synthtool_commitish="",
template_excludes=[],
path_to_yaml="",
grpc_version="",
protobuf_version="",
libraries=[self.baseline_library],
)
self.latest_config = GenerationConfig(
gapic_generator_version="",
googleapis_commitish="",
owlbot_cli_image="",
synthtool_commitish="",
template_excludes=[],
path_to_yaml="",
grpc_version="",
protobuf_version="",
libraries=[self.latest_library],
)

def test_compare_config_not_change(self):
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertTrue(len(result) == 0)

def test_compare_config_googleapis_update(self):
self.baseline_config.googleapis_commitish = (
"1a45bf7393b52407188c82e63101db7dc9c72026"
)
self.latest_config.googleapis_commitish = (
"1e6517ef4f949191c9e471857cf5811c8abcab84"
)
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.GOOGLEAPIS_COMMIT: []}, result)

def test_compare_config_generator_update(self):
self.baseline_config.gapic_generator_version = "1.2.3"
self.latest_config.gapic_generator_version = "1.2.4"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.GENERATOR: []}, result)

def test_compare_config_owlbot_cli_update(self):
self.baseline_config.owlbot_cli_image = "image_version_123"
self.latest_config.owlbot_cli_image = "image_version_456"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.OWLBOT_CLI: []}, result)

def test_compare_config_synthtool_update(self):
self.baseline_config.synthtool_commitish = "commit123"
self.latest_config.synthtool_commitish = "commit456"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.SYNTHTOOL: []}, result)

def test_compare_protobuf_update(self):
self.baseline_config.protobuf_version = "3.25.2"
self.latest_config.protobuf_version = "3.27.0"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.PROTOBUF: []}, result)

def test_compare_config_grpc_update(self):
self.baseline_config.grpc_version = "1.60.0"
self.latest_config.grpc_version = "1.61.0"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.GRPC: []}, result)

def test_compare_config_template_excludes_update(self):
self.baseline_config.template_excludes = [".github/*", ".kokoro/*"]
self.latest_config.template_excludes = [
".github/*",
".kokoro/*",
"samples/*",
"CODE_OF_CONDUCT.md",
]
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.TEMPLATE_EXCLUDES: []}, result)

def test_compare_config_library_addition(self):
self.latest_config.libraries.append(
LibraryConfig(
api_shortname="new_library",
api_description="",
name_pretty="",
product_documentation="",
gapic_configs=[],
)
)
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.LIBRARIES_ADDITION: ["new_library"]}, result)

def test_compare_config_library_removal(self):
self.latest_config.libraries = []
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.LIBRARIES_REMOVAL: ["existing_library"]}, result)

def test_compare_config_api_description_update(self):
self.latest_config.libraries[0].api_description = "updated description"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.API_DESCRIPTION: ["existing_library"]}, result)

def test_compare_config_name_pretty_update(self):
self.latest_config.libraries[0].name_pretty = "new name"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.NAME_PRETTY: ["existing_library"]}, result)

def test_compare_config_product_docs_update(self):
self.latest_config.libraries[0].product_documentation = "new docs"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.PRODUCT_DOCS: ["existing_library"]}, result)

def test_compare_config_library_type_update(self):
self.latest_config.libraries[0].library_type = "GAPIC_COMBO"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.LIBRARY_TYPE: ["existing_library"]}, result)

def test_compare_config_release_level_update(self):
self.latest_config.libraries[0].release_level = "STABLE"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.RELEASE_LEVEL: ["existing_library"]}, result)

def test_compare_config_api_id_update(self):
self.latest_config.libraries[0].api_id = "new_id"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.API_ID: ["existing_library"]}, result)

def test_compare_config_api_reference_update(self):
self.latest_config.libraries[0].api_reference = "new api_reference"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.API_REFERENCE: ["existing_library"]}, result)

def test_compare_config_code_owner_team_update(self):
self.latest_config.libraries[0].codeowner_team = "new team"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.CODEOWNER_TEAM: ["existing_library"]}, result)

def test_compare_config_excluded_deps_update(self):
self.latest_config.libraries[0].excluded_dependencies = "group:artifact"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual(
{ChangeType.EXCLUDED_DEPENDENCIES: ["existing_library"]}, result
)

def test_compare_config_excluded_poms_update(self):
self.latest_config.libraries[0].excluded_poms = "pom.xml"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.EXCLUDED_POMS: ["existing_library"]}, result)

def test_compare_config_client_docs_update(self):
self.latest_config.libraries[0].client_documentation = "new client docs"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.CLIENT_DOCS: ["existing_library"]}, result)

def test_compare_config_issue_tracker_update(self):
self.latest_config.libraries[0].issue_tracker = "new issue tracker"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.ISSUE_TRACKER: ["existing_library"]}, result)

def test_compare_config_rest_docs_update(self):
self.latest_config.libraries[0].rest_documentation = "new rest docs"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.REST_DOCS: ["existing_library"]}, result)

def test_compare_config_rpc_docs_update(self):
self.latest_config.libraries[0].rpc_documentation = "new rpc docs"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.RPC_DOCS: ["existing_library"]}, result)

def test_compare_config_requires_billing_update(self):
self.latest_config.libraries[0].requires_billing = False
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.REQUIRES_BILLING: ["existing_library"]}, result)

def test_compare_config_extra_versioned_mod_update(self):
self.latest_config.libraries[0].extra_versioned_modules = "extra module"
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual(
{ChangeType.EXTRA_VERSIONED_MODULES: ["existing_library"]}, result
)

def test_compare_config_version_addition(self):
self.latest_config.libraries[0].gapic_configs = [
GapicConfig(proto_path="google/new/library/v1")
]
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.VERSION_ADDITION: ["existing_library"]}, result)

def test_compare_config_version_removal(self):
self.baseline_config.libraries[0].gapic_configs = [
GapicConfig(proto_path="google/old/library/v1")
]
result = compare_config(
baseline_config=self.baseline_config,
latest_config=self.latest_config,
)
self.assertEqual({ChangeType.VERSION_REMOVAL: ["existing_library"]}, result)
Loading
Loading