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: bake gapic-generator-java into the hermetic build docker image #3067

Merged
merged 72 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
8de1c01
chore: bake the grpc plugin in the hermetic library generation image
diegomarquezp Jul 11, 2024
15b2fc5
improve comments
diegomarquezp Jul 11, 2024
0a95554
Update library_generation/utils/utilities.sh
diegomarquezp Jul 22, 2024
034edf9
add grpc to renovate.json
diegomarquezp Jul 22, 2024
9795e23
add GRPC_VERSION to renovate config
diegomarquezp Jul 22, 2024
89fc562
feat: bake gapic-generator-java into the hermetic docker image
diegomarquezp Jul 24, 2024
1f2ea9e
add tests
diegomarquezp Jul 24, 2024
8af8bec
remove generator version from generation config
diegomarquezp Jul 25, 2024
b5e49dd
Merge remote-tracking branch 'origin/main' into bake-ggj-docker-image-2
diegomarquezp Jul 31, 2024
1649403
expand unit test to test file
diegomarquezp Jul 31, 2024
34c5355
remove unused function
diegomarquezp Jul 31, 2024
651af1e
remove xtrace
diegomarquezp Jul 31, 2024
4ef977b
adjust to other env var provided
diegomarquezp Jul 31, 2024
6e20135
update docker image generator versoin
diegomarquezp Jul 31, 2024
a5c18b2
remove old generator_version, rename config key variable
diegomarquezp Aug 7, 2024
89e16c1
improve comment
diegomarquezp Aug 7, 2024
1cf63ea
adapt tests
diegomarquezp Aug 8, 2024
74b36d3
add docker environment for tests
diegomarquezp Aug 8, 2024
e582817
adapt generate_pr_description
diegomarquezp Aug 8, 2024
82e6b8e
adapt generate_repo
diegomarquezp Aug 8, 2024
3f0dc7f
adapt cli
diegomarquezp Aug 8, 2024
b599d6f
adapt model
diegomarquezp Aug 8, 2024
ddb4ff9
adapt utils
diegomarquezp Aug 8, 2024
6d35e7f
adapt utilities
diegomarquezp Aug 8, 2024
d08e739
black
diegomarquezp Aug 8, 2024
eea978d
simplify generator fetching logic
diegomarquezp Aug 9, 2024
cdb137e
update documentation
diegomarquezp Aug 9, 2024
9b50a73
make generate_pr_desc executable
diegomarquezp Aug 9, 2024
4ac8caf
remove m2 mapping
diegomarquezp Aug 9, 2024
4a57a7d
remove gapic_generator_version
diegomarquezp Aug 9, 2024
1164694
remove unnecessary version in Dockerfile
diegomarquezp Aug 9, 2024
5a4cfdc
do not use env vars
diegomarquezp Aug 27, 2024
a9257fe
Merge remote-tracking branch 'origin/main' into bake-ggj-docker-image-2
diegomarquezp Aug 27, 2024
ab7a684
update ggj version
diegomarquezp Aug 27, 2024
ddaeaf1
adapt shell tests
diegomarquezp Aug 27, 2024
62b281d
restore hermetic_library_generation script
diegomarquezp Aug 29, 2024
e0de3c9
explain how to setup the generator jar in development guide
diegomarquezp Aug 29, 2024
1bc545a
restore model
diegomarquezp Aug 29, 2024
9022ba0
restore commit message formatter
diegomarquezp Aug 29, 2024
6f1e200
restore usage of gapic_generator_version argument
diegomarquezp Aug 29, 2024
bd71775
Revert "restore usage of gapic_generator_version argument"
diegomarquezp Aug 30, 2024
0e90ddc
fix test
diegomarquezp Aug 30, 2024
25f2d7f
restore readme
diegomarquezp Aug 30, 2024
902f656
restore templates
diegomarquezp Aug 30, 2024
a06cd0b
restore pr description tests
diegomarquezp Aug 30, 2024
7194148
restore gen config units
diegomarquezp Aug 30, 2024
41ab2da
restore gen config in unit tests
diegomarquezp Aug 30, 2024
1301b0f
restore simulated docker env
diegomarquezp Aug 30, 2024
c4933ea
Update library_generation/test/generate_library_unit_tests.sh
diegomarquezp Aug 30, 2024
6379c0d
improve development guide
diegomarquezp Aug 30, 2024
16435c4
fix showcase tests
diegomarquezp Aug 30, 2024
1b4a8cc
Merge remote-tracking branch 'origin/bake-ggj-docker-image-2' into ba…
diegomarquezp Aug 30, 2024
8e0ddcc
fix showcase ii
diegomarquezp Aug 30, 2024
81f6748
get protoc and grpc versions in showcase golden test
diegomarquezp Aug 30, 2024
35ad97e
fix utilities comment
diegomarquezp Aug 30, 2024
32e9af3
Merge remote-tracking branch 'origin/main' into bake-ggj-docker-image-2
diegomarquezp Aug 30, 2024
d6844ce
install spring without relying on published versions
diegomarquezp Aug 30, 2024
d776b32
use locked-in jar
diegomarquezp Aug 31, 2024
1de293f
fix spring test
diegomarquezp Aug 31, 2024
1895792
fix path to mvnw
diegomarquezp Aug 31, 2024
7d805e2
chmod the spring script to allow execution
diegomarquezp Aug 31, 2024
1eec008
Merge remote-tracking branch 'origin/main' into bake-ggj-docker-image-2
diegomarquezp Aug 31, 2024
935534e
Update library_generation/test/integration_tests.py
diegomarquezp Aug 31, 2024
b01717a
one sentence per line in DEVELOPMENT.md
diegomarquezp Aug 31, 2024
5fb1be8
Merge remote-tracking branch 'origin/bake-ggj-docker-image-2' into ba…
diegomarquezp Aug 31, 2024
38b53a2
Update .kokoro/presubmit/downstream-compatibility-spring.sh
diegomarquezp Aug 31, 2024
87b7425
use python for newer generate_library units
diegomarquezp Sep 3, 2024
e639d2c
Merge remote-tracking branch 'origin/bake-ggj-docker-image-2' into ba…
diegomarquezp Sep 3, 2024
7dd0f3e
Merge branch 'main' into bake-ggj-docker-image-2
diegomarquezp Sep 3, 2024
6a4f446
Remove uncertain prediction in DEVELOPMENT.md
diegomarquezp Sep 3, 2024
b524768
ignore jars in library_generation, from root blacklist
diegomarquezp Sep 3, 2024
01d8fa0
Merge remote-tracking branch 'origin/bake-ggj-docker-image-2' into ba…
diegomarquezp Sep 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion .cloudbuild/library_generation/library_generation.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,25 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# install gapic-generator-java in a separate layer so we don't overload the image
# with the transferred source code and jars
FROM gcr.io/cloud-devrel-public-resources/java21 AS ggj-build
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved

WORKDIR /sdk-platform-java
COPY . .
# {x-version-update-start:gapic-generator-java:current}
ENV DOCKER_GAPIC_GENERATOR_VERSION="2.42.1-SNAPSHOT"

RUN mvn install -DskipTests -Dclirr.skip -Dcheckstyle.skip
RUN ls "/root/.m2/repository/com/google/api/gapic-generator-java/"
RUN cp "/root/.m2/repository/com/google/api/gapic-generator-java/${DOCKER_GAPIC_GENERATOR_VERSION}/gapic-generator-java-${DOCKER_GAPIC_GENERATOR_VERSION}.jar" .
Copy link
Contributor Author

@diegomarquezp diegomarquezp Jul 31, 2024

Choose a reason for hiding this comment

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

Only copying the jar (as opposed to copying the entire .m2 folder) allows us for a more precise test. We can use the env vars DOCKER_GAPIC_GENERATOR_LOCATION and DOCKER_GAPIC_GENERATOR_VERSION to confirm if the preconfigured generator was used

Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this jar have all the info we need? Can you test running the image without internet? Sometimes the dependencies of the jar are still downloaded.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I ran docker run --network none and could get past generate_library.sh (i.e. no jars needed), but I found two things we may want to follow up with:

This function from the transferred synthtool fetches data from Maven:

def latest_maven_version(group_id: str, artifact_id: str) -> Optional[str]:

Our script pulls googleapis' proto definitions:

if not (
os.path.exists(f"{output_folder}/google")
and os.path.exists(f"{output_folder}/grafeas")
):
print("downloading googleapis")
sh_util(
f"download_googleapis_files_and_folders {output_folder} {googleapis_commitish}"
)

I thought there was a commit in synthtool that fetches libraries_bom from our config yaml?

metadata["latest_version"] = latest_maven_version(
group_id=group_id, artifact_id=artifact_id
)
metadata["latest_bom_version"] = latest_maven_version(
group_id="com.google.cloud",
artifact_id="libraries-bom",
)

For the googleapis download, I guess it's expected behavior

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did a temporary bypass (not committed) to see if the generation is successful. It is except for the mvn fmt:format part that needs to fetch data when processing a library. The data includes fetching the parent pom of the target library. Nothing about sdk-platform is fetched.

https://paste.googleplex.com/5092731556986880?raw

Copy link
Collaborator

@blakeli0 blakeli0 Aug 7, 2024

Choose a reason for hiding this comment

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

Sounds good! Yes we should definitely follow up but I don't think they should block this PR, since we already have all the jars in the docker image.


# build from the root of this repo:
FROM gcr.io/cloud-devrel-public-resources/python
JoeWang1127 marked this conversation as resolved.
Show resolved Hide resolved

SHELL [ "/bin/bash", "-c" ]


ARG OWLBOT_CLI_COMMITTISH=ac84fa5c423a0069bbce3d2d869c9730c8fdf550
ARG PROTOC_VERSION=25.3
ARG GRPC_VERSION=1.65.1
Expand Down Expand Up @@ -47,7 +61,16 @@ RUN source /src/utils/utilities.sh \
ENV DOCKER_GRPC_LOCATION="/grpc/protoc-gen-grpc-java-${GRPC_VERSION}-${OS_ARCHITECTURE}.exe"
ENV DOCKER_GRPC_VERSION="${GRPC_VERSION}"

# use python 3.11 (the base image has several python versions; here we define the default one)

# we transfer gapic-generator-java from the previous stage.
# here we redeclare this env var since they are not preserved between stages
ENV DOCKER_GAPIC_GENERATOR_VERSION="2.42.1-SNAPSHOT"
# {x-version-update-end:gapic-generator-java:current}
ENV DOCKER_GAPIC_GENERATOR_LOCATION="/gapic-generator-java/gapic-generator-java-${DOCKER_GAPIC_GENERATOR_VERSION}.jar"
COPY --from=ggj-build "/root/.m2/repository/com/google/api/gapic-generator-java/${DOCKER_GAPIC_GENERATOR_VERSION}/gapic-generator-java-${DOCKER_GAPIC_GENERATOR_VERSION}.jar" "${DOCKER_GAPIC_GENERATOR_LOCATION}"
RUN chmod 755 "${DOCKER_GAPIC_GENERATOR_LOCATION}"

# use python 3.11 (the base image has several python versions; here we define the default one)
RUN rm $(which python3)
RUN ln -s $(which python3.11) /usr/local/bin/python
RUN ln -s $(which python3.11) /usr/local/bin/python3
Expand Down
3 changes: 0 additions & 3 deletions .github/scripts/hermetic_library_generation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,6 @@ fi
git show "${target_branch}":"${generation_config}" > "${baseline_generation_config}"
config_diff=$(diff "${generation_config}" "${baseline_generation_config}" || true)

generator_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout -pl gapic-generator-java)
diegomarquezp marked this conversation as resolved.
Show resolved Hide resolved
echo "Local generator version: ${generator_version}"

# install generator locally since we're using a SNAPSHOT version.
mvn -V -B -ntp clean install -DskipTests

Expand Down
7 changes: 4 additions & 3 deletions library_generation/generate_library.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ case $key in
;;
--gapic_generator_version)
gapic_generator_version="$2"
# export this variable so that it can be used in gapic-generator-java-wrapper.sh
export gapic_generator_version
shift
;;
--protoc_version)
Expand Down Expand Up @@ -77,7 +75,7 @@ script_dir=$(dirname "$(readlink -f "$0")")
source "${script_dir}"/utils/utilities.sh
output_folder="$(get_output_folder)"

if [ -z "${gapic_generator_version}" ]; then
if [[ -z "${gapic_generator_version}" ]] ; then
echo 'missing required argument --gapic_generator_version'
exit 1
fi
Expand Down Expand Up @@ -126,6 +124,9 @@ if [ -z "${os_architecture}" ]; then
os_architecture=$(detect_os_architecture)
fi

# export this variable so that it can be used in gapic-generator-java-wrapper.sh
export gapic_generator_version

temp_destination_path="${output_folder}/temp_preprocessed"
mkdir -p "${output_folder}/${destination_path}"
if [ -d "${temp_destination_path}" ]; then
Expand Down
10 changes: 6 additions & 4 deletions library_generation/model/generation_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
COMMON_PROTOS_LIBRARY_NAME = "common-protos"
GAPIC_GENERATOR_VERSION = "gapic_generator_version"
LIBRARIES_BOM_VERSION = "libraries_bom_version"
GENERATOR_VERSION_ENV_KEY = "GENERATOR_VERSION"
GENERATOR_VERSION_ENV_KEY = "DOCKER_GAPIC_GENERATOR_VERSION"
diegomarquezp marked this conversation as resolved.
Show resolved Hide resolved


class GenerationConfig:
Expand Down Expand Up @@ -90,9 +90,11 @@ def __set_generator_version(gapic_generator_version: Optional[str]) -> str:
gapic_generator_version = os.getenv(GENERATOR_VERSION_ENV_KEY)
if not gapic_generator_version:
raise ValueError(
f"Environment variable {GENERATOR_VERSION_ENV_KEY}"
f" is not set when the generator version is not"
f" specified in the generation config."
f"gapic_generator_version was not specified in the "
f"configuration yaml and the fall-back env var "
f"{GENERATOR_VERSION_ENV_KEY} was not found. At "
f"least one of them must be set to proceed with the "
f"generation."
)
return gapic_generator_version

Expand Down
45 changes: 45 additions & 0 deletions library_generation/test/generate_library_unit_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,50 @@ download_tools_succeed_with_baked_grpc() {
unset grpc_path
}

download_tools_succeed_with_baked_generator() {
# This test has the same structure as
# download_tools_succeed_with_baked_protoc, but meant for
# gapic-generator-java.
local test_dir=$(mktemp -d)
pushd "${test_dir}"
generator_folder=$(mktemp -d)
touch "${generator_folder}/gapic-generator-java.fakejar"
export DOCKER_GAPIC_GENERATOR_LOCATION="${generator_folder}/gapic-generator-java.fakejar"
export DOCKER_GAPIC_GENERATOR_VERSION="99.99"
export output_folder=$(get_output_folder)
mkdir "${output_folder}"

local test_protoc_version="1.64.0"
local test_grpc_version="1.64.0"
# we expect download_tools to decide to use DOCKER_GAPIC_GENERATOR_LOCATION because
# the protoc version we want to download is the same as DOCKER_GRPC_VERSION
log=$(download_tools "99.99" "${test_protoc_version}" "${test_grpc_version}" "linux-x86_64" 2>&1 1>/dev/null)

# the assertion functions are designed to be called only once per function.
# Here we do two manual tests that are then coverged into a single
# pseudo-boolean
has_expected_log="false"
has_expected_file="false"
is_output_correct="false"
if grep -q "Using gapic-generator-java version baked into the container: 99.99" <<< "${log}"; then
has_expected_log="true"
fi
if [[ -f "${output_folder}/gapic-generator-java.fakejar" ]]; then
has_expected_file="true"
fi
if [[ "${has_expected_log}" == "true" ]] && [[ "${has_expected_file}" == "true" ]]; then
is_output_correct="true"
fi

assertEquals "true" "${is_output_correct}"

rm -rdf "${output_folder}"
unset DOCKER_GRPC_LOCATION
unset DOCKER_GRPC_VERSION
unset output_folder
unset grpc_path
}

download_grpc_plugin_succeed_with_valid_version_linux_test() {
download_grpc_plugin "1.55.1" "linux-x86_64"
assertFileOrDirectoryExists "protoc-gen-grpc-java-1.55.1-linux-x86_64.exe"
Expand Down Expand Up @@ -350,6 +394,7 @@ test_list=(
download_protoc_failed_with_invalid_arch_test
download_tools_succeed_with_baked_protoc
download_tools_succeed_with_baked_grpc
download_tools_succeed_with_baked_generator
download_grpc_plugin_succeed_with_valid_version_linux_test
download_grpc_plugin_succeed_with_valid_version_macos_test
download_grpc_plugin_failed_with_invalid_version_linux_test
Expand Down
6 changes: 3 additions & 3 deletions library_generation/test/model/generation_config_unit_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,20 @@ def test_generation_config_default_value(self):
def test_generation_config_with_generator_version_env_raise_exception(self):
self.assertRaisesRegex(
ValueError,
"Environment variable GENERATOR_VERSION is not set",
"the fall-back env var DOCKER_GAPIC_GENERATOR_VERSION was not found",
GenerationConfig,
googleapis_commitish="",
libraries=[],
)

def test_generation_config_set_generator_version_from_env(self):
os.environ["GENERATOR_VERSION"] = "1.2.3"
os.environ["DOCKER_GAPIC_GENERATOR_VERSION"] = "1.2.3"
config = GenerationConfig(
googleapis_commitish="",
libraries=[],
)
self.assertEqual("1.2.3", config.gapic_generator_version)
os.environ.pop("GENERATOR_VERSION")
os.environ.pop("DOCKER_GAPIC_GENERATOR_VERSION")

def test_from_yaml_succeeds(self):
config = from_yaml(f"{test_config_dir}/generation_config.yaml")
Expand Down
2 changes: 1 addition & 1 deletion library_generation/test/test_utilities.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ __test_failed() {
}


############# Functions used in test execution #############
############# Functions used in test execution. They can only be called once per test #############

assertEquals() {
local expected=$1
Expand Down
14 changes: 13 additions & 1 deletion library_generation/utils/utilities.sh
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ download_tools() {
local grpc_version=$3
local os_architecture=$4
pushd "${output_folder}"
download_generator_artifact "${gapic_generator_version}" "gapic-generator-java-${gapic_generator_version}.jar"
diegomarquezp marked this conversation as resolved.
Show resolved Hide resolved

# the variable protoc_path is used in generate_library.sh. It is explicitly
# exported to make clear that it is used outside this utilities file.
Expand All @@ -179,6 +178,19 @@ download_tools() {
export grpc_path=$(download_grpc_plugin "${grpc_version}" "${os_architecture}")
fi

# similar case with gapic-generator-java
if [[ "${DOCKER_GAPIC_GENERATOR_VERSION}" == "${gapic_generator_version}" ]]; then
# if the specified gapic_generator_version matches the one baked in the docker
# container, we copy the generator jar into the output folder so it can be
# picked up by gapic-generator-java-wrapper
>&2 echo "Using gapic-generator-java version baked into the container: ${DOCKER_GAPIC_GENERATOR_VERSION}"
cp "${DOCKER_GAPIC_GENERATOR_LOCATION}" "${output_folder}"
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 this copy logic might already be covered here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I decided to not follow the .m2 folder structure in favor of easier testing (https://github.com/googleapis/sdk-platform-java/pull/3067/files#r1698944411). I think it's ok to treat this baked-in jar as a special case outside of .m2?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I see. Yes it's definitely OK to put it into a different location, as long as we don't use maven to retrieve it. Let's see if we can get rid of gapic_generator_version so that we don't need this whole block.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we just use the jar as it is without copying? Is it for gapic-generator-java-wrapper?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The wrapper assumes the jar to be in CWD

exec java -classpath "gapic-generator-java-${gapic_generator_version}.jar" com.google.api.generator.Main

I'm not sure if we can both avoid copying the jar and at the same time not have a DOCKER_GAPIC_GENERATOR_LOCATION variable. We need a way to know where the jar is and make it compatible with local development as well.

Maybe we can copy the jar directly into the home .m2 folder? We would still be copying it just like we've been doing so far.

else
download_generator_artifact \
"${gapic_generator_version}" \
"gapic-generator-java-${gapic_generator_version}.jar"
fi

popd
}

Expand Down
Loading