From 959dd2907beba58352f0543d10afd1b5150245b2 Mon Sep 17 00:00:00 2001 From: ivanmkc Date: Fri, 14 Nov 2025 23:36:41 -0500 Subject: [PATCH 1/9] Added pr checks and regression test code --- tools/go-snippets/runner.sh | 118 +++++++++++++++++++++++++++ tools/go-snippets/snippets.txt | 29 +++++++ tools/pr-checks/check_go_snippets.sh | 50 ++++++++++++ 3 files changed, 197 insertions(+) create mode 100755 tools/go-snippets/runner.sh create mode 100644 tools/go-snippets/snippets.txt create mode 100755 tools/pr-checks/check_go_snippets.sh diff --git a/tools/go-snippets/runner.sh b/tools/go-snippets/runner.sh new file mode 100755 index 000000000..446540078 --- /dev/null +++ b/tools/go-snippets/runner.sh @@ -0,0 +1,118 @@ +#!/bin/bash +# Copyright 2025 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. + +# This script builds and runs Go snippets. It is designed to be run from the project root. +# +# It can run in two modes: +# 1. Targeted Mode: If file paths are provided as arguments, it runs only those files. +# This is used in PR checks to test only the changed files. +# Example: ./tools/go-snippets/runner.sh build examples/go/snippets/quickstart/main.go +# +# 2. Full Regression Mode: If no arguments are provided, it runs a predefined +# list of all Go snippets in the repository. This is used for scheduled weekly tests. +# Example: ./tools/go-snippets/runner.sh run + +# --- Configuration --- +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' # No Color +EXIT_CODE=0 +SNIPPETS_FILE="tools/go-snippets/snippets.txt" + +# --- Helper Function --- +# execute_and_check executes a command, captures the output, +# and prints a formatted, colored status message. +# +# @param {string} command - The full command to execute. +# @param {string} display_name - A user-friendly name for the command/file. +execute_and_check() { + local command=$1 + local display_name=$2 + + # Capture the run output and exit code. + local output + output=$(eval ${command} 2>&1) + local exit_code=$? + + if [ ${exit_code} -eq 0 ]; then + # Print PASS status in green if run is successful. + echo -e "[${GREEN}PASS${NC}] ${display_name}" + else + # Print FAIL status in red and the indented error message. + echo -e "[${RED}FAIL${NC}] ${display_name}" + echo "${output}" | sed 's/^/ /' + # Set the script's exit code to 1 to fail the CI check. + EXIT_CODE=1 + fi +} + +# --- Main Logic --- + +if [[ "$1" != "build" && "$1" != "run" ]]; then + echo "Usage: $0 [file1 file2 ...]" + exit 1 +fi + +ACTION=$1 +shift + +# Run go mod tidy once for the entire examples/go module +(cd examples/go && go mod tidy) +if [ $? -ne 0 ]; then + echo -e "[${RED}FAIL${NC}] go mod tidy failed in examples/go" + EXIT_CODE=1 +fi + +if [ "$#" -gt 0 ]; then + echo "Running targeted Go snippet ${ACTION} for changed files..." + echo + for file in "$@"; do + # Find the line in snippets.txt that contains the changed file + line=$(grep "${file#examples/go/}" ${SNIPPETS_FILE}) + if [ "${ACTION}" == "build" ]; then + command_to_execute="go build ${line}" + elif [ "${ACTION}" == "run" ]; then + command_to_execute="go run ${line}" + fi + + if [[ -n "${command_to_execute}" ]]; then + execute_and_check "(cd examples/go && ${command_to_execute})" "${file}" + fi + done +else + echo "Running full Go snippet ${ACTION}..." + echo + while IFS= read -r line; do + command_to_execute="" + if [ "${ACTION}" == "build" ]; then + command_to_execute="go build ${line}" + elif [ "${ACTION}" == "run" ]; then + # Special case for quickstart + if [[ "${line}" == "snippets/quickstart/main.go" ]]; then + command_to_execute="go run ${line} \"What is the weather in London?\"" + else + command_to_execute="go run ${line}" + fi + fi + + if [[ -n "${command_to_execute}" ]]; then + execute_and_check "(cd examples/go && ${command_to_execute})" "${line}" + fi + done < "${SNIPPETS_FILE}" +fi + +echo +echo "Script finished." +exit ${EXIT_CODE} \ No newline at end of file diff --git a/tools/go-snippets/snippets.txt b/tools/go-snippets/snippets.txt new file mode 100644 index 000000000..19fec67f5 --- /dev/null +++ b/tools/go-snippets/snippets.txt @@ -0,0 +1,29 @@ +cloud-run/main.go +a2a_basic/remote_a2a/check_prime_agent/main.go +a2a_basic/main.go +snippets/tools-custom/doc_analysis/main.go snippets/tools-custom/doc_analysis/doc_analysis.go +snippets/tools-custom/order_status/main.go snippets/tools-custom/order_status/order_status.go +snippets/tools-custom/user_preference/main.go snippets/tools-custom/user_preference/user_preference.go +snippets/tools-custom/weather_sentiment/main.go +snippets/callbacks/types_of_callbacks/main.go +snippets/context/main.go +snippets/tools/function-tools/func_tool.go +snippets/sessions/state_example/state_example.go +snippets/sessions/session_management_example/session_management_example.go +snippets/sessions/instruction_template/instruction_template_example.go +snippets/sessions/instruction_provider/instruction_provider_example.go +snippets/artifacts/main.go +snippets/tools/built-in-tools/google_search.go +snippets/callbacks/main.go +snippets/agents/models/models.go +snippets/agents/custom-agent/storyflow_agent.go +snippets/agents/workflow-agents/sequential/main.go +snippets/agents/workflow-agents/parallel/main.go +snippets/agents/workflow-agents/loop/main.go +snippets/quickstart/main.go "What is the weather in London?" +snippets/agents/multi-agent/main.go +snippets/tools/function-tools/long-running-tool/long_running_tool.go +snippets/agents/llm-agents/snippets/main.go +snippets/agents/llm-agents/main.go +snippets/sessions/memory_example/memory_example.go +snippets/tools-custom/customer_support_agent/main.go diff --git a/tools/pr-checks/check_go_snippets.sh b/tools/pr-checks/check_go_snippets.sh new file mode 100755 index 000000000..0e986796f --- /dev/null +++ b/tools/pr-checks/check_go_snippets.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Copyright 2025 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. + +# This script ensures that every .go file within the Go snippets directory +# is referenced in the runner.sh script. This prevents new snippets +# from being added without being included in the regression test suite. + +# --- Configuration --- +RED='\033[0;31m' +NC='\033[0m' # No Color +EXIT_CODE=0 +RUNNER_SCRIPT="tools/go-snippets/runner.sh" + +# --- Logic --- +echo "Checking for Go files that are not registered in the runner script..." + +# Find all .go files in the snippets directory, excluding _test.go files. +all_go_files=$(find examples/go/snippets -type f -name "*.go" ! -name "*_test.go" | sort) + +# Extract all .go file paths from the ALL_FILES array in the runner script. +referenced_files=$(sed -n '/ALL_FILES=/,/)/p' ${RUNNER_SCRIPT} | grep -o '[a-zA-Z0-9/._-]*\.go' | sort | uniq) + +# Compare the list of all .go files with the list of referenced files. +# The 'comm' command is used to find lines that are unique to the first file (all_go_files). +unreferenced_files=$(comm -23 <(echo "${all_go_files}") <(echo "${referenced_files}")) + +if [[ -n "${unreferenced_files}" ]]; then + echo -e "${RED}Error: The following Go files were found but are not referenced in ${RUNNER_SCRIPT}:${NC}" + # Indent the list of files for readability. + echo "${unreferenced_files}" | sed 's/^/ /' + echo + echo "Please add them to the ALL_FILES array in ${RUNNER_SCRIPT} to include them in the regression tests." + EXIT_CODE=1 +else + echo "All Go files are correctly referenced in the runner script." +fi + +exit ${EXIT_CODE} \ No newline at end of file From 265978d11149c7ec30b650880a6902e9513ee4e1 Mon Sep 17 00:00:00 2001 From: ivanmkc Date: Fri, 14 Nov 2025 23:58:48 -0500 Subject: [PATCH 2/9] Added github workflows and go.mod/go.sum --- .github/workflows/go-pr-test.yaml | 32 +++++++++ .github/workflows/go_snippets_test.yaml | 88 ++++++++++++++++++++++++ docs/runtime/index.md | 4 +- examples/go/go.mod | 44 ++++++++++++ examples/go/go.sum | 90 +++++++++++++++++++++++++ tools/go-snippets/snippets.txt | 2 +- 6 files changed, 257 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/go-pr-test.yaml create mode 100644 .github/workflows/go_snippets_test.yaml create mode 100644 examples/go/go.mod create mode 100644 examples/go/go.sum diff --git a/.github/workflows/go-pr-test.yaml b/.github/workflows/go-pr-test.yaml new file mode 100644 index 000000000..24c6d191a --- /dev/null +++ b/.github/workflows/go-pr-test.yaml @@ -0,0 +1,32 @@ +name: Go PR Test + +on: + pull_request: + paths: + - 'examples/go/**' + - '.github/workflows/go-pr-test.yaml' + +jobs: + go-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: '1.21' + + - name: Tidy modules + run: | + find examples/go -name 'go.mod' -execdir go mod tidy \; + + - name: Run go test + working-directory: ./examples/go + run: go test ./... + + - name: Run build_all.sh + working-directory: ./examples/go/snippets + run: ./build_all.sh + + - name: Run run_all.sh + working-directory: ./examples/go/snippets + run: ./run_all.sh diff --git a/.github/workflows/go_snippets_test.yaml b/.github/workflows/go_snippets_test.yaml new file mode 100644 index 000000000..8ff20cd54 --- /dev/null +++ b/.github/workflows/go_snippets_test.yaml @@ -0,0 +1,88 @@ +# Copyright 2025 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. + +name: Go Snippets CI + +on: + # Run on pull requests targeting the main branch. + pull_request: + branches: [ "main" ] + + # Run on a weekly schedule (every Sunday at 3:00 AM UTC). + schedule: + - cron: '0 3 * * 0' + +jobs: + # This job builds and runs the Go snippets. + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + # Fetch the entire history to compare branches in the PR. + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.22' + + # --- PR-Specific Checks --- + # These steps only run for pull request events. + + - name: Find new, un-tested Go files (PR only) + if: github.event_name == 'pull_request' + run: | + echo "Checking for any new Go files that are not in the build script..." + ./tools/pr-checks/check_go_snippets.sh + + - name: Get changed Go snippet files (PR only) + if: github.event_name == 'pull_request' + id: changed-files + run: | + # This command gets the list of changed .go files in the snippets directory + # between the PR's head and the base branch. + # The output is an escaped, space-separated string suitable for shell commands. + CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} -- 'examples/go/snippets/**/*.go' | xargs) + echo "changed_files=${CHANGED_FILES}" >> $GITHUB_OUTPUT + echo "Detected changes in: ${CHANGED_FILES}" + + - name: Build changed Go snippets (PR only) + if: github.event_name == 'pull_request' && steps.changed-files.outputs.changed_files != '' + run: | + echo "Building only the changed Go files..." + ./tools/go-snippets/runner.sh build ${{ steps.changed-files.outputs.changed_files }} + + - name: Run changed Go snippets (PR only) + if: github.event_name == 'pull_request' && steps.changed-files.outputs.changed_files != '' + run: | + echo "Running only the changed Go files..." + ./tools/go-snippets/runner.sh run ${{ steps.changed-files.outputs.changed_files }} + + # --- Scheduled Checks --- + # These steps only run on the weekly schedule. + + - name: Build all Go snippets (Scheduled) + if: github.event_name == 'schedule' + run: | + echo "Running weekly build for all Go snippets..." + ./tools/go-snippets/runner.sh build + + - name: Run all Go snippets (Scheduled) + if: github.event_name == 'schedule' + run: | + echo "Running weekly run for all Go snippets..." + ./tools/go-snippets/runner.sh run diff --git a/docs/runtime/index.md b/docs/runtime/index.md index 09430cb62..60e2a9444 100644 --- a/docs/runtime/index.md +++ b/docs/runtime/index.md @@ -1,8 +1,8 @@ # Runtime
- Supported in ADKPython v0.1.0Go v0.1.0Java v0.1.0 -
+ Supported in ADKPython v0.1.0Go v0.1.0 +Java v0.1.0 The ADK Runtime is the underlying engine that powers your agent application during user interactions. It's the system that takes your defined agents, tools, and callbacks and orchestrates their execution in response to user input, managing the flow of information, state changes, and interactions with external services like LLMs or storage. diff --git a/examples/go/go.mod b/examples/go/go.mod new file mode 100644 index 000000000..8cea5b1fd --- /dev/null +++ b/examples/go/go.mod @@ -0,0 +1,44 @@ +module snippets + +go 1.25.1 + +require ( + google.golang.org/adk v0.1.0 + google.golang.org/genai v1.35.0 +) + +require ( + cloud.google.com/go v0.123.0 // indirect + cloud.google.com/go/auth v0.17.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect + github.com/a2aproject/a2a-go v0.3.0 // indirect + github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/jsonschema-go v0.3.0 // indirect + github.com/google/s2a-go v0.1.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect + github.com/googleapis/gax-go/v2 v2.15.0 // indirect + github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect + go.opentelemetry.io/otel v1.38.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/sdk v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect + golang.org/x/crypto v0.43.0 // indirect + golang.org/x/net v0.46.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/text v0.30.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect + rsc.io/omap v1.2.0 // indirect + rsc.io/ordered v1.1.1 // indirect +) diff --git a/examples/go/go.sum b/examples/go/go.sum new file mode 100644 index 000000000..9ada95150 --- /dev/null +++ b/examples/go/go.sum @@ -0,0 +1,90 @@ +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4= +cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= +github.com/a2aproject/a2a-go v0.3.0 h1:mnfBEDJXShzEhXCmUbfZ9xo8sXfq2pCxemsY9uasvzg= +github.com/a2aproject/a2a-go v0.3.0/go.mod h1:8C0O6lsfR7zWFEqVZz/+zWCoxe8gSWpknEpqm/Vgj3E= +github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E= +github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/jsonschema-go v0.3.0 h1:6AH2TxVNtk3IlvkkhjrtbUc4S8AvO0Xii0DxIygDg+Q= +github.com/google/jsonschema-go v0.3.0/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= +github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= +github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4= +github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= +github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo= +github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/adk v0.1.0 h1:+w/fHuqRVolotOATlujRA+2DKUuDrFH2poRdEX2QjB8= +google.golang.org/adk v0.1.0/go.mod h1:NvtSLoNx7UzZIiUAI1KoJQLMmt9sG3oCgiCx1TLqKFw= +google.golang.org/genai v1.35.0 h1:Jo6g25CzVqFzGrX5mhWyBgQqXAUzxcx5jeK7U74zv9c= +google.golang.org/genai v1.35.0/go.mod h1:A3kkl0nyBjyFlNjgxIwKq70julKbIxpSxqKO5gw/gmk= +google.golang.org/genproto v0.0.0-20251014184007-4626949a642f h1:vLd1CJuJOUgV6qijD7KT5Y2ZtC97ll4dxjTUappMnbo= +google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f h1:OiFuztEyBivVKDvguQJYWq1yDcfAHIID/FVrPR4oiI0= +google.golang.org/genproto/googleapis/api v0.0.0-20251014184007-4626949a642f/go.mod h1:kprOiu9Tr0JYyD6DORrc4Hfyk3RFXqkQ3ctHEum3ZbM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f h1:1FTH6cpXFsENbPR5Bu8NQddPSaUUE6NA2XdZdDSAJK4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/omap v1.2.0 h1:c1M8jchnHbzmJALzGLclfH3xDWXrPxSUHXzH5C+8Kdw= +rsc.io/omap v1.2.0/go.mod h1:C8pkI0AWexHopQtZX+qiUeJGzvc8HkdgnsWK4/mAa00= +rsc.io/ordered v1.1.1 h1:1kZM6RkTmceJgsFH/8DLQvkCVEYomVDJfBRLT595Uak= +rsc.io/ordered v1.1.1/go.mod h1:evAi8739bWVBRG9aaufsjVc202+6okf8u2QeVL84BCM= diff --git a/tools/go-snippets/snippets.txt b/tools/go-snippets/snippets.txt index 19fec67f5..c3a0637f9 100644 --- a/tools/go-snippets/snippets.txt +++ b/tools/go-snippets/snippets.txt @@ -20,7 +20,7 @@ snippets/agents/custom-agent/storyflow_agent.go snippets/agents/workflow-agents/sequential/main.go snippets/agents/workflow-agents/parallel/main.go snippets/agents/workflow-agents/loop/main.go -snippets/quickstart/main.go "What is the weather in London?" +snippets/quickstart/main.go snippets/agents/multi-agent/main.go snippets/tools/function-tools/long-running-tool/long_running_tool.go snippets/agents/llm-agents/snippets/main.go From 81117afab69a1183eb9c00627f837726ee50f182 Mon Sep 17 00:00:00 2001 From: ivanmkc Date: Sat, 15 Nov 2025 00:21:16 -0500 Subject: [PATCH 3/9] Added comments to files_to_test.txt --- .../{snippets.txt => files_to_test.txt} | 22 +++++++++++++++++-- tools/go-snippets/runner.sh | 11 +++------- 2 files changed, 23 insertions(+), 10 deletions(-) rename tools/go-snippets/{snippets.txt => files_to_test.txt} (61%) diff --git a/tools/go-snippets/snippets.txt b/tools/go-snippets/files_to_test.txt similarity index 61% rename from tools/go-snippets/snippets.txt rename to tools/go-snippets/files_to_test.txt index c3a0637f9..ff4943426 100644 --- a/tools/go-snippets/snippets.txt +++ b/tools/go-snippets/files_to_test.txt @@ -1,3 +1,21 @@ +# This file lists Go snippet files to be built and run by runner.sh. +# Each line represents a single build/run target. +# +# Format: +# - Lines starting with '#' are treated as comments and ignored. +# - Each non-comment line should contain one or more Go file paths, +# relative to the 'examples/go/' directory. +# - If multiple files are on a single line, they are treated as part of the same package +# and built/run together (e.g., for files with shared dependencies). +# - Arguments are not supported +# +# Examples: +# # Single file example +# snippets/quickstart/main.go +# +# # Multiple files in a single package example +# snippets/tools-custom/doc_analysis/main.go snippets/tools-custom/doc_analysis/doc_analysis.go + cloud-run/main.go a2a_basic/remote_a2a/check_prime_agent/main.go a2a_basic/main.go @@ -20,10 +38,10 @@ snippets/agents/custom-agent/storyflow_agent.go snippets/agents/workflow-agents/sequential/main.go snippets/agents/workflow-agents/parallel/main.go snippets/agents/workflow-agents/loop/main.go -snippets/quickstart/main.go +snippets/quickstart/main.go "What is the weather in London?" snippets/agents/multi-agent/main.go snippets/tools/function-tools/long-running-tool/long_running_tool.go snippets/agents/llm-agents/snippets/main.go snippets/agents/llm-agents/main.go snippets/sessions/memory_example/memory_example.go -snippets/tools-custom/customer_support_agent/main.go +snippets/tools-custom/customer_support_agent/main.go \ No newline at end of file diff --git a/tools/go-snippets/runner.sh b/tools/go-snippets/runner.sh index 446540078..2957c37de 100755 --- a/tools/go-snippets/runner.sh +++ b/tools/go-snippets/runner.sh @@ -29,7 +29,7 @@ RED='\033[0;31m' GREEN='\033[0;32m' NC='\033[0m' # No Color EXIT_CODE=0 -SNIPPETS_FILE="tools/go-snippets/snippets.txt" +SNIPPETS_FILE="tools/go-snippets/files_to_test.txt" # --- Helper Function --- # execute_and_check executes a command, captures the output, @@ -63,7 +63,7 @@ execute_and_check() { if [[ "$1" != "build" && "$1" != "run" ]]; then echo "Usage: $0 [file1 file2 ...]" exit 1 -fi +} ACTION=$1 shift @@ -99,12 +99,7 @@ else if [ "${ACTION}" == "build" ]; then command_to_execute="go build ${line}" elif [ "${ACTION}" == "run" ]; then - # Special case for quickstart - if [[ "${line}" == "snippets/quickstart/main.go" ]]; then - command_to_execute="go run ${line} \"What is the weather in London?\"" - else - command_to_execute="go run ${line}" - fi + command_to_execute="go run ${line}" fi if [[ -n "${command_to_execute}" ]]; then From b9f8037b12bbafe01c6c33b0bf8778de28717d08 Mon Sep 17 00:00:00 2001 From: ivanmkc Date: Sat, 15 Nov 2025 00:28:14 -0500 Subject: [PATCH 4/9] Moved check_go_snippets.sh --- .github/workflows/go_snippets_test.yaml | 2 +- tools/pr-checks/check_go_snippets.sh | 50 ------------------------- 2 files changed, 1 insertion(+), 51 deletions(-) delete mode 100755 tools/pr-checks/check_go_snippets.sh diff --git a/.github/workflows/go_snippets_test.yaml b/.github/workflows/go_snippets_test.yaml index 8ff20cd54..5e909d72c 100644 --- a/.github/workflows/go_snippets_test.yaml +++ b/.github/workflows/go_snippets_test.yaml @@ -47,7 +47,7 @@ jobs: if: github.event_name == 'pull_request' run: | echo "Checking for any new Go files that are not in the build script..." - ./tools/pr-checks/check_go_snippets.sh + ./tools/go-snippets/check_go_snippets.sh - name: Get changed Go snippet files (PR only) if: github.event_name == 'pull_request' diff --git a/tools/pr-checks/check_go_snippets.sh b/tools/pr-checks/check_go_snippets.sh deleted file mode 100755 index 0e986796f..000000000 --- a/tools/pr-checks/check_go_snippets.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -# Copyright 2025 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. - -# This script ensures that every .go file within the Go snippets directory -# is referenced in the runner.sh script. This prevents new snippets -# from being added without being included in the regression test suite. - -# --- Configuration --- -RED='\033[0;31m' -NC='\033[0m' # No Color -EXIT_CODE=0 -RUNNER_SCRIPT="tools/go-snippets/runner.sh" - -# --- Logic --- -echo "Checking for Go files that are not registered in the runner script..." - -# Find all .go files in the snippets directory, excluding _test.go files. -all_go_files=$(find examples/go/snippets -type f -name "*.go" ! -name "*_test.go" | sort) - -# Extract all .go file paths from the ALL_FILES array in the runner script. -referenced_files=$(sed -n '/ALL_FILES=/,/)/p' ${RUNNER_SCRIPT} | grep -o '[a-zA-Z0-9/._-]*\.go' | sort | uniq) - -# Compare the list of all .go files with the list of referenced files. -# The 'comm' command is used to find lines that are unique to the first file (all_go_files). -unreferenced_files=$(comm -23 <(echo "${all_go_files}") <(echo "${referenced_files}")) - -if [[ -n "${unreferenced_files}" ]]; then - echo -e "${RED}Error: The following Go files were found but are not referenced in ${RUNNER_SCRIPT}:${NC}" - # Indent the list of files for readability. - echo "${unreferenced_files}" | sed 's/^/ /' - echo - echo "Please add them to the ALL_FILES array in ${RUNNER_SCRIPT} to include them in the regression tests." - EXIT_CODE=1 -else - echo "All Go files are correctly referenced in the runner script." -fi - -exit ${EXIT_CODE} \ No newline at end of file From d1260fae3774a4d6be966fadaaeccadfe394b342 Mon Sep 17 00:00:00 2001 From: ivanmkc Date: Sat, 15 Nov 2025 01:18:19 -0500 Subject: [PATCH 5/9] Fixed issues with workflows --- ...go-pr-test.yaml => go-build-and-test.yaml} | 9 +--- ...ts_test.yaml => go-snippets-pr-check.yaml} | 12 ----- tools/go-snippets/check_go_snippets.sh | 49 +++++++++++++++++++ tools/go-snippets/runner.sh | 2 +- 4 files changed, 52 insertions(+), 20 deletions(-) rename .github/workflows/{go-pr-test.yaml => go-build-and-test.yaml} (69%) rename .github/workflows/{go_snippets_test.yaml => go-snippets-pr-check.yaml} (84%) create mode 100755 tools/go-snippets/check_go_snippets.sh diff --git a/.github/workflows/go-pr-test.yaml b/.github/workflows/go-build-and-test.yaml similarity index 69% rename from .github/workflows/go-pr-test.yaml rename to .github/workflows/go-build-and-test.yaml index 24c6d191a..5aca62958 100644 --- a/.github/workflows/go-pr-test.yaml +++ b/.github/workflows/go-build-and-test.yaml @@ -23,10 +23,5 @@ jobs: working-directory: ./examples/go run: go test ./... - - name: Run build_all.sh - working-directory: ./examples/go/snippets - run: ./build_all.sh - - - name: Run run_all.sh - working-directory: ./examples/go/snippets - run: ./run_all.sh + - name: Build Go snippets + run: ./tools/go-snippets/runner.sh build diff --git a/.github/workflows/go_snippets_test.yaml b/.github/workflows/go-snippets-pr-check.yaml similarity index 84% rename from .github/workflows/go_snippets_test.yaml rename to .github/workflows/go-snippets-pr-check.yaml index 5e909d72c..845ea7221 100644 --- a/.github/workflows/go_snippets_test.yaml +++ b/.github/workflows/go-snippets-pr-check.yaml @@ -66,12 +66,6 @@ jobs: echo "Building only the changed Go files..." ./tools/go-snippets/runner.sh build ${{ steps.changed-files.outputs.changed_files }} - - name: Run changed Go snippets (PR only) - if: github.event_name == 'pull_request' && steps.changed-files.outputs.changed_files != '' - run: | - echo "Running only the changed Go files..." - ./tools/go-snippets/runner.sh run ${{ steps.changed-files.outputs.changed_files }} - # --- Scheduled Checks --- # These steps only run on the weekly schedule. @@ -80,9 +74,3 @@ jobs: run: | echo "Running weekly build for all Go snippets..." ./tools/go-snippets/runner.sh build - - - name: Run all Go snippets (Scheduled) - if: github.event_name == 'schedule' - run: | - echo "Running weekly run for all Go snippets..." - ./tools/go-snippets/runner.sh run diff --git a/tools/go-snippets/check_go_snippets.sh b/tools/go-snippets/check_go_snippets.sh new file mode 100755 index 000000000..1d41ee282 --- /dev/null +++ b/tools/go-snippets/check_go_snippets.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# Copyright 2025 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. + +# This script ensures that every .go file within the Go snippets directory +# is referenced in the files_to_test.txt file. This prevents new snippets +# from being added without being included in the regression test suite. + +# --- Configuration --- +RED='\033[0;31m' +NC='\033[0m' # No Color +EXIT_CODE=0 +SNIPPETS_FILE="tools/go-snippets/files_to_test.txt" + +# --- Logic --- +echo "Checking for Go files that are not registered in ${SNIPPETS_FILE}..." + +# Find all .go files in the snippets directory, excluding _test.go files. +all_go_files=$(find examples/go -type f -name "*.go" ! -name "*_test.go" | sed 's|examples/go/||' | sort) + +# Extract all .go file paths from the snippets file, ignoring comments and arguments. +referenced_files=$(grep -v '^\s*#' "${SNIPPETS_FILE}" | grep -o '[a-zA-Z0-9/._-]*\.go' | sort | uniq) + +# Compare the list of all .go files with the list of referenced files. +unreferenced_files=$(comm -23 <(echo "${all_go_files}") <(echo "${referenced_files}")) + +if [[ -n "${unreferenced_files}" ]]; then + echo -e "${RED}Error: The following Go files were found but are not referenced in ${SNIPPETS_FILE}:${NC}" + # Indent the list of files for readability. + echo "${unreferenced_files}" | sed 's/^/ /' + echo + echo "Please add them to ${SNIPPETS_FILE} to include them in the regression tests." + EXIT_CODE=1 +else + echo "All Go files are correctly referenced in the snippets file." +fi + +exit ${EXIT_CODE} diff --git a/tools/go-snippets/runner.sh b/tools/go-snippets/runner.sh index 2957c37de..e5b856491 100755 --- a/tools/go-snippets/runner.sh +++ b/tools/go-snippets/runner.sh @@ -63,7 +63,7 @@ execute_and_check() { if [[ "$1" != "build" && "$1" != "run" ]]; then echo "Usage: $0 [file1 file2 ...]" exit 1 -} +fi ACTION=$1 shift From 9c62f833daaee20abcf955814f79d5a45805af8c Mon Sep 17 00:00:00 2001 From: ivanmkc Date: Sat, 15 Nov 2025 01:22:09 -0500 Subject: [PATCH 6/9] Removed unneeded workflow --- .github/workflows/go-build-and-test.yaml | 27 --------------------- .github/workflows/go-snippets-pr-check.yaml | 2 +- 2 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 .github/workflows/go-build-and-test.yaml diff --git a/.github/workflows/go-build-and-test.yaml b/.github/workflows/go-build-and-test.yaml deleted file mode 100644 index 5aca62958..000000000 --- a/.github/workflows/go-build-and-test.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Go PR Test - -on: - pull_request: - paths: - - 'examples/go/**' - - '.github/workflows/go-pr-test.yaml' - -jobs: - go-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 - with: - go-version: '1.21' - - - name: Tidy modules - run: | - find examples/go -name 'go.mod' -execdir go mod tidy \; - - - name: Run go test - working-directory: ./examples/go - run: go test ./... - - - name: Build Go snippets - run: ./tools/go-snippets/runner.sh build diff --git a/.github/workflows/go-snippets-pr-check.yaml b/.github/workflows/go-snippets-pr-check.yaml index 845ea7221..83343d305 100644 --- a/.github/workflows/go-snippets-pr-check.yaml +++ b/.github/workflows/go-snippets-pr-check.yaml @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -name: Go Snippets CI +name: Go Snippets Build on PR and Schedule on: # Run on pull requests targeting the main branch. From dd8f5fe836603670f9b426d6d48c579321c86d0c Mon Sep 17 00:00:00 2001 From: ivanmkc Date: Sat, 15 Nov 2025 01:24:32 -0500 Subject: [PATCH 7/9] Revert bad change --- docs/runtime/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/runtime/index.md b/docs/runtime/index.md index 60e2a9444..09430cb62 100644 --- a/docs/runtime/index.md +++ b/docs/runtime/index.md @@ -1,8 +1,8 @@ # Runtime
- Supported in ADKPython v0.1.0Go v0.1.0 -
Java v0.1.0 + Supported in ADKPython v0.1.0Go v0.1.0Java v0.1.0 + The ADK Runtime is the underlying engine that powers your agent application during user interactions. It's the system that takes your defined agents, tools, and callbacks and orchestrates their execution in response to user input, managing the flow of information, state changes, and interactions with external services like LLMs or storage. From 3f0743715955f75cd31e3106a4b76f67a6c2368c Mon Sep 17 00:00:00 2001 From: ivanmkc Date: Sat, 15 Nov 2025 10:09:19 -0500 Subject: [PATCH 8/9] Added runner tests --- .github/workflows/go-snippets-pr-check.yaml | 8 + tools/go-snippets/check_go_snippets.sh | 11 ++ tools/go-snippets/files_to_test.txt | 1 - tools/go-snippets/runner.sh | 177 ++++++++++++++------ tools/go-snippets/runner_test.sh | 141 ++++++++++++++++ 5 files changed, 283 insertions(+), 55 deletions(-) create mode 100755 tools/go-snippets/runner_test.sh diff --git a/.github/workflows/go-snippets-pr-check.yaml b/.github/workflows/go-snippets-pr-check.yaml index 83343d305..25a91b8c8 100644 --- a/.github/workflows/go-snippets-pr-check.yaml +++ b/.github/workflows/go-snippets-pr-check.yaml @@ -40,6 +40,14 @@ jobs: with: go-version: '1.22' + - name: Cache Go modules + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + # --- PR-Specific Checks --- # These steps only run for pull request events. diff --git a/tools/go-snippets/check_go_snippets.sh b/tools/go-snippets/check_go_snippets.sh index 1d41ee282..7243324e5 100755 --- a/tools/go-snippets/check_go_snippets.sh +++ b/tools/go-snippets/check_go_snippets.sh @@ -46,4 +46,15 @@ else echo "All Go files are correctly referenced in the snippets file." fi +# Check for files in the list that don't exist on disk +dangling_references=$(comm -23 <(echo "${referenced_files}") <(echo "${all_go_files}")) + +if [[ -n "${dangling_references}" ]]; then + echo -e "${RED}Error: The following files are referenced in ${SNIPPETS_FILE} but do not exist:${NC}" + echo "${dangling_references}" | sed 's/^/ /' + echo + echo "Please remove them from ${SNIPPETS_FILE}." + EXIT_CODE=1 +fi + exit ${EXIT_CODE} diff --git a/tools/go-snippets/files_to_test.txt b/tools/go-snippets/files_to_test.txt index ff4943426..631c38cdb 100644 --- a/tools/go-snippets/files_to_test.txt +++ b/tools/go-snippets/files_to_test.txt @@ -38,7 +38,6 @@ snippets/agents/custom-agent/storyflow_agent.go snippets/agents/workflow-agents/sequential/main.go snippets/agents/workflow-agents/parallel/main.go snippets/agents/workflow-agents/loop/main.go -snippets/quickstart/main.go "What is the weather in London?" snippets/agents/multi-agent/main.go snippets/tools/function-tools/long-running-tool/long_running_tool.go snippets/agents/llm-agents/snippets/main.go diff --git a/tools/go-snippets/runner.sh b/tools/go-snippets/runner.sh index e5b856491..a130396e6 100755 --- a/tools/go-snippets/runner.sh +++ b/tools/go-snippets/runner.sh @@ -22,18 +22,76 @@ # # 2. Full Regression Mode: If no arguments are provided, it runs a predefined # list of all Go snippets in the repository. This is used for scheduled weekly tests. -# Example: ./tools/go-snippets/runner.sh run +# Example: ./tools/go-snippets/runner.sh build # --- Configuration --- +# Define color codes for colored output. RED='\033[0;31m' GREEN='\033[0;32m' NC='\033[0m' # No Color + +# Global exit code for the script. It is set to 1 if any test fails. EXIT_CODE=0 + +# The configuration file that lists all Go snippets to be tested. SNIPPETS_FILE="tools/go-snippets/files_to_test.txt" -# --- Helper Function --- -# execute_and_check executes a command, captures the output, -# and prints a formatted, colored status message. +# --- Helper Functions --- + +# should_process_line determines if a line from the snippets file should be processed. +# It returns 0 (success) for valid lines and 1 (failure) for comments or empty lines. +# +# @param {string} line - The line to check. +# @returns {int} 0 if the line should be processed, 1 otherwise. +should_process_line() { + local line=$1 + # Remove all whitespace from the line to correctly handle lines with only spaces or tabs. + local trimmed_line=$(echo "${line}" | tr -d '[:space:]') + # Return failure (1) if the trimmed line is empty or starts with a hash. + if [[ -z "${trimmed_line}" || "${trimmed_line}" =~ ^# ]]; then + return 1 + else + return 0 + fi +} + +# find_snippet_line searches the SNIPPETS_FILE for a given Go file path. +# It ignores comments and returns the full line from the file. +# +# @param {string} file_path_from_root - The full path to the Go file relative to the project root (e.g., "examples/go/snippets/quickstart/main.go"). +# @returns {string} The matching line from SNIPPETS_FILE, or an empty string if not found. +find_snippet_line() { + local file_path_from_root=$1 + # The SNIPPETS_FILE contains paths relative to 'examples/go/', so we strip that prefix from the input path. + local relative_path=${file_path_from_root#examples/go/} + # First, filter out all commented lines, then search for the relative path. + grep -v '^\s*#' "${SNIPPETS_FILE}" | grep "${relative_path}" +} + +# get_command_for_action constructs the appropriate Go command based on the action. +# It specifically handles stripping arguments for the 'build' action. +# +# @param {string} action - The action to perform ("build" or "run"). +# @param {string} line - The line from the snippets file, which may include arguments. +# @returns {string} The fully formed Go command. +get_command_for_action() { + local action=$1 + local line=$2 + local command="" + + if [ "${action}" == "build" ]; then + # For 'build', extract only the file paths, ignoring any arguments. + # 'go build' does not accept application arguments, so they must be stripped. + local files_to_build=$(echo "${line}" | awk '{for(i=1;i<=NF;i++) if($i ~ /\.go$/) printf "%s ", $i}') + command="go build ${files_to_build}" + elif [ "${action}" == "run" ]; then + # For 'run', use the line as is, as 'go run' will pass arguments to the application. + command="go run ${line}" + fi + echo "${command}" +} + +# execute_and_check executes a command and prints a formatted status message. # # @param {string} command - The full command to execute. # @param {string} display_name - A user-friendly name for the command/file. @@ -41,73 +99,84 @@ execute_and_check() { local command=$1 local display_name=$2 - # Capture the run output and exit code. + # 'eval' is used to correctly execute the command string, which may contain quotes and other special characters. local output output=$(eval ${command} 2>&1) local exit_code=$? if [ ${exit_code} -eq 0 ]; then - # Print PASS status in green if run is successful. echo -e "[${GREEN}PASS${NC}] ${display_name}" else - # Print FAIL status in red and the indented error message. echo -e "[${RED}FAIL${NC}] ${display_name}" + # Indent the error output for better readability. echo "${output}" | sed 's/^/ /' - # Set the script's exit code to 1 to fail the CI check. + # Set the global exit code to indicate failure. EXIT_CODE=1 fi } # --- Main Logic --- -if [[ "$1" != "build" && "$1" != "run" ]]; then - echo "Usage: $0 [file1 file2 ...]" - exit 1 -fi +# This check prevents the main logic from running if the script is being sourced (e.g., by the test script). +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + # Validate the first argument is either 'build' or 'run'. + if [[ "$1" != "build" && "$1" != "run" ]]; then + echo "Usage: $0 [file1 file2 ...]" + exit 1 + fi -ACTION=$1 -shift + ACTION=$1 + shift # Remove the first argument, so '$@' contains only the file paths. -# Run go mod tidy once for the entire examples/go module -(cd examples/go && go mod tidy) -if [ $? -ne 0 ]; then - echo -e "[${RED}FAIL${NC}] go mod tidy failed in examples/go" - EXIT_CODE=1 -fi + # Ensure all Go module dependencies are tidy before running any builds or tests. + # This is run from the 'examples/go' directory where the go.mod file is located. + (cd examples/go && go mod tidy) + if [ $? -ne 0 ]; then + echo -e "[${RED}FAIL${NC}] go mod tidy failed in examples/go" + exit 1 # Exit immediately if dependencies are not clean. + fi + + # Check if file paths were provided as arguments (Targeted Mode). + if [ "$#" -gt 0 ]; then + echo "Running targeted Go snippet ${ACTION} for changed files..." + echo + for file in "$@"; do + # Find the corresponding line in the snippets file for the changed file. + line=$(find_snippet_line "${file}") + if [[ -z "${line}" ]]; then + echo -e "[${RED}FAIL${NC}] ${file}" + echo " Error: No corresponding entry found in ${SNIPPETS_FILE}." + EXIT_CODE=1 + continue # Skip to the next file. + fi + + # Construct the appropriate build or run command. + command_to_execute=$(get_command_for_action "${ACTION}" "${line}") + if [[ -n "${command_to_execute}" ]]; then + # Execute the command from the 'examples/go' directory. + execute_and_check "(cd examples/go && ${command_to_execute})" "${file}" + fi + done + else + # If no file paths were provided, run in Full Regression Mode. + echo "Running full Go snippet ${ACTION}..." + echo + # Read the snippets file line by line. + while IFS= read -r line; do + # Skip empty lines and comments. + if ! should_process_line "${line}"; then + continue + fi + + command_to_execute=$(get_command_for_action "${ACTION}" "${line}") + if [[ -n "${command_to_execute}" ]]; then + execute_and_check "(cd examples/go && ${command_to_execute})" "${line}" + fi + done < "${SNIPPETS_FILE}" + fi -if [ "$#" -gt 0 ]; then - echo "Running targeted Go snippet ${ACTION} for changed files..." - echo - for file in "$@"; do - # Find the line in snippets.txt that contains the changed file - line=$(grep "${file#examples/go/}" ${SNIPPETS_FILE}) - if [ "${ACTION}" == "build" ]; then - command_to_execute="go build ${line}" - elif [ "${ACTION}" == "run" ]; then - command_to_execute="go run ${line}" - fi - - if [[ -n "${command_to_execute}" ]]; then - execute_and_check "(cd examples/go && ${command_to_execute})" "${file}" - fi - done -else - echo "Running full Go snippet ${ACTION}..." echo - while IFS= read -r line; do - command_to_execute="" - if [ "${ACTION}" == "build" ]; then - command_to_execute="go build ${line}" - elif [ "${ACTION}" == "run" ]; then - command_to_execute="go run ${line}" - fi - - if [[ -n "${command_to_execute}" ]]; then - execute_and_check "(cd examples/go && ${command_to_execute})" "${line}" - fi - done < "${SNIPPETS_FILE}" + echo "Script finished." + # Exit with the final status code (0 for success, 1 for failure). + exit ${EXIT_CODE} fi - -echo -echo "Script finished." -exit ${EXIT_CODE} \ No newline at end of file diff --git a/tools/go-snippets/runner_test.sh b/tools/go-snippets/runner_test.sh new file mode 100755 index 000000000..fa6696924 --- /dev/null +++ b/tools/go-snippets/runner_test.sh @@ -0,0 +1,141 @@ +#!/bin/bash +# Copyright 2025 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. + +# Unit tests for runner.sh. +# This script can be run directly to validate the logic of the functions in runner.sh. + +# --- Test Setup --- +# Source the script to make its functions available for testing. +source "$(dirname "$0")/runner.sh" + +# --- Test Harness --- +# Simple assertion function to check for equality. +assert_equals() { + local expected=$1 + local actual=$2 + local test_name=$3 + + if [ "${expected}" == "${actual}" ]; then + echo -e "[${GREEN}PASS${NC}] ${test_name}" + else + echo -e "[${RED}FAIL${NC}] ${test_name}" + echo " Expected: '${expected}'" + echo " Actual: '${actual}'" + exit 1 + fi +} + +# --- Test Cases --- + +# Tests that the 'run' action correctly forms a 'go run' command, +# preserving any arguments that might be on the line. +test_get_command_for_run_action() { + local line="snippets/quickstart/main.go" + local expected="go run snippets/quickstart/main.go" + local actual=$(get_command_for_action "run" "${line}") + assert_equals "${expected}" "${actual}" "Should create correct 'run' command without arguments" +} + +# Tests that the 'build' action correctly forms a 'go build' command +# and, most importantly, strips any non-.go file arguments from the line. +# This is critical because 'go build' does not accept application arguments. +test_get_command_for_build_action_strips_args() { + local line="snippets/quickstart/main.go" + local expected="go build snippets/quickstart/main.go " + local actual=$(get_command_for_action "build" "${line}") + assert_equals "${expected}" "${actual}" "Should create correct 'build' command and strip arguments" +} + +# Tests that a line with multiple .go files is correctly handled for a build. +# This is important for packages that are split across multiple files. +test_get_command_for_multi_file_build() { + local line="file1.go file2.go" + local expected="go build file1.go file2.go " + local actual=$(get_command_for_action "build" "${line}") + assert_equals "${expected}" "${actual}" "Should handle multiple files correctly for build" +} + +# Tests that a line with multiple .go files is correctly handled for a run. +test_get_command_for_multi_file_run() { + local line="file1.go file2.go" + local expected="go run file1.go file2.go" + local actual=$(get_command_for_action "run" "${line}") + assert_equals "${expected}" "${actual}" "Should handle multiple files correctly for run" +} + +# Tests the core logic for finding a snippet in the configuration file. +# It ensures that: +# 1. The 'examples/go/' prefix is correctly stripped from the input path. +# 2. The correct line is found in the test file. +# 3. Commented-out lines are ignored. +test_find_snippet_line() { + # Create a temporary SNIPPETS_FILE for this test to isolate it. + local original_snippets_file="${SNIPPETS_FILE}" + SNIPPETS_FILE=$(mktemp) + # Populate the temporary file with test data. + # This first line acts as a negative test case. The test specifically searches for 'snippets/quickstart/main.go', + # so this line should be correctly ignored by the grep logic, ensuring the function doesn't just return the first line it finds. + echo "file1.go" > "${SNIPPETS_FILE}" + # This line is a commented-out version of our target and should also be ignored. + echo "# snippets/quickstart/main.go" >> "${SNIPPETS_FILE}" # This line should be ignored by grep. + # This is the actual line we expect the function to find and return. + echo "snippets/quickstart/main.go" >> "${SNIPPETS_FILE}" # This is the line we expect to find. + + # This simulates the file path that would be passed to the script (e.g., from 'git diff'). + local input_file_path="examples/go/snippets/quickstart/main.go" + local expected_line="snippets/quickstart/main.go" + + # Call the function under test. + local actual_line=$(find_snippet_line "${input_file_path}") + + assert_equals "${expected_line}" "${actual_line}" "Should find the correct snippet line, ignoring comments" + + # Cleanup + rm "${SNIPPETS_FILE}" + SNIPPETS_FILE="${original_snippets_file}" # Restore original path +} + +# Tests the logic for determining if a line should be processed. +test_should_process_line() { + # A valid line should return 0 (success). + should_process_line "file1.go" + assert_equals "0" "$?" "Should return success for a valid line" + + # An empty line should return 1 (failure). + should_process_line "" + assert_equals "1" "$?" "Should return failure for an empty line" + + # A line with only whitespace should return 1 (failure). + should_process_line " " + assert_equals "1" "$?" "Should return failure for a whitespace-only line" + + # A commented line should return 1 (failure). + should_process_line "# file1.go" + assert_equals "1" "$?" "Should return failure for a commented line" + + # A commented line with leading spaces should return 1 (failure). + should_process_line " # file1.go" + assert_equals "1" "$?" "Should return failure for a commented line with leading spaces" +} + +# --- Run Tests --- +echo "Running tests for runner.sh..." +test_get_command_for_run_action +test_get_command_for_build_action_strips_args +test_get_command_for_multi_file_build +test_get_command_for_multi_file_run +test_find_snippet_line +test_should_process_line +echo "All tests passed." From cd0c700208b9b1195fcbe23295e12869e40efc2d Mon Sep 17 00:00:00 2001 From: ivanmkc Date: Tue, 18 Nov 2025 13:20:33 -0500 Subject: [PATCH 9/9] Added README --- tools/go-snippets/README.md | 80 +++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tools/go-snippets/README.md diff --git a/tools/go-snippets/README.md b/tools/go-snippets/README.md new file mode 100644 index 000000000..4234d2429 --- /dev/null +++ b/tools/go-snippets/README.md @@ -0,0 +1,80 @@ +# Go Snippets Tooling + +This directory contains the scripts and configuration for building, running, and testing the Go snippets located in `examples/go/`. + +## Overview + +The tooling is designed to ensure that all Go snippets are continuously validated and to provide a fast feedback loop for developers. It consists of a unified runner script, a configuration file to manage the list of snippets, and a suite of unit tests for the runner itself. + +## Key Components + +- **`runner.sh`**: The main script for building and running Go snippets. +- **`files_to_test.txt`**: The configuration file that lists all Go snippets to be tested. +- **`check_go_snippets.sh`**: A PR check script that ensures all `.go` files are registered in `files_to_test.txt`. +- **`runner_test.sh`**: Unit tests for the `runner.sh` script. + +--- + +## How to Use + +### Automatic Execution (CI/CD) + +The scripts are primarily designed to be run automatically by GitHub Actions. + +- **On Pull Requests:** When a pull request is opened, two workflows are triggered: + 1. **Go Snippets Build on PR and Schedule:** This workflow runs `check_go_snippets.sh` to ensure new files are registered. It then intelligently builds **only the `.go` files that were changed** in the PR. + 2. **Go Build and Test on PR:** This workflow runs a full build of **all** Go snippets and executes any unit tests (`go test ./...`) to ensure that a change has not broken any other part of the Go codebase. + +- **Scheduled Runs:** A full regression build of all Go snippets is run automatically every Sunday at 3:00 AM UTC to catch any potential issues. + +### Manual Execution + +You can also run the scripts locally to test your changes before pushing. All commands should be run from the **root of the repository**. + +#### Building All Snippets + +To run a full build of every Go snippet listed in `files_to_test.txt`: + +```bash +./tools/go-snippets/runner.sh build +``` + +#### Building Specific Snippets + +To build one or more specific Go snippets (for example, if you are working on them and want a quick check): + +```bash +./tools/go-snippets/runner.sh build examples/go/snippets/quickstart/main.go +``` + +#### Running the Unit Tests + +To run the unit tests for the `runner.sh` script itself: + +```bash +./tools/go-snippets/runner_test.sh +``` + +--- + +## Maintaining the Snippet List + +### Adding a New Snippet + +1. Create your new `.go` file (e.g., `examples/go/snippets/my-new-snippet/main.go`). +2. Open `tools/go-snippets/files_to_test.txt`. +3. Add a new line with the path to your file, relative to the `examples/go/` directory. + + ``` + # In files_to_test.txt + snippets/my-new-snippet/main.go + ``` + +4. If your snippet is part of a package that requires multiple files to be built together, add them all to the same line: + + ``` + # In files_to_test.txt + snippets/my-multi-file-snippet/main.go snippets/my-multi-file-snippet/helpers.go + ``` + +The `check_go_snippets.sh` script will automatically run on your PR and remind you if you've forgotten to add your new file to the list.