From c457eb2c1317870faabab129d3139ed150d949a8 Mon Sep 17 00:00:00 2001 From: diegomarquezp Date: Sun, 12 May 2024 22:57:13 +0000 Subject: [PATCH] chore: centralize hermetic build workflow implementations --- library_generation/workflow_scripts/README.md | 5 + .../hermetic_library_generation.sh | 115 ++++++++++++++++++ .../update_googleapis_committish.sh | 88 ++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 library_generation/workflow_scripts/README.md create mode 100644 library_generation/workflow_scripts/hermetic_library_generation.sh create mode 100644 library_generation/workflow_scripts/update_googleapis_committish.sh diff --git a/library_generation/workflow_scripts/README.md b/library_generation/workflow_scripts/README.md new file mode 100644 index 0000000000..9e586bf79d --- /dev/null +++ b/library_generation/workflow_scripts/README.md @@ -0,0 +1,5 @@ +This folder contains the implementations of GH actions that use the hermetic +build scripts. We centralize them here so we can reference the workflows +(defined in sdk-platform-java/.github/workflows) from other repos (e.g. +google-cloud-java, java-bigtable) without having to copy the implementations in +each one. diff --git a/library_generation/workflow_scripts/hermetic_library_generation.sh b/library_generation/workflow_scripts/hermetic_library_generation.sh new file mode 100644 index 0000000000..0d1f8e48a7 --- /dev/null +++ b/library_generation/workflow_scripts/hermetic_library_generation.sh @@ -0,0 +1,115 @@ +#!/bin/bash +# This script should be run at the root of the repository. +# This script will perform the following actionswhen 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 the 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 the 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. image_tag, the tag of gcr.io/cloud-devrel-public-resources/java-library-generation. +# 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 + ;; + --image_tag) + image_tag="$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 "${image_tag}" ]; then + echo "missing required argument --image_tag" + exit 1 +fi + +if [ -z "${generation_config}" ]; then + generation_config=generation_config.yaml + echo "Use 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. +contains_config_change=$(git diff-tree --no-commit-id --name-only HEAD~1..HEAD -r | grep "${generation_config}") +if [[ "${contains_config_change}" == "" ]]; then + echo "The last commit doesn't contain any changes to the generation_config.yaml, skipping the whole generation process." + 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}") + +# 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. +git add java-* pom.xml gapic-libraries-bom/pom.xml versions.txt +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 diff --git a/library_generation/workflow_scripts/update_googleapis_committish.sh b/library_generation/workflow_scripts/update_googleapis_committish.sh new file mode 100644 index 0000000000..8ee5d93dfe --- /dev/null +++ b/library_generation/workflow_scripts/update_googleapis_committish.sh @@ -0,0 +1,88 @@ +#!/bin/bash +set -e +# This script should be run at the root of the repository. +# This script is used to update the googleapis committish found in +# generation_config.yaml to the latest one and create a pull request. + +# The following commands need to be installed before running the script: +# 1. git +# 2. gh + +# 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 googleapis commit 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 +sed -i -e "s/^googleapis_commitish.*$/googleapis_commitish: ${latest_commit}/" "${generation_config}" + + +git add "${generation_config}" +# use --allow-empty because (rarely) there's no change. +git commit --allow-empty -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 +fi