|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# Copyright 2024 Google LLC |
| 3 | +# |
| 4 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | +# you may not use this file except in compliance with the License. |
| 6 | +# You may obtain a copy of the License at |
| 7 | +# |
| 8 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +# |
| 10 | +# Unless required by applicable law or agreed to in writing, software |
| 11 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | +# See the License for the specific language governing permissions and |
| 14 | +# limitations under the License. |
| 15 | + |
1 | 16 | """
|
2 | 17 | This script allows generation of libraries that are composed of more than one
|
3 | 18 | service version. It is achieved by calling `generate_library.sh` without
|
|
12 | 27 | - A "grafeas" folder found in the googleapis/googleapis repository
|
13 | 28 | Note: googleapis repo is found in https://github.com/googleapis/googleapis.
|
14 | 29 | """
|
15 |
| - |
16 |
| -import click |
17 |
| -import utilities as util |
18 | 30 | import os
|
19 |
| -import sys |
20 |
| -import subprocess |
21 |
| -import json |
22 |
| -from model.GenerationConfig import GenerationConfig |
23 |
| -from model.LibraryConfig import LibraryConfig |
24 |
| -from model.ClientInputs import parse as parse_build_file |
| 31 | +from pathlib import Path |
| 32 | +from typing import List |
| 33 | +import library_generation.utilities as util |
| 34 | +from library_generation.model.generation_config import GenerationConfig |
| 35 | +from library_generation.model.gapic_config import GapicConfig |
| 36 | +from library_generation.model.gapic_inputs import GapicInputs |
| 37 | +from library_generation.model.library_config import LibraryConfig |
| 38 | +from library_generation.model.gapic_inputs import parse as parse_build_file |
25 | 39 |
|
26 | 40 | script_dir = os.path.dirname(os.path.realpath(__file__))
|
27 | 41 |
|
28 |
| -""" |
29 |
| -Main function in charge of generating libraries composed of more than one |
30 |
| -service or service version. |
31 |
| -Arguments |
32 |
| - - config: a GenerationConfig object representing a parsed configuration |
33 |
| - yaml |
34 |
| - - library: a LibraryConfig object contained inside config, passed here for |
35 |
| - convenience and to prevent all libraries to be processed |
36 |
| - - enable_postprocessing: true if postprocessing should be done on the generated |
37 |
| - libraries |
38 |
| - - repository_path: path to the repository where the generated files will be |
39 |
| - sent. If not specified, it will default to the one defined in the configuration yaml |
40 |
| - and will be downloaded. The versions file will be inferred from this folder |
41 |
| -""" |
| 42 | + |
42 | 43 | def generate_composed_library(
|
43 | 44 | config: GenerationConfig,
|
| 45 | + library_path: str, |
44 | 46 | library: LibraryConfig,
|
45 |
| - repository_path: str, |
46 |
| - enable_postprocessing: bool = True, |
| 47 | + output_folder: str, |
| 48 | + versions_file: str, |
47 | 49 | ) -> None:
|
48 |
| - output_folder = util.sh_util('get_output_folder') |
49 |
| - |
50 |
| - print(f'output_folder: {output_folder}') |
51 |
| - print('library: ', library) |
52 |
| - os.makedirs(output_folder, exist_ok=True) |
53 |
| - |
54 |
| - googleapis_commitish = config.googleapis_commitish |
55 |
| - if library.googleapis_commitish is not None: |
56 |
| - googleapis_commitish = library.googleapis_commitish |
57 |
| - print('using library-specific googleapis commitish: ' + googleapis_commitish) |
58 |
| - else: |
59 |
| - print('using common googleapis_commitish') |
60 |
| - |
61 |
| - print('removing old googleapis folders and files') |
62 |
| - util.delete_if_exists(f'{output_folder}/google') |
63 |
| - util.delete_if_exists(f'{output_folder}/grafeas') |
64 |
| - |
65 |
| - print('downloading googleapis') |
66 |
| - util.sh_util(f'download_googleapis_files_and_folders "{output_folder}" "{googleapis_commitish}"') |
67 |
| - |
68 |
| - is_monorepo = len(config.libraries) > 1 |
| 50 | + """ |
| 51 | + Generate libraries composed of more than one service or service version |
| 52 | + :param config: a GenerationConfig object representing a parsed configuration |
| 53 | + yaml |
| 54 | + :param library_path: the path to which the generated file goes |
| 55 | + :param library: a LibraryConfig object contained inside config, passed here |
| 56 | + for convenience and to prevent all libraries to be processed |
| 57 | + :param output_folder: |
| 58 | + :param versions_file: |
| 59 | + :return None |
| 60 | + """ |
| 61 | + util.pull_api_definition( |
| 62 | + config=config, library=library, output_folder=output_folder |
| 63 | + ) |
| 64 | + |
| 65 | + is_monorepo = util.check_monorepo(config=config) |
| 66 | + base_arguments = __construct_tooling_arg(config=config) |
| 67 | + owlbot_cli_source_folder = util.sh_util("mktemp -d") |
| 68 | + os.makedirs(f"{library_path}", exist_ok=True) |
| 69 | + for gapic in library.gapic_configs: |
| 70 | + build_file_folder = Path(f"{output_folder}/{gapic.proto_path}").resolve() |
| 71 | + print(f"build_file_folder: {build_file_folder}") |
| 72 | + gapic_inputs = parse_build_file(build_file_folder, gapic.proto_path) |
| 73 | + # generate prerequisite files (.repo-metadata.json, .OwlBot.yaml, |
| 74 | + # owlbot.py) here because transport is parsed from BUILD.bazel, |
| 75 | + # which lives in a versioned proto_path. |
| 76 | + util.generate_prerequisite_files( |
| 77 | + library=library, |
| 78 | + proto_path=util.remove_version_from(gapic.proto_path), |
| 79 | + transport=gapic_inputs.transport, |
| 80 | + library_path=library_path, |
| 81 | + ) |
| 82 | + service_version = gapic.proto_path.split("/")[-1] |
| 83 | + temp_destination_path = f"java-{library.api_shortname}-{service_version}" |
| 84 | + effective_arguments = __construct_effective_arg( |
| 85 | + base_arguments=base_arguments, |
| 86 | + gapic=gapic, |
| 87 | + gapic_inputs=gapic_inputs, |
| 88 | + temp_destination_path=temp_destination_path, |
| 89 | + ) |
| 90 | + print("arguments: ") |
| 91 | + print(effective_arguments) |
| 92 | + print(f"Generating library from {gapic.proto_path} to {library_path}") |
| 93 | + util.run_process_and_print_output( |
| 94 | + ["bash", f"{script_dir}/generate_library.sh", *effective_arguments], |
| 95 | + "Library generation", |
| 96 | + ) |
| 97 | + |
| 98 | + util.sh_util( |
| 99 | + f'build_owlbot_cli_source_folder "{library_path}"' |
| 100 | + + f' "{owlbot_cli_source_folder}" "{output_folder}/{temp_destination_path}"' |
| 101 | + + f' "{gapic.proto_path}"', |
| 102 | + cwd=output_folder, |
| 103 | + ) |
69 | 104 |
|
70 |
| - base_arguments = [] |
71 |
| - base_arguments += util.create_argument('gapic_generator_version', config) |
72 |
| - base_arguments += util.create_argument('grpc_version', config) |
73 |
| - base_arguments += util.create_argument('protobuf_version', config) |
74 |
| - |
75 |
| - library_name = f'java-{library.api_shortname}' |
76 |
| - library_path = None |
77 |
| - |
78 |
| - versions_file = '' |
79 |
| - if is_monorepo: |
80 |
| - print('this is a monorepo library') |
81 |
| - destination_path = config.destination_path + '/' + library_name |
82 |
| - library_folder = destination_path.split('/')[-1] |
83 |
| - if repository_path is None: |
84 |
| - print(f'sparse_cloning monorepo with {library_name}') |
85 |
| - repository_path = f'{output_folder}/{config.destination_path}' |
86 |
| - clone_out = util.sh_util(f'sparse_clone "https://github.com/googleapis/{MONOREPO_NAME}.git" "{library_folder} google-cloud-pom-parent google-cloud-jar-parent versions.txt .github"', cwd=output_folder) |
87 |
| - print(clone_out) |
88 |
| - library_path = f'{repository_path}/{library_name}' |
89 |
| - versions_file = f'{repository_path}/versions.txt' |
90 |
| - else: |
91 |
| - print('this is a HW library') |
92 |
| - destination_path = library_name |
93 |
| - if repository_path is None: |
94 |
| - repository_path = f'{output_folder}/{destination_path}' |
95 |
| - util.delete_if_exists(f'{output_folder}/{destination_path}') |
96 |
| - clone_out = util.sh_util(f'git clone "https://github.com/googleapis/{destination_path}.git"', cwd=output_folder) |
97 |
| - print(clone_out) |
98 |
| - library_path = f'{repository_path}' |
99 |
| - versions_file = f'{repository_path}/versions.txt' |
100 |
| - |
101 |
| - owlbot_cli_source_folder = util.sh_util('mktemp -d') |
102 |
| - for gapic in library.gapic_configs: |
103 |
| - |
104 |
| - effective_arguments = list(base_arguments) |
105 |
| - effective_arguments += util.create_argument('proto_path', gapic) |
106 |
| - |
107 |
| - build_file_folder = f'{output_folder}/{gapic.proto_path}' |
108 |
| - print(f'build_file_folder: {build_file_folder}') |
109 |
| - client_inputs = parse_build_file(build_file_folder, gapic.proto_path) |
110 |
| - effective_arguments += [ |
111 |
| - '--proto_only', client_inputs.proto_only, |
112 |
| - '--gapic_additional_protos', client_inputs.additional_protos, |
113 |
| - '--transport', client_inputs.transport, |
114 |
| - '--rest_numeric_enums', client_inputs.rest_numeric_enum, |
115 |
| - '--gapic_yaml', client_inputs.gapic_yaml, |
116 |
| - '--service_config', client_inputs.service_config, |
117 |
| - '--service_yaml', client_inputs.service_yaml, |
118 |
| - '--include_samples', client_inputs.include_samples, |
119 |
| - ] |
120 |
| - service_version = gapic.proto_path.split('/')[-1] |
121 |
| - temp_destination_path = f'java-{library.api_shortname}-{service_version}' |
122 |
| - effective_arguments += [ '--destination_path', temp_destination_path ] |
123 |
| - print('arguments: ') |
124 |
| - print(effective_arguments) |
125 |
| - print(f'Generating library from {gapic.proto_path} to {destination_path}...') |
126 |
| - util.run_process_and_print_output(['bash', '-x', f'{script_dir}/generate_library.sh', |
127 |
| - *effective_arguments], 'Library generation') |
128 |
| - |
129 |
| - |
130 |
| - if enable_postprocessing: |
131 |
| - util.sh_util(f'build_owlbot_cli_source_folder "{library_path}"' |
132 |
| - + f' "{owlbot_cli_source_folder}" "{output_folder}/{temp_destination_path}"' |
133 |
| - + f' "{gapic.proto_path}"', |
134 |
| - cwd=output_folder) |
135 |
| - |
136 |
| - if enable_postprocessing: |
137 | 105 | # call postprocess library
|
138 |
| - util.run_process_and_print_output([f'{script_dir}/postprocess_library.sh', |
139 |
| - f'{library_path}', '', versions_file, owlbot_cli_source_folder, |
140 |
| - config.owlbot_cli_image, config.synthtool_commitish, str(is_monorepo).lower()], 'Library postprocessing') |
| 106 | + util.run_process_and_print_output( |
| 107 | + [ |
| 108 | + f"{script_dir}/postprocess_library.sh", |
| 109 | + f"{library_path}", |
| 110 | + "", |
| 111 | + versions_file, |
| 112 | + owlbot_cli_source_folder, |
| 113 | + config.owlbot_cli_image, |
| 114 | + config.synthtool_commitish, |
| 115 | + str(is_monorepo).lower(), |
| 116 | + ], |
| 117 | + "Library postprocessing", |
| 118 | + ) |
| 119 | + |
| 120 | + |
| 121 | +def __construct_tooling_arg(config: GenerationConfig) -> List[str]: |
| 122 | + """ |
| 123 | + Construct arguments of tooling versions used in generate_library.sh |
| 124 | + :param config: the generation config |
| 125 | + :return: arguments containing tooling versions |
| 126 | + """ |
| 127 | + arguments = [] |
| 128 | + arguments += util.create_argument("gapic_generator_version", config) |
| 129 | + arguments += util.create_argument("grpc_version", config) |
| 130 | + arguments += util.create_argument("protobuf_version", config) |
| 131 | + |
| 132 | + return arguments |
| 133 | + |
| 134 | + |
| 135 | +def __construct_effective_arg( |
| 136 | + base_arguments: List[str], |
| 137 | + gapic: GapicConfig, |
| 138 | + gapic_inputs: GapicInputs, |
| 139 | + temp_destination_path: str, |
| 140 | +) -> List[str]: |
| 141 | + """ |
| 142 | + Construct arguments consist attributes of a GAPIC library which used in |
| 143 | + generate_library.sh |
| 144 | + :param base_arguments: arguments consist of tooling versions |
| 145 | + :param gapic: an object of GapicConfig |
| 146 | + :param gapic_inputs: an object of GapicInput |
| 147 | + :param temp_destination_path: the path to which the generated library goes |
| 148 | + :return: arguments containing attributes to generate a GAPIC library |
| 149 | + """ |
| 150 | + arguments = list(base_arguments) |
| 151 | + arguments += util.create_argument("proto_path", gapic) |
| 152 | + arguments += [ |
| 153 | + "--proto_only", |
| 154 | + gapic_inputs.proto_only, |
| 155 | + "--gapic_additional_protos", |
| 156 | + gapic_inputs.additional_protos, |
| 157 | + "--transport", |
| 158 | + gapic_inputs.transport, |
| 159 | + "--rest_numeric_enums", |
| 160 | + gapic_inputs.rest_numeric_enum, |
| 161 | + "--gapic_yaml", |
| 162 | + gapic_inputs.gapic_yaml, |
| 163 | + "--service_config", |
| 164 | + gapic_inputs.service_config, |
| 165 | + "--service_yaml", |
| 166 | + gapic_inputs.service_yaml, |
| 167 | + "--include_samples", |
| 168 | + gapic_inputs.include_samples, |
| 169 | + ] |
| 170 | + arguments += ["--destination_path", temp_destination_path] |
141 | 171 |
|
| 172 | + return arguments |
0 commit comments