diff --git a/.github/snippet-bot.yml b/.github/snippet-bot.yml
index c7ee6ca54b..9458774ff0 100644
--- a/.github/snippet-bot.yml
+++ b/.github/snippet-bot.yml
@@ -4,3 +4,4 @@ ignoreFiles:
- src/test/**
- test/**
- showcase/**
+ - library_generation/owlbot/templates/java_library/samples/install-without-bom/pom.xml
diff --git a/.github/workflows/verify_library_generation.yaml b/.github/workflows/verify_library_generation.yaml
index f3dc825c85..89cec5ddc9 100644
--- a/.github/workflows/verify_library_generation.yaml
+++ b/.github/workflows/verify_library_generation.yaml
@@ -42,6 +42,7 @@ jobs:
set -ex
pushd library_generation
pip install -r requirements.in
+ pip install .
popd
- name: Run integration tests
shell: bash
@@ -74,6 +75,21 @@ jobs:
pushd library_generation
pip install -r requirements.in
popd
+ - name: install synthtool
+ shell: bash
+ run: |
+ set -ex
+ mkdir -p /tmp/synthtool
+ pushd /tmp/synthtool
+ if [ ! -d "synthtool" ]; then
+ git clone https://github.com/googleapis/synthtool.git
+ fi
+ pushd "synthtool"
+
+ git reset --hard origin/no-java-templates
+
+ python3 -m pip install -e .
+ python3 -m pip install -r requirements.in
- name: Run shell unit tests
run: |
set -x
@@ -108,4 +124,4 @@ jobs:
run: |
# exclude generated golden files
# exclude owlbot until further refaction
- black --check library_generation --exclude "(library_generation/owlbot)|(library_generation/test/resources/goldens)"
+ black --check library_generation --exclude "(library_generation/test/resources/goldens)"
diff --git a/library_generation/generate_composed_library.py b/library_generation/generate_composed_library.py
index 6f8216f511..1c2e1a4a91 100755
--- a/library_generation/generate_composed_library.py
+++ b/library_generation/generate_composed_library.py
@@ -113,6 +113,7 @@ def generate_composed_library(
config.owlbot_cli_image,
config.synthtool_commitish,
str(is_monorepo).lower(),
+ config.path_to_yaml,
],
"Library postprocessing",
)
diff --git a/library_generation/model/generation_config.py b/library_generation/model/generation_config.py
index 1c3c62d1fb..7317edc932 100644
--- a/library_generation/model/generation_config.py
+++ b/library_generation/model/generation_config.py
@@ -31,6 +31,8 @@ def __init__(
googleapis_commitish: str,
owlbot_cli_image: str,
synthtool_commitish: str,
+ template_excludes: str,
+ path_to_yaml: str,
libraries: List[LibraryConfig],
grpc_version: Optional[str] = None,
protobuf_version: Optional[str] = None,
@@ -39,6 +41,8 @@ def __init__(
self.googleapis_commitish = googleapis_commitish
self.owlbot_cli_image = owlbot_cli_image
self.synthtool_commitish = synthtool_commitish
+ self.template_excludes = template_excludes
+ self.path_to_yaml = path_to_yaml
self.libraries = libraries
self.grpc_version = grpc_version
self.protobuf_version = protobuf_version
@@ -94,6 +98,8 @@ def from_yaml(path_to_yaml: str):
googleapis_commitish=__required(config, "googleapis_commitish"),
owlbot_cli_image=__required(config, "owlbot_cli_image"),
synthtool_commitish=__required(config, "synthtool_commitish"),
+ template_excludes=__required(config, "template_excludes"),
+ path_to_yaml=path_to_yaml,
libraries=parsed_libraries,
)
diff --git a/library_generation/owlbot/bin/entrypoint.sh b/library_generation/owlbot/bin/entrypoint.sh
index a26eaec996..a8d5a730e3 100755
--- a/library_generation/owlbot/bin/entrypoint.sh
+++ b/library_generation/owlbot/bin/entrypoint.sh
@@ -26,50 +26,14 @@
set -ex
scripts_root=$1
versions_file=$2
-
-# Runs template and etc in current working directory
-function processModule() {
- # templates as well as retrieving files from owl-bot-staging
- echo "Generating templates and retrieving files from owl-bot-staging directory..."
- if [ -f "owlbot.py" ]
- then
- # defaults to run owlbot.py
- python3 owlbot.py
- fi
- echo "...done"
-
- # write or restore pom.xml files
- echo "Generating missing pom.xml..."
- python3 "${scripts_root}/owlbot/src/fix-poms.py" "${versions_file}" "true"
- echo "...done"
-
- # write or restore clirr-ignored-differences.xml
- echo "Generating clirr-ignored-differences.xml..."
- ${scripts_root}/owlbot/bin/write_clirr_ignore.sh "${scripts_root}"
- echo "...done"
-
- # fix license headers
- echo "Fixing missing license headers..."
- python3 "${scripts_root}/owlbot/src/fix-license-headers.py"
- echo "...done"
-
- # TODO: re-enable this once we resolve thrashing
- # restore license headers years
- # echo "Restoring copyright years..."
- # /owlbot/bin/restore_license_headers.sh
- # echo "...done"
-
- # ensure formatting on all .java files in the repository
- echo "Reformatting source..."
- mvn fmt:format -q
- echo "...done"
-}
+configuration_yaml=$3
# This script can be used to process HW libraries and monorepo
# (google-cloud-java) libraries, which require a slightly different treatment
# monorepo folders have an .OwlBot.yaml file in the module folder (e.g.
# java-asset/.OwlBot.yaml), whereas HW libraries have the yaml in
# `.github/.OwlBot.yaml`
+monorepo="false"
if [[ -f "$(pwd)/.OwlBot.yaml" ]]; then
monorepo="true"
fi
@@ -80,4 +44,48 @@ if [[ "${monorepo}" == "true" ]]; then
mv temp owl-bot-staging
fi
-processModule
+
+# Runs template and etc in current working directory
+monorepo=$1
+
+# apply repo templates
+echo "Rendering templates"
+python3 "${scripts_root}/owlbot/src/apply_repo_templates.py" "${configuration_yaml}" "${monorepo}"
+
+# templates as well as retrieving files from owl-bot-staging
+echo "Retrieving files from owl-bot-staging directory..."
+if [ -f "owlbot.py" ]
+then
+ # defaults to run owlbot.py
+ python3 owlbot.py
+fi
+echo "...done"
+
+# write or restore pom.xml files
+echo "Generating missing pom.xml..."
+python3 "${scripts_root}/owlbot/src/fix-poms.py" "${versions_file}" "true"
+echo "...done"
+
+# write or restore clirr-ignored-differences.xml
+echo "Generating clirr-ignored-differences.xml..."
+${scripts_root}/owlbot/bin/write_clirr_ignore.sh "${scripts_root}"
+echo "...done"
+
+# fix license headers
+echo "Fixing missing license headers..."
+python3 "${scripts_root}/owlbot/src/fix-license-headers.py"
+echo "...done"
+
+# TODO: re-enable this once we resolve thrashing
+# restore license headers years
+# echo "Restoring copyright years..."
+# /owlbot/bin/restore_license_headers.sh
+# echo "...done"
+
+# ensure formatting on all .java files in the repository
+echo "Reformatting source..."
+mvn fmt:format
+echo "...done"
+
+
+
diff --git a/library_generation/owlbot/src/apply_repo_templates.py b/library_generation/owlbot/src/apply_repo_templates.py
new file mode 100644
index 0000000000..929ffb66f2
--- /dev/null
+++ b/library_generation/owlbot/src/apply_repo_templates.py
@@ -0,0 +1,42 @@
+"""
+This script parses an owlbot.py file, specifically the call to `java.common_templates` in
+order to extract the excluded files so it can be called with a custom template path
+pointing to the templates hosted in `sdk-platform-java/library_generation/owlbot/templates`.
+Briefly, this wraps the call to synthtool's common templates using a custom template folder.
+"""
+
+import os
+import sys
+from collections.abc import Sequence
+from synthtool.languages.java import common_templates
+from pathlib import Path
+from library_generation.model.generation_config import from_yaml
+
+script_dir = os.path.dirname(os.path.realpath(__file__))
+repo_templates_path = os.path.join(script_dir, "..", "templates", "java_library")
+
+
+def apply_repo_templates(configuration_yaml_path: str, monorepo: bool) -> None:
+ config = from_yaml(configuration_yaml_path)
+ print(f"repo_templates_path: {repo_templates_path}")
+ print(f"excludes: {config.template_excludes}")
+ common_templates(
+ excludes=config.template_excludes,
+ template_path=Path(repo_templates_path),
+ monorepo=monorepo,
+ )
+
+
+def main(argv: Sequence[str]) -> None:
+ if len(argv) != 3:
+ raise ValueError(
+ "Usage: python apply-repo-templates.py configuration_yaml_path monorepo"
+ )
+
+ configuration_yaml_path = argv[1]
+ monorepo = argv[2]
+ apply_repo_templates(configuration_yaml_path, monorepo.lower() == "true")
+
+
+if __name__ == "__main__":
+ main(sys.argv)
diff --git a/library_generation/owlbot/src/fix-poms.py b/library_generation/owlbot/src/fix-poms.py
index 87df4a46bb..b57012fcf8 100644
--- a/library_generation/owlbot/src/fix-poms.py
+++ b/library_generation/owlbot/src/fix-poms.py
@@ -285,9 +285,11 @@ def update_bom_pom(filename: str, modules: List[module.Module]):
# https://github.com/googleapis/google-cloud-java/issues/9304
def __proto_group_id(main_artifact_group_id: str) -> str:
prefix = "com.google"
- list_of_group_id = ["com.google.cloud",
- "com.google.area120",
- "com.google.analytics"]
+ list_of_group_id = [
+ "com.google.cloud",
+ "com.google.area120",
+ "com.google.analytics",
+ ]
if main_artifact_group_id not in list_of_group_id:
prefix = main_artifact_group_id
return f"{prefix}.api.grpc"
@@ -343,11 +345,17 @@ def main(versions_file, monorepo):
main_module = existing_modules[artifact_id]
# Artifact ID is part of distribution name field in .repo-metadata.json
- if artifact_id in ["grafeas", "google-cloud-dns",
- "google-cloud-notification", "google-iam-policy"]:
+ if artifact_id in [
+ "grafeas",
+ "google-cloud-dns",
+ "google-cloud-notification",
+ "google-iam-policy",
+ ]:
# There are special libraries that are not automatically generated
- print(f"Skipping a special case library {artifact_id} that do not have "
- " the standard module structure.")
+ print(
+ f"Skipping a special case library {artifact_id} that do not have "
+ " the standard module structure."
+ )
return
parent_artifact_id = f"{artifact_id}-parent"
@@ -383,8 +391,10 @@ def main(versions_file, monorepo):
version=main_module.version,
release_version=main_module.release_version,
)
- if path not in excluded_dependencies_list \
- and path not in main_module.artifact_id:
+ if (
+ path not in excluded_dependencies_list
+ and path not in main_module.artifact_id
+ ):
required_dependencies[path] = module.Module(
group_id=__proto_group_id(group_id),
artifact_id=path,
@@ -401,8 +411,10 @@ def main(versions_file, monorepo):
main_module=main_module,
monorepo=monorepo,
)
- if path not in excluded_dependencies_list \
- and path not in main_module.artifact_id:
+ if (
+ path not in excluded_dependencies_list
+ and path not in main_module.artifact_id
+ ):
required_dependencies[path] = module.Module(
group_id=__proto_group_id(group_id),
artifact_id=path,
@@ -418,8 +430,10 @@ def main(versions_file, monorepo):
version=main_module.version,
release_version=main_module.release_version,
)
- if path not in excluded_dependencies_list \
- and path not in main_module.artifact_id:
+ if (
+ path not in excluded_dependencies_list
+ and path not in main_module.artifact_id
+ ):
required_dependencies[path] = module.Module(
group_id=__proto_group_id(group_id),
artifact_id=path,
@@ -439,8 +453,10 @@ def main(versions_file, monorepo):
proto_module=existing_modules[proto_artifact_id],
monorepo=monorepo,
)
- if path not in excluded_dependencies_list \
- and path not in main_module.artifact_id:
+ if (
+ path not in excluded_dependencies_list
+ and path not in main_module.artifact_id
+ ):
required_dependencies[path] = module.Module(
group_id=__proto_group_id(group_id),
artifact_id=path,
@@ -451,13 +467,13 @@ def main(versions_file, monorepo):
module
for module in required_dependencies.values()
if module.artifact_id.startswith("proto-")
- and module.artifact_id not in parent_artifact_id
+ and module.artifact_id not in parent_artifact_id
]
grpc_modules = [
module
for module in required_dependencies.values()
- if module.artifact_id.startswith("grpc-") \
- and module.artifact_id not in parent_artifact_id
+ if module.artifact_id.startswith("grpc-")
+ and module.artifact_id not in parent_artifact_id
]
if main_module in grpc_modules or main_module in proto_modules:
modules = grpc_modules + proto_modules
@@ -489,12 +505,11 @@ def main(versions_file, monorepo):
if os.path.isfile(f"{artifact_id}-bom/pom.xml"):
print("updating modules in bom pom.xml")
- if artifact_id+"-bom" not in excluded_poms_list:
+ if artifact_id + "-bom" not in excluded_poms_list:
update_bom_pom(f"{artifact_id}-bom/pom.xml", modules)
- elif artifact_id+"-bom" not in excluded_poms_list:
+ elif artifact_id + "-bom" not in excluded_poms_list:
print("creating missing bom pom.xml")
- monorepo_version = __get_monorepo_version(versions_file) \
- if monorepo else ""
+ monorepo_version = __get_monorepo_version(versions_file) if monorepo else ""
templates.render(
template_name="bom_pom.xml.j2",
output_name=f"{artifact_id}-bom/pom.xml",
@@ -503,7 +518,7 @@ def main(versions_file, monorepo):
modules=modules,
main_module=main_module,
monorepo=monorepo,
- monorepo_version=monorepo_version
+ monorepo_version=monorepo_version,
)
if os.path.isfile("pom.xml"):
@@ -511,8 +526,7 @@ def main(versions_file, monorepo):
update_parent_pom("pom.xml", modules)
else:
print("creating missing parent pom.xml")
- monorepo_version = __get_monorepo_version(versions_file) \
- if monorepo else ""
+ monorepo_version = __get_monorepo_version(versions_file) if monorepo else ""
templates.render(
template_name="parent_pom.xml.j2",
output_name="./pom.xml",
@@ -521,7 +535,7 @@ def main(versions_file, monorepo):
main_module=main_module,
name=name,
monorepo=monorepo,
- monorepo_version=monorepo_version
+ monorepo_version=monorepo_version,
)
print(f"updating modules in {versions_file}")
@@ -537,13 +551,15 @@ def main(versions_file, monorepo):
release_version=main_module.release_version,
)
templates.render(
- template_name="versions.txt.j2", output_name=versions_file, modules=existing_modules.values(),
+ template_name="versions.txt.j2",
+ output_name=versions_file,
+ modules=existing_modules.values(),
)
if __name__ == "__main__":
versions_file = sys.argv[1]
monorepo = sys.argv[2]
- if monorepo == 'true':
+ if monorepo == "true":
monorepo = True
main(versions_file, monorepo)
diff --git a/library_generation/owlbot/src/gen-template.py b/library_generation/owlbot/src/gen-template.py
index fd3015ebf8..30f8c43529 100644
--- a/library_generation/owlbot/src/gen-template.py
+++ b/library_generation/owlbot/src/gen-template.py
@@ -24,7 +24,8 @@
@click.command()
@click.option(
- "--folder", help="Path to folder of templates",
+ "--folder",
+ help="Path to folder of templates",
)
@click.option("--file", help="Path to template file")
@click.option(
@@ -34,7 +35,9 @@
required=True,
)
@click.option(
- "--output", help="Path to output", default=".",
+ "--output",
+ help="Path to output",
+ default=".",
)
def main(folder: str, file: str, data: List[str], output: str):
"""Generate templates"""
diff --git a/library_generation/owlbot/src/poms/module.py b/library_generation/owlbot/src/poms/module.py
index 3beafd22b0..b4274ea969 100644
--- a/library_generation/owlbot/src/poms/module.py
+++ b/library_generation/owlbot/src/poms/module.py
@@ -35,7 +35,11 @@ def read_module(pom: str) -> Module:
if artifact_id.startswith("google-cloud")
else "com.google.api.grpc"
)
- return Module(group_id=group_id, artifact_id=artifact_id, version=version,)
+ return Module(
+ group_id=group_id,
+ artifact_id=artifact_id,
+ version=version,
+ )
def read_modules(service: str) -> List[Module]:
diff --git a/library_generation/owlbot/src/requirements.in b/library_generation/owlbot/src/requirements.in
index 1dbbb3c666..fed3e32d94 100644
--- a/library_generation/owlbot/src/requirements.in
+++ b/library_generation/owlbot/src/requirements.in
@@ -8,4 +8,3 @@ colorlog
protobuf
watchdog
requests
-pyyaml
\ No newline at end of file
diff --git a/library_generation/owlbot/templates/java_library/CODE_OF_CONDUCT.md b/library_generation/owlbot/templates/java_library/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000000..2add2547a8
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/CODE_OF_CONDUCT.md
@@ -0,0 +1,94 @@
+
+# Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of
+experience, education, socio-economic status, nationality, personal appearance,
+race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, or to ban temporarily or permanently any
+contributor for other behaviors that they deem inappropriate, threatening,
+offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+This Code of Conduct also applies outside the project spaces when the Project
+Steward has a reasonable belief that an individual's behavior may have a
+negative impact on the project or its community.
+
+## Conflict Resolution
+
+We do not believe that all conflict is bad; healthy debate and disagreement
+often yield positive results. However, it is never okay to be disrespectful or
+to engage in behavior that violates the project’s code of conduct.
+
+If you see someone violating the code of conduct, you are encouraged to address
+the behavior directly with those involved. Many issues can be resolved quickly
+and easily, and this gives people more control over the outcome of their
+dispute. If you are unable to resolve the matter for any reason, or if the
+behavior is threatening or harassing, report it. We are dedicated to providing
+an environment where participants feel welcome and safe.
+
+Reports should be directed to *googleapis-stewards@google.com*, the
+Project Steward(s) for *Google Cloud Client Libraries*. It is the Project Steward’s duty to
+receive and address reported violations of the code of conduct. They will then
+work with a committee consisting of representatives from the Open Source
+Programs Office and the Google Open Source Strategy team. If for any reason you
+are uncomfortable reaching out to the Project Steward, please email
+opensource@google.com.
+
+We will investigate every complaint, but you may not receive a direct response.
+We will use our discretion in determining when and how to follow up on reported
+incidents, which may range from not taking action to permanent expulsion from
+the project and project-sponsored spaces. We will notify the accused of the
+report and provide them an opportunity to discuss it before any action is taken.
+The identity of the reporter will be omitted from the details of the report
+supplied to the accused. In potentially harmful situations, such as ongoing
+harassment or threats to anyone's safety, we may take action without notice.
+
+## Attribution
+
+This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
+available at
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
\ No newline at end of file
diff --git a/library_generation/owlbot/templates/java_library/CONTRIBUTING.md b/library_generation/owlbot/templates/java_library/CONTRIBUTING.md
new file mode 100644
index 0000000000..b65dd279c9
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/CONTRIBUTING.md
@@ -0,0 +1,92 @@
+# How to Contribute
+
+We'd love to accept your patches and contributions to this project. There are
+just a few small guidelines you need to follow.
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement. You (or your employer) retain the copyright to your contribution;
+this simply gives us permission to use and redistribute your contributions as
+part of the project. Head over to to see
+your current agreements on file or to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code reviews
+
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose. Consult
+[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
+information on using pull requests.
+
+## Community Guidelines
+
+This project follows
+[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
+
+## Building the project
+
+To build, package, and run all unit tests run the command
+
+```
+mvn clean verify
+```
+
+### Running Integration tests
+
+To include integration tests when building the project, you need access to
+a GCP Project with a valid service account.
+
+For instructions on how to generate a service account and corresponding
+credentials JSON see: [Creating a Service Account][1].
+
+Then run the following to build, package, run all unit tests and run all
+integration tests.
+
+```bash
+export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account.json
+mvn -Penable-integration-tests clean verify
+```
+
+## Code Samples
+
+All code samples must be in compliance with the [java sample formatting guide][3].
+Code Samples must be bundled in separate Maven modules.
+
+The samples must be separate from the primary project for a few reasons:
+1. Primary projects have a minimum Java version of Java 8 whereas samples can have
+ Java version of Java 11. Due to this we need the ability to
+ selectively exclude samples from a build run.
+2. Many code samples depend on external GCP services and need
+ credentials to access the service.
+3. Code samples are not released as Maven artifacts and must be excluded from
+ release builds.
+
+### Building
+
+```bash
+mvn clean verify
+```
+
+Some samples require access to GCP services and require a service account:
+
+```bash
+export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account.json
+mvn clean verify
+```
+
+### Code Formatting
+
+Code in this repo is formatted with
+[google-java-format](https://github.com/google/google-java-format).
+To run formatting on your project, you can run:
+```
+mvn com.coveo:fmt-maven-plugin:format
+```
+
+[1]: https://cloud.google.com/docs/authentication/getting-started#creating_a_service_account
+[2]: https://maven.apache.org/settings.html#Active_Profiles
+[3]: https://github.com/GoogleCloudPlatform/java-docs-samples/blob/main/SAMPLE_FORMAT.md
\ No newline at end of file
diff --git a/library_generation/owlbot/templates/java_library/LICENSE b/library_generation/owlbot/templates/java_library/LICENSE
new file mode 100644
index 0000000000..261eeb9e9f
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/library_generation/owlbot/templates/java_library/README.md b/library_generation/owlbot/templates/java_library/README.md
new file mode 100644
index 0000000000..e849a97147
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/README.md
@@ -0,0 +1,288 @@
+{% set group_id = metadata['repo']['distribution_name'].split(':')|first -%}
+{% set artifact_id = metadata['repo']['distribution_name'].split(':')|last -%}
+{% set repo_short = metadata['repo']['repo'].split('/')|last -%}
+
+# Google {{ metadata['repo']['name_pretty'] }} Client for Java
+
+Java idiomatic client for [{{metadata['repo']['name_pretty']}}][product-docs].
+
+[![Maven][maven-version-image]][maven-version-link]
+![Stability][stability-image]
+
+- [Product Documentation][product-docs]
+- [Client Library Documentation][javadocs]
+{% if 'partials' in metadata and metadata['partials']['deprecation_warning'] -%}
+{{ metadata['partials']['deprecation_warning'] }}
+{% elif metadata['repo']['release_level'] in ['preview'] %}
+> Note: This client is a work-in-progress, and may occasionally
+> make backwards-incompatible changes.
+{% endif %}
+{% if migrated_split_repo %}
+:bus: In October 2022, this library has moved to
+[google-cloud-java/{{ metadata['repo']['repo_short'] }}](
+https://github.com/googleapis/google-cloud-java/tree/main/{{ metadata['repo']['repo_short'] }}).
+This repository will be archived in the future.
+Future releases will appear in the new repository (https://github.com/googleapis/google-cloud-java/releases).
+The Maven artifact coordinates (`{{ group_id }}:{{ artifact_id }}`) remain the same.
+{% endif %}
+## Quickstart
+
+{% if 'snippets' in metadata and metadata['snippets'][metadata['repo']['api_shortname'] + '_install_with_bom'] -%}
+If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file:
+
+```xml
+{{ metadata['snippets'][metadata['repo']['api_shortname'] + '_install_with_bom'] }}
+```
+
+If you are using Maven without the BOM, add this to your dependencies:
+{% elif monorepo %}
+If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file:
+
+```xml
+
+
+
+ com.google.cloud
+ libraries-bom
+ {{ metadata['latest_bom_version'] }}
+ pom
+ import
+
+
+
+
+
+
+ {{ group_id }}
+ {{ artifact_id }}
+
+```
+
+If you are using Maven without the BOM, add this to your dependencies:
+{% else %}
+If you are using Maven, add this to your pom.xml file:
+{% endif %}
+
+
+```xml
+{% if 'snippets' in metadata and metadata['snippets'][metadata['repo']['api_shortname'] + '_install_without_bom'] -%}
+{{ metadata['snippets'][metadata['repo']['api_shortname'] + '_install_without_bom'] }}
+{% else -%}
+
+ {{ group_id }}
+ {{ artifact_id }}
+ {{ metadata['latest_version'] }}
+
+{% endif -%}
+```
+
+{% if 'snippets' in metadata and metadata['snippets'][metadata['repo']['api_shortname'] + '_install_with_bom'] -%}
+If you are using Gradle 5.x or later, add this to your dependencies:
+
+```Groovy
+implementation platform('com.google.cloud:libraries-bom:{{metadata['latest_bom_version']}}')
+
+implementation '{{ group_id }}:{{ artifact_id }}'
+```
+{% endif -%}
+
+If you are using Gradle without BOM, add this to your dependencies:
+
+```Groovy
+implementation '{{ group_id }}:{{ artifact_id }}:{{ metadata['latest_version'] }}'
+```
+
+If you are using SBT, add this to your dependencies:
+
+```Scala
+libraryDependencies += "{{ group_id }}" % "{{ artifact_id }}" % "{{ metadata['latest_version'] }}"
+```
+
+
+## Authentication
+
+See the [Authentication][authentication] section in the base directory's README.
+
+## Authorization
+
+The client application making API calls must be granted [authorization scopes][auth-scopes] required for the desired {{metadata['repo']['name_pretty']}} APIs, and the authenticated principal must have the [IAM role(s)][predefined-iam-roles] required to access GCP resources using the {{metadata['repo']['name_pretty']}} API calls.
+
+## Getting Started
+
+### Prerequisites
+
+You will need a [Google Cloud Platform Console][developer-console] project with the {{metadata['repo']['name_pretty']}} [API enabled][enable-api].
+{% if metadata['repo']['requires_billing'] %}You will need to [enable billing][enable-billing] to use Google {{metadata['repo']['name_pretty']}}.{% endif %}
+[Follow these instructions][create-project] to get your project set up. You will also need to set up the local development environment by
+[installing the Google Cloud Command Line Interface][cloud-cli] and running the following commands in command line:
+`gcloud auth login` and `gcloud config set project [YOUR PROJECT ID]`.
+
+### Installation and setup
+
+You'll need to obtain the `{{ artifact_id }}` library. See the [Quickstart](#quickstart) section
+to add `{{ artifact_id }}` as a dependency in your code.
+
+## About {{metadata['repo']['name_pretty']}}
+
+{% if 'partials' in metadata and metadata['partials']['about'] -%}
+{{ metadata['partials']['about'] }}
+{% else %}
+[{{ metadata['repo']['name_pretty'] }}][product-docs] {{ metadata['repo']['api_description'] }}
+
+See the [{{metadata['repo']['name_pretty']}} client library docs][javadocs] to learn how to
+use this {{metadata['repo']['name_pretty']}} Client Library.
+{% endif %}
+
+{% if 'partials' in metadata and metadata['partials']['custom_content'] -%}
+{{ metadata['partials']['custom_content'] }}
+{% endif %}
+
+{% if metadata['samples']|length %}
+## Samples
+
+Samples are in the [`samples/`](https://github.com/{{ metadata['repo']['repo'] }}/tree/main/samples) directory.
+
+| Sample | Source Code | Try it |
+| --------------------------- | --------------------------------- | ------ |
+{% for sample in metadata['samples'] %}| {{ sample.title }} | [source code](https://github.com/{{ metadata['repo']['repo'] }}/blob/main/{{ sample.file }}) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/{{ metadata['repo']['repo'] }}&page=editor&open_in_editor={{ sample.file }}) |
+{% endfor %}
+{% endif %}
+
+## Troubleshooting
+
+To get help, follow the instructions in the [shared Troubleshooting document][troubleshooting].
+
+{% if metadata['repo']['transport'] -%}
+## Transport
+
+{% if metadata['repo']['transport'] == 'grpc' -%}
+{{metadata['repo']['name_pretty']}} uses gRPC for the transport layer.
+{% elif metadata['repo']['transport'] == 'http' -%}
+{{metadata['repo']['name_pretty']}} uses HTTP/JSON for the transport layer.
+{% elif metadata['repo']['transport'] == 'both' -%}
+{{metadata['repo']['name_pretty']}} uses both gRPC and HTTP/JSON for the transport layer.
+{% endif %}
+{% endif -%}
+
+## Supported Java Versions
+
+Java {{ metadata['min_java_version'] }} or above is required for using this client.
+
+Google's Java client libraries,
+[Google Cloud Client Libraries][cloudlibs]
+and
+[Google Cloud API Libraries][apilibs],
+follow the
+[Oracle Java SE support roadmap][oracle]
+(see the Oracle Java SE Product Releases section).
+
+### For new development
+
+In general, new feature development occurs with support for the lowest Java
+LTS version covered by Oracle's Premier Support (which typically lasts 5 years
+from initial General Availability). If the minimum required JVM for a given
+library is changed, it is accompanied by a [semver][semver] major release.
+
+Java 11 and (in September 2021) Java 17 are the best choices for new
+development.
+
+### Keeping production systems current
+
+Google tests its client libraries with all current LTS versions covered by
+Oracle's Extended Support (which typically lasts 8 years from initial
+General Availability).
+
+#### Legacy support
+
+Google's client libraries support legacy versions of Java runtimes with long
+term stable libraries that don't receive feature updates on a best efforts basis
+as it may not be possible to backport all patches.
+
+Google provides updates on a best efforts basis to apps that continue to use
+Java 7, though apps might need to upgrade to current versions of the library
+that supports their JVM.
+
+#### Where to find specific information
+
+The latest versions and the supported Java versions are identified on
+the individual GitHub repository `github.com/GoogleAPIs/java-SERVICENAME`
+and on [google-cloud-java][g-c-j].
+
+## Versioning
+
+{% if 'partials' in metadata and metadata['partials']['versioning'] -%}
+{{ metadata['partials']['versioning'] }}
+{% else %}
+This library follows [Semantic Versioning](http://semver.org/).
+
+{% if metadata['repo']['release_level'] in ['preview'] %}
+It is currently in major version zero (``0.y.z``), which means that anything may change at any time
+and the public API should not be considered stable.
+{% endif %}{% endif %}
+
+## Contributing
+
+{% if 'partials' in metadata and metadata['partials']['contributing'] -%}
+{{ metadata['partials']['contributing'] }}
+{% else %}
+Contributions to this library are always welcome and highly encouraged.
+
+See [CONTRIBUTING][contributing] for more information how to get started.
+
+Please note that this project is released with a Contributor Code of Conduct. By participating in
+this project you agree to abide by its terms. See [Code of Conduct][code-of-conduct] for more
+information.
+{% endif %}
+
+## License
+
+Apache 2.0 - See [LICENSE][license] for more information.
+
+## CI Status
+
+Java Version | Status
+------------ | ------{% if metadata['min_java_version'] <= 7 %}
+Java 7 | [![Kokoro CI][kokoro-badge-image-1]][kokoro-badge-link-1]{% endif %}
+Java 8 | [![Kokoro CI][kokoro-badge-image-2]][kokoro-badge-link-2]
+Java 8 OSX | [![Kokoro CI][kokoro-badge-image-3]][kokoro-badge-link-3]
+Java 8 Windows | [![Kokoro CI][kokoro-badge-image-4]][kokoro-badge-link-4]
+Java 11 | [![Kokoro CI][kokoro-badge-image-5]][kokoro-badge-link-5]
+
+Java is a registered trademark of Oracle and/or its affiliates.
+
+[product-docs]: {{metadata['repo']['product_documentation']}}
+[javadocs]: {{metadata['repo']['client_documentation']}}
+[kokoro-badge-image-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/{{ repo_short }}/java7.svg
+[kokoro-badge-link-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/{{ repo_short }}/java7.html
+[kokoro-badge-image-2]: http://storage.googleapis.com/cloud-devrel-public/java/badges/{{ repo_short }}/java8.svg
+[kokoro-badge-link-2]: http://storage.googleapis.com/cloud-devrel-public/java/badges/{{ repo_short }}/java8.html
+[kokoro-badge-image-3]: http://storage.googleapis.com/cloud-devrel-public/java/badges/{{ repo_short }}/java8-osx.svg
+[kokoro-badge-link-3]: http://storage.googleapis.com/cloud-devrel-public/java/badges/{{ repo_short }}/java8-osx.html
+[kokoro-badge-image-4]: http://storage.googleapis.com/cloud-devrel-public/java/badges/{{ repo_short }}/java8-win.svg
+[kokoro-badge-link-4]: http://storage.googleapis.com/cloud-devrel-public/java/badges/{{ repo_short }}/java8-win.html
+[kokoro-badge-image-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/{{ repo_short }}/java11.svg
+[kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/{{ repo_short }}/java11.html
+[stability-image]: https://img.shields.io/badge/stability-{% if metadata['repo']['release_level'] == 'stable' %}stable-green{% elif metadata['repo']['release_level'] == 'preview' %}preview-yellow{% else %}unknown-red{% endif %}
+[maven-version-image]: https://img.shields.io/maven-central/v/{{ group_id }}/{{ artifact_id }}.svg
+[maven-version-link]: https://central.sonatype.com/artifact/{{ group_id }}/{{ artifact_id }}/{{ metadata['latest_version'] }}
+[authentication]: https://github.com/googleapis/google-cloud-java#authentication
+[auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes
+[predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles
+[iam-policy]: https://cloud.google.com/iam/docs/overview#cloud-iam-policy
+[developer-console]: https://console.developers.google.com/
+[create-project]: https://cloud.google.com/resource-manager/docs/creating-managing-projects
+[cloud-cli]: https://cloud.google.com/cli
+[troubleshooting]: https://github.com/googleapis/google-cloud-java/blob/main/TROUBLESHOOTING.md
+[contributing]: https://github.com/{{metadata['repo']['repo']}}/blob/main/CONTRIBUTING.md
+[code-of-conduct]: https://github.com/{{metadata['repo']['repo']}}/blob/main/CODE_OF_CONDUCT.md#contributor-code-of-conduct
+[license]: https://github.com/{{metadata['repo']['repo']}}/blob/main/LICENSE
+{% if metadata['repo']['requires_billing'] %}[enable-billing]: https://cloud.google.com/apis/docs/getting-started#enabling_billing{% endif %}
+{% if metadata['repo']['api_id'] %}[enable-api]: https://console.cloud.google.com/flows/enableapi?apiid={{ metadata['repo']['api_id'] }}{% endif %}
+[libraries-bom]: https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/The-Google-Cloud-Platform-Libraries-BOM
+[shell_img]: https://gstatic.com/cloudssh/images/open-btn.png
+
+[semver]: https://semver.org/
+[cloudlibs]: https://cloud.google.com/apis/docs/client-libraries-explained
+[apilibs]: https://cloud.google.com/apis/docs/client-libraries-explained#google_api_client_libraries
+[oracle]: https://www.oracle.com/java/technologies/java-se-support-roadmap.html
+[g-c-j]: http://github.com/googleapis/google-cloud-java
diff --git a/library_generation/owlbot/templates/java_library/SECURITY.md b/library_generation/owlbot/templates/java_library/SECURITY.md
new file mode 100644
index 0000000000..8b58ae9c01
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/SECURITY.md
@@ -0,0 +1,7 @@
+# Security Policy
+
+To report a security issue, please use [g.co/vulnz](https://g.co/vulnz).
+
+The Google Security Team will respond within 5 working days of your report on g.co/vulnz.
+
+We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue.
diff --git a/library_generation/owlbot/templates/java_library/java.header b/library_generation/owlbot/templates/java_library/java.header
new file mode 100644
index 0000000000..d0970ba7d3
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/java.header
@@ -0,0 +1,15 @@
+^/\*$
+^ \* Copyright \d\d\d\d,? Google (Inc\.|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\.$
+^ \*/$
diff --git a/library_generation/owlbot/templates/java_library/license-checks.xml b/library_generation/owlbot/templates/java_library/license-checks.xml
new file mode 100644
index 0000000000..6597fced80
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/license-checks.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/library_generation/owlbot/templates/java_library/renovate.json b/library_generation/owlbot/templates/java_library/renovate.json
new file mode 100644
index 0000000000..16c68a2387
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/renovate.json
@@ -0,0 +1,80 @@
+{% if migrated_split_repo %}{
+ "enabled": false,
+{% else %}{
+{% endif %} "extends": [
+ ":separateMajorReleases",
+ ":combinePatchMinorReleases",
+ ":ignoreUnstable",
+ ":prImmediately",
+ ":updateNotScheduled",
+ ":automergeDisabled",
+ ":ignoreModulesAndTests",
+ ":maintainLockFilesDisabled",
+ ":autodetectPinVersions"
+ ],
+ "ignorePaths": [
+ ".kokoro/requirements.txt",
+ ".github/workflows/**"
+ ],
+ "packageRules": [
+ {
+ "packagePatterns": [
+ "^com.google.guava:"
+ ],
+ "versionScheme": "docker"
+ },
+ {
+ "packagePatterns": [
+ "*"
+ ],
+ "semanticCommitType": "deps",
+ "semanticCommitScope": null
+ },
+ {
+ "packagePatterns": [
+ "^org.apache.maven",
+ "^org.jacoco:",
+ "^org.codehaus.mojo:",
+ "^org.sonatype.plugins:",
+ "^com.coveo:",
+ "^com.google.cloud:google-cloud-shared-config"
+ ],
+ "semanticCommitType": "build",
+ "semanticCommitScope": "deps"
+ },
+ {
+ "packagePatterns": [
+ "^{{metadata['repo']['distribution_name']}}",
+ "^com.google.cloud:libraries-bom",
+ "^com.google.cloud.samples:shared-configuration"
+ ],
+ "semanticCommitType": "chore",
+ "semanticCommitScope": "deps"
+ },
+ {
+ "packagePatterns": [
+ "^junit:junit",
+ "^com.google.truth:truth",
+ "^org.mockito:mockito-core",
+ "^org.objenesis:objenesis",
+ "^com.google.cloud:google-cloud-conformance-tests"
+ ],
+ "semanticCommitType": "test",
+ "semanticCommitScope": "deps"
+ },
+ {
+ "packagePatterns": [
+ "^com.google.cloud:google-cloud-"
+ ],
+ "ignoreUnstable": false
+ },
+ {
+ "packagePatterns": [
+ "^com.fasterxml.jackson.core"
+ ],
+ "groupName": "jackson dependencies"
+ }
+ ],
+ "semanticCommits": true,
+ "dependencyDashboard": true
+}
diff --git a/library_generation/owlbot/templates/java_library/samples/install-without-bom/pom.xml b/library_generation/owlbot/templates/java_library/samples/install-without-bom/pom.xml
new file mode 100644
index 0000000000..110250d003
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/samples/install-without-bom/pom.xml
@@ -0,0 +1,86 @@
+{% set group_id = metadata['repo']['distribution_name'].split(':')|first -%}
+{% set artifact_id = metadata['repo']['distribution_name'].split(':')|last -%}
+
+
+ 4.0.0
+ com.google.cloud
+ {{metadata['repo']['name']}}-install-without-bom
+ jar
+ Google {{metadata['repo']['name_pretty']}} Install Without Bom
+ https://github.com/{{metadata['repo']['repo']}}
+
+
+
+ com.google.cloud.samples
+ shared-configuration
+ 1.2.0
+
+
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+
+
+
+ {{ group_id }}
+ {{ artifact_id }}
+ {{ metadata['latest_version'] }}
+
+
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+ com.google.truth
+ truth
+ 1.1.3
+ test
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.3.0
+
+
+ add-snippets-source
+
+ add-source
+
+
+
+
+
+
+
+
+ add-snippets-tests
+
+ add-test-source
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library_generation/owlbot/templates/java_library/samples/pom.xml b/library_generation/owlbot/templates/java_library/samples/pom.xml
new file mode 100644
index 0000000000..0f11429996
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/samples/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+ com.google.cloud
+ google-cloud-{{metadata['repo']['name']}}-samples
+ 0.0.1-SNAPSHOT
+ pom
+ Google {{metadata['repo']['name_pretty']}} Samples Parent
+ https://github.com/{{metadata['repo']['repo']}}
+
+ Java idiomatic client for Google Cloud Platform services.
+
+
+
+
+ com.google.cloud.samples
+ shared-configuration
+ 1.2.0
+
+
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+ install-without-bom
+ snapshot
+ snippets
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ 2.8.2
+
+ true
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.13
+
+ true
+
+
+
+
+
diff --git a/library_generation/owlbot/templates/java_library/samples/snapshot/pom.xml b/library_generation/owlbot/templates/java_library/samples/snapshot/pom.xml
new file mode 100644
index 0000000000..62a83b440e
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/samples/snapshot/pom.xml
@@ -0,0 +1,85 @@
+{% set group_id = metadata['repo']['distribution_name'].split(':')|first -%}
+{% set artifact_id = metadata['repo']['distribution_name'].split(':')|last -%}
+
+
+ 4.0.0
+ com.google.cloud
+ {{metadata['repo']['name']}}-snapshot
+ jar
+ Google {{metadata['repo']['name_pretty']}} Snapshot Samples
+ https://github.com/{{metadata['repo']['repo']}}
+
+
+
+ com.google.cloud.samples
+ shared-configuration
+ 1.2.0
+
+
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+
+
+ {{ group_id }}
+ {{ artifact_id }}
+ {{ metadata['latest_version'] }}
+
+
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+ com.google.truth
+ truth
+ 1.1.3
+ test
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.3.0
+
+
+ add-snippets-source
+
+ add-source
+
+
+
+
+
+
+
+
+ add-snippets-tests
+
+ add-test-source
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library_generation/owlbot/templates/java_library/samples/snippets/pom.xml b/library_generation/owlbot/templates/java_library/samples/snippets/pom.xml
new file mode 100644
index 0000000000..c6b9981507
--- /dev/null
+++ b/library_generation/owlbot/templates/java_library/samples/snippets/pom.xml
@@ -0,0 +1,49 @@
+{% set group_id = metadata['repo']['distribution_name'].split(':')|first -%}
+{% set artifact_id = metadata['repo']['distribution_name'].split(':')|last -%}
+
+
+ 4.0.0
+ com.google.cloud
+ {{metadata['repo']['name']}}-snippets
+ jar
+ Google {{metadata['repo']['name_pretty']}} Snippets
+ https://github.com/{{metadata['repo']['repo']}}
+
+
+
+ com.google.cloud.samples
+ shared-configuration
+ 1.2.0
+
+
+
+ 1.8
+ 1.8
+ UTF-8
+
+
+
+
+
+ {{ group_id }}
+ {{ artifact_id }}
+ {{ metadata['latest_version'] }}
+
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+ com.google.truth
+ truth
+ 1.1.3
+ test
+
+
+
diff --git a/library_generation/postprocess_library.sh b/library_generation/postprocess_library.sh
index d46a9c890c..8ab7f1527a 100755
--- a/library_generation/postprocess_library.sh
+++ b/library_generation/postprocess_library.sh
@@ -20,6 +20,8 @@
# provided
# 7 - is_monorepo: whether this library is a monorepo, which implies slightly
# different logic
+# 8 - configuration_yaml_path: path to the configuration yaml containing library
+# generation information for this library
set -eo pipefail
scripts_root=$(dirname "$(readlink -f "$0")")
@@ -30,6 +32,7 @@ owlbot_cli_source_folder=$4
owlbot_cli_image_sha=$5
synthtool_commitish=$6
is_monorepo=$7
+configuration_yaml_path=$8
source "${scripts_root}"/utilities.sh
@@ -79,11 +82,14 @@ docker run --rm \
# we clone the synthtool library and manually build it
mkdir -p /tmp/synthtool
pushd /tmp/synthtool
+
if [ ! -d "synthtool" ]; then
git clone https://github.com/googleapis/synthtool.git
fi
pushd "synthtool"
+
git reset --hard "${synthtool_commitish}"
+
python3 -m pip install -e .
python3 -m pip install -r requirements.in
popd # synthtool
@@ -97,5 +103,5 @@ popd # owlbot/src
# run the postprocessor
echo 'running owl-bot post-processor'
pushd "${postprocessing_target}"
-bash "${scripts_root}/owlbot/bin/entrypoint.sh" "${scripts_root}" "${versions_file}"
+bash "${scripts_root}/owlbot/bin/entrypoint.sh" "${scripts_root}" "${versions_file}" "${configuration_yaml_path}"
popd # postprocessing_target
diff --git a/library_generation/setup.py b/library_generation/setup.py
index 132cee48f0..c8b3418cf4 100644
--- a/library_generation/setup.py
+++ b/library_generation/setup.py
@@ -4,20 +4,21 @@
from setuptools import setup
-setup(name='library_generation',
- version='0.1',
- package_dir={
- 'library_generation': '.',
- },
- package_data={
- 'library_generation': [
- '*.sh',
- 'templates/*.j2',
- 'gapic-generator-java-wrapper',
- 'requirements.*',
- 'owlbot/src/requirements.*',
- 'owlbot/bin/*.sh',
- 'owlbot/templates/**/*.j2',
- ],
- }
+setup(
+ name="library_generation",
+ version="0.1",
+ package_dir={
+ "library_generation": ".",
+ },
+ package_data={
+ "library_generation": [
+ "*.sh",
+ "templates/*.j2",
+ "gapic-generator-java-wrapper",
+ "requirements.*",
+ "owlbot/src/requirements.*",
+ "owlbot/bin/*.sh",
+ "owlbot/templates/**/*.j2",
+ ],
+ },
)
diff --git a/library_generation/test/integration_tests.py b/library_generation/test/integration_tests.py
index 55f9b88658..2380e15452 100644
--- a/library_generation/test/integration_tests.py
+++ b/library_generation/test/integration_tests.py
@@ -108,7 +108,7 @@ def test_generate_repo(self):
@classmethod
def __pull_repo_to(cls, dest: Path, repo: str, committish: str):
repo_url = f"{repo_prefix}/{repo}"
- print(f'Cloning repository {repo_url}')
+ print(f"Cloning repository {repo_url}")
repo = Repo.clone_from(repo_url, dest)
repo.git.checkout(committish)
diff --git a/library_generation/test/resources/integration/google-cloud-java/generation_config.yaml b/library_generation/test/resources/integration/google-cloud-java/generation_config.yaml
index 67164271fb..a7ca6bec7b 100644
--- a/library_generation/test/resources/integration/google-cloud-java/generation_config.yaml
+++ b/library_generation/test/resources/integration/google-cloud-java/generation_config.yaml
@@ -4,6 +4,18 @@ googleapis_commitish: 1a45bf7393b52407188c82e63101db7dc9c72026
owlbot_cli_image: sha256:623647ee79ac605858d09e60c1382a716c125fb776f69301b72de1cd35d49409
synthtool_commitish: 6612ab8f3afcd5e292aecd647f0fa68812c9f5b5
destination_path: google-cloud-java
+template_excludes:
+ - ".github/*"
+ - ".kokoro/*"
+ - "samples/*"
+ - "CODE_OF_CONDUCT.md"
+ - "CONTRIBUTING.md"
+ - "LICENSE"
+ - "SECURITY.md"
+ - "java.header"
+ - "license-checks.xml"
+ - "renovate.json"
+ - ".gitignore"
libraries:
- api_shortname: apigeeconnect
name_pretty: Apigee Connect
diff --git a/library_generation/test/resources/integration/java-bigtable/generation_config.yaml b/library_generation/test/resources/integration/java-bigtable/generation_config.yaml
index fcad57c819..7e62bea404 100644
--- a/library_generation/test/resources/integration/java-bigtable/generation_config.yaml
+++ b/library_generation/test/resources/integration/java-bigtable/generation_config.yaml
@@ -1,10 +1,26 @@
gapic_generator_version: 2.32.0
grpc_version: 1.61.0
-protobuf_version: 23.2
-googleapis_commitish: 4512234113a18c1fda1fb0d0ceac8f4b4efe9801
+protobuf_version: 25.2
+googleapis_commitish: 40203ca1880849480bbff7b8715491060bbccdf1
owlbot_cli_image: sha256:623647ee79ac605858d09e60c1382a716c125fb776f69301b72de1cd35d49409
synthtool_commitish: 6612ab8f3afcd5e292aecd647f0fa68812c9f5b5
destination_path: java-bigtable
+template_excludes:
+ - ".gitignore"
+ - ".kokoro/presubmit/integration.cfg"
+ - ".kokoro/presubmit/graalvm-native.cfg"
+ - ".kokoro/presubmit/graalvm-native-17.cfg"
+ - ".kokoro/nightly/integration.cfg"
+ - ".kokoro/presubmit/samples.cfg"
+ - ".kokoro/nightly/samples.cfg"
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
+ - ".github/PULL_REQUEST_TEMPLATE.md"
+ - "CONTRIBUTING.md"
+ - "codecov.yaml"
+ - ".github/release-please.yml"
+ - "renovate.json"
+ - ".kokoro/requirements.in"
+ - ".kokoro/requirements.txt"
libraries:
- api_shortname: bigtable
name_pretty: Cloud Bigtable
diff --git a/library_generation/test/unit_tests.py b/library_generation/test/unit_tests.py
index f819bae3e7..268b3ff0c8 100644
--- a/library_generation/test/unit_tests.py
+++ b/library_generation/test/unit_tests.py
@@ -12,6 +12,9 @@
# 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.
+"""
+Unit tests for python scripts
+"""
import unittest
import os
@@ -354,6 +357,8 @@ def __get_a_gen_config(num: int):
googleapis_commitish="",
owlbot_cli_image="",
synthtool_commitish="",
+ template_excludes=[],
+ path_to_yaml=".",
libraries=libraries,
)