@@ -148,3 +148,129 @@ jobs:
148148 -n auto \
149149 --ignore=tests/unittests/artifacts/test_artifact_service.py \
150150 --ignore=tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py
151+
152+ # 4. Custom file content compliance checks (PR only)
153+ compliance-check :
154+ name : File Content Compliance
155+ runs-on : ubuntu-latest
156+ if : github.event_name == 'pull_request'
157+ steps :
158+ - name : Checkout Code
159+ uses : actions/checkout@v6
160+ with :
161+ # Fetch full history (depth: 0) instead of shallow clone (depth: 2) to ensure
162+ # git diff origin/${base_ref}...HEAD can reliably find the merge base,
163+ # preventing fatal git errors on deep PRs or when the target branch has progressed.
164+ fetch-depth : 0
165+
166+ - name : Check for logger pattern in all changed Python files
167+ run : |
168+ git fetch origin ${GITHUB_BASE_REF}
169+ CHANGED_FILES=$(git diff --diff-filter=ACMR --name-only origin/${GITHUB_BASE_REF}...HEAD | grep -E '\.py$' || true)
170+ if [ -n "$CHANGED_FILES" ]; then
171+ echo "Changed Python files to check:"
172+ echo "$CHANGED_FILES"
173+ echo ""
174+
175+ # Check for 'logger = logging.getLogger(__name__)' in changed .py files.
176+ set +e
177+ FILES_WITH_FORBIDDEN_LOGGER=$(grep -lE 'logger = logging\.getLogger\(__name__\)' $CHANGED_FILES)
178+ GREP_EXIT_CODE=$?
179+ set -e
180+
181+ if [ $GREP_EXIT_CODE -eq 0 ]; then
182+ echo "❌ Found forbidden use of 'logger = logging.getLogger(__name__)'. Please use 'logger = logging.getLogger('google_adk.' + __name__)' instead."
183+ echo "The following files contain the forbidden pattern:"
184+ echo "$FILES_WITH_FORBIDDEN_LOGGER"
185+ exit 1
186+ elif [ $GREP_EXIT_CODE -eq 1 ]; then
187+ echo "✅ No instances of 'logger = logging.getLogger(__name__)' found in changed Python files."
188+ fi
189+ else
190+ echo "✅ No relevant Python files found."
191+ fi
192+
193+ - name : Check for import pattern in certain changed Python files
194+ run : |
195+ git fetch origin ${GITHUB_BASE_REF}
196+ CHANGED_FILES=$(git diff --diff-filter=ACMR --name-only origin/${GITHUB_BASE_REF}...HEAD | grep -E '\.py$' | grep -v -E '__init__.py$|version.py$|tests/.*|contributing/samples/' || true)
197+ if [ -n "$CHANGED_FILES" ]; then
198+ echo "Changed Python files to check:"
199+ echo "$CHANGED_FILES"
200+ echo ""
201+
202+ # Use grep -L to find files that DO NOT contain the pattern.
203+ FILES_MISSING_IMPORT=$(grep -L 'from __future__ import annotations' $CHANGED_FILES || true)
204+
205+ if [ -z "$FILES_MISSING_IMPORT" ]; then
206+ echo "✅ All modified Python files include 'from __future__ import annotations'."
207+ exit 0
208+ else
209+ echo "❌ The following files are missing 'from __future__ import annotations':"
210+ echo "$FILES_MISSING_IMPORT"
211+ echo "This import is required to allow forward references in type annotations without quotes."
212+ exit 1
213+ fi
214+ else
215+ echo "✅ No relevant Python files found."
216+ fi
217+
218+ - name : Check for import from cli package in certain changed Python files
219+ run : |
220+ git fetch origin ${GITHUB_BASE_REF}
221+ CHANGED_FILES=$(git diff --diff-filter=ACMR --name-only origin/${GITHUB_BASE_REF}...HEAD | grep -E '\.py$' | grep -v -E 'cli/.*|src/google/adk/tools/apihub_tool/apihub_toolset.py|tests/.*|contributing/samples/' || true)
222+ if [ -n "$CHANGED_FILES" ]; then
223+ echo "Changed Python files to check:"
224+ echo "$CHANGED_FILES"
225+ echo ""
226+
227+ set +e
228+ FILES_WITH_FORBIDDEN_IMPORT=$(grep -lE '^from.*\bcli\b.*import.*$' $CHANGED_FILES)
229+ GREP_EXIT_CODE=$?
230+ set -e
231+
232+ if [[ $GREP_EXIT_CODE -eq 0 ]]; then
233+ echo "❌ Do not import from the cli package outside of the cli package. If you need to reuse the code elsewhere, please move the code outside of the cli package."
234+ echo "The following files contain the forbidden pattern:"
235+ echo "$FILES_WITH_FORBIDDEN_IMPORT"
236+ exit 1
237+ else
238+ echo "✅ No instances of importing from the cli package found in relevant changed Python files."
239+ fi
240+ else
241+ echo "✅ No relevant Python files found."
242+ fi
243+
244+ - name : Check for hardcoded googleapis.com endpoints
245+ run : |
246+ git fetch origin ${GITHUB_BASE_REF}
247+ CHANGED_FILES=$(git diff --diff-filter=ACMR --name-only origin/${GITHUB_BASE_REF}...HEAD | grep -E '\.py$' || true)
248+ if [ -n "$CHANGED_FILES" ]; then
249+ echo "Checking for hardcoded endpoints in: $CHANGED_FILES"
250+
251+ # 1. Identify files containing any googleapis.com URL.
252+ set +e
253+ FILES_WITH_ENDPOINTS=$(grep -lE 'https?://[a-zA-Z0-9.-]+\.googleapis\.com' $CHANGED_FILES)
254+
255+ # 2. From those, identify files that are MISSING the required mTLS version.
256+ if [ -n "$FILES_WITH_ENDPOINTS" ]; then
257+ FILES_MISSING_MTLS=$(grep -L '.mtls.googleapis.com' $FILES_WITH_ENDPOINTS)
258+ fi
259+ set -e
260+
261+ if [ -n "$FILES_MISSING_MTLS" ]; then
262+ echo "❌ Found hardcoded googleapis.com endpoints without mTLS support."
263+ echo "The following files must define both standard and mTLS (.mtls.googleapis.com) endpoints"
264+ echo "to support dynamic endpoint selection as required by security policy:"
265+ echo "$FILES_MISSING_MTLS"
266+ echo ""
267+ echo "To fix this, please follow these steps:"
268+ echo "1. Initialize an AuthorizedSession with your credentials."
269+ echo "2. Use 'mtls.has_default_client_cert_source() from google-auth' to check for available client certificates."
270+ echo "3. If certificates are present, use 'session.configure_mtls_channel()'."
271+ echo "4. Dynamically select the '.mtls.' variant of the endpoint when mTLS is active."
272+ exit 1
273+ else
274+ echo "✅ All hardcoded endpoints have corresponding mTLS definitions or no endpoints found."
275+ fi
276+ fi
0 commit comments