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

chore: add docker image for hermetic build scripts #2493

Merged
merged 54 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
683c31f
feat: add docker image for `library_generation` scripts
diegomarquezp Feb 8, 2024
5807d4e
add initial dockerfile
diegomarquezp Feb 8, 2024
d4cc19a
mark integration_tests.py as executable
diegomarquezp Feb 8, 2024
a5f3c8e
add dockerignore, improve dockerfile
diegomarquezp Feb 13, 2024
6ca4360
install more utils for scripts
diegomarquezp Feb 13, 2024
7e111b2
install more dependencies for docker image
diegomarquezp Feb 14, 2024
80d73ee
use is_monorepo to compute path to owlbot yaml
diegomarquezp Feb 14, 2024
1988bc5
Merge remote-tracking branch 'origin/main' into library-generation-do…
diegomarquezp Feb 14, 2024
f096c3c
allow mounting volumes via env vars
diegomarquezp Feb 16, 2024
bd81ca2
use `python` instead of `python3`
diegomarquezp Feb 16, 2024
24b591b
use ptyhon 3.11, install maven
diegomarquezp Feb 16, 2024
6880df9
properly install pip
diegomarquezp Feb 16, 2024
9c82bec
Revert "use `python` instead of `python3`"
diegomarquezp Feb 16, 2024
76965c2
fix symbolic link to python3
diegomarquezp Feb 16, 2024
bb95d9c
restore postprocess_library
diegomarquezp Feb 16, 2024
6ffde65
Merge remote-tracking branch 'origin/main' into library-generation-do…
diegomarquezp Feb 16, 2024
73ae31c
remove debug prints
diegomarquezp Feb 16, 2024
46ea110
remove debug print 2
diegomarquezp Feb 16, 2024
720d5f0
fix comment
diegomarquezp Feb 16, 2024
e622ccb
initial cloudbuild config
diegomarquezp Feb 20, 2024
b28fd30
move dockerfile to .cloudbuild
diegomarquezp Feb 20, 2024
70c5d82
restore run.sh
diegomarquezp Feb 20, 2024
5cbcdc6
adapt integration test for docker image
diegomarquezp Feb 20, 2024
ee1d5fd
fix typo in cloudbuild definition
diegomarquezp Feb 20, 2024
f6e73ae
add container IT script
diegomarquezp Feb 20, 2024
f39cb82
format source
diegomarquezp Feb 20, 2024
c7e30eb
Merge branch 'main' into library-generation-docker-image
diegomarquezp Feb 20, 2024
6c43da9
fix cloudbuild entrypoint
diegomarquezp Feb 20, 2024
f9894ba
Merge branch 'library-generation-docker-image-2' into library-generat…
diegomarquezp Feb 20, 2024
3671aeb
fix entrypoint for cloudbuild file
diegomarquezp Feb 20, 2024
5ab1d90
conditional volume removal
diegomarquezp Feb 20, 2024
a14f407
correct volume removal condition
diegomarquezp Feb 20, 2024
91cc061
do not use interactive mode
diegomarquezp Feb 20, 2024
60fd188
add image publishing to cloudbuild release yaml
diegomarquezp Feb 20, 2024
ade90e4
fix dockerfile year
diegomarquezp Feb 20, 2024
77214c6
move pull logic to its corresponding function
diegomarquezp Feb 20, 2024
ed45a9c
lint
diegomarquezp Feb 20, 2024
fbf133b
try with updated google-cloud-java test branch
diegomarquezp Feb 21, 2024
19f75f9
remove xtrace from postprocess library
diegomarquezp Feb 21, 2024
460ded2
Update library_generation/test/integration_tests.py
diegomarquezp Feb 21, 2024
53d1fe4
Update library_generation/test/integration_tests.py
diegomarquezp Feb 21, 2024
fa23a3c
Merge remote-tracking branch 'origin/library-generation-docker-image'…
diegomarquezp Feb 21, 2024
fbcf12e
use better variable names in IT
diegomarquezp Feb 21, 2024
0af136c
link a source of docker volumes comment
diegomarquezp Feb 21, 2024
e204536
fix variable name in IT
diegomarquezp Feb 21, 2024
8029dc2
lint
diegomarquezp Feb 21, 2024
d26c5da
add release cloudbuild yaml for library generation
diegomarquezp Feb 21, 2024
6248c2d
add comments for volume creationg
diegomarquezp Feb 24, 2024
2717c54
pass image_id as an argument from within cloudbuild
diegomarquezp Feb 24, 2024
c253f8d
remove quotes from tag id
diegomarquezp Feb 24, 2024
ad79348
correct quotes in image id
diegomarquezp Feb 24, 2024
a4bf286
use commit hash as image id version
diegomarquezp Feb 24, 2024
6ff386c
push both `latest` and `commit_sha` images
diegomarquezp Feb 24, 2024
dc520fb
Merge remote-tracking branch 'origin/main' into library-generation-do…
diegomarquezp Feb 24, 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
31 changes: 31 additions & 0 deletions .cloudbuild/cloudbuild-test-library-generation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright 2024 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
#
# http://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.

timeout: 7200s # 2 hours
substitutions:
_SHARED_DEPENDENCIES_VERSION: '3.25.1-SNAPSHOT' # {x-version-update:google-cloud-shared-dependencies:current}

steps:
# Library generation build
- name: gcr.io/cloud-builders/docker
args: ["build", "-t", "gcr.io/cloud-devrel-public-resources/java-library-generation:${_SHARED_DEPENDENCIES_VERSION}", "--file", ".cloudbuild/library_generation.Dockerfile", "."]
id: library-generation-build
waitFor: ["-"]
- name: gcr.io/cloud-devrel-public-resources/java-library-generation:${_SHARED_DEPENDENCIES_VERSION}
entrypoint: bash
args: [ './library_generation/test/container_integration_tests.sh' ]
waitFor: [ "library-generation-build" ]
env:
- 'SHARED_DEPENDENCIES_VERSION=${_SHARED_DEPENDENCIES_VERSION}'

7 changes: 7 additions & 0 deletions .cloudbuild/cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@ steps:
id: graalvm-b-build
waitFor: [ "-" ]

# Library generation build
- name: gcr.io/cloud-builders/docker
args: ["build", "-t", "gcr.io/cloud-devrel-public-resources/java-library-generation:${_SHARED_DEPENDENCIES_VERSION}", "--file", ".cloudbuild/library_generation.Dockerfile", "."]
id: library-generation-build
waitFor: ["-"]


images:
- gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:${_SHARED_DEPENDENCIES_VERSION}
- gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:${_SHARED_DEPENDENCIES_VERSION}
- gcr.io/cloud-devrel-public-resources/java-library-generation:${_SHARED_DEPENDENCIES_VERSION}
40 changes: 40 additions & 0 deletions .cloudbuild/library_generation.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright 2024 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.

# build from the root of this repo:
FROM gcr.io/cloud-devrel-public-resources/python

# install tools
RUN apt-get update && apt-get install -y \
unzip openjdk-17-jdk rsync maven \
&& apt-get clean

COPY library_generation /src

RUN rm $(which python3)
RUN ln -s $(which python3.11) /usr/local/bin/python
RUN ln -s $(which python3.11) /usr/local/bin/python3
diegomarquezp marked this conversation as resolved.
Show resolved Hide resolved
RUN python -m pip install --upgrade pip
RUN cd /src && python -m pip install -r requirements.in
RUN cd /src && python -m pip install .

# set dummy git credentials for empty commit used in postprocessing
RUN git config --global user.email "cloud-java-bot@google.com"
RUN git config --global user.name "Cloud Java Bot"

WORKDIR /workspace
RUN chmod 750 /workspace
RUN chmod 750 /src/generate_repo.py

CMD [ "/src/generate_repo.py" ]
6 changes: 6 additions & 0 deletions library_generation/dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
README.md
**/__pycache__/
**/*.egg-info/
**/output/
**/build/
**/google-cloud-java/
Empty file modified library_generation/generate_repo.py
100644 → 100755
Empty file.
37 changes: 32 additions & 5 deletions library_generation/postprocess_library.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,48 @@ fi

# we determine the location of the .OwlBot.yaml file by checking if the target
# folder is a monorepo folder or not
if [[ "${postprocessing_target}" == *google-cloud-java* ]]; then
if [[ "${is_monorepo}" == "true" ]]; then
owlbot_yaml_relative_path=".OwlBot.yaml"
else
owlbot_yaml_relative_path=".github/.OwlBot.yaml"
fi

# Default values for running copy-code directly from host
repo_binding="${postprocessing_target}"
repo_workspace="/repo"
preprocessed_libraries_binding="${owlbot_cli_source_folder}"

# When running docker inside docker, we run into the issue of volume bindings
# being mapped from the host machine to the child container (instead of the
# parent container to child container) because we bind the `docker.sock` socket
# to the parent container (i.e. docker calls use the host's filesystem context)
# see https://serverfault.com/a/819371
# We solve this by referencing environment variables that will be
# set to produce the correct volume mapping.
diegomarquezp marked this conversation as resolved.
Show resolved Hide resolved
#
# The workflow is: to check if we are in a docker container (via passed env var)
# and use managed volumes (docker volume create) instead of bindings
# (-v /path:/other-path). The volume names are also received as env vars.

if [[ -n "${RUNNING_IN_DOCKER}" ]]; then
set -u # temporarily fail on unset variables
repo_binding="${REPO_BINDING_VOLUME}"
set +u
if [[ "${is_monorepo}" == "true" ]]; then
repo_workspace="/repo/$(echo "${postprocessing_target}" | rev | cut -d'/' -f1 | rev)"
fi
fi

docker run --rm \
--user "$(id -u)":"$(id -g)" \
-v "${postprocessing_target}:/repo" \
-v "${owlbot_cli_source_folder}:/pre-processed-libraries" \
-w /repo \
-v "${repo_binding}:/repo" \
-v "/tmp:/tmp" \
-w "${repo_workspace}" \
--env HOME=/tmp \
gcr.io/cloud-devrel-public-resources/owlbot-cli@"${owlbot_cli_image_sha}" \
copy-code \
--source-repo-commit-hash=none \
--source-repo=/pre-processed-libraries \
--source-repo="${preprocessed_libraries_binding}" \
--config-file="${owlbot_yaml_relative_path}"

# we clone the synthtool library and manually build it
Expand All @@ -86,6 +112,7 @@ pushd /tmp/synthtool
if [ ! -d "synthtool" ]; then
git clone https://github.com/googleapis/synthtool.git
fi
git config --global --add safe.directory /tmp/synthtool/synthtool
pushd "synthtool"

git reset --hard "${synthtool_commitish}"
Expand Down
Empty file modified library_generation/setup.py
100644 → 100755
Empty file.
31 changes: 31 additions & 0 deletions library_generation/test/container_integration_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
# This is a wrapper of integration_tests.py that sets up the environment to run
# the script in a docker container

set -xe
if [[ -z "${SHARED_DEPENDENCIES_VERSION}" ]]; then
echo "required environemnt variable SHARED_DEPENDENCIES_VERSION is not set"
exit 1
fi

if [[ ! -d google-cloud-java ]]; then
git clone https://github.com/googleapis/google-cloud-java
fi
pushd google-cloud-java
git reset --hard main
popd
if [[ $(docker volume inspect repo) != '[]' ]]; then
docker volume rm repo
fi
docker volume create --name "repo" --opt "type=none" --opt "device=$(pwd)/google-cloud-java" --opt "o=bind"
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Since this requires a bit of docker-specific knowledge, perhaps we can add a quick comment explaining what we're trying to do 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.

Added a comment explaining why we create this volume


image_id="gcr.io/cloud-devrel-public-resources/java-library-generation:${SHARED_DEPENDENCIES_VERSION}"
Copy link
Contributor

Choose a reason for hiding this comment

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

How about we pass this in as an argument to the script? In case the image id changes in the future (or if we pick a different project), it can all be changes in a single location in the cloudbuild yaml file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good. I added IMAGE_ID as a passed env var

docker run --rm \
-v repo:/workspace \
-v /tmp:/tmp \
-v /var/run/docker.sock:/var/run/docker.sock \
-e "RUNNING_IN_DOCKER=true" \
-e "REPO_BINDING_VOLUME=repo" \
-w "/src" \
"${image_id}" \
python -m unittest /src/test/integration_tests.py
35 changes: 28 additions & 7 deletions library_generation/test/integration_tests.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from library_generation.generate_repo import generate_from_yaml
from library_generation.model.generation_config import from_yaml
from library_generation.test.compare_poms import compare_xml
from library_generation.utilities import get_library_name
from library_generation.utilities import get_library_name, run_process_and_print_output

config_name = "generation_config.yaml"
script_dir = os.path.dirname(os.path.realpath(__file__))
Expand All @@ -46,8 +46,9 @@ def test_generate_repo(self):
config_files = self.__get_config_files(config_dir)
i = 0
for repo, config_file in config_files.items():
repo_dest = f"{golden_dir}/{repo}"
self.__pull_repo_to(Path(repo_dest), repo, committish_list[i])
repo_dest = self.__pull_repo_to(
Path(f"{golden_dir}/{repo}"), repo, committish_list[i]
)
library_names = self.__get_library_names_from_config(config_file)
# prepare golden files
for library_name in library_names:
Expand Down Expand Up @@ -106,11 +107,31 @@ def test_generate_repo(self):
i += 1

@classmethod
def __pull_repo_to(cls, dest: Path, repo: str, committish: str):
repo_url = f"{repo_prefix}/{repo}"
print(f"Cloning repository {repo_url}")
repo = Repo.clone_from(repo_url, dest)
def __pull_repo_to(cls, default_dest: Path, repo: str, committish: str) -> str:
if "RUNNING_IN_DOCKER" in os.environ:
# the docker image expects the repo to be in /workspace
dest_in_docker = "/workspace"
run_process_and_print_output(
[
"git",
"config",
"--global",
"--add",
"safe.directory",
dest_in_docker,
],
"Add /workspace to safe directories",
)
dest = Path(dest_in_docker)
repo = Repo(dest)
diegomarquezp marked this conversation as resolved.
Show resolved Hide resolved
else:
dest = default_dest
repo_dest = f"{golden_dir}/{repo}"
repo_url = f"{repo_prefix}/{repo}"
print(f"Cloning repository {repo_url}")
repo = Repo.clone_from(repo_url, dest)
repo.git.checkout(committish)
return str(dest)

@classmethod
def __get_library_names_from_config(cls, config_path: str) -> List[str]:
Expand Down
Loading