Skip to content

Commit

Permalink
feat: selectively generate libraries (#3290)
Browse files Browse the repository at this point in the history
In this PR:
- Allow selectively generate libraries by adding `--library-names` to
CLI.

We have a request of partially releasing google-cloud-java
(b/331628538), which requires only generating a selective list of
libraries.

This change allows a user-defined list of libraries to be generated even
if the corresponding library configs are the same.
  • Loading branch information
JoeWang1127 authored Oct 16, 2024
1 parent 771bd0e commit dfe1a50
Show file tree
Hide file tree
Showing 6 changed files with 351 additions and 13 deletions.
54 changes: 45 additions & 9 deletions library_generation/cli/entry_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.
import os
import sys

from typing import Optional
import click as click
from library_generation.generate_pr_description import generate_pr_descriptions
from library_generation.generate_repo import generate_from_yaml
Expand Down Expand Up @@ -51,6 +51,17 @@ def main(ctx):
metadata about library generation.
""",
)
@click.option(
"--library-names",
type=str,
default=None,
show_default=True,
help="""
A list of library names that will be generated, separated by comma.
The library name of a library is the value of library_name or api_shortname,
if library_name is not specified, in the generation configuration.
""",
)
@click.option(
"--repository-path",
type=str,
Expand All @@ -77,6 +88,7 @@ def main(ctx):
def generate(
baseline_generation_config_path: str,
current_generation_config_path: str,
library_names: Optional[str],
repository_path: str,
api_definitions_path: str,
):
Expand All @@ -86,24 +98,32 @@ def generate(
history.
If baseline generation config is not specified but current generation
config is specified, generate all libraries based on current generation
config without commit history.
config is specified, generate all libraries if `library_names` is not
specified, based on current generation config without commit history.
If current generation config is not specified but baseline generation
config is specified, raise FileNotFoundError because current generation
config should be the source of truth of library generation.
If both baseline generation config and current generation config are not
specified, generate all libraries based on the default generation config,
which is generation_config.yaml in the current working directory. Raise
FileNotFoundError if the default config does not exist.
which is generation_config.yaml in the current working directory.
If `library_names` is specified, only libraries whose name can be found in
the current generation config or default generation config, if current
generation config is not specified, will be generated. Changed libraries
will be ignored even if baseline and current generation config are
specified.
Raise FileNotFoundError if the default config does not exist.
The commit history, if generated, will be available in
repository_path/pr_description.txt.
"""
__generate_repo_and_pr_description_impl(
baseline_generation_config_path=baseline_generation_config_path,
current_generation_config_path=current_generation_config_path,
library_names=library_names,
repository_path=repository_path,
api_definitions_path=api_definitions_path,
)
Expand All @@ -112,6 +132,7 @@ def generate(
def __generate_repo_and_pr_description_impl(
baseline_generation_config_path: str,
current_generation_config_path: str,
library_names: Optional[str],
repository_path: str,
api_definitions_path: str,
):
Expand Down Expand Up @@ -146,30 +167,39 @@ def __generate_repo_and_pr_description_impl(
current_generation_config_path = os.path.abspath(current_generation_config_path)
repository_path = os.path.abspath(repository_path)
api_definitions_path = os.path.abspath(api_definitions_path)
include_library_names = _parse_library_name_from(library_names)

if not baseline_generation_config_path:
# Execute full generation based on current_generation_config if
# Execute selective generation based on current_generation_config if
# baseline_generation_config is not specified.
# Do not generate pull request description.
generate_from_yaml(
config=from_yaml(current_generation_config_path),
repository_path=repository_path,
api_definitions_path=api_definitions_path,
target_library_names=include_library_names,
)
return

# Compare two generation configs and only generate changed libraries.
# Compare two generation configs to get changed libraries.
# Generate pull request description.
baseline_generation_config_path = os.path.abspath(baseline_generation_config_path)
config_change = compare_config(
baseline_config=from_yaml(baseline_generation_config_path),
current_config=from_yaml(current_generation_config_path),
)
# pass None if we want to fully generate the repository.
target_library_names = (
# Pass None if we want to fully generate the repository.
changed_library_names = (
config_change.get_changed_libraries()
if not _needs_full_repo_generation(config_change=config_change)
else None
)
# Include library names takes preference if specified.
target_library_names = (
include_library_names
if include_library_names is not None
else changed_library_names
)
generate_from_yaml(
config=config_change.current_config,
repository_path=repository_path,
Expand All @@ -191,6 +221,12 @@ def _needs_full_repo_generation(config_change: ConfigChange) -> bool:
return not current_config.is_monorepo() or current_config.contains_common_protos()


def _parse_library_name_from(includes: str) -> Optional[list[str]]:
if includes is None:
return None
return [library_name.strip() for library_name in includes.split(",")]


@main.command()
@click.option(
"--generation-config-path",
Expand Down
5 changes: 2 additions & 3 deletions library_generation/generate_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
# 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 os
import shutil

from typing import Optional
import library_generation.utils.utilities as util
from library_generation.generate_composed_library import generate_composed_library
from library_generation.model.generation_config import GenerationConfig
Expand All @@ -26,7 +25,7 @@ def generate_from_yaml(
config: GenerationConfig,
repository_path: str,
api_definitions_path: str,
target_library_names: list[str] = None,
target_library_names: Optional[list[str]],
) -> None:
"""
Based on the generation config, generates libraries via
Expand Down
Loading

0 comments on commit dfe1a50

Please sign in to comment.