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

feat: move Java Owlbot into this repository for postprocessing #2282

Merged
merged 74 commits into from Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from 72 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
1394f1c
use local synthtool and owlbot
diegomarquezp Nov 9, 2023
bf80792
remove unused files
diegomarquezp Nov 9, 2023
ce3e9a2
remove more unused files
diegomarquezp Nov 9, 2023
76d4892
remove cache files in owlbot
diegomarquezp Nov 9, 2023
bd00a72
use java 11 for it
diegomarquezp Nov 9, 2023
988132e
remove kokoro files
diegomarquezp Nov 9, 2023
5b1b70e
use glob in owlbot entrypoint
diegomarquezp Nov 9, 2023
5340c39
remove unused files
diegomarquezp Nov 9, 2023
c62a373
do not do post-process IT on mac
diegomarquezp Nov 9, 2023
3f28553
concise entrypoint logic
diegomarquezp Nov 13, 2023
46a0c89
cleanup i
diegomarquezp Nov 13, 2023
ddf202e
cleanup ii
diegomarquezp Nov 13, 2023
7cfbd6f
cleanup iii
diegomarquezp Nov 13, 2023
a2b843d
cleanup iv
diegomarquezp Nov 13, 2023
35b7916
remove templates
diegomarquezp Nov 13, 2023
81d4d60
remove protos folder
diegomarquezp Nov 13, 2023
1e9a788
remove synthtool
diegomarquezp Nov 17, 2023
d99e0ae
connect image to owlbot entrypoint
diegomarquezp Nov 17, 2023
b1baed7
simplify synthtool docker run command
diegomarquezp Nov 17, 2023
860c45b
install synthtool locally
diegomarquezp Dec 1, 2023
6755cd1
install synthtool only once
diegomarquezp Dec 1, 2023
6ecef4e
Merge remote-tracking branch 'origin/main' into local-owlbot-java-owl…
diegomarquezp Dec 1, 2023
558118d
use virtualenvs to run python scripts
diegomarquezp Dec 1, 2023
f8183f8
install pyenv in action
diegomarquezp Dec 1, 2023
bdb6cd0
remove jar from history
diegomarquezp Dec 1, 2023
e42fc0f
download google-java-format
diegomarquezp Dec 1, 2023
4c489e6
fix pyenv init
diegomarquezp Dec 1, 2023
d125c9d
attempt to fix pyenv installation in gh action
diegomarquezp Dec 5, 2023
40c5d24
fix manual pyenv installation
diegomarquezp Dec 5, 2023
60075b3
install pyenv in profile
diegomarquezp Dec 5, 2023
e956f4f
install pyenv in bashrc as well
diegomarquezp Dec 5, 2023
0d1c466
use bash shell explicitly in gh action
diegomarquezp Dec 5, 2023
0e6d547
install pyenv in same step as IT
diegomarquezp Dec 5, 2023
7604f3c
do not restart shell
diegomarquezp Dec 5, 2023
5cce976
set pyenv path manually
diegomarquezp Dec 5, 2023
30392b8
install pyenv in its own step
diegomarquezp Dec 5, 2023
29291a7
propagate environment variables to other steps
diegomarquezp Dec 5, 2023
ecd3b13
fix global env var setup
diegomarquezp Dec 5, 2023
87ac0ab
remove wrong env settings
diegomarquezp Dec 5, 2023
91d5be6
explain usage of pyenv in README
diegomarquezp Dec 5, 2023
9d4a54c
simplify pyenv setup
diegomarquezp Dec 5, 2023
f923b65
add comment to owlbot entrypoint
diegomarquezp Dec 5, 2023
6bda94a
rename destination_path to preprocessed_libraries_path
diegomarquezp Dec 6, 2023
e27a402
infer scripts_root in postprocess_library.sh
diegomarquezp Dec 6, 2023
182c111
use temporary folder for preprocess step
diegomarquezp Dec 6, 2023
d0db9a0
use owlbot files from workspace
diegomarquezp Dec 6, 2023
4516ba4
get rid of output_folder argument
diegomarquezp Dec 7, 2023
d59e65c
use common temp dir to clone synthtool into
diegomarquezp Dec 7, 2023
d0915f3
lock synthtool to a specific commitish
diegomarquezp Dec 7, 2023
e7ea3b1
fix file transfer
diegomarquezp Dec 7, 2023
8ab96e1
fix owl-bot-staging unpacking
diegomarquezp Dec 7, 2023
b140e08
remove unnecessary workspace variable
diegomarquezp Dec 10, 2023
60736ae
rename workspace to postprocessing_target
diegomarquezp Dec 10, 2023
39c3156
remove owlbot sha logic
diegomarquezp Dec 10, 2023
ba561c2
remove repository_root variable
diegomarquezp Dec 10, 2023
86e6a3f
cleanup
diegomarquezp Dec 10, 2023
c98ba18
correct pyenv comment
diegomarquezp Dec 10, 2023
b453c47
clean temp sources folder on each run
diegomarquezp Dec 10, 2023
65f0090
safety checks for get_proto_path_from_preprocessed_sources
diegomarquezp Dec 10, 2023
143534a
fix integration test
diegomarquezp Dec 12, 2023
57e81fa
Merge remote-tracking branch 'origin/main' into move-java-owlbot
diegomarquezp Dec 12, 2023
91fd696
disable compute and asset/v1p2beta1 temporarily
diegomarquezp Dec 12, 2023
33e268a
fix unit tests
diegomarquezp Dec 13, 2023
ae3e577
correct comment
diegomarquezp Dec 13, 2023
b37cc0d
do not install docker for macos
diegomarquezp Dec 13, 2023
1d25e77
fix owlbot files check
diegomarquezp Dec 13, 2023
f0ec962
fix license headers
diegomarquezp Dec 13, 2023
a179552
remove unnecessary owlbot_sha
diegomarquezp Dec 13, 2023
3c20c45
add explanation on why are there no macos + postprocess ITs
diegomarquezp Dec 14, 2023
a38efb0
use `fmt:format` instead of google formatter
diegomarquezp Dec 15, 2023
1d97cdf
clean templates
diegomarquezp Dec 15, 2023
747560f
remove more unnecessary elements
diegomarquezp Dec 15, 2023
f2c937d
add README entry explaining owlbot maintenance
diegomarquezp Dec 18, 2023
5bc7c7f
remove unnecessary java format version
diegomarquezp Dec 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 19 additions & 10 deletions .github/workflows/verify_library_generation.yaml
Expand Up @@ -12,7 +12,7 @@ jobs:
integration_tests:
strategy:
matrix:
java: [ 8 ]
java: [ 11 ]
os: [ ubuntu-22.04, macos-12 ]
post_processing: [ 'true', 'false' ]
runs-on: ${{ matrix.os }}
Expand All @@ -26,8 +26,23 @@ jobs:
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: install pyenv
shell: bash
run: |
set -ex
curl https://pyenv.run | bash
# setup environment
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
echo "PYENV_ROOT=${PYENV_ROOT}" >> $GITHUB_ENV
echo "PATH=${PATH}" >> $GITHUB_ENV
# init pyenv
eval "$(pyenv init --path)"
eval "$(pyenv init -)"
set +ex
- name: install docker (ubuntu)
if: matrix.os == 'ubuntu-22.04'
shell: bash
run: |
set -x
# install docker
Expand All @@ -36,17 +51,11 @@ jobs:

# launch docker
sudo systemctl start docker
- name: install docker (macos)
if: matrix.os == 'macos-12'
run: |
brew update --preinstall
brew install docker docker-compose qemu
brew upgrade qemu
colima start
docker run --user $(id -u):$(id -g) --rm hello-world
- name: Run integration tests
# we don't run ITs with postprocessing on macos because one of its dependencies "synthtool" is designed to run on linux only
if: matrix.os == 'ubuntu-22.04' || matrix.post_processing == 'false'
suztomo marked this conversation as resolved.
Show resolved Hide resolved
shell: bash
run: |
set -x
git config --global user.email "github-workflow@github.com"
git config --global user.name "Github Workflow"
library_generation/test/generate_library_integration_test.sh \
Expand Down
8 changes: 7 additions & 1 deletion library_generation/README.md
@@ -1,4 +1,4 @@
# Generate GAPIC Client Library without post-processing
# Generate GAPIC Client Library with and without post-processing

The script, `generate_library.sh`, allows you to generate a GAPIC client library from proto files.

Expand Down Expand Up @@ -28,6 +28,12 @@ This repository will be the source of truth for pre-existing
pom.xml files, owlbot.py and .OwlBot.yaml files. See the option belows for
custom postprocessed generations (e.g. custom `versions.txt` file).

Post-processing makes use of python scripts. The script will automatically use
`pyenv` to use the specified version in
`library_generation/configuration/python-version`. Pyenv is then a requirement
in the environment.


## Parameters to run `generate_library.sh`

You need to run the script with the following parameters.
Expand Down
1 change: 1 addition & 0 deletions library_generation/configuration/java-format-version
diegomarquezp marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1 @@
1.7
1 change: 1 addition & 0 deletions library_generation/configuration/python-version
@@ -0,0 +1 @@
3.11.2
1 change: 1 addition & 0 deletions library_generation/configuration/synthtool-commitish
@@ -0,0 +1 @@
59fe44fde9866a26e7ee4e4450fd79f67f8cf599
70 changes: 35 additions & 35 deletions library_generation/generate_library.sh
Expand Up @@ -133,7 +133,13 @@ if [ -z "${os_architecture}" ]; then
os_architecture=$(detect_os_architecture)
fi

temp_destination_path="${output_folder}/temp_preprocessed"
mkdir -p "${output_folder}/${destination_path}"
if [ -d "${temp_destination_path}" ]; then
# we don't want the preprocessed sources of a previous run
rm -rd "${temp_destination_path}"
fi
mkdir -p "${temp_destination_path}"
##################### Section 0 #####################
# prepare tooling
#####################################################
Expand Down Expand Up @@ -185,30 +191,30 @@ download_tools "${gapic_generator_version}" "${protobuf_version}" "${grpc_versio
if [[ ! "${transport}" == "rest" ]]; then
# do not need to generate grpc-* if the transport is `rest`.
"${protoc_path}"/protoc "--plugin=protoc-gen-rpc-plugin=protoc-gen-grpc-java-${grpc_version}-${os_architecture}.exe" \
"--rpc-plugin_out=:${destination_path}/java_grpc.jar" \
"--rpc-plugin_out=:${temp_destination_path}/java_grpc.jar" \
${proto_files} # Do not quote because this variable should not be treated as one long string.
# unzip java_grpc.jar to grpc-*/src/main/java
unzip_src_files "grpc"
unzip_src_files "grpc" "${temp_destination_path}"
# remove empty files in grpc-*/src/main/java
remove_empty_files "grpc"
remove_empty_files "grpc" "${temp_destination_path}"
# remove grpc version in *ServiceGrpc.java file so the content is identical with bazel build.
remove_grpc_version
remove_grpc_version "${temp_destination_path}"
fi
###################### Section 2 #####################
## generate gapic-*/, part of proto-*/, samples/
######################################################
if [[ "${proto_only}" == "false" ]]; then
"$protoc_path"/protoc --experimental_allow_proto3_optional \
"--plugin=protoc-gen-java_gapic=${script_dir}/gapic-generator-java-wrapper" \
"--java_gapic_out=metadata:${destination_path}/java_gapic_srcjar_raw.srcjar.zip" \
"--java_gapic_out=metadata:${temp_destination_path}/java_gapic_srcjar_raw.srcjar.zip" \
"--java_gapic_opt=$(get_gapic_opts "${transport}" "${rest_numeric_enums}" "${gapic_yaml}" "${service_config}" "${service_yaml}")" \
${proto_files} ${gapic_additional_protos}

unzip -o -q "${destination_path}/java_gapic_srcjar_raw.srcjar.zip" -d "${destination_path}"
unzip -o -q "${temp_destination_path}/java_gapic_srcjar_raw.srcjar.zip" -d "${temp_destination_path}"
# Sync'\''d to the output file name in Writer.java.
unzip -o -q "${destination_path}/temp-codegen.srcjar" -d "${destination_path}/java_gapic_srcjar"
unzip -o -q "${temp_destination_path}/temp-codegen.srcjar" -d "${temp_destination_path}/java_gapic_srcjar"
# Resource name source files.
proto_dir=${destination_path}/java_gapic_srcjar/proto/src/main/java
proto_dir=${temp_destination_path}/java_gapic_srcjar/proto/src/main/java
if [ ! -d "${proto_dir}" ]; then
# Some APIs don't have resource name helpers, like BigQuery v2.
# Create an empty file so we can finish building. Gating the resource name rule definition
Expand All @@ -218,14 +224,14 @@ if [[ "${proto_only}" == "false" ]]; then
touch "${proto_dir}"/PlaceholderFile.java
fi
# move java_gapic_srcjar/src/main to gapic-*/src.
mv_src_files "gapic" "main"
mv_src_files "gapic" "main" "${temp_destination_path}"
# remove empty files in gapic-*/src/main/java
remove_empty_files "gapic"
remove_empty_files "gapic" "${temp_destination_path}"
# move java_gapic_srcjar/src/test to gapic-*/src
mv_src_files "gapic" "test"
mv_src_files "gapic" "test" "${temp_destination_path}"
if [ "${include_samples}" == "true" ]; then
# move java_gapic_srcjar/samples/snippets to samples/snippets
mv_src_files "samples" "main"
mv_src_files "samples" "main" "${temp_destination_path}"
fi
fi
##################### Section 3 #####################
Expand All @@ -247,16 +253,16 @@ case "${proto_path}" in
proto_files="${proto_files//${removed_proto}/}"
;;
esac
"$protoc_path"/protoc "--java_out=${destination_path}/java_proto.jar" ${proto_files}
"$protoc_path"/protoc "--java_out=${temp_destination_path}/java_proto.jar" ${proto_files}
if [[ "${proto_only}" == "false" ]]; then
# move java_gapic_srcjar/proto/src/main/java (generated resource name helper class)
# to proto-*/src/main
mv_src_files "proto" "main"
mv_src_files "proto" "main" "${temp_destination_path}"
fi
# unzip java_proto.jar to proto-*/src/main/java
unzip_src_files "proto"
unzip_src_files "proto" "${temp_destination_path}"
# remove empty files in proto-*/src/main/java
remove_empty_files "proto"
remove_empty_files "proto" "${temp_destination_path}"
case "${proto_path}" in
"google/cloud/aiplatform/v1beta1"*)
prefix="google/cloud/aiplatform/v1beta1/schema"
Expand All @@ -282,14 +288,14 @@ for proto_src in ${proto_files}; do
if [[ "${proto_src}" == "google/cloud/common/operation_metadata.proto" ]]; then
continue
fi
mkdir -p "${destination_path}/proto-${folder_name}/src/main/proto"
rsync -R "${proto_src}" "${destination_path}/proto-${folder_name}/src/main/proto"
mkdir -p "${temp_destination_path}/proto-${folder_name}/src/main/proto"
rsync -R "${proto_src}" "${temp_destination_path}/proto-${folder_name}/src/main/proto"
done
popd # output_folder
##################### Section 4 #####################
# rm tar files
#####################################################
pushd "${output_folder}/${destination_path}"
pushd "${temp_destination_path}"
rm -rf java_gapic_srcjar java_gapic_srcjar_raw.srcjar.zip java_grpc.jar java_proto.jar temp-codegen.srcjar
popd # destination path
##################### Section 5 #####################
Expand All @@ -298,6 +304,8 @@ popd # destination path
if [ "${enable_postprocessing}" != "true" ];
then
echo "post processing is disabled"
cp -r ${temp_destination_path}/* "${output_folder}/${destination_path}"
rm -rdf "${temp_destination_path}"
exit 0
fi
if [ -z "${versions_file}" ];then
Expand All @@ -311,21 +319,13 @@ fi

mkdir -p "${workspace}"

# if destination_path is not empty, it will be used as a starting workspace for
# postprocessing
if [[ $(find "${output_folder}/${destination_path}" -mindepth 1 -maxdepth 1 -type d,f | wc -l) -gt 0 ]];then
workspace="${output_folder}/${destination_path}"
fi

bash -x "${script_dir}/postprocess_library.sh" "${workspace}" \
"${script_dir}" \
"${destination_path}" \
"${proto_path}" \
"${versions_file}" \
"${output_folder}"
"${temp_destination_path}" \
"${versions_file}"

# for post-procesed libraries, remove pre-processed folders
pushd "${output_folder}/${destination_path}"
rm -rdf "proto-${folder_name}"
rm -rdf "grpc-${folder_name}"
rm -rdf "gapic-${folder_name}"
if [ "${include_samples}" == "false" ]; then
rm -rdf "samples"
fi
popd # output_folder
# move contents of the post-processed library into destination_path
cp -r ${workspace}/* "${output_folder}/${destination_path}"
113 changes: 113 additions & 0 deletions library_generation/owlbot/bin/entrypoint.sh
@@ -0,0 +1,113 @@
#!/bin/bash
# Copyright 2023 Google 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.

# This is the entrypoint script for java owlbot. This is not intended to be
# called directly but rather be called from postproces_library.sh
# For reference, the positional arguments are
# 1: scripts_root: location of postprocess_library.sh
# 2: versions_file: points to a versions.txt containing versions to be applied
# both to README and pom.xml files

# The scripts assumes the CWD is the folder where postprocessing is going to be
# applied

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
echo "...done"
}

if [ "$(ls */.OwlBot.yaml|wc -l)" -gt 1 ];then
# Monorepo (googleapis/google-cloud-java) has multiple OwlBot.yaml config
# files in the modules.
echo "Processing monorepo"
if [ -d owl-bot-staging ]; then
# The content of owl-bot-staging is controlled by Owlbot.yaml files in
# each module in the monorepo
echo "Extracting contents from owl-bot-staging"
for module in owl-bot-staging/* ; do
if [ ! -d "$module" ]; then
continue
fi
# This relocation allows us continue to use owlbot.py without modification
# after monorepo migration.
mv "owl-bot-staging/$module" "$module/owl-bot-staging"
pushd "$module"
processModule
popd
done
rm -r owl-bot-staging
else
echo "In monorepo but no owl-bot-staging." \
"Formatting changes in the last commit"
# Find the files that were touched by the last commit.
last_commit=$(git log -1 --format=%H)
# [A]dded, [C]reated, [M]odified, and [R]enamed
changed_files=$(git show --name-only --no-renames --diff-filter=ACMR \
"${last_commit}")
changed_modules=$(echo "$changed_files" |grep -E '.java$' |cut -d '/' -f 1 \
|sort -u)
for module in ${changed_modules}; do
if [ ! -f "$module/.OwlBot.yaml" ]; then
# Changes irrelevant to Owlbot-generated module (such as .github) do not
# need formatting
continue
fi
pushd "$module"
processModule
popd
done
fi
else
# Split repository
echo "Processing a split repo"
processModule
fi
34 changes: 34 additions & 0 deletions library_generation/owlbot/bin/write_clirr_ignore.sh
@@ -0,0 +1,34 @@
#!/bin/bash
# Copyright 2023 Google 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.

set -e

scripts_root=$1
templates_dir=$(realpath $(dirname "${BASH_SOURCE[0]}")/../templates/clirr)

# restore default clirr-ignored-differences.xml for protos if the file does not exist
for dir in `ls -d proto-google-*`
do
if [ ! -f "${dir}/clirr-ignored-differences.xml" ]
then
tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX)
pushd ${dir}
pushd src/main/java
find * -name *OrBuilder.java | xargs dirname | sort -u | jq -Rns ' (inputs | rtrimstr("\n") | split("\n") ) as $data | {proto_paths: $data}' > ${tmp_dir}/paths.json
popd
python3 "${scripts_root}/owlbot/src/gen-template.py" --data=${tmp_dir}/paths.json --folder=${templates_dir}
popd
fi
done