Skip to content

Commit f8969d2

Browse files
feat: move Java Owlbot into this repository for postprocessing (#2282)
* use local synthtool and owlbot * remove unused files * remove more unused files * remove cache files in owlbot * use java 11 for it * remove kokoro files * use glob in owlbot entrypoint * remove unused files * do not do post-process IT on mac * concise entrypoint logic * cleanup i * cleanup ii * cleanup iii * cleanup iv * remove templates * remove protos folder * remove synthtool * connect image to owlbot entrypoint * simplify synthtool docker run command * install synthtool locally * install synthtool only once * use virtualenvs to run python scripts * install pyenv in action * remove jar from history * download google-java-format * fix pyenv init * attempt to fix pyenv installation in gh action * fix manual pyenv installation * install pyenv in profile * install pyenv in bashrc as well * use bash shell explicitly in gh action * install pyenv in same step as IT * do not restart shell * set pyenv path manually * install pyenv in its own step * propagate environment variables to other steps * fix global env var setup * remove wrong env settings * explain usage of pyenv in README * simplify pyenv setup * add comment to owlbot entrypoint * rename destination_path to preprocessed_libraries_path * infer scripts_root in postprocess_library.sh * use temporary folder for preprocess step * use owlbot files from workspace * get rid of output_folder argument * use common temp dir to clone synthtool into * lock synthtool to a specific commitish * fix file transfer * fix owl-bot-staging unpacking * remove unnecessary workspace variable * rename workspace to postprocessing_target * remove owlbot sha logic * remove repository_root variable * cleanup * correct pyenv comment * clean temp sources folder on each run * safety checks for get_proto_path_from_preprocessed_sources * fix integration test * disable compute and asset/v1p2beta1 temporarily they have changes in googleapis that have not been reflected yet in google-cloud-java * fix unit tests * correct comment * do not install docker for macos * fix owlbot files check * fix license headers * remove unnecessary owlbot_sha * add explanation on why are there no macos + postprocess ITs * use `fmt:format` instead of google formatter * clean templates * remove more unnecessary elements * add README entry explaining owlbot maintenance * remove unnecessary java format version
1 parent c9cf66b commit f8969d2

30 files changed

+1828
-203
lines changed

.github/workflows/verify_library_generation.yaml

+19-10
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
integration_tests:
1313
strategy:
1414
matrix:
15-
java: [ 8 ]
15+
java: [ 11 ]
1616
os: [ ubuntu-22.04, macos-12 ]
1717
post_processing: [ 'true', 'false' ]
1818
runs-on: ${{ matrix.os }}
@@ -26,8 +26,23 @@ jobs:
2626
- uses: actions/setup-python@v4
2727
with:
2828
python-version: '3.11'
29+
- name: install pyenv
30+
shell: bash
31+
run: |
32+
set -ex
33+
curl https://pyenv.run | bash
34+
# setup environment
35+
export PYENV_ROOT="$HOME/.pyenv"
36+
export PATH="$PYENV_ROOT/bin:$PATH"
37+
echo "PYENV_ROOT=${PYENV_ROOT}" >> $GITHUB_ENV
38+
echo "PATH=${PATH}" >> $GITHUB_ENV
39+
# init pyenv
40+
eval "$(pyenv init --path)"
41+
eval "$(pyenv init -)"
42+
set +ex
2943
- name: install docker (ubuntu)
3044
if: matrix.os == 'ubuntu-22.04'
45+
shell: bash
3146
run: |
3247
set -x
3348
# install docker
@@ -36,17 +51,11 @@ jobs:
3651
3752
# launch docker
3853
sudo systemctl start docker
39-
- name: install docker (macos)
40-
if: matrix.os == 'macos-12'
41-
run: |
42-
brew update --preinstall
43-
brew install docker docker-compose qemu
44-
brew upgrade qemu
45-
colima start
46-
docker run --user $(id -u):$(id -g) --rm hello-world
4754
- name: Run integration tests
55+
# we don't run ITs with postprocessing on macos because one of its dependencies "synthtool" is designed to run on linux only
56+
if: matrix.os == 'ubuntu-22.04' || matrix.post_processing == 'false'
57+
shell: bash
4858
run: |
49-
set -x
5059
git config --global user.email "[email protected]"
5160
git config --global user.name "Github Workflow"
5261
library_generation/test/generate_library_integration_test.sh \

library_generation/README.md

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generate GAPIC Client Library without post-processing
1+
# Generate GAPIC Client Library with and without post-processing
22

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

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

31+
Post-processing makes use of python scripts. The script will automatically use
32+
`pyenv` to use the specified version in
33+
`library_generation/configuration/python-version`. Pyenv is then a requirement
34+
in the environment.
35+
36+
3137
## Parameters to run `generate_library.sh`
3238

3339
You need to run the script with the following parameters.
@@ -225,3 +231,26 @@ library_generation/generate_library.sh \
225231
--versions_file "path/to/versions.txt" \
226232
--include_samples true
227233
```
234+
235+
# Owlbot Java Postprocessor
236+
237+
We have transferred the
238+
[implementation](https://github.com/googleapis/synthtool/tree/59fe44fde9866a26e7ee4e4450fd79f67f8cf599/docker/owlbot/java)
239+
of Java Owlbot Postprocessor into `sdk-platform-java/library_generation`. The
240+
implementation in synthtool is still valid and used by other services, so we
241+
have two versions during a transition period.
242+
243+
## Reflecting changes in synthtool/docker/owlbot/java into this repository
244+
The transfer was not a verbatim copy, it rather had modifications:
245+
* `format-source.sh` was replaced by a call to `mvn fmt:format`
246+
* `entrypoint.sh` was modified to have input arguments and slightly modified
247+
the way the helper scripts are called
248+
* Other helper scripts were modified to have input arguments.
249+
* `fix-poms.py` modified the way the monorepo is detected
250+
251+
All these modifications imply that whenever we want to reflect a change from the
252+
original owlbot in synthtool we may be better off modifying the affected source
253+
files one by one. The mapping is from
254+
[`synthtool/docker/owlbot/java`](https://github.com/googleapis/synthtool/tree/59fe44fde9866a26e7ee4e4450fd79f67f8cf599/docker/owlbot/java)
255+
to
256+
[`sdk-platform-java/library_generation/owlbot`](https://github.com/googleapis/sdk-platform-java/tree/move-java-owlbot/library_generation/owlbot)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.11.2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
59fe44fde9866a26e7ee4e4450fd79f67f8cf599

library_generation/generate_library.sh

+35-35
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,13 @@ if [ -z "${os_architecture}" ]; then
133133
os_architecture=$(detect_os_architecture)
134134
fi
135135

136+
temp_destination_path="${output_folder}/temp_preprocessed"
136137
mkdir -p "${output_folder}/${destination_path}"
138+
if [ -d "${temp_destination_path}" ]; then
139+
# we don't want the preprocessed sources of a previous run
140+
rm -rd "${temp_destination_path}"
141+
fi
142+
mkdir -p "${temp_destination_path}"
137143
##################### Section 0 #####################
138144
# prepare tooling
139145
#####################################################
@@ -185,30 +191,30 @@ download_tools "${gapic_generator_version}" "${protobuf_version}" "${grpc_versio
185191
if [[ ! "${transport}" == "rest" ]]; then
186192
# do not need to generate grpc-* if the transport is `rest`.
187193
"${protoc_path}"/protoc "--plugin=protoc-gen-rpc-plugin=protoc-gen-grpc-java-${grpc_version}-${os_architecture}.exe" \
188-
"--rpc-plugin_out=:${destination_path}/java_grpc.jar" \
194+
"--rpc-plugin_out=:${temp_destination_path}/java_grpc.jar" \
189195
${proto_files} # Do not quote because this variable should not be treated as one long string.
190196
# unzip java_grpc.jar to grpc-*/src/main/java
191-
unzip_src_files "grpc"
197+
unzip_src_files "grpc" "${temp_destination_path}"
192198
# remove empty files in grpc-*/src/main/java
193-
remove_empty_files "grpc"
199+
remove_empty_files "grpc" "${temp_destination_path}"
194200
# remove grpc version in *ServiceGrpc.java file so the content is identical with bazel build.
195-
remove_grpc_version
201+
remove_grpc_version "${temp_destination_path}"
196202
fi
197203
###################### Section 2 #####################
198204
## generate gapic-*/, part of proto-*/, samples/
199205
######################################################
200206
if [[ "${proto_only}" == "false" ]]; then
201207
"$protoc_path"/protoc --experimental_allow_proto3_optional \
202208
"--plugin=protoc-gen-java_gapic=${script_dir}/gapic-generator-java-wrapper" \
203-
"--java_gapic_out=metadata:${destination_path}/java_gapic_srcjar_raw.srcjar.zip" \
209+
"--java_gapic_out=metadata:${temp_destination_path}/java_gapic_srcjar_raw.srcjar.zip" \
204210
"--java_gapic_opt=$(get_gapic_opts "${transport}" "${rest_numeric_enums}" "${gapic_yaml}" "${service_config}" "${service_yaml}")" \
205211
${proto_files} ${gapic_additional_protos}
206212

207-
unzip -o -q "${destination_path}/java_gapic_srcjar_raw.srcjar.zip" -d "${destination_path}"
213+
unzip -o -q "${temp_destination_path}/java_gapic_srcjar_raw.srcjar.zip" -d "${temp_destination_path}"
208214
# Sync'\''d to the output file name in Writer.java.
209-
unzip -o -q "${destination_path}/temp-codegen.srcjar" -d "${destination_path}/java_gapic_srcjar"
215+
unzip -o -q "${temp_destination_path}/temp-codegen.srcjar" -d "${temp_destination_path}/java_gapic_srcjar"
210216
# Resource name source files.
211-
proto_dir=${destination_path}/java_gapic_srcjar/proto/src/main/java
217+
proto_dir=${temp_destination_path}/java_gapic_srcjar/proto/src/main/java
212218
if [ ! -d "${proto_dir}" ]; then
213219
# Some APIs don't have resource name helpers, like BigQuery v2.
214220
# Create an empty file so we can finish building. Gating the resource name rule definition
@@ -218,14 +224,14 @@ if [[ "${proto_only}" == "false" ]]; then
218224
touch "${proto_dir}"/PlaceholderFile.java
219225
fi
220226
# move java_gapic_srcjar/src/main to gapic-*/src.
221-
mv_src_files "gapic" "main"
227+
mv_src_files "gapic" "main" "${temp_destination_path}"
222228
# remove empty files in gapic-*/src/main/java
223-
remove_empty_files "gapic"
229+
remove_empty_files "gapic" "${temp_destination_path}"
224230
# move java_gapic_srcjar/src/test to gapic-*/src
225-
mv_src_files "gapic" "test"
231+
mv_src_files "gapic" "test" "${temp_destination_path}"
226232
if [ "${include_samples}" == "true" ]; then
227233
# move java_gapic_srcjar/samples/snippets to samples/snippets
228-
mv_src_files "samples" "main"
234+
mv_src_files "samples" "main" "${temp_destination_path}"
229235
fi
230236
fi
231237
##################### Section 3 #####################
@@ -247,16 +253,16 @@ case "${proto_path}" in
247253
proto_files="${proto_files//${removed_proto}/}"
248254
;;
249255
esac
250-
"$protoc_path"/protoc "--java_out=${destination_path}/java_proto.jar" ${proto_files}
256+
"$protoc_path"/protoc "--java_out=${temp_destination_path}/java_proto.jar" ${proto_files}
251257
if [[ "${proto_only}" == "false" ]]; then
252258
# move java_gapic_srcjar/proto/src/main/java (generated resource name helper class)
253259
# to proto-*/src/main
254-
mv_src_files "proto" "main"
260+
mv_src_files "proto" "main" "${temp_destination_path}"
255261
fi
256262
# unzip java_proto.jar to proto-*/src/main/java
257-
unzip_src_files "proto"
263+
unzip_src_files "proto" "${temp_destination_path}"
258264
# remove empty files in proto-*/src/main/java
259-
remove_empty_files "proto"
265+
remove_empty_files "proto" "${temp_destination_path}"
260266
case "${proto_path}" in
261267
"google/cloud/aiplatform/v1beta1"*)
262268
prefix="google/cloud/aiplatform/v1beta1/schema"
@@ -282,14 +288,14 @@ for proto_src in ${proto_files}; do
282288
if [[ "${proto_src}" == "google/cloud/common/operation_metadata.proto" ]]; then
283289
continue
284290
fi
285-
mkdir -p "${destination_path}/proto-${folder_name}/src/main/proto"
286-
rsync -R "${proto_src}" "${destination_path}/proto-${folder_name}/src/main/proto"
291+
mkdir -p "${temp_destination_path}/proto-${folder_name}/src/main/proto"
292+
rsync -R "${proto_src}" "${temp_destination_path}/proto-${folder_name}/src/main/proto"
287293
done
288294
popd # output_folder
289295
##################### Section 4 #####################
290296
# rm tar files
291297
#####################################################
292-
pushd "${output_folder}/${destination_path}"
298+
pushd "${temp_destination_path}"
293299
rm -rf java_gapic_srcjar java_gapic_srcjar_raw.srcjar.zip java_grpc.jar java_proto.jar temp-codegen.srcjar
294300
popd # destination path
295301
##################### Section 5 #####################
@@ -298,6 +304,8 @@ popd # destination path
298304
if [ "${enable_postprocessing}" != "true" ];
299305
then
300306
echo "post processing is disabled"
307+
cp -r ${temp_destination_path}/* "${output_folder}/${destination_path}"
308+
rm -rdf "${temp_destination_path}"
301309
exit 0
302310
fi
303311
if [ -z "${versions_file}" ];then
@@ -311,21 +319,13 @@ fi
311319

312320
mkdir -p "${workspace}"
313321

322+
# if destination_path is not empty, it will be used as a starting workspace for
323+
# postprocessing
324+
if [[ $(find "${output_folder}/${destination_path}" -mindepth 1 -maxdepth 1 -type d,f | wc -l) -gt 0 ]];then
325+
workspace="${output_folder}/${destination_path}"
326+
fi
327+
314328
bash -x "${script_dir}/postprocess_library.sh" "${workspace}" \
315-
"${script_dir}" \
316-
"${destination_path}" \
317-
"${proto_path}" \
318-
"${versions_file}" \
319-
"${output_folder}"
329+
"${temp_destination_path}" \
330+
"${versions_file}"
320331

321-
# for post-procesed libraries, remove pre-processed folders
322-
pushd "${output_folder}/${destination_path}"
323-
rm -rdf "proto-${folder_name}"
324-
rm -rdf "grpc-${folder_name}"
325-
rm -rdf "gapic-${folder_name}"
326-
if [ "${include_samples}" == "false" ]; then
327-
rm -rdf "samples"
328-
fi
329-
popd # output_folder
330-
# move contents of the post-processed library into destination_path
331-
cp -r ${workspace}/* "${output_folder}/${destination_path}"
+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/bin/bash
2+
# Copyright 2023 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# This is the entrypoint script for java owlbot. This is not intended to be
17+
# called directly but rather be called from postproces_library.sh
18+
# For reference, the positional arguments are
19+
# 1: scripts_root: location of postprocess_library.sh
20+
# 2: versions_file: points to a versions.txt containing versions to be applied
21+
# both to README and pom.xml files
22+
23+
# The scripts assumes the CWD is the folder where postprocessing is going to be
24+
# applied
25+
26+
set -ex
27+
scripts_root=$1
28+
versions_file=$2
29+
30+
# Runs template and etc in current working directory
31+
function processModule() {
32+
# templates as well as retrieving files from owl-bot-staging
33+
echo "Generating templates and retrieving files from owl-bot-staging directory..."
34+
if [ -f "owlbot.py" ]
35+
then
36+
# defaults to run owlbot.py
37+
python3 owlbot.py
38+
fi
39+
echo "...done"
40+
41+
# write or restore pom.xml files
42+
echo "Generating missing pom.xml..."
43+
python3 "${scripts_root}/owlbot/src/fix-poms.py" "${versions_file}" "true"
44+
echo "...done"
45+
46+
# write or restore clirr-ignored-differences.xml
47+
echo "Generating clirr-ignored-differences.xml..."
48+
${scripts_root}/owlbot/bin/write_clirr_ignore.sh "${scripts_root}"
49+
echo "...done"
50+
51+
# fix license headers
52+
echo "Fixing missing license headers..."
53+
python3 "${scripts_root}/owlbot/src/fix-license-headers.py"
54+
echo "...done"
55+
56+
# TODO: re-enable this once we resolve thrashing
57+
# restore license headers years
58+
# echo "Restoring copyright years..."
59+
# /owlbot/bin/restore_license_headers.sh
60+
# echo "...done"
61+
62+
# ensure formatting on all .java files in the repository
63+
echo "Reformatting source..."
64+
mvn fmt:format
65+
echo "...done"
66+
}
67+
68+
if [ "$(ls */.OwlBot.yaml|wc -l)" -gt 1 ];then
69+
# Monorepo (googleapis/google-cloud-java) has multiple OwlBot.yaml config
70+
# files in the modules.
71+
echo "Processing monorepo"
72+
if [ -d owl-bot-staging ]; then
73+
# The content of owl-bot-staging is controlled by Owlbot.yaml files in
74+
# each module in the monorepo
75+
echo "Extracting contents from owl-bot-staging"
76+
for module in owl-bot-staging/* ; do
77+
if [ ! -d "$module" ]; then
78+
continue
79+
fi
80+
# This relocation allows us continue to use owlbot.py without modification
81+
# after monorepo migration.
82+
mv "owl-bot-staging/$module" "$module/owl-bot-staging"
83+
pushd "$module"
84+
processModule
85+
popd
86+
done
87+
rm -r owl-bot-staging
88+
else
89+
echo "In monorepo but no owl-bot-staging." \
90+
"Formatting changes in the last commit"
91+
# Find the files that were touched by the last commit.
92+
last_commit=$(git log -1 --format=%H)
93+
# [A]dded, [C]reated, [M]odified, and [R]enamed
94+
changed_files=$(git show --name-only --no-renames --diff-filter=ACMR \
95+
"${last_commit}")
96+
changed_modules=$(echo "$changed_files" |grep -E '.java$' |cut -d '/' -f 1 \
97+
|sort -u)
98+
for module in ${changed_modules}; do
99+
if [ ! -f "$module/.OwlBot.yaml" ]; then
100+
# Changes irrelevant to Owlbot-generated module (such as .github) do not
101+
# need formatting
102+
continue
103+
fi
104+
pushd "$module"
105+
processModule
106+
popd
107+
done
108+
fi
109+
else
110+
# Split repository
111+
echo "Processing a split repo"
112+
processModule
113+
fi

0 commit comments

Comments
 (0)