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: generate showcase using docker image #3568

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f61c630
feat: generate showcase with hermetic build image
diegomarquezp Jan 10, 2025
99c711f
add showcase generation files
diegomarquezp Jan 10, 2025
7c0ed51
exclude bom generation
diegomarquezp Jan 10, 2025
0328d96
fix owlbot-cli config
diegomarquezp Jan 10, 2025
c1d1696
fix paths in owlbot cli
diegomarquezp Jan 10, 2025
bb28ae6
add historical bazel file
diegomarquezp Jan 10, 2025
85201ee
fix owlbot yaml
diegomarquezp Jan 10, 2025
cad57f6
parse additional protos also including gapic targets
diegomarquezp Jan 14, 2025
bfc9bba
fix service yaml and gapic config
diegomarquezp Jan 14, 2025
b4aa910
adapt to docker image generation
diegomarquezp Jan 14, 2025
779d011
update proto, gapic and grpc
diegomarquezp Jan 14, 2025
d29ce8c
add samples
diegomarquezp Jan 14, 2025
334384a
adapt showcase readme
diegomarquezp Jan 14, 2025
66e7366
explain new input in generation config
diegomarquezp Jan 14, 2025
f0a7d53
uncomment image building
diegomarquezp Jan 14, 2025
072ee70
ignore full generation when only generating showcase
diegomarquezp Jan 14, 2025
0214666
add showcase to versions.txt
diegomarquezp Jan 14, 2025
2f47daa
do not generate showcase automatically on generation config changes
diegomarquezp Jan 15, 2025
3063dab
update gapic showcase files
diegomarquezp Jan 15, 2025
e1c270a
fix build rule patterns
diegomarquezp Jan 15, 2025
1514dd7
lint
diegomarquezp Jan 15, 2025
6476131
skip generation on no target libraries
diegomarquezp Jan 15, 2025
4880451
exit early when no libraries need to be generated
diegomarquezp Jan 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 9 additions & 1 deletion .github/scripts/hermetic_library_generation.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
set -e
set -ex
# This script should be run at the root of the repository.
# This script is used to, when a pull request changes the generation
# configuration (generation_config.yaml by default) or Dockerfile:
Expand Down Expand Up @@ -95,6 +95,14 @@ changed_libraries=$(python hermetic_build/common/cli/get_changed_libraries.py cr
--current-generation-config-path="${generation_config}")
echo "Changed libraries are: ${changed_libraries:-"No changed library"}."

# do not generate showcase automatically
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably do want to generate showcase automatically? For example, if we update protoc version in the docker image, we do want the showcase module to be updated.

changed_libraries=$(echo "${changed_libraries}" | sed 's/showcase,//' | sed 's/,showcase//' | sed 's/showcase//')
echo "${changed_libraries}"
if [[ -z "${changed_libraries}" ]]; then
echo 'No libraries to generate. Aborting generation'
exit 0
fi

# run hermetic code generation docker image.
docker run \
--rm \
Expand Down
40 changes: 25 additions & 15 deletions generation_config.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
googleapis_commitish: 3cef095370b3176f67542e527ffde81e019df091
# the libraries are ordered with respect to library name, which is
# java-{library.library_name} or java-{library.api-shortname} when
# library.library_name is not defined.
# the libraries are ordered with respect to library name, which defaults to
# {library.folder_name} or java-{library.library_name} or
# java-{library.api-shortname} in sequence (i.e. if first is None, then try second and so on).
libraries:
- api_shortname: showcase
folder_name: showcase # prevents java-showcase
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel it is probably too much effort to introduce a new argument folder_name, just to prevent showcase to be renamed to java-showcase. I think it is OK to rename it.

excluded_poms: gapic-showcase-bom
name_pretty: Showcase
api_description: Showcase module
product_documentation: https://cloud.google.com/dummy
distribution_name: com.google.cloud:gapic-showcase
library_type: OTHER
GAPICs:
- proto_path: schema/google/showcase/v1beta1
- api_shortname: common-protos
name_pretty: Common Protos
product_documentation: https://github.com/googleapis/api-common-protos
Expand All @@ -14,18 +24,18 @@ libraries:
excluded_poms: "proto-google-common-protos-bom,proto-google-common-protos"
library_type: OTHER
GAPICs:
- proto_path: google/api
- proto_path: google/apps/card/v1
- proto_path: google/cloud
- proto_path: google/cloud/audit
- proto_path: google/cloud/location
- proto_path: google/geo/type
- proto_path: google/logging/type
- proto_path: google/longrunning
- proto_path: google/rpc
- proto_path: google/rpc/context
- proto_path: google/shopping/type
- proto_path: google/type
- proto_path: google/api
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change intended?

- proto_path: google/apps/card/v1
- proto_path: google/cloud
- proto_path: google/cloud/audit
- proto_path: google/cloud/location
- proto_path: google/geo/type
- proto_path: google/logging/type
- proto_path: google/longrunning
- proto_path: google/rpc
- proto_path: google/rpc/context
- proto_path: google/shopping/type
- proto_path: google/type
- api_shortname: iam
name_pretty: IAM
product_documentation: https://cloud.google.com/iam
Expand Down
1 change: 1 addition & 0 deletions hermetic_build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ They are shared by all GAPICs of a library.
| cloud_api | No | `true` if not specified |
| requires-billing | No | `true` if not specified |
| transport | No | must be one of `grpc`, `rest` or `both`. This value would only be used for generating .repo-metadata.json and relevant sections in README |
| folder_name | No | Only used in monorepos. This allows to override the default folder name where the library is created (e.g. monorepo/my-folder) |


Note that `cloud_prefix` is `cloud-` if `cloud_api` is `true`; empty otherwise.
Expand Down
64 changes: 47 additions & 17 deletions hermetic_build/common/model/gapic_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,32 @@
proto_library_pattern = r"""
proto_library_with_info\(
(.*?)
\)
\\?[\nn]\)
"""
gapic_pattern = r"""
java_gapic_library\(
(.*?)
\)
\\?[\nn]\)
"""
assembly_pattern = r"""
java_gapic_assembly_gradle_pkg\(
(.*?)
\)
\\?[\nn]\)
"""
# match a line which the first character is "#".
comment_pattern = r"^\s*\#+"
pattern_to_proto = {
r"//google/cloud:common_resources_proto": "google/cloud/common_resources.proto",
r"//google/cloud/location:location_proto": "google/cloud/location/locations.proto",
r"//google/iam/v1:iam_policy_proto": "google/iam/v1/iam_policy.proto",
# This pattern ignores api definitions that externally reference other repos.
# For example: @googleapis_repo//google/cloud/...
pattern_proto_library_to_additional_protos = {
r".*//google/cloud:common_resources_proto": "google/cloud/common_resources.proto",
r".*//google/cloud/location:location_proto": "google/cloud/location/locations.proto",
r".*//google/iam/v1:iam_policy_proto": "google/iam/v1/iam_policy.proto",
}
# This is a special case for showcase, where the additional protos
# are not declared in the gapic library instead
pattern_gapic_library_to_additional_protos = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind elaborating on why we need this special case?

r".*//google/cloud/location:location_java_proto": "google/cloud/location/locations.proto",
r".*//google/iam/v1:iam_java_proto": "google/iam/v1/iam_policy.proto",
}
transport_pattern = r"transport = \"(.*?)\""
rest_pattern = r"rest_numeric_enums = True"
Expand Down Expand Up @@ -108,9 +116,8 @@ def parse_build_str(build_str: str, versioned_path: str) -> GapicInputs:
proto_library_pattern, re.DOTALL | re.VERBOSE
).findall(build_str)
additional_protos = ""
if len(proto_library_target) > 0:
additional_protos = __parse_additional_protos(proto_library_target[0])
gapic_target = re.compile(gapic_pattern, re.DOTALL | re.VERBOSE).findall(build_str)
additional_protos = __parse_additional_protos(proto_library_target, gapic_target)
assembly_target = re.compile(assembly_pattern, re.DOTALL | re.VERBOSE).findall(
build_str
)
Expand Down Expand Up @@ -140,19 +147,42 @@ def parse_build_str(build_str: str, versioned_path: str) -> GapicInputs:
)


def __parse_additional_protos(proto_library_target: str) -> str:
res = [" "]
lines = proto_library_target.split("\n")
for line in lines:
def __get_lines_without_comments(target: list[str]):
"""
skips comment lines
"""
if len(target) == 0:
return []
result = []
for line in target[0].split("\n"):
if len(re.findall(comment_pattern, line)) != 0:
# skip a line which the first charactor is "#" since it's
# skip lines whose first character is "#" since it's
# a comment.
continue
for pattern in pattern_to_proto:
result.append(line)
return result


def __parse_additional_protos(
proto_library_target: list[str], gapic_library_target: list[str]
) -> str:
res = [" "]
lines = __get_lines_without_comments(proto_library_target)
# first, parse the proto library definition
for line in lines:
for pattern in pattern_proto_library_to_additional_protos:
if len(re.findall(pattern, line)) == 0:
continue
res.append(pattern_proto_library_to_additional_protos[pattern])
# then, parse the gapic library definition
lines = __get_lines_without_comments(gapic_library_target)
for line in lines:
for pattern in pattern_gapic_library_to_additional_protos:
if len(re.findall(pattern, line)) == 0:
continue
res.append(pattern_to_proto[pattern])
return " ".join(res)
res.append(pattern_gapic_library_to_additional_protos[pattern])
# finally, return the additional protos without duplicates
return " ".join(list(dict.fromkeys(res)))


def __parse_transport(gapic_target: str) -> str:
Expand Down
1 change: 1 addition & 0 deletions hermetic_build/common/model/generation_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ def from_yaml(path_to_yaml: str) -> GenerationConfig:
recommended_package=__optional(library, "recommended_package", None),
min_java_version=__optional(library, "min_java_version", None),
transport=__optional(library, "transport", None),
folder_name=__optional(library, "folder_name", None),
)
parsed_libraries.append(new_library)

Expand Down
13 changes: 13 additions & 0 deletions hermetic_build/common/model/library_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def __init__(
recommended_package: Optional[str] = None,
min_java_version: Optional[int] = None,
transport: Optional[str] = None,
folder_name: Optional[str] = None,
):
self.api_shortname = api_shortname
self.api_description = api_description
Expand Down Expand Up @@ -81,6 +82,18 @@ def __init__(
self.min_java_version = min_java_version
self.distribution_name = self.__get_distribution_name(distribution_name)
self.transport = self.__validate_transport(transport)
self.folder_name = folder_name

def get_folder_name(self, language: str = "java") -> str:
"""
This property is meant to be used for generating monorepos.
It will not have any effect when generating a non-monorepo library.
It allows specifying the final library's name inside the repo.
For example, sdk-platform-java/showcase
"""
if self.folder_name is not None:
return self.folder_name
return f"{language}-{self.get_library_name()}"

def get_library_name(self) -> str:
"""
Expand Down
8 changes: 8 additions & 0 deletions hermetic_build/common/tests/model/gapic_inputs_unit_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ class UtilitiesTest(unittest.TestCase):
"BUILD_iam_locations.bazel",
" google/cloud/location/locations.proto google/iam/v1/iam_policy.proto",
),
(
"BUILD_additional_protos_in_gapic.bazel",
" google/cloud/location/locations.proto google/iam/v1/iam_policy.proto",
),
(
"BUILD_target_with_nested_parenthesis.bazel",
" google/cloud/location/locations.proto google/iam/v1/iam_policy.proto",
),
]
)
def test_gapic_inputs_parse_additional_protos(self, build_name, expected):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
java_gapic_library(
deps = [
"//google/cloud/location:location_java_proto",
"//google/iam/v1:iam_java_proto"
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
proto_library_with_info(
# this comment should not indicate an end of a pattern match )
deps = [
"//google/cloud/location:location_proto",
]
)

java_gapic_library(
# this comment should not indicate an end of a pattern match )
deps = [
"//google/iam/v1:iam_java_proto"
],
)
10 changes: 7 additions & 3 deletions hermetic_build/library_generation/cli/entry_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,16 @@ def __generate_repo_impl(
)


def _needs_full_repo_generation(generation_config: GenerationConfig) -> bool:
def _needs_full_repo_generation(
generation_config: GenerationConfig, includes: Optional[str]
) -> bool:
"""
Whether you should need a full repo generation, i.e., generate all
libraries in the generation configuration.
If only showcase is specified, then it will return to false despite
other conditions (allows overriding contains_common_protos())
"""
return (
return (includes is None or includes.strip() != "showcase") and (
not generation_config.is_monorepo()
or generation_config.contains_common_protos()
)
Expand All @@ -147,7 +151,7 @@ def _needs_full_repo_generation(generation_config: GenerationConfig) -> bool:
def _parse_library_name_from(
includes: Optional[str], generation_config: GenerationConfig
) -> Optional[list[str]]:
if includes is None or _needs_full_repo_generation(generation_config):
if includes is None or _needs_full_repo_generation(generation_config, includes):
return None
return [library_name.strip() for library_name in includes.split(",")]

Expand Down
4 changes: 2 additions & 2 deletions hermetic_build/library_generation/utils/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ def prepare_repo(
os.makedirs(output_folder, exist_ok=True)
libraries = {}
for library in library_config:
library_name = f"{language}-{library.get_library_name()}"
library_folder_name = library.get_folder_name(language)
library_path = (
f"{repo_path}/{library_name}"
f"{repo_path}/{library_folder_name}"
if gen_config.is_monorepo()
else f"{repo_path}"
)
Expand Down
35 changes: 35 additions & 0 deletions showcase/.OwlBot-hermetic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# 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
#
# 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.


deep-remove-regex:
- "/showcase/grpc-gapic-showcase-v1beta1/src"
- "/showcase/proto-gapic-showcase-v1beta1/src"
- "/showcase/gapic-showcase/src"
- "/showcase/samples/snippets/generated"

deep-preserve-regex:
- "/showcase/gapic-showcase/src/test"

deep-copy-regex:
- source: "/schema/google/showcase/(v.*)/.*-java/proto-.*/src"
dest: "/owl-bot-staging/showcase/$1/proto-gapic-showcase-$1/src"
- source: "/schema/google/showcase/(v.*)/.*-java/grpc-.*/src"
dest: "/owl-bot-staging/showcase/$1/grpc-gapic-showcase-$1/src"
- source: "/schema/google/showcase/(v.*)/.*-java/gapic-.*/src"
dest: "/owl-bot-staging/showcase/$1/gapic-showcase/src"
- source: "/schema/google/showcase/(v.*)/.*-java/samples/snippets/generated"
dest: "/owl-bot-staging/showcase/$1/samples/snippets/generated"

api-name: showcase
16 changes: 16 additions & 0 deletions showcase/.repo-metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"api_shortname": "showcase",
"name_pretty": "Showcase",
"product_documentation": "https://cloud.google.com/dummy",
"api_description": "Showcase module",
"client_documentation": "https://cloud.google.com/java/docs/reference/gapic-showcase/latest/overview",
"release_level": "preview",
"transport": "both",
"language": "java",
"repo": "googleapis/sdk-platform-java",
"repo_short": "java-showcase",
"distribution_name": "com.google.cloud:gapic-showcase",
"library_type": "OTHER",
"requires_billing": true,
"excluded_poms": "gapic-showcase-bom"
}
5 changes: 0 additions & 5 deletions showcase/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,6 @@ Note:
## Update the Golden Showcase Files

Open a new terminal window in the root project directory.
Note that the underlying scripts will modify your `$HOME` folder by creating a
`.library_generation` folder.
This is the well-known location of the artifacts the generation scripts use.
For more details see the
[development guide](https://github.com/googleapis/sdk-platform-java/blob/main/library_generation/DEVELOPMENT.md#the-hermetic-builds-well-known-folder)

```shell
# In repository's root directory
Expand Down
5 changes: 2 additions & 3 deletions showcase/gapic-showcase/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.cloud</groupId>
<artifactId>gapic-showcase</artifactId>
Expand Down Expand Up @@ -104,6 +102,7 @@
<dependency>
<groupId>com.google.api.grpc</groupId>
<artifactId>grpc-google-common-protos</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.api.grpc</groupId>
Expand Down
Loading
Loading