3636
3737logger = logging .getLogger ()
3838
39- LIBRARIAN_DIR = "librarian "
39+ BUILD_REQUEST_FILE = "build-request.json "
4040GENERATE_REQUEST_FILE = "generate-request.json"
41+ RELEASE_INIT_REQUEST_FILE = "release-init-request.json"
42+
4143INPUT_DIR = "input"
42- BUILD_REQUEST_FILE = "build-request.json"
43- SOURCE_DIR = "source"
44+ LIBRARIAN_DIR = "librarian"
4445OUTPUT_DIR = "output"
4546REPO_DIR = "repo"
47+ SOURCE_DIR = "source"
4648
4749
4850def _read_json_file (path : str ) -> Dict :
@@ -371,7 +373,6 @@ def handle_generate(
371373 except Exception as e :
372374 raise ValueError ("Generation failed." ) from e
373375
374- # TODO(https://github.com/googleapis/librarian/issues/448): Implement generate command and update docstring.
375376 logger .info ("'generate' command executed." )
376377
377378
@@ -433,23 +434,91 @@ def handle_build(librarian: str = LIBRARIAN_DIR, repo: str = REPO_DIR):
433434 logger .info ("'build' command executed." )
434435
435436
437+ def _get_libraries_to_prepare_for_release (library_entries : Dict ) -> List [dict ]:
438+ """Get libraries which should be prepared for release. Only libraries
439+ which have the `release_triggered` field set to `True` will be returned.
440+
441+ Args:
442+ library_entries(Dict): Dictionary containing all of the libraries to
443+ evaluate.
444+
445+ Returns:
446+ List[dict]: List of all libraries which should be prepared for release,
447+ along with the corresponding information for the release.
448+ """
449+ return [
450+ library
451+ for library in library_entries ["libraries" ]
452+ if library .get ("release_triggered" )
453+ ]
454+
455+
456+ def handle_release_init (
457+ librarian : str = LIBRARIAN_DIR , repo : str = REPO_DIR , output : str = OUTPUT_DIR
458+ ):
459+ """The main coordinator for the release preparation process.
460+
461+ This function prepares for the release of client libraries by reading a
462+ `librarian/release-init-request.json` file. The primary responsibility is
463+ to update all required files with the new version and commit information
464+ for libraries that have the `release_triggered` field set to `True`.
465+
466+ See https://github.com/googleapis/librarian/blob/main/doc/container-contract.md#generate-container-command
467+
468+ Args:
469+ librarian(str): Path to the directory in the container which contains
470+ the `release-init-request.json` file.
471+ repo(str): This directory will contain all directories that make up a
472+ library, the .librarian folder, and any global file declared in
473+ the config.yaml.
474+ output(str): Path to the directory in the container where modified
475+ code should be placed.
476+ """
477+
478+ try :
479+ # Read a release-init-request.json file
480+ request_data = _read_json_file (f"{ librarian } /{ RELEASE_INIT_REQUEST_FILE } " )
481+ libraries_to_prep_for_release = _get_libraries_to_prepare_for_release (
482+ request_data
483+ )
484+
485+ # TODO(https://github.com/googleapis/google-cloud-python/pull/14349):
486+ # Update library global changelog file.
487+
488+ # Prepare the release for each library by updating the
489+ # library specific version files and library specific changelog.
490+ for library_release_data in libraries_to_prep_for_release :
491+ # TODO(https://github.com/googleapis/google-cloud-python/pull/14350):
492+ # Update library specific version files.
493+ # TODO(https://github.com/googleapis/google-cloud-python/pull/14351):
494+ # Conditionally update the library specific CHANGELOG if there is a change.
495+ pass
496+
497+ except Exception as e :
498+ raise ValueError (f"Release init failed: { e } " ) from e
499+
500+ logger .info ("'release-init' command executed." )
501+
502+
436503if __name__ == "__main__" : # pragma: NO COVER
437504 parser = argparse .ArgumentParser (description = "A simple CLI tool." )
438505 subparsers = parser .add_subparsers (
439506 dest = "command" , required = True , help = "Available commands"
440507 )
441508
442- # Define commands
509+ # Define commands and their corresponding handler functions
443510 handler_map = {
444511 "configure" : handle_configure ,
445512 "generate" : handle_generate ,
446513 "build" : handle_build ,
514+ "release-init" : handle_release_init ,
447515 }
448516
449517 for command_name , help_text in [
450518 ("configure" , "Onboard a new library or an api path to Librarian workflow." ),
451519 ("generate" , "generate a python client for an API." ),
452520 ("build" , "Run unit tests via nox for the generated library." ),
521+ ("release-init" , "Prepare to release a given set of libraries" ),
453522 ]:
454523 parser_cmd = subparsers .add_parser (command_name , help = help_text )
455524 parser_cmd .set_defaults (func = handler_map [command_name ])
@@ -483,6 +552,7 @@ def handle_build(librarian: str = LIBRARIAN_DIR, repo: str = REPO_DIR):
483552 help = "Path to the directory in the container which contains google-cloud-python repository" ,
484553 default = REPO_DIR ,
485554 )
555+
486556 if len (sys .argv ) == 1 :
487557 parser .print_help (sys .stderr )
488558 sys .exit (1 )
@@ -499,5 +569,7 @@ def handle_build(librarian: str = LIBRARIAN_DIR, repo: str = REPO_DIR):
499569 )
500570 elif args .command == "build" :
501571 args .func (librarian = args .librarian , repo = args .repo )
572+ elif args .command == "release-init" :
573+ args .func (librarian = args .librarian , repo = args .repo , output = args .output )
502574 else :
503575 args .func ()
0 commit comments