Skip to content

Commit b170f7b

Browse files
Jacksunweicopybara-github
authored andcommitted
chore(dev): add standalone pre-commit check script
Merge #6084 ## Summary Adds `scripts/run_precommit_checks.py` to run the `.pre-commit-config.yaml` checks **without** the `pre-commit` framework, which requires a git repository and so cannot run in environments such as a piper checkout that has no `.git`. - Parses `.pre-commit-config.yaml` so the file lists, global/per-hook `exclude` and `files` patterns, and `args` all come from the config — only the hook-id → CLI command mapping (and each hook's implicit file-type/text filter) is maintained in the script. - Defaults to fixing in place; pass `--check` to verify only (CI behavior). - Limits the walk to `src`/`tests`/`contributing`/`pyproject.toml` and never follows symlinks, so `.venv`, build artifacts, and out-of-repo code (e.g. a symlinked `a2a`) are never touched. - Skips binary files for text fixers, and batches arguments to stay under the OS arg limit. - `scripts/run_precommit.sh` is a thin wrapper that prefers an already-synced interpreter (`.venv` / active venv) before falling back to `uv run`. - Adds the standalone lint tools to the `dev` extra (capped at the next major) so `uv sync --extra dev` provides everything the script needs. ## Test plan - [ ] `scripts/run_precommit.sh --check` passes on a clean tree - [ ] `scripts/run_precommit.sh` (default fix mode) does not modify binaries (images/PDFs) or `.venv` - [ ] Runs from any directory; PATH args are repo-root-relative - [ ] `addlicense` / `check-new-py-prefix` degrade gracefully when unavailable / git-only Co-authored-by: Wei Sun (Jack) <weisun@google.com> COPYBARA_INTEGRATE_REVIEW=#6084 from google:chore/dev-precommit-script fa38633 PiperOrigin-RevId: 930799785
1 parent 62808f7 commit b170f7b

5 files changed

Lines changed: 483 additions & 113 deletions

File tree

.agents/skills/adk-unit-guide/SKILL.md

Lines changed: 0 additions & 76 deletions
This file was deleted.

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ repos:
88
- id: end-of-file-fixer
99
- id: trailing-whitespace
1010
- repo: https://github.com/tox-dev/pyproject-fmt
11-
rev: v2.5.0
11+
rev: v2.24.0
1212
hooks:
1313
- id: pyproject-fmt
1414
- repo: https://github.com/PyCQA/isort

pyproject.toml

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
[build-system]
22
build-backend = "flit_core.buildapi"
3-
43
# Build system specify which backend is used to build/install the project (flit,
54
# poetry, setuptools,...). All backends are supported by `pip install`
65
requires = [ "flit-core>=3.8,<4" ]
76

87
[project]
98
# Project metadata. Available keys are documented at:
109
# https://packaging.python.org/en/latest/specifications/declaring-project-metadata
11-
1210
name = "google-adk"
1311
description = "Agent Development Kit"
1412
readme = "README.md"
@@ -26,12 +24,12 @@ classifiers = [
2624
"Programming Language :: Python :: 3.11",
2725
"Programming Language :: Python :: 3.12",
2826
"Programming Language :: Python :: 3.13",
27+
"Programming Language :: Python :: 3.14",
2928
"Topic :: Software Development :: Libraries :: Python Modules",
3029
# List of https://pypi.org/classifiers/
3130
"Typing :: Typed",
3231
]
3332
dynamic = [ "version" ]
34-
3533
dependencies = [
3634
"aiosqlite>=0.21",
3735
"authlib>=1.6.6,<2",
@@ -58,7 +56,6 @@ dependencies = [
5856
"watchdog>=6,<7",
5957
"websockets>=15.0.1,<16",
6058
]
61-
6259
optional-dependencies.a2a = [
6360
"a2a-sdk>=0.3.4,<0.4",
6461
]
@@ -94,31 +91,35 @@ optional-dependencies.all = [
9491
"sqlalchemy>=2,<3",
9592
"sqlalchemy-spanner>=1.14",
9693
]
97-
9894
optional-dependencies.antigravity = [
9995
"google-antigravity>=0.1,<0.2",
10096
"protobuf>=6",
10197
]
102-
10398
optional-dependencies.community = [
10499
"google-adk-community",
105100
]
106-
107101
optional-dependencies.db = [
108102
"sqlalchemy>=2,<3",
109103
"sqlalchemy-spanner>=1.14",
110104
]
111-
112105
optional-dependencies.dev = [
113106
"flit>=3.10",
107+
# Lint tools used by scripts/run_precommit_checks.sh (which runs them directly,
108+
# without the pre-commit framework). Formatters that rewrite files are pinned
109+
# to the exact versions in .pre-commit-config.yaml so local runs produce
110+
# byte-identical output to CI.
111+
"isort==8.0.1",
112+
"mdformat==0.7.22",
113+
"mdformat-gfm",
114114
"mypy>=1.15",
115115
"pre-commit>=4",
116-
"pyink>=25.12",
116+
"pre-commit-hooks==4.6",
117+
"pyink==25.12",
117118
"pylint>=2.6",
119+
"pyproject-fmt==2.24",
118120
"tox>=4.23.2",
119121
"tox-uv>=1.33.2",
120122
]
121-
122123
optional-dependencies.docs = [
123124
"autodoc-pydantic",
124125
"furo",
@@ -128,7 +129,6 @@ optional-dependencies.docs = [
128129
"sphinx-click",
129130
"sphinx-rtd-theme",
130131
]
131-
132132
optional-dependencies.e2b = [
133133
"e2b>=2,<3", # For E2BEnvironment remote sandbox.
134134
]
@@ -140,7 +140,6 @@ optional-dependencies.eval = [
140140
"rouge-score>=0.1.2",
141141
"tabulate>=0.9",
142142
]
143-
144143
optional-dependencies.extensions = [
145144
"anthropic>=0.78", # For anthropic model support; 0.78 introduced ThinkingConfigAdaptiveParam (required for Claude Opus 4.7).
146145
"beautifulsoup4>=3.2.2", # For load_web_page tool.
@@ -157,7 +156,6 @@ optional-dependencies.extensions = [
157156
"pypika>=0.50",
158157
"toolbox-adk>=1,<2",
159158
]
160-
161159
optional-dependencies.gcp = [
162160
"google-cloud-aiplatform[agent-engines]>=1.148.1,<2",
163161
"google-cloud-bigquery>=2.2",
@@ -180,12 +178,10 @@ optional-dependencies.gcp = [
180178
"pyarrow>=14",
181179
"python-dateutil>=2.9.0.post0,<3",
182180
]
183-
184181
optional-dependencies.mcp = [
185182
"anyio>=4.9,<5",
186183
"mcp>=1.24,<2",
187184
]
188-
189185
optional-dependencies.otel-gcp = [
190186
"opentelemetry-instrumentation-google-genai>=0.6b0,<1",
191187
"opentelemetry-instrumentation-grpc>=0.43b0,<1",
@@ -248,45 +244,40 @@ optional-dependencies.test = [
248244
"tabulate>=0.9",
249245
"tomli>=2,<3; python_version<'3.11'",
250246
]
251-
252247
optional-dependencies.toolbox = [ "toolbox-adk>=1,<2" ]
253-
254248
optional-dependencies.tools = [
255249
"google-api-python-client>=2.157,<3",
256250
]
257-
258251
urls.changelog = "https://github.com/google/adk-python/blob/main/CHANGELOG.md"
259252
urls.documentation = "https://google.github.io/adk-docs/"
260253
urls.homepage = "https://google.github.io/adk-docs/"
261254
urls.repository = "https://github.com/google/adk-python"
262255
scripts.adk = "google.adk.cli:main"
263256

264-
[tool.flit.sdist]
265-
include = [ 'src/**/*', 'README.md', 'pyproject.toml', 'LICENSE' ]
266-
exclude = [ 'src/**/*.sh', 'src/**/README.md' ]
267-
268-
[tool.flit.module]
269-
name = "google.adk"
270-
include = [ "py.typed" ]
257+
[tool.flit]
258+
module.name = "google.adk"
259+
module.include = [ "py.typed" ]
260+
sdist.include = [ "src/**/*", "README.md", "pyproject.toml", "LICENSE" ]
261+
sdist.exclude = [ "src/**/*.sh", "src/**/README.md" ]
271262

272263
[tool.isort]
273264
profile = "google"
274-
single_line_exclusions = [ ]
275265
line_length = 200
276-
known_third_party = [ "google.adk", "a2a" ]
277-
278-
[tool.pytest.ini_options]
279-
testpaths = [ "tests" ]
280-
asyncio_default_fixture_loop_scope = "function"
281-
asyncio_mode = "auto"
266+
single_line_exclusions = []
267+
known_third_party = [ "a2a", "google.adk" ]
282268

283269
[tool.mypy]
270+
exclude = [ "contributing/samples/", "tests/" ]
271+
follow_imports = "skip"
284272
python_version = "3.11"
285-
exclude = [ "tests/", "contributing/samples/" ]
286-
plugins = [ "pydantic.mypy" ]
287-
strict = true
288273
disable_error_code = [ "import-not-found", "import-untyped", "unused-ignore" ]
289-
follow_imports = "skip"
274+
strict = true
275+
plugins = [ "pydantic.mypy" ]
276+
277+
[tool.pytest]
278+
ini_options.testpaths = [ "tests" ]
279+
ini_options.asyncio_default_fixture_loop_scope = "function"
280+
ini_options.asyncio_mode = "auto"
290281

291282
[tool.pyink]
292283
line-length = 80

scripts/run_precommit.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/bash
2+
# Copyright 2026 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
# Convenience wrapper for scripts/run_precommit_checks.py.
17+
#
18+
# scripts/run_precommit.sh # auto-fix everything (default)
19+
# scripts/run_precommit.sh --check # verify only, no changes (like CI)
20+
# scripts/run_precommit.sh src tests # auto-fix specific paths
21+
#
22+
# Picks an interpreter that already has the dev tools installed, in order:
23+
# 1. the repo's .venv (created by `uv sync --extra dev`)
24+
# 2. an active virtualenv ($VIRTUAL_ENV)
25+
# 3. `uv run --extra dev` (resolves/syncs on the fly; slower)
26+
# 4. plain python3
27+
# This avoids re-running `uv run` (which re-resolves the environment) when a
28+
# synced interpreter is already available.
29+
set -euo pipefail
30+
31+
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
32+
checker="${repo_root}/scripts/run_precommit_checks.py"
33+
34+
if [[ -x "${repo_root}/.venv/bin/python" ]]; then
35+
exec "${repo_root}/.venv/bin/python" "${checker}" "$@"
36+
elif [[ -n "${VIRTUAL_ENV:-}" && -x "${VIRTUAL_ENV}/bin/python" ]]; then
37+
exec "${VIRTUAL_ENV}/bin/python" "${checker}" "$@"
38+
elif command -v uv >/dev/null 2>&1; then
39+
exec uv run --extra dev python "${checker}" "$@"
40+
else
41+
exec python3 "${checker}" "$@"
42+
fi

0 commit comments

Comments
 (0)