1- name : " Check file contents"
1+ # Copyright 2026 Google LLC
2+ #
3+ # Licensed under the Apache License, Version 2.0 (the "License");
4+ # you may not use this file except in compliance with the License.
5+ # You may obtain a copy of the License at
6+ #
7+ # http://www.apache.org/licenses/LICENSE-2.0
8+ #
9+ # Unless required by applicable law or agreed to in writing, software
10+ # distributed under the License is distributed on an "AS IS" BASIS,
11+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ # See the License for the specific language governing permissions and
13+ # limitations under the License.
14+
15+ name : Continuous Integration
216
317on :
18+ push :
19+ branches : [main, v1]
20+ paths :
21+ - ' **.py'
22+ - ' .pre-commit-config.yaml'
23+ - ' pyproject.toml'
24+ - ' tests/**'
425 pull_request :
26+ branches : [main, v1]
527 paths :
628 - ' **.py'
29+ - ' .pre-commit-config.yaml'
30+ - ' pyproject.toml'
31+ - ' tests/**'
732
833permissions :
934 contents : read
1035
1136jobs :
12- check-file-contents :
37+ # 1. Code format and linting (Linter)
38+ lint :
39+ name : Pre-commit Linter
40+ runs-on : ubuntu-latest
41+ steps :
42+ - name : Checkout Code
43+ uses : actions/checkout@v6
44+
45+ - name : Run pre-commit checks
46+ uses : pre-commit/action@v3.0.1
47+
48+ # 2. Static type analysis (Mypy Check with Matrix)
49+ # Compares new changes against the target base branch dynamically to support v1.
50+ type-check :
51+ name : Mypy Check (Python ${{ matrix.python-version }})
52+ runs-on : ubuntu-latest
53+ strategy :
54+ fail-fast : false
55+ matrix :
56+ python-version : ['3.10', '3.11', '3.12', '3.13']
57+ steps :
58+ - name : Checkout code
59+ uses : actions/checkout@v6
60+ with :
61+ fetch-depth : 0
62+
63+ - name : Set up Python
64+ uses : actions/setup-python@v6
65+ with :
66+ python-version : ${{ matrix.python-version }}
67+
68+ - name : Install uv
69+ uses : astral-sh/setup-uv@v7
70+
71+ - name : Generate Baseline
72+ env :
73+ TARGET_BRANCH : ${{ github.base_ref || github.ref_name }}
74+ run : |
75+ # Switch to target base branch to generate baseline
76+ git checkout origin/$TARGET_BRANCH
77+
78+ git checkout ${{ github.sha }} -- pyproject.toml
79+
80+ # Install dependencies for target branch
81+ uv venv .venv
82+ source .venv/bin/activate
83+ uv sync --all-extras
84+
85+ # Run mypy, filter for errors only, remove line numbers, and sort
86+ # We ignore exit code (|| true) because we expect errors on baseline
87+ uv run mypy . | grep "error:" | sed 's/:\([0-9]\+\):/::/g' | sort > baseline_errors.txt || true
88+ echo "Found $(wc -l < baseline_errors.txt) errors on $TARGET_BRANCH."
89+
90+ - name : Check PR Branch
91+ run : |
92+ # Switch back to the PR commit
93+ git checkout ${{ github.sha }}
94+
95+ # Re-sync dependencies in case the PR changed them
96+ source .venv/bin/activate
97+ uv sync --all-extras
98+
99+ # Run mypy on PR code, apply same processing
100+ uv run mypy . | grep "error:" | sed 's/:\([0-9]\+\):/::/g' | sort > pr_errors.txt || true
101+ echo "Found $(wc -l < pr_errors.txt) errors on PR branch."
102+
103+ - name : Compare and Fail on New Errors
104+ run : |
105+ # 'comm -13' suppresses unique lines in file1 (baseline) and common lines,
106+ # leaving only lines unique to file2 (PR) -> The new errors.
107+ comm -13 baseline_errors.txt pr_errors.txt > new_errors.txt
108+
109+ if [ -s new_errors.txt ]; then
110+ echo "::error::The following NEW mypy errors were introduced:"
111+ cat new_errors.txt
112+ exit 1
113+ else
114+ echo "Great job! No new mypy errors introduced."
115+ fi
116+
117+ # 3. Unit testing (Unit Tests with Matrix)
118+ unit-test :
119+ name : Unit Tests (Python ${{ matrix.python-version }})
120+ runs-on : ubuntu-latest
121+ strategy :
122+ fail-fast : false
123+ matrix :
124+ python-version : ["3.10", "3.11", "3.12", "3.13", "3.14"]
125+ timeout-minutes : 10
126+ steps :
127+ - name : Checkout code
128+ uses : actions/checkout@v6
129+
130+ - name : Set up Python ${{ matrix.python-version }}
131+ uses : actions/setup-python@v6
132+ with :
133+ python-version : ${{ matrix.python-version }}
134+
135+ - name : Install the latest version of uv
136+ uses : astral-sh/setup-uv@v7
137+
138+ - name : Install dependencies
139+ run : |
140+ uv venv .venv
141+ source .venv/bin/activate
142+ uv sync --extra test
143+
144+ - name : Run unit tests with pytest
145+ run : |
146+ source .venv/bin/activate
147+ pytest tests/unittests \
148+ -n auto \
149+ --ignore=tests/unittests/artifacts/test_artifact_service.py \
150+ --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
13155 runs-on : ubuntu-latest
156+ if : github.event_name == 'pull_request'
14157 steps :
15158 - name : Checkout Code
16159 uses : actions/checkout@v6
17160 with :
18- fetch-depth : 2
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
19165
20166 - name : Check for logger pattern in all changed Python files
21167 run : |
@@ -27,15 +173,11 @@ jobs:
27173 echo ""
28174
29175 # Check for 'logger = logging.getLogger(__name__)' in changed .py files.
30- # The grep command will exit with a non-zero status code if the pattern is not found.
31- # We invert the exit code with ! so the step succeeds if the pattern is NOT found.
32176 set +e
33177 FILES_WITH_FORBIDDEN_LOGGER=$(grep -lE 'logger = logging\.getLogger\(__name__\)' $CHANGED_FILES)
34178 GREP_EXIT_CODE=$?
35179 set -e
36180
37- # grep exits with 0 if matches are found, 1 if no matches are found.
38- # A non-zero exit code other than 1 indicates an error.
39181 if [ $GREP_EXIT_CODE -eq 0 ]; then
40182 echo "❌ Found forbidden use of 'logger = logging.getLogger(__name__)'. Please use 'logger = logging.getLogger('google_adk.' + __name__)' instead."
41183 echo "The following files contain the forbidden pattern:"
@@ -58,10 +200,8 @@ jobs:
58200 echo ""
59201
60202 # Use grep -L to find files that DO NOT contain the pattern.
61- # This command will output a list of non-compliant files.
62203 FILES_MISSING_IMPORT=$(grep -L 'from __future__ import annotations' $CHANGED_FILES || true)
63204
64- # Check if the list of non-compliant files is empty
65205 if [ -z "$FILES_MISSING_IMPORT" ]; then
66206 echo "✅ All modified Python files include 'from __future__ import annotations'."
67207 exit 0
0 commit comments