Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
96 changes: 57 additions & 39 deletions .kokoro/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,53 +90,56 @@ function retry_with_backoff {
# and naturally survives single-module components without throwing exit signals.
function extract_pom_modules() {
local pom_file="$1"
local modules_list=""
if [[ ! -f "${pom_file}" ]]; then
return 1
fi
local line module
local in_profiles=false
local in_modules=false

while IFS= read -r line || [ -n "$line" ]; do
if [[ "$line" == *"<profiles>"* ]]; then
local -a modules=()

while IFS= read -r line || [[ -n "${line}" ]]; do
if [[ "${line}" == *"<profiles>"* ]]; then
in_profiles=true
elif [[ "$line" == *"</profiles>"* ]]; then
elif [[ "${line}" == *"</profiles>"* ]]; then
in_profiles=false
elif [[ "$line" == *"<modules>"* ]] && [ "$in_profiles" = false ]; then
elif [[ "${line}" == *"<modules>"* && "${in_profiles}" == "false" ]]; then
in_modules=true
elif [[ "$line" == *"</modules>"* ]] && [ "$in_profiles" = false ]; then
elif [[ "${line}" == *"</modules>"* && "${in_profiles}" == "false" ]]; then
in_modules=false
break
elif [ "$in_modules" = true ] && [[ "$line" == *"<module>"* ]]; then
elif [[ "${in_modules}" == "true" && "${line}" == *"<module>"* ]]; then
# Extract text between tags
local module="${line#*<module>}"
module="${line#*<module>}"
module="${module%</module>*}"
# Trim whitespace natively

# Trim leading/trailing whitespace without spawning external processes
module="${module#"${module%%[![:space:]]*}"}"
module="${module%"${module##*[![:space:]]}"}"

if [ -z "$modules_list" ]; then
modules_list="$module"
else
modules_list="${modules_list} ${module}"

if [[ -n "${module}" ]]; then
modules+=("${module}")
fi
fi
done < "$pom_file"
echo "$modules_list"
done < "${pom_file}"

echo "${modules[*]}"
}

# Given a folder containing a maven multi-module, assign the variable 'submodules' to a
# comma-delimited list of <folder>/<submodule>.
function parse_submodules() {
submodules_array=()
if [ -f "$1/pom.xml" ]; then
if [[ -f "$1/pom.xml" ]]; then
local modules
local submodule

# Use pure Bash extraction to find the modules in the aggregator pom file.
# Faster than invoking mvn help:evaluate to list all the project modules,
# cleanly ignores optional <profiles>, and gracefully skips flat POMs.
modules=$(extract_pom_modules "$1/pom.xml")
if [ -n "$modules" ]; then
for submodule in $modules; do
if [[ -n "${modules}" ]]; then
for submodule in ${modules}; do
# Each entry = <folder>/<submodule>
submodules_array+=("$1/${submodule}")
done
Expand Down Expand Up @@ -285,39 +288,54 @@ function generate_modified_modules_list() {
files=$(get_modified_files)
printf "Modified files:\n%s\n" "${files}"

# Generate the list of valid maven modules
maven_modules_list=$(mvn help:evaluate -Dexpression=project.modules | grep '<.*>.*</.*>' | sed -e 's/<.*>\(.*\)<\/.*>/\1/g')
# Extract valid maven modules directly from pom.xml in pure Bash (~0.02s).
# This replaces 'mvn help:evaluate -Dexpression=project.modules' which previously
# spent 20-30+ seconds booting a JVM and evaluating the monorepo POMs on every run.
local root_pom="${commonScriptDir}/../pom.xml"
if [[ ! -f "${root_pom}" ]]; then
root_pom="pom.xml"
fi
local maven_modules_list
maven_modules_list=$(extract_pom_modules "${root_pom}")
maven_modules=()

# If the first argument is "true" (default), then use the module exclusion list
use_exclusion_list=${1:-true}
# Positional parameter $1 specifies whether to apply the exclusion list (defaults to true).
local use_exclusion_list="${1:-true}"
local -a all_modules=()
read -r -a all_modules <<< "${maven_modules_list}"

local module
if [[ "${use_exclusion_list}" == "true" ]]; then
echo "Excluding modules from the global exclusion list"
for module in $maven_modules_list; do
if [[ ! " ${excluded_modules[*]} " =~ " ${module} " ]]; then
for module in "${all_modules[@]}"; do
if [[ ! " ${excluded_modules[*]} " == *" ${module} "* ]]; then
maven_modules+=("${module}")
fi
done
else
maven_modules=(${maven_modules_list[*]})
maven_modules=("${all_modules[@]}")
fi

modified_module_list=()
# If either parent pom.xml or core shared dependency is touched, run ITs on all the modules
if should_test_all_modules; then
modified_module_list=(${maven_modules[*]})
# '("${maven_modules[@]}")' copies the array elements safely.
modified_module_list=("${maven_modules[@]}")
echo "Testing the entire monorepo"
else
modules=$(echo "${files}" | grep -E '(google-auth|java)-.*' || true)
# Extract the top-level directory from each modified file path:
# 'cut -d '/' -f1' takes the first path segment (e.g. 'java-bigquery/src/...' -> 'java-bigquery').
# 'sort -u' sorts and deduplicates the candidate directory names.
local modules
modules=$(cut -d '/' -f1 <<< "${files}" | sort -u)
printf "Files in java modules:\n%s\n" "${modules}"
if [[ -n $modules ]]; then
modules=$(echo "${modules}" | cut -d '/' -f1 | sort -u)
for module in $modules; do
if [[ " ${maven_modules[*]} " =~ " ${module} " ]]; then
modified_module_list+=("${module}")
fi
done
else
for module in ${modules}; do
# If this top-level directory is a recognized Maven module, add it to our list.
if [[ " ${maven_modules[*]} " == *" ${module} "* ]]; then
modified_module_list+=("${module}")
fi
done
if [[ ${#modified_module_list[@]} -eq 0 ]]; then
echo "Found no changes in the java modules"
fi

Expand Down
106 changes: 106 additions & 0 deletions .kokoro/common_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,35 @@ function test_parse_pom_version {
popd
}

# Test that extract_pom_modules correctly extracts modules from root pom.xml
# in pure Bash without launching Maven, and handles non-existent files safely.
function test_extract_pom_modules {
local -a modules
read -r -a modules <<< "$(extract_pom_modules "${scriptDir}/../pom.xml")"
if (( ${#modules[@]} < 200 )); then
echo "extract_pom_modules failed: expected at least 200 modules, got ${#modules[@]}"
exit 1
fi
if [[ ! " ${modules[*]} " =~ " java-bigquery " ]]; then
echo "extract_pom_modules missing java-bigquery"
exit 1
fi
if [[ ! " ${modules[*]} " =~ " java-bigquerystorage " ]]; then
echo "extract_pom_modules missing java-bigquerystorage"
exit 1
fi
if [[ ! " ${modules[*]} " =~ " sdk-platform-java " ]]; then
echo "extract_pom_modules missing sdk-platform-java"
exit 1
fi

# Verify non-existent file returns 1 and empty output
if extract_pom_modules "non_existent_pom.xml" &>/dev/null; then
echo "extract_pom_modules should return non-zero for non-existent pom"
exit 1
fi
}

# Tests that is_module_modified strictly matches the module directory prefix,
# preventing prefix collisions (e.g. java-bigquery vs java-bigquerystorage).
function test_is_module_modified {
Expand Down Expand Up @@ -308,10 +337,87 @@ function test_mock_get_modified_files {
unset TEST_MODIFIED_FILES
}

# Test that parse_submodules expands multi-module directories to child modules
# and preserves single-module/flat components.
function test_parse_submodules {
pushd "${scriptDir}/.." >/dev/null

parse_submodules "java-bigquery"
if [[ "${submodules}" != "java-bigquery/google-cloud-bigquery,java-bigquery/google-cloud-bigquery-bom" ]]; then
echo "parse_submodules failed for java-bigquery: got ${submodules}"
exit 1
fi

parse_submodules "google-cloud-jar-parent"
if [[ "${submodules}" != "google-cloud-jar-parent" ]]; then
echo "parse_submodules failed for google-cloud-jar-parent: got ${submodules}"
exit 1
fi

popd >/dev/null
}

# Test that generate_modified_modules_list correctly maps modified files to
# their top-level module names without requiring mvn help:evaluate, and verifies
# both exclusion list enabled (default) and disabled modes.
function test_generate_modified_modules_list {
pushd "${scriptDir}/.." >/dev/null
TEST_MODIFIED_FILES="java-bigquery/google-cloud-bigquery/src/main/java/Foo.java
java-asset/google-cloud-asset/pom.xml"
generate_modified_modules_list false >/dev/null

local has_bigquery="false"
local has_asset="false"
local has_bigquerystorage="false"

if [[ " ${modified_module_list[*]} " =~ " java-bigquery " ]]; then
has_bigquery="true"
fi
if [[ " ${modified_module_list[*]} " =~ " java-asset " ]]; then
has_asset="true"
fi
if [[ " ${modified_module_list[*]} " =~ " java-bigquerystorage " ]]; then
has_bigquerystorage="true"
fi

if [[ "${has_bigquery}" != "true" ]]; then
echo "generate_modified_modules_list missing java-bigquery"
exit 1
fi
if [[ "${has_asset}" != "true" ]]; then
echo "generate_modified_modules_list missing java-asset"
exit 1
fi
if [[ "${has_bigquerystorage}" == "true" ]]; then
echo "generate_modified_modules_list incorrectly included java-bigquerystorage"
exit 1
fi

# Test default exclusion list behavior: java-bigquery is excluded, while java-asset is included
TEST_MODIFIED_FILES="java-asset/google-cloud-asset/Foo.java
java-bigquery/google-cloud-bigquery/Bar.java"
generate_modified_modules_list true >/dev/null

if [[ " ${modified_module_list[*]} " =~ " java-bigquery " ]]; then
echo "generate_modified_modules_list should exclude java-bigquery when exclusion list is true"
exit 1
fi
if [[ ! " ${modified_module_list[*]} " =~ " java-asset " ]]; then
echo "generate_modified_modules_list missing java-asset when exclusion list is true"
exit 1
fi

popd >/dev/null
unset TEST_MODIFIED_FILES
}

test_find_all_poms_with_versioned_dependency
test_update_pom_dependency
test_parse_pom_version
test_mock_get_modified_files
test_extract_pom_modules
test_parse_submodules
test_should_test_all_modules
test_is_module_modified
test_is_upstream_module_modified
test_generate_modified_modules_list
22 changes: 17 additions & 5 deletions .kokoro/presubmit/downstream-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,26 @@ pushd java-showcase
modify_shared_config
popd

# Parse showcase version from the local directory
pushd java-showcase/gapic-showcase
SHOWCASE_VERSION=$(mvn help:evaluate -Dexpression=gapic-showcase.version -q -DforceStdout)
popd
# Extract the showcase version directly from pom.xml using sed:
# - 'sed -n': suppresses default line printing.
# - 's:...[[:space:]]*\([^<[:space:]]*\).*:\1:p': captures non-whitespace version text and prints it.
# - '/.../q': quits immediately on first match, avoiding trailing passes and external pipe utilities.
# This replaces 'mvn help:evaluate' which previously took 15+ seconds to boot Maven.
SHOWCASE_VERSION=$(sed -n 's:.*<gapic-showcase\.version>[[:space:]]*\([^<[:space:]]*\).*:\1:p; /<gapic-showcase\.version>/q' java-showcase/gapic-showcase/pom.xml)

# Fail fast with a clear error message if the version could not be parsed,
# preventing malformed curl URLs and ambiguous downstream failures.
if [[ -z "${SHOWCASE_VERSION}" ]]; then
echo "Error: Failed to parse gapic-showcase.version from java-showcase/gapic-showcase/pom.xml" >&2
exit 1
fi

# Start showcase server
mkdir -p /usr/src/showcase
curl --location https://github.com/googleapis/gapic-showcase/releases/download/v"${SHOWCASE_VERSION}"/gapic-showcase-"${SHOWCASE_VERSION}"-linux-amd64.tar.gz --output /usr/src/showcase/showcase-"${SHOWCASE_VERSION}"-linux-amd64.tar.gz
# Use '--fail' so curl exits with an error status on HTTP failures (e.g., 404/500).
# Without '--fail', curl writes the error response body (HTML) to the tar.gz file
# and returns exit code 0, which results in cryptic tar decompression failures.
curl --fail --location https://github.com/googleapis/gapic-showcase/releases/download/v"${SHOWCASE_VERSION}"/gapic-showcase-"${SHOWCASE_VERSION}"-linux-amd64.tar.gz --output /usr/src/showcase/showcase-"${SHOWCASE_VERSION}"-linux-amd64.tar.gz
pushd /usr/src/showcase/
tar -xf showcase-*
./gapic-showcase run &
Expand Down
9 changes: 7 additions & 2 deletions google-auth-library-java/scripts/update_javadoc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@

set -e

VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -Ev '(^\[|\w+:)')
# Extract the project's version from pom.xml:
# - '/<parent>/,/<\/parent>/d' deletes the <parent> block so we do not mistakenly
# extract the parent POM's version (e.g. google-cloud-shared-config) if a <parent>
# block appears before or contains a <version> declaration.
# - '/<version>/...q;' captures the project's own <version> tag and exits immediately.
VERSION=$(sed -n '/<parent>/,/<\/parent>/d; /<version>/{s:.*<version>[[:space:]]*\([^<[:space:]]*\).*:\1:p; q;}' pom.xml)

if [ -z "$VERSION" ]; then
echo "Error updating Javadoc: could not obtain version number from maven-help-plugin."
echo "Error updating Javadoc: could not obtain version number from pom.xml."
exit 1
fi

Expand Down
17 changes: 14 additions & 3 deletions sdk-platform-java/.kokoro/presubmit/showcase-native.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,23 @@ mvn install --projects '!gapic-generator-java' \
SHARED_DEPS_VERSION=$(parse_pom_version java-shared-dependencies)

# Run showcase integration tests in GraalVM
pushd java-showcase/gapic-showcase
SHOWCASE_VERSION=$(mvn help:evaluate -Dexpression=gapic-showcase.version -q -DforceStdout)
popd
SHOWCASE_POM="java-showcase/gapic-showcase/pom.xml"
if [[ ! -f "${SHOWCASE_POM}" && -f "../java-showcase/gapic-showcase/pom.xml" ]]; then
SHOWCASE_POM="../java-showcase/gapic-showcase/pom.xml"
fi
SHOWCASE_VERSION=$(sed -n 's:.*<gapic-showcase\.version>[[:space:]]*\([^<[:space:]]*\).*:\1:p; /<gapic-showcase\.version>/q' "${SHOWCASE_POM}")
if [[ -z "${SHOWCASE_VERSION}" ]]; then
echo "Error: Failed to parse gapic-showcase.version from ${SHOWCASE_POM}" >&2
exit 1
fi

# Start showcase server
mkdir -p /usr/src/showcase
# Use '--fail' so curl exits with an error status on HTTP failures (e.g., 404/500).
# Without '--fail', curl writes the error response body (HTML) to the tar.gz file
# and returns exit code 0, which results in cryptic tar decompression failures.
curl \
--fail \
--location https://github.com/googleapis/gapic-showcase/releases/download/v"${SHOWCASE_VERSION}"/gapic-showcase-"${SHOWCASE_VERSION}"-linux-amd64.tar.gz \
--output /usr/src/showcase/showcase-"${SHOWCASE_VERSION}"-linux-amd64.tar.gz
pushd /usr/src/showcase/
Expand Down
Loading