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

docs: modify hermetic build docs #3331

Merged
merged 17 commits into from
Nov 5, 2024
Merged
194 changes: 142 additions & 52 deletions hermetic_build/library_generation/README.md → hermetic_build/README.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,43 @@
> [!IMPORTANT]
> All scripts/examples assume you are inside the repository root folder.

# Generate a repository containing GAPIC Client Libraries

The script, `entry_point.py`, allows you to generate a repository containing
GAPIC client libraries (a monorepo, for example, google-cloud-java) from a
configuration file.
Running the docker image built from `hermetic_build/library_generation`
directory, you can generate a repository containing GAPIC client libraries (a
monorepo, for example, google-cloud-java) from a configuration file.

Instead of running docker image, if you prefer running the underlying python
script directly, please refer to [development guide](DEVELOPMENT.md) for
additional instructions.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think the purpose of README is to instruct users how to do things in the most convenient way, thus I moved the part of running the script directly to development guide as it requires additional setups that users typically don't bother to do.

Instead, I moved the image building part here because it's the most straightforward way (i.e., no need to install dependencies) of generating a repository.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the differences between README and DEVELOPMENT is that, README is for external users that just want to run our hermetic image as a product, while DEVELOPMENT is for internal developers that try to maintain the scripts and images.
Hence for README users, they can think hermetic code generation as a blackbox, all they need to know is the input and output. For DEVELOPMENT users, they need to understand how the process uses Python/Shell/Docker etc, so build image locally is better suited for DEVELOPMENT.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

SG, I moved the instructions on building image from source to development guide.


## Environment

- OS: Linux
- Java runtime environment (8 or above)
- Python (3.12 or above)
- Docker
- Git
- Docker

## Prerequisite
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved

In order to generate a version for each library, a versions.txt has to exist
in `repository_path`.
Please refer to [Repository path](#repository-path--repositorypath---optional) for more information.

## Parameters to generate a repository using `entry_point.py`

### Baseline generation configuration yaml (`baseline_generation_config`)
in `repository-path`.
Please refer to [Repository path](#repository-path--repositorypath---optional)
for more information.

An absolute or relative path to a generation_config.yaml.
This config file is used for computing changed libraries, not library
generation.
## Parameters to generate a repository using the docker image

### Current generation configuration yaml (`current_generation_config`)
### Generation configuration yaml (`generation-config-path`)

An absolute or relative path to a configuration file containing parameters to
generate the repository.
Please refer [Configuration to generate a repository](#configuration-to-generate-a-repository)
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved
for more information.

### Repository path (`repository_path`), optional
### Repository path (`repository-path`), optional

The path to where the generated repository goes.

The default value is the current working directory when running the script.
For example, `cd google-cloud-java && python entry_point.py ...` without
For example, `cd google-cloud-java && python /path/to/entry_point.py ...` without
specifying the `--repository_path` option will modify the `google-cloud-java`
repository the user `cd`'d into.

Expand All @@ -47,28 +46,37 @@ right version for each library.
Please refer [here](go/java-client-releasing#versionstxt-manifest) for more info
of versions.txt.

### Api definitions path (`api_definitions_path`), optional
### A list of library names (`library-names`), optional

A list of library names that will be generated, separated by comma.
diegomarquezp marked this conversation as resolved.
Show resolved Hide resolved
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.

If `library_names` is not specified, all libraries in the generation
configuration will be generated.

### Api definitions path (`api-definitions-path`), optional

The path to where the api definition (proto, service yaml) resides.

The default value is the current working directory when running the script.

Note that you need not only the protos defined the service, but also the transitive
dependencies of those protos.
Note that you need not only the protos defined the service, but also the
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved
transitive dependencies of those protos.
Any missing dependencies will cause `File not found` error.

For example, if your service is defined in `example_service.proto` and it imports
`google/api/annotations.proto`, you need the `annotations.proto` resides in a
folder that has the exact structure of the import statement (`google/api` in this
case), and set `api_definitions_path` to the path contains the root folder (`google`
in this case).
For example, if your service is defined in `example_service.proto` and it
imports `google/api/annotations.proto`, you need the `annotations.proto` resides
in a folder that has the exact structure of the import statement (`google/api`
in this case), and set `api_definitions_path` to the path contains the root
folder (`google` in this case).

## Output of `entry_point.py`
## Output

### GAPIC libraries

For each module (e.g. `google-cloud-java/java-asset`), the following files/folders
will be created/modified:
For each module (e.g. `google-cloud-java/java-asset`), the following
files/folders will be created/modified:

| Name | Notes |
|:------------------------------------|:-------------------------------------------------------------------------|
Expand Down Expand Up @@ -129,7 +137,7 @@ They are shared by all GAPICs of a library.
| distribution_name | No | `{group_id}:google-{cloud_prefix}{library_name}` if not specified |
| excluded_poms | No | |
| excluded_dependencies | No | |
| googleapis_commitish | No | use repository level `googleapis_commitish` if not specified. |
| googleapis_commitish | No | use repository level `googleapis_committish` if not specified. |
Copy link
Contributor

@diegomarquezp diegomarquezp Nov 4, 2024

Choose a reason for hiding this comment

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

Suggested change
| googleapis_commitish | No | use repository level `googleapis_committish` if not specified. |
| googleapis_commitish | No | use repository level `googleapis_commitish` if not specified. |

Not the right spelling but it's what's defined in the repo-level section.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, it should be googleapis_committish according to #3208 (comment).

However, I think the refactor should be in its own PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry I misspelled the suggestion string. I was trying to point out that we should stick to googleapis_commitish (one t) since we haven't done such refactor.

| group_id | No | `com.google.cloud` if not specified |
| issue_tracker | No | |
| library_name | No | `api_shortname` is not specified. This value should be unique among all libraries. |
Expand Down Expand Up @@ -185,32 +193,53 @@ libraries:
- proto_path: google/cloud/asset/v1p7beta1
```

# Local Environment Setup before running `entry_point.py`
# Build the image from source

1. Assuming Python 3 is installed, follow official guide from [Python.org](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#create-and-use-virtual-environments) to create a virtual environment.
The virtual environment can be installed to any folder, usually it is recommended to be installed under the root folder of the project(`sdk-platform-java` in this case).
2. Assuming the virtual environment is installed under `sdk-platform-java`.
Run the following command under the root folder of `sdk-platform-java` to install `library_generation` and its dependencies.
1. Run the following command to build the image from source

```bash
python -m pip install --require-hashes -r hermetic_build/common/requirements.txt
python -m pip install hermetic_build/common
python -m pip install --require-hashes -r hermetic_build/library_generation/requirements.txt
python -m pip install hermetic_build/library_generation
```shell
docker build \
-f .cloudbuild/library_generation/library_generation.Dockerfile \
-t local:image-tag \
.
```

3. Download api definition to a local directory
2. Download api definition to a local directory
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved
```shell
api_def_dir=/path/to/api_definition
```

## An example to generate a repository using `entry_point.py`
3. Set the version of gapic-generator-java
```shell
LOCAL_GENERATOR_VERSION=$(mvn \
org.apache.maven.plugins:maven-help-plugin:evaluate \
-Dexpression=project.version \
-pl gapic-generator-java \
-DforceStdout \
-q)
```

```bash
python hermetic_build/library_generation/cli/entry_point.py generate \
--baseline-generation-config-path=/path/to/baseline_config_file \
--current-generation-config-path=/path/to/current_config_file \
--repository-path=path/to/repository \
--api-definitions-path=path/to/api_definition
```
If you run `entry_point.py` with the example [configuration](#an-example-of-generation-configuration)
4. Run the docker image
```shell
# Assume you want to generate the library in the current working directory
# and the generation configuration is in the same directory.
docker run \
Copy link
Collaborator

Choose a reason for hiding this comment

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

This command includes all the possible parameters, can we provide an example with minimum parameters?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Your original example still makes sense for more advanced use cases, I didn't mean to ask you to delete it, we can still have another example with all the parameters. On the other hand, maybe we don't have to provide a more complex example as it could confuse other users. So either way works for me, feel free to decide as you see fit.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I added back the advance example with explanations.

--rm \
--quiet \
-u "$(id -u):$(id -g)" \
-v "$(pwd):/workspace" \
-v "${api_def_dir}:/workspace/googleapis" \
-e GENERATOR_VERSION="${LOCAL_GENERATOR_VERSION}" \
local:image-tag \
--generation-config-path=/workspace/generation_config_file \
--library-names=apigee-connect,asset \
--repository-path=/workspace \
--api-definitions-path=/workspace/googleapis
```

## An example to generate a repository using the docker image

If you run the docker image with the example [configuration](#an-example-of-generation-configuration)
shown above, the repository structure is:
```
$repository_path
Expand Down Expand Up @@ -284,7 +313,68 @@ $repository_path
|_versions.txt
```

# Owlbot Java Postprocessor
# Generate release note from api definition changes

The script, `hermetic_build/release_note_generation/cli/generate_release_note.py`
allows you to generate release note from api definition changes in
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved
[googleapis](https://github.com/googleapis/googleapis) GitHub repository.

## Environment

- OS: Linux
- Python (3.12.0 or above)

## Parameters to generate a release note

### Baseline generation configuration path (`baseline-generation-config-path`)

Absolute or relative path to a generation configuration.
Please refer [Configuration to generate a repository](#configuration-to-generate-a-repository)
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved
for more information.

Note that the `googleapis_commitish` in this configuration is used to retrieve
the first commit, exclusively, to generate the release note.
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved

### Current generation configuration path (`current-generation-config-path`)

Absolute or relative path to a generation configuration.
The release note will be generated from commits that related to the libraries
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved
specified in this configuration.
Please refer [Configuration to generate a repository](#configuration-to-generate-a-repository)
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved
for more information.

Note that the `googleapis_commitish` in this configuration is used to retrieve
the last commit, inclusively, to generate the release note.
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved

### Repository path (`repository-path`), optional

The path to which the file, `pr_description.txt` containing the release note
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved
will be sent.
If not specified, the file will be generated to the current working directory.

## Generate a release note in local environment
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved

1. Install python (>= 3.12.0), it is recommended to create a python virtual
environment through [official guide](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#create-and-use-virtual-environments).
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved

2. Running the following commands to install python packages
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved
```shell
cd /path/to/sdk-platform-java
pip install --require-hashes -r hermetic_build/common/requirements.txt
pip install hermetic_build/common
pip install --require-hashes -r hermetic_build/release_note_generation/requirements.txt
pip install hermetic_build/release_note_generation
```
3. Running the following commands to generate a release note
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved
```shell
cd /path/to/sdk-platform-java
python hermetic_build/release_note_generation/cli/generate_release_note.py generate \
--baseline-generation-config-path=/path/to/baseline_generation_config \
--current-generation-config-path=/path/to/current_generation_config \
--repository-path=/path/to/send/release_note
```

# OwlBot Java Postprocessor

We have transferred the
[implementation](https://github.com/googleapis/synthtool/tree/59fe44fde9866a26e7ee4e4450fd79f67f8cf599/docker/owlbot/java)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ def main(ctx):
default=".",
show_default=True,
help="""
The repository path to which the generated files will be sent.
If not specified, the repository will be generated to the current working
The path to which the file, `pr_description.txt` containing the release note
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved
will be sent.
If not specified, the file will be generated to the current working
directory.
""",
)
Expand Down
Loading