Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
4f980bd
feat: implement ad-hoc package selection for CI/CD
chalmerlowe Jul 29, 2026
59b5102
chore: revert ad-hoc integration in run_conditional_tests.sh to focus…
chalmerlowe Jul 29, 2026
55baa28
docs: add comment explaining inline python usage in system.sh
chalmerlowe Jul 29, 2026
bc3081b
docs: tweak comment explaining inline python usage
chalmerlowe Jul 29, 2026
b0d077e
fix: make grep commands safe and quote variables in adhoc_test_runner.sh
chalmerlowe Jul 29, 2026
e710e45
fix: add auth token to curl and harden inline python in system.sh
chalmerlowe Jul 29, 2026
fbab28a
Apply suggestion from @chalmerlowe
chalmerlowe Jul 29, 2026
4bda578
fix: harden ad-hoc integration in system.sh against silent failures
chalmerlowe Jul 29, 2026
4424735
chore: add experimental comment to trigger kokoro
chalmerlowe Jul 29, 2026
f38b42c
chore: add experimental timeout to parallel test execution in system.sh
chalmerlowe Jul 29, 2026
962bc9e
chore: replace heavy packages (bigquery, bigtable) with lighter ones …
chalmerlowe Jul 29, 2026
7ca31c9
fix: wrap run_package_test in bash -c for timeout command
chalmerlowe Jul 29, 2026
801d0f6
chore: inject intentional failure in google-resumable-media to test a…
chalmerlowe Jul 29, 2026
3ac8fa5
chore: break setup.py in google-resumable-media to guarantee failure
chalmerlowe Jul 30, 2026
2269f4e
chore: dump logs for passed packages in system.sh for debugging
chalmerlowe Jul 30, 2026
4861794
chore: add debug echoes and robustify log dumping in system.sh
chalmerlowe Jul 30, 2026
b2199b3
fix: resolve nested quoting bug in timeout command
chalmerlowe Jul 30, 2026
aeac1b1
fix: refactor xargs to use -n 1 for robust argument passing
chalmerlowe Jul 30, 2026
73100e7
fix: simplify argument passing to bash -c in xargs to avoid positiona…
chalmerlowe Jul 30, 2026
042227d
fix: resolve catastrophic quoting bug caused by single quotes in comment
chalmerlowe Jul 30, 2026
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
91 changes: 81 additions & 10 deletions .kokoro/system.sh
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,23 @@ reap_parallel_results() {

if [ ${#passed_packages[@]} -gt 0 ]; then
echo ""
echo "PASSED PACKAGES:"
printf "%s\n" "${passed_packages[@]}" | sort | sed 's/^/- /'
echo "=================================================="
echo " LOGS FOR PASSED PACKAGES "
echo "=================================================="
for pkg in "${passed_packages[@]}"; do
echo "--------------------------------------------------"
echo "LOGS FOR PASSED PACKAGE: $pkg"
echo "--------------------------------------------------"
if [ -n "$KOKORO_ARTIFACTS_DIR" ] && [ -f "$KOKORO_ARTIFACTS_DIR/$pkg/sponge_log.log" ]; then
cat "$KOKORO_ARTIFACTS_DIR/$pkg/sponge_log.log"
elif [ -f "$LOG_DIR/$pkg.log" ]; then
cat "$LOG_DIR/$pkg.log"
else
echo "Warning: No log file found for passed package $pkg"
echo "Expected either $KOKORO_ARTIFACTS_DIR/$pkg/sponge_log.log or $LOG_DIR/$pkg.log"
fi
echo ""
done
fi

if [ "$failed_count" -gt 0 ]; then
Expand All @@ -175,8 +190,11 @@ reap_parallel_results() {
echo "--------------------------------------------------"
if [ -n "$KOKORO_ARTIFACTS_DIR" ] && [ -f "$KOKORO_ARTIFACTS_DIR/$pkg/sponge_log.log" ]; then
cat "$KOKORO_ARTIFACTS_DIR/$pkg/sponge_log.log"
else
elif [ -f "$LOG_DIR/$pkg.log" ]; then
cat "$LOG_DIR/$pkg.log"
else
echo "Warning: No log file found for failed package $pkg"
echo "Expected either $KOKORO_ARTIFACTS_DIR/$pkg/sponge_log.log or $LOG_DIR/$pkg.log"
fi
echo ""
fi
Expand Down Expand Up @@ -246,6 +264,54 @@ for path in `find 'packages' \
fi
done

# --- Ad-hoc Testing Integration ---
TRIGGER_ADHOC="false"
if [[ -n "${KOKORO_GITHUB_PULL_REQUEST_NUMBER}" ]]; then
echo "Checking for adhoc test label on PR #${KOKORO_GITHUB_PULL_REQUEST_NUMBER}..."
headers=(-H "User-Agent: Kokoro")
if [[ -n "${GITHUB_TOKEN:-${GH_TOKEN}}" ]]; then
headers+=(-H "Authorization: token ${GITHUB_TOKEN:-${GH_TOKEN}}")
fi
# Hardened curl call with || true to prevent script termination if network fails
LABELS_JSON=$(curl -s "${headers[@]}" "https://api.github.com/repos/googleapis/google-cloud-python/issues/${KOKORO_GITHUB_PULL_REQUEST_NUMBER}/labels" || echo "[]")

# For this prototype:
# we use a small inline Python snippet here because parsing JSON in pure Bash is difficult/error-prone,
# and we cannot guarantee that tools like 'jq' or 'gh' are installed in the test environment.
# Python and its built-in 'json' module are guaranteed to be available in this repository.
IS_ADHOC=$(python3 -c "
import json
import sys
try:
labels = json.loads(sys.argv[1])
if isinstance(labels, list):
if any(isinstance(l, dict) and l.get('name') == 'test:adhoc' for l in labels):
print('true')
except Exception:
pass
" "$LABELS_JSON")
Comment thread
chalmerlowe marked this conversation as resolved.

if [[ "$IS_ADHOC" == "true" ]]; then
TRIGGER_ADHOC="true"
echo "Adhoc test label 'test:adhoc' found!"
else
echo "Adhoc test label not found or error occurred."
fi
fi

if [[ "$TRIGGER_ADHOC" == "true" ]]; then
echo "Running ad-hoc package selection..."
source ci/adhoc/adhoc_test_runner.sh

echo "Deduplicating packages..."
# Portable deduplication avoiding 'declare -A' (compatible with older Bash)
COMBINED=$(printf "%s\n" "${PACKAGES_TO_TEST[@]}" $ADHOC_PACKAGES | sort -u | grep -v '^$' || true)
PACKAGES_TO_TEST=($COMBINED)

echo "Combined packages to test: ${PACKAGES_TO_TEST[*]}"
fi
# --- End Ad-hoc Testing Integration ---

# Parallel Execution Logic
MAX_JOBS=${MAX_JOBS:-4}

Expand All @@ -272,21 +338,26 @@ export system_test_script PROJECT_ROOT KOKORO_GFILE_DIR
# -P "$MAX_JOBS" controls concurrency
# -I {} replaces {} with the package name
printf '%s\n' "${PACKAGES_TO_TEST[@]}" \
| xargs -P "$MAX_JOBS" -I {} \
| xargs -n 1 -P "$MAX_JOBS" \
bash -c '
pkg="$1"
pkg="$0"
echo "Processing package: $pkg"
# Determine log location: prefer Sponge artifacts directory if available
if [ -n "$KOKORO_ARTIFACTS_DIR" ]; then
pkg_log_dir="$KOKORO_ARTIFACTS_DIR/$pkg"
mkdir -p "$pkg_log_dir" || { touch "$LOG_DIR/$pkg.failed"; exit 1; }
mkdir -p "$pkg_log_dir" || { echo "Failed to mkdir $pkg_log_dir"; touch "$LOG_DIR/$pkg.failed"; exit 1; }
log_file="$pkg_log_dir/sponge_log.log"
else
log_file="$LOG_DIR/$pkg.log"
fi

# Run test; if it fails, create a .failed file to signal failure to the reaper
run_package_test "$pkg" > "$log_file" 2>&1 || touch "$LOG_DIR/$pkg.failed"
' _ "{}"
echo "Log file for $pkg: $log_file"

# EXPERIMENTAL: Added timeout to prevent hanging tests from blocking the whole run.
# This is for experimentation only and will be removed in the final design.
# We must use "bash -c" because timeout expects an executable, not an exported function.
# Using double quotes to avoid breaking the outer single-quoted script.
timeout 45m bash -c "run_package_test \"\$1\"" _ "$pkg" > "$log_file" 2>&1 || touch "$LOG_DIR/$pkg.failed"
'

reap_parallel_results || RETVAL=1

Expand Down
4 changes: 4 additions & 0 deletions ci/adhoc/.package_groups.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
handwritten: google-cloud-translate
handwritten: google-cloud-logging
core: google-api-core
core: google-cloud-core
3 changes: 3 additions & 0 deletions ci/adhoc/.standalone_package_list.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package: google-cloud-logging
package: google-cloud-dns
group: handwritten
40 changes: 40 additions & 0 deletions ci/adhoc/adhoc_test_runner.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash

# Script to determine ad-hoc packages to test.
# This script is intended to be sourced from main test scripts.
#
# Ensure we are in the project root if called directly,
# but usually this is sourced and CWD is already project root.
# For safety, we can use script location but if sourced $0 might be the parent script.
# Let's assume CWD is project root as per system.sh behavior.

ADHOC_DIR="ci/adhoc"
STANDALONE_LIST="${ADHOC_DIR}/.standalone_package_list.txt"
GROUPS_FILE="${ADHOC_DIR}/.package_groups.txt"

if [[ ! -f "$STANDALONE_LIST" ]]; then
echo "Warning: $STANDALONE_LIST not found."
return 0 2>/dev/null || exit 0
fi

if [[ ! -f "$GROUPS_FILE" ]]; then
echo "Warning: $GROUPS_FILE not found."
return 0 2>/dev/null || exit 0
fi

# Grab individual packages
adhoc_packages=$(grep "^package:" "$STANDALONE_LIST" | cut -d':' -f2 | xargs || true)

# Grab requested groups
requested_groups=$(grep "^group:" "$STANDALONE_LIST" | cut -d':' -f2 | xargs || true)

# Expand groups
for group in $requested_groups; do
group_pkgs=$(grep "^$group:" "$GROUPS_FILE" | cut -d':' -f2 | xargs || true)
adhoc_packages="$adhoc_packages $group_pkgs"
done

# Convert to unique list (deduplicate our adhoc packages)
ADHOC_PACKAGES=$(echo "$adhoc_packages" | tr ' ' '\n' | sort -u | xargs)

export ADHOC_PACKAGES
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# EXPERIMENTAL: This is a temporary change to trigger Kokoro system tests.
# Because Kokoro is currently configured to only watch specific package paths (like packages/google-cloud-speech/.*),
# we must touch a file in one of those paths to wake it up.
#
# This file is GAPIC_AUTO, and this specific file is NOT one of the 5 tracked files (setup.py, etc.)
# in system.sh, so this change will NOT trigger tests for google-cloud-speech itself.
#
# If this ad-hoc testing prototype proves successful, we will update the internal Kokoro
# JobConfigs to watch 'ci/adhoc/.*' instead, eliminating the need for this workaround.

import json
import logging as std_logging
import os
Expand Down Expand Up @@ -45,9 +55,8 @@
from google.auth.exceptions import MutualTLSChannelError # type: ignore
from google.auth.transport import mtls # type: ignore
from google.auth.transport.grpc import SslCredentials # type: ignore
from google.oauth2 import service_account # type: ignore

from google.cloud.speech_v1 import gapic_version as package_version
from google.oauth2 import service_account # type: ignore

try:
OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None]
Expand All @@ -67,9 +76,8 @@
import google.api_core.operation_async as operation_async # type: ignore
import google.protobuf.duration_pb2 as duration_pb2 # type: ignore
import google.rpc.status_pb2 as status_pb2 # type: ignore
from google.longrunning import operations_pb2 # type: ignore

from google.cloud.speech_v1.types import cloud_speech
from google.longrunning import operations_pb2 # type: ignore

from .transports.base import DEFAULT_CLIENT_INFO, SpeechTransport
from .transports.grpc import SpeechGrpcTransport
Expand Down
1 change: 1 addition & 0 deletions packages/google-resumable-media/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import setuptools

raise RuntimeError("Intentional breakage to verify ad-hoc testing behavior")

PACKAGE_ROOT = os.path.abspath(os.path.dirname(__file__))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@

import google.auth # type: ignore
import google.auth.transport.requests as tr_requests # type: ignore
import pytest # type: ignore

from google.resumable_media import common
import google.resumable_media.requests as resumable_requests
from google.resumable_media import _helpers
from google.resumable_media.requests import _request_helpers
import google.resumable_media.requests.download as download_mod
from tests.system import utils
import pytest # type: ignore
from google.resumable_media import _helpers, common
from google.resumable_media.requests import _request_helpers

from tests.system import utils

CURR_DIR = os.path.dirname(os.path.realpath(__file__))
DATA_DIR = os.path.join(CURR_DIR, "..", "..", "data")
Expand Down
Loading