Skip to content

Commit 4bbb8ac

Browse files
chore: bake the grpc plugin in the hermetic library generation image (#3045)
This PR bakes the gRPC plugin in the hermetic library generation image. The approach is very similar to #2707 * The docker image will have a configurable `ARG` for the gRPC plugin * The docker image will download the gRPC plugin at the version specified in the previous point * The docker image will set the variables DOCKER_GRPC_VERSION and DOCKER_GRPC_LOCATION * `generate_library.sh` will now be able to avoid downloading the gRPC plugin if the computed plugin version is the same as DOCKER_GRPC_VERSION (all this via `utilities.sh`). --------- Co-authored-by: Blake Li <[email protected]>
1 parent b29ef26 commit 4bbb8ac

File tree

5 files changed

+101
-11
lines changed

5 files changed

+101
-11
lines changed

.cloudbuild/library_generation/library_generation.Dockerfile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ SHELL [ "/bin/bash", "-c" ]
1919

2020
ARG OWLBOT_CLI_COMMITTISH=ac84fa5c423a0069bbce3d2d869c9730c8fdf550
2121
ARG PROTOC_VERSION=25.3
22+
ARG GRPC_VERSION=1.65.1
2223
ENV HOME=/home
24+
ENV OS_ARCHITECTURE="linux-x86_64"
2325

2426
# install OS tools
2527
RUN apt-get update && apt-get install -y \
@@ -32,11 +34,19 @@ COPY library_generation /src
3234
# install protoc
3335
WORKDIR /protoc
3436
RUN source /src/utils/utilities.sh \
35-
&& download_protoc "${PROTOC_VERSION}" "linux-x86_64"
37+
&& download_protoc "${PROTOC_VERSION}" "${OS_ARCHITECTURE}"
3638
# we indicate protoc is available in the container via env vars
3739
ENV DOCKER_PROTOC_LOCATION=/protoc
3840
ENV DOCKER_PROTOC_VERSION="${PROTOC_VERSION}"
3941

42+
# install grpc
43+
WORKDIR /grpc
44+
RUN source /src/utils/utilities.sh \
45+
&& download_grpc_plugin "${GRPC_VERSION}" "${OS_ARCHITECTURE}"
46+
# similar to protoc, we indicate grpc is available in the container via env vars
47+
ENV DOCKER_GRPC_LOCATION="/grpc/protoc-gen-grpc-java-${GRPC_VERSION}-${OS_ARCHITECTURE}.exe"
48+
ENV DOCKER_GRPC_VERSION="${GRPC_VERSION}"
49+
4050
# use python 3.11 (the base image has several python versions; here we define the default one)
4151
RUN rm $(which python3)
4252
RUN ln -s $(which python3.11) /usr/local/bin/python

library_generation/generate_library.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,15 @@ case "${proto_path}" in
183183
;;
184184
esac
185185
# download gapic-generator-java, protobuf and grpc plugin.
186+
# the download_tools function will create the environment variables "protoc_path"
187+
# and "grpc_path", to be used in the protoc calls below.
186188
download_tools "${gapic_generator_version}" "${protoc_version}" "${grpc_version}" "${os_architecture}"
187189
##################### Section 1 #####################
188190
# generate grpc-*/
189191
#####################################################
190192
if [[ ! "${transport}" == "rest" ]]; then
191193
# do not need to generate grpc-* if the transport is `rest`.
192-
"${protoc_path}"/protoc "--plugin=protoc-gen-rpc-plugin=protoc-gen-grpc-java-${grpc_version}-${os_architecture}.exe" \
194+
"${protoc_path}"/protoc "--plugin=protoc-gen-rpc-plugin=${grpc_path}" \
193195
"--rpc-plugin_out=:${temp_destination_path}/java_grpc.jar" \
194196
${proto_files} # Do not quote because this variable should not be treated as one long string.
195197
# unzip java_grpc.jar to grpc-*/src/main/java

library_generation/test/generate_library_unit_tests.sh

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,21 @@ get_grpc_version_failed_with_invalid_generator_version_test() {
2828
assertEquals 1 $((res))
2929
}
3030

31+
get_grpc_version_succeed_docker_env_var_test() {
32+
local version_with_docker
33+
local version_without_docker
34+
export DOCKER_GRPC_VERSION="9.9.9"
35+
# get_grpc_version should prioritize DOCKER_GRPC_VERSION
36+
version_with_docker=$(get_grpc_version "2.24.0")
37+
assertEquals "${DOCKER_GRPC_VERSION}" "${version_with_docker}"
38+
unset DOCKER_GRPC_VERSION
39+
}
40+
3141
get_protoc_version_succeed_docker_env_var_test() {
3242
local version_with_docker
3343
local version_without_docker
3444
export DOCKER_PROTOC_VERSION="9.9.9"
45+
# get_protoc_version should prioritize DOCKER_PROTOC_VERSION
3546
version_with_docker=$(get_protoc_version "2.24.0")
3647
assertEquals "${DOCKER_PROTOC_VERSION}" "${version_with_docker}"
3748
unset DOCKER_PROTOC_VERSION
@@ -162,13 +173,43 @@ download_tools_succeed_with_baked_protoc() {
162173

163174
local test_ggj_version="2.40.0"
164175
local test_grpc_version="1.64.0"
176+
# we expect download_tools to decide to use DOCKER_PROTOC_LOCATION because
177+
# the protoc version we want to download is the same as DOCKER_PROTOC_VERSION.
178+
# Note that `protoc_bin_folder` is just the expected formatted value that
179+
# download_tools will format using DOCKER_PROTOC_VERSION (via
180+
# download_protoc).
165181
download_tools "${test_ggj_version}" "99.99" "${test_grpc_version}" "linux-x86_64"
166182
assertEquals "${protoc_bin_folder}" "${protoc_path}"
167183

168184
rm -rdf "${output_folder}"
169185
unset DOCKER_PROTOC_LOCATION
170186
unset DOCKER_PROTOC_VERSION
171187
unset output_folder
188+
unset protoc_path
189+
}
190+
191+
download_tools_succeed_with_baked_grpc() {
192+
# This test has the same structure as
193+
# download_tools_succeed_with_baked_protoc, but meant for the grpc plugin.
194+
local test_dir=$(mktemp -d)
195+
pushd "${test_dir}"
196+
export DOCKER_GRPC_LOCATION=$(mktemp -d)
197+
export DOCKER_GRPC_VERSION="99.99"
198+
export output_folder=$(get_output_folder)
199+
mkdir "${output_folder}"
200+
201+
local test_ggj_version="2.40.0"
202+
local test_protoc_version="1.64.0"
203+
# we expect download_tools to decide to use DOCKER_GRPC_LOCATION because
204+
# the protoc version we want to download is the same as DOCKER_GRPC_VERSION
205+
download_tools "${test_ggj_version}" "${test_protoc_version}" "99.99" "linux-x86_64"
206+
assertEquals "${DOCKER_GRPC_LOCATION}" "${grpc_path}"
207+
208+
rm -rdf "${output_folder}"
209+
unset DOCKER_GRPC_LOCATION
210+
unset DOCKER_GRPC_VERSION
211+
unset output_folder
212+
unset grpc_path
172213
}
173214

174215
download_grpc_plugin_succeed_with_valid_version_linux_test() {
@@ -293,6 +334,7 @@ test_list=(
293334
extract_folder_name_test
294335
get_grpc_version_succeed_with_valid_generator_version_test
295336
get_grpc_version_failed_with_invalid_generator_version_test
337+
get_grpc_version_succeed_docker_env_var_test
296338
get_protoc_version_succeed_docker_env_var_test
297339
get_protoc_version_succeed_with_valid_generator_version_test
298340
get_protoc_version_failed_with_invalid_generator_version_test
@@ -307,6 +349,7 @@ test_list=(
307349
download_protoc_failed_with_invalid_version_linux_test
308350
download_protoc_failed_with_invalid_arch_test
309351
download_tools_succeed_with_baked_protoc
352+
download_tools_succeed_with_baked_grpc
310353
download_grpc_plugin_succeed_with_valid_version_linux_test
311354
download_grpc_plugin_succeed_with_valid_version_macos_test
312355
download_grpc_plugin_failed_with_invalid_version_linux_test

library_generation/utils/utilities.sh

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,18 @@ download_gapic_generator_pom_parent() {
102102
download_generator_artifact "${gapic_generator_version}" "gapic-generator-java-pom-parent-${gapic_generator_version}.pom" "gapic-generator-java-pom-parent"
103103
}
104104

105+
# This function returns the version of the grpc plugin to generate the libraries. If
106+
# DOCKER_GRPC_VERSION is set, this will be the version. Otherwise, it will be
107+
# computed from the gapic-generator-pom-parent artifact at the specified
108+
# gapic_generator_version.
105109
get_grpc_version() {
106110
local gapic_generator_version=$1
107111
local grpc_version
112+
if [[ -n "${DOCKER_GRPC_VERSION}" ]]; then
113+
>&2 echo "Using grpc version baked into the container: ${DOCKER_GRPC_VERSION}"
114+
echo "${DOCKER_GRPC_VERSION}"
115+
return
116+
fi
108117
pushd "${output_folder}" > /dev/null
109118
# get grpc version from gapic-generator-java-pom-parent/pom.xml
110119
download_gapic_generator_pom_parent "${gapic_generator_version}"
@@ -113,6 +122,10 @@ get_grpc_version() {
113122
echo "${grpc_version}"
114123
}
115124

125+
# This function returns the version of protoc to generate the libraries. If
126+
# DOCKER_PROTOC_VERSION is set, this will be the version. Otherwise, it will be
127+
# computed from the gapic-generator-pom-parent artifact at the specified
128+
# gapic_generator_version.
116129
get_protoc_version() {
117130
local gapic_generator_version=$1
118131
local protoc_version
@@ -129,6 +142,16 @@ get_protoc_version() {
129142
echo "${protoc_version}"
130143
}
131144

145+
# Given the versions of the gapic generator, protoc and the protoc-grpc plugin,
146+
# this function will download each one of the tools and create the environment
147+
# variables "protoc_path" and "grpc_path" which are expected upstream. Note that
148+
# if the specified versions of protoc and grpc match DOCKER_PROTOC_VERSION and
149+
# DOCKER_GRPC_VERSION respectively, this function will instead set "protoc_path"
150+
# and "grpc_path" to DOCKER_PROTOC_PATH and DOCKER_GRPC_PATH respectively (no
151+
# download), since the docker image will have downloaded these tools beforehand.
152+
# For the case of gapic-generator-java, no env var will be exported for the
153+
# upstream flow, but instead it will be assigned a default filename that will be
154+
# referenced by the file `library_generation/gapic-generator-java-wrapper`.
132155
download_tools() {
133156
local gapic_generator_version=$1
134157
local protoc_version=$2
@@ -147,7 +170,15 @@ download_tools() {
147170
export protoc_path=$(download_protoc "${protoc_version}" "${os_architecture}")
148171
fi
149172

150-
download_grpc_plugin "${grpc_version}" "${os_architecture}"
173+
# similar case with grpc
174+
if [[ "${DOCKER_GRPC_VERSION}" == "${grpc_version}" ]]; then
175+
# if the specified grpc_version matches the one baked in the docker
176+
# container, we just point grpc_path to its location.
177+
export grpc_path="${DOCKER_GRPC_LOCATION}"
178+
else
179+
export grpc_path=$(download_grpc_plugin "${grpc_version}" "${os_architecture}")
180+
fi
181+
151182
popd
152183
}
153184

@@ -198,13 +229,15 @@ download_protoc() {
198229
download_grpc_plugin() {
199230
local grpc_version=$1
200231
local os_architecture=$2
201-
if [ ! -f "protoc-gen-grpc-java-${grpc_version}-${os_architecture}.exe" ]; then
232+
grpc_filename="protoc-gen-grpc-java-${grpc_version}-${os_architecture}.exe"
233+
if [ ! -f "${grpc_filename}" ]; then
202234
# download protoc-gen-grpc-java plugin from Google maven central mirror.
203235
download_from \
204-
"https://maven-central.storage-download.googleapis.com/maven2/io/grpc/protoc-gen-grpc-java/${grpc_version}/protoc-gen-grpc-java-${grpc_version}-${os_architecture}.exe" \
205-
"protoc-gen-grpc-java-${grpc_version}-${os_architecture}.exe"
206-
chmod +x "protoc-gen-grpc-java-${grpc_version}-${os_architecture}.exe"
236+
"https://maven-central.storage-download.googleapis.com/maven2/io/grpc/protoc-gen-grpc-java/${grpc_version}/${grpc_filename}" \
237+
"${grpc_filename}"
238+
chmod +x "${grpc_filename}"
207239
fi
240+
echo "$(pwd)/${grpc_filename}"
208241
}
209242

210243
download_from() {
@@ -282,7 +315,7 @@ get_proto_path_from_preprocessed_sources() {
282315
pushd "${sources}" > /dev/null
283316
local proto_library=$(find . -maxdepth 1 -type d -name 'proto-*' | sed 's/\.\///')
284317
local found_libraries=$(echo "${proto_library}" | wc -l)
285-
if [ -z ${proto_library} ]; then
318+
if [[ -z ${proto_library} ]]; then
286319
echo "no proto libraries found in the supplied sources path"
287320
exit 1
288321
elif [ ${found_libraries} -gt 1 ]; then

renovate.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
{
3333
"customType": "regex",
3434
"fileMatch": [
35-
"^\\.cloudbuild/library_generation/library_generation\\.Dockerfile$"
35+
"^\\.cloudbuild/library_generation/library_generation\\.Dockerfile$"
3636
],
3737
"matchStrings": [
3838
"ARG PROTOC_VERSION=[\"']?(?<currentValue>.+?)[\"']?\\s+"
@@ -55,10 +55,12 @@
5555
{
5656
"customType": "regex",
5757
"fileMatch": [
58-
"^gax-java/dependencies\\.properties$"
58+
"^gax-java/dependencies\\.properties$",
59+
"^\\.cloudbuild/library_generation/library_generation\\.Dockerfile$"
5960
],
6061
"matchStrings": [
61-
"version\\.io_grpc=(?<currentValue>.+?)\\n"
62+
"version\\.io_grpc=(?<currentValue>.+?)\\n",
63+
"ARG GRPC_VERSION=[\"']?(?<currentValue>.+?)[\"']?\\s+"
6264
],
6365
"depNameTemplate": "io.grpc:grpc-core",
6466
"datasourceTemplate": "maven"

0 commit comments

Comments
 (0)