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: enable hermetic library generation #2234

Merged
merged 35 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7093757
feat: enable hermetic library generation
diegomarquezp May 15, 2024
839e2ec
add generation config
diegomarquezp May 15, 2024
1418fb6
fix script reference
diegomarquezp May 15, 2024
9afb973
rename scripts
diegomarquezp May 15, 2024
a6aee82
enclose @ string with quotes
diegomarquezp May 15, 2024
958200f
use committish instead of commit
diegomarquezp May 15, 2024
55a4e6b
add api_description
diegomarquezp May 15, 2024
f15a24d
fix logic for staging files in git
diegomarquezp May 15, 2024
98752d9
fix repo name inference
diegomarquezp May 15, 2024
ff99176
infer ggj version from config yaml
diegomarquezp May 23, 2024
fe4cbb1
use test committish
diegomarquezp May 23, 2024
5e10ae4
rename .OwlBot to .OwlBot-hermetic
diegomarquezp May 23, 2024
9fbff0c
update ggj version
diegomarquezp May 23, 2024
a1dd67e
fix config
diegomarquezp May 23, 2024
d1c3a2c
map host .m2 folder
diegomarquezp May 23, 2024
86a532a
do not map runner's home folder
diegomarquezp May 28, 2024
cbd27c4
preserve PR description file
diegomarquezp May 29, 2024
dc627c0
Merge branch 'main' of https://github.com/diegomarquezp/java-bigtable
diegomarquezp May 29, 2024
82e44ad
preserve pr_description
diegomarquezp May 29, 2024
a286520
update code generator
diegomarquezp Jun 4, 2024
9ee5c70
Merge branch 'main' of https://github.com/diegomarquezp/java-bigtable
diegomarquezp Jun 4, 2024
a6f91f1
fix protoc_version
diegomarquezp Jun 10, 2024
e8a4f24
replicate image_tag logic of google-cloud-java
diegomarquezp Jun 12, 2024
805dcf8
correct workflow name
diegomarquezp Jun 12, 2024
793a6b0
update generation scripts and yamls
diegomarquezp Jun 12, 2024
895d41a
fix paths and typo
diegomarquezp Jun 25, 2024
c6e9bb2
use single quotes in codeowner_team
diegomarquezp Jun 26, 2024
be6a2a3
update generator version
diegomarquezp Jun 26, 2024
12b74fd
correct path to scripts
diegomarquezp Jul 2, 2024
3efcb13
skip prs from forks
diegomarquezp Jul 2, 2024
31307dc
Merge remote-tracking branch 'googleapis/main'
diegomarquezp Jul 18, 2024
2da0108
update generation_config to latest values
diegomarquezp Aug 15, 2024
4b37e2c
secure workflow
diegomarquezp Aug 16, 2024
8304d36
add logging and exit on fail, remove protoc version
diegomarquezp Aug 19, 2024
9bcc2f6
🦉 Updates from OwlBot post-processor
gcf-owl-bot[bot] Aug 19, 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
File renamed without changes.
117 changes: 117 additions & 0 deletions .github/scripts/hermetic_library_generation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/bin/bash
set -e
# This script should be run at the root of the repository.
# This script is used to, when a pull request changes the generation
# configuration (generation_config.yaml by default):
# 1. Find whether the last commit in this pull request contains changes to
# the generation configuration and exit early if it doesn't have such a change
# since the generation result would be the same.
# 2. Compare generation configurations in the current branch (with which the
# pull request associated) and target branch (into which the pull request is
# merged);
# 3. Generate changed libraries using library_generation image;
# 4. Commit the changes to the pull request, if any.
# 5. Edit the PR body with generated pull request description, if applicable.

# The following commands need to be installed before running the script:
# 1. git
# 2. gh
# 3. docker

# The parameters of this script is:
# 1. target_branch, the branch into which the pull request is merged.
# 2. current_branch, the branch with which the pull request is associated.
# 3. [optional] generation_config, the path to the generation configuration,
# the default value is generation_config.yaml in the repository root.
while [[ $# -gt 0 ]]; do
key="$1"
case "${key}" in
--target_branch)
target_branch="$2"
shift
;;
--current_branch)
current_branch="$2"
shift
;;
--generation_config)
generation_config="$2"
shift
;;
*)
echo "Invalid option: [$1]"
exit 1
;;
esac
shift
done

if [ -z "${target_branch}" ]; then
echo "missing required argument --target_branch"
exit 1
fi

if [ -z "${current_branch}" ]; then
echo "missing required argument --current_branch"
exit 1
fi

if [ -z "${generation_config}" ]; then
generation_config=generation_config.yaml
echo "Using default generation config: ${generation_config}"
fi

workspace_name="/workspace"
baseline_generation_config="baseline_generation_config.yaml"
message="chore: generate libraries at $(date)"

git checkout "${target_branch}"
git checkout "${current_branch}"
# if the last commit doesn't contain changes to generation configuration,
# do not generate again as the result will be the same.
change_of_last_commit="$(git diff-tree --no-commit-id --name-only HEAD~1..HEAD -r)"
if [[ ! ("${change_of_last_commit}" == *"${generation_config}"*) ]]; then
echo "The last commit doesn't contain any changes to the generation_config.yaml, skipping the whole generation process." || true
exit 0
fi
# copy generation configuration from target branch to current branch.
git show "${target_branch}":"${generation_config}" > "${baseline_generation_config}"
config_diff=$(diff "${generation_config}" "${baseline_generation_config}" || true)

# parse image tag from the generation configuration.
image_tag=$(grep "gapic_generator_version" "${generation_config}" | cut -d ':' -f 2 | xargs)

# run hermetic code generation docker image.
docker run \
--rm \
-u "$(id -u):$(id -g)" \
-v "$(pwd):${workspace_name}" \
gcr.io/cloud-devrel-public-resources/java-library-generation:"${image_tag}" \
--baseline-generation-config-path="${workspace_name}/${baseline_generation_config}" \
--current-generation-config-path="${workspace_name}/${generation_config}"


# commit the change to the pull request.
if [[ $(basename $(pwd)) == "google-cloud-java" ]]; then
git add java-* pom.xml gapic-libraries-bom/pom.xml versions.txt
else
# The image leaves intermediate folders and files it works with. Here we remove them
rm -rdf output googleapis "${baseline_generation_config}"
git add --all -- ':!pr_description.txt'
fi
changed_files=$(git diff --cached --name-only)
if [[ "${changed_files}" == "" ]]; then
echo "There is no generated code change with the generation config change ${config_diff}."
echo "Skip committing to the pull request."
exit 0
fi

echo "Configuration diff:"
echo "${config_diff}"
git commit -m "${message}"
git push
# set pr body if pr_description.txt is generated.
if [[ -f "pr_description.txt" ]]; then
pr_num=$(gh pr list -s open -H "${current_branch}" -q . --json number | jq ".[] | .number")
gh pr edit "${pr_num}" --body "$(cat pr_description.txt)"
fi
121 changes: 121 additions & 0 deletions .github/scripts/update_generation_config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/bin/bash
set -e
# This script should be run at the root of the repository.
# This script is used to update googleapis_commitish, gapic_generator_version,
# and libraries_bom_version in generation configuration at the time of running
# and create a pull request.

# The following commands need to be installed before running the script:
# 1. git
# 2. gh
# 3. jq

Copy link
Contributor

Choose a reason for hiding this comment

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

can you either add logging which commitish this processing? or at least set -x?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

# Utility functions
# Get the latest released version of a Maven artifact.
function get_latest_released_version() {
local group_id=$1
local artifact_id=$2
latest=$(curl -s "https://search.maven.org/solrsearch/select?q=g:${group_id}+AND+a:${artifact_id}&core=gav&rows=500&wt=json" | jq -r '.response.docs[] | select(.v | test("^[0-9]+(\\.[0-9]+)*$")) | .v' | sort -V | tail -n 1)
echo "${latest}"
}

# Update a key to a new value in the generation config.
function update_config() {
local key_word=$1
local new_value=$2
local file=$3
echo "Update ${key_word} to ${new_value} in ${file}"
sed -i -e "s/^${key_word}.*$/${key_word}: ${new_value}/" "${file}"
}

# The parameters of this script is:
# 1. base_branch, the base branch of the result pull request.
# 2. repo, organization/repo-name, e.g., googleapis/google-cloud-java
# 3. [optional] generation_config, the path to the generation configuration,
# the default value is generation_config.yaml in the repository root.
while [[ $# -gt 0 ]]; do
key="$1"
case "${key}" in
--base_branch)
base_branch="$2"
shift
;;
--repo)
repo="$2"
shift
;;
--generation_config)
generation_config="$2"
shift
;;
*)
echo "Invalid option: [$1]"
exit 1
;;
esac
shift
done

if [ -z "${base_branch}" ]; then
echo "missing required argument --base_branch"
exit 1
fi

if [ -z "${repo}" ]; then
echo "missing required argument --repo"
exit 1
fi

if [ -z "${generation_config}" ]; then
generation_config="generation_config.yaml"
echo "Use default generation config: ${generation_config}"
fi

current_branch="generate-libraries-${base_branch}"
title="chore: Update generation configuration at $(date)"

# try to find a open pull request associated with the branch
pr_num=$(gh pr list -s open -H "${current_branch}" -q . --json number | jq ".[] | .number")
# create a branch if there's no open pull request associated with the
# branch; otherwise checkout the pull request.
if [ -z "${pr_num}" ]; then
git checkout -b "${current_branch}"
else
gh pr checkout "${pr_num}"
fi

mkdir tmp-googleapis
# use partial clone because only commit history is needed.
git clone --filter=blob:none https://github.com/googleapis/googleapis.git tmp-googleapis
pushd tmp-googleapis
git pull
latest_commit=$(git rev-parse HEAD)
popd
rm -rf tmp-googleapis
update_config "googleapis_commitish" "${latest_commit}" "${generation_config}"

# update gapic-generator-java version to the latest
latest_version=$(get_latest_released_version "com.google.api" "gapic-generator-java")
update_config "gapic_generator_version" "${latest_version}" "${generation_config}"

# update libraries-bom version to the latest
latest_version=$(get_latest_released_version "com.google.cloud" "libraries-bom")
update_config "libraries_bom_version" "${latest_version}" "${generation_config}"

git add "${generation_config}"
changed_files=$(git diff --cached --name-only)
if [[ "${changed_files}" == "" ]]; then
echo "The latest generation config is not changed."
echo "Skip committing to the pull request."
exit 0
fi
git commit -m "${title}"
if [ -z "${pr_num}" ]; then
git remote add remote_repo https://cloud-java-bot:"${GH_TOKEN}@github.com/${repo}.git"
git fetch -q --unshallow remote_repo
git push -f remote_repo "${current_branch}"
gh pr create --title "${title}" --head "${current_branch}" --body "${title}" --base "${base_branch}"
else
git push
gh pr edit "${pr_num}" --title "${title}" --body "${title}"
fi
43 changes: 43 additions & 0 deletions .github/workflows/hermetic_library_generation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# 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.
# GitHub action job to test core java library features on
# downstream client libraries before they are released.
name: Hermetic library generation upon generation config change through pull requests
on:
pull_request:

env:
HEAD_REF: ${{ github.head_ref }}

jobs:
library_generation:
# skip pull requests come from a forked repository
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }}
- name: Generate changed libraries
shell: bash
run: |
set -x
Copy link
Contributor

Choose a reason for hiding this comment

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

does this need a set -e?

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 -e

[ -z "$(git config user.email)" ] && git config --global user.email "[email protected]"
[ -z "$(git config user.name)" ] && git config --global user.name "cloud-java-bot"
bash .github/scripts/hermetic_library_generation.sh \
--target_branch ${{ github.base_ref }} \
--current_branch $HEAD_REF
env:
GH_TOKEN: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }}
42 changes: 42 additions & 0 deletions .github/workflows/update_generation_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# 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.
# GitHub action job to test core java library features on
# downstream client libraries before they are released.
name: Update generation configuration
on:
schedule:
- cron: '0 2 * * *'
workflow_dispatch:

jobs:
update-generation-config:
runs-on: ubuntu-22.04
env:
# the branch into which the pull request is merged
base_branch: main
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }}
- name: Update params in generation config to latest
shell: bash
run: |
set -x
Copy link
Contributor

Choose a reason for hiding this comment

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

does this need a set -e?

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 -e

[ -z "$(git config user.email)" ] && git config --global user.email "[email protected]"
[ -z "$(git config user.name)" ] && git config --global user.name "cloud-java-bot"
bash .github/scripts/update_generation_config.sh \
--base_branch "${base_branch}"\
--repo ${{ github.repository }}
env:
GH_TOKEN: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }}
37 changes: 37 additions & 0 deletions generation_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
protoc_version: '25.3'
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add a comment here and in the existing owl bot config that these are mirrors of each other?

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually protoc version is now baked into our docker image, @diegomarquezp can you please remove it to reflect the recent changes?

The protoc version used to come from the googleapis/WORKSPACE, which is shared by all languages. This is now configurable by Java.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

googleapis_commitish: c93b54fa3060c7185f6dc724f0f9ec0c12bc44fc
libraries_bom_version: 26.44.0
template_excludes:
- .gitignore
- .kokoro/presubmit/integration.cfg
- .kokoro/presubmit/graalvm-native.cfg
- .kokoro/presubmit/graalvm-native-17.cfg
- .kokoro/nightly/integration.cfg
- .kokoro/presubmit/samples.cfg
- .kokoro/nightly/samples.cfg
- .github/ISSUE_TEMPLATE/bug_report.md
- .github/PULL_REQUEST_TEMPLATE.md
- .github/trusted-contribution.yml
- CONTRIBUTING.md
- codecov.yaml
- .github/release-please.yml
- renovate.json
- .kokoro/requirements.in
- .kokoro/requirements.txt
libraries:
- api_shortname: bigtable
api_description: API for reading and writing the contents of Bigtables associated with a cloud project.
name_pretty: Cloud Bigtable
product_documentation: https://cloud.google.com/bigtable
client_documentation: https://cloud.google.com/java/docs/reference/google-cloud-bigtable/latest/history
issue_tracker: https://issuetracker.google.com/savedsearches/559777
release_level: stable
distribution_name: com.google.cloud:google-cloud-bigtable
codeowner_team: '@googleapis/api-bigtable @googleapis/api-bigtable-partners'
api_id: bigtable.googleapis.com
library_type: GAPIC_COMBO
extra_versioned_modules: google-cloud-bigtable-emulator,google-cloud-bigtable-emulator-core
excluded_poms: google-cloud-bigtable-bom
GAPICs:
- proto_path: google/bigtable/v2
- proto_path: google/bigtable/admin/v2
Loading