diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 70a10ca..195188b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,27 +3,34 @@ # SPDX-License-Identifier: GPL-3.0-or-later repos: - - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.2 - hooks: - - id: ruff - args: [--fix] - files: ^(src|tests)/ - - id: ruff-format - files: ^(src|tests)/ - - repo: local hooks: + - id: lint + name: lint + language: system + entry: make lint + pass_filenames: false + + - id: format-check + name: format-check + language: system + entry: make format-check + pass_filenames: false + - id: license-headers - name: Check license headers - language: python - entry: python scripts/check_license_headers.py - files: \.py$ + name: license-headers + language: system + entry: make license + pass_filenames: false + + - id: security + name: security + language: system + entry: make security pass_filenames: false - - id: bandit - name: bandit security scan - language: python - entry: python -m bandit -r src/ipsdk --configfile pyproject.toml - files: ^src/ipsdk/ + - id: typecheck + name: typecheck + language: system + entry: make typecheck pass_filenames: false diff --git a/AGENTS.md b/AGENTS.md index 62e1aff..2aea7a1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -45,6 +45,7 @@ Port auto-resolution: if `port=0` (default), uses 443 for TLS, 80 without. Ports ```bash # Setup: requires uv uv sync --all-extras --dev +make hooks # Install pre-commit hooks (once after cloning) # Daily workflow make test # pytest @@ -98,10 +99,6 @@ CI (`ci.yaml`): runs lint, format-check, typecheck, security, license, then a ma - Gateway: always basic auth. Defaults are `user="admin@itential"`, `password="admin"`. No OAuth support; `client_id`/`client_secret` are not accepted. - Never mix OAuth + basic auth params. -## Known Issues - -**Missing `.pre-commit-config.yaml`**: `pre-commit` is listed as a dev dependency but the config file doesn't exist in the repo. - ## Gotchas - `want_async=False` by default — easy to forget when you need async diff --git a/Makefile b/Makefile index d801289..cf06419 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,7 @@ build: ## Build distribution packages (wheel + sdist) # Quality checks # ------------------------------------------------------------------------------ -.PHONY: lint format format-check ruff-fix security typecheck license license-fix notice-check +.PHONY: hooks lint format format-check ruff-fix security typecheck license license-fix notice-check typecheck: ## Run mypy static type checking $(UV) run mypy $(SRC) @@ -79,6 +79,9 @@ license: ## Check all Python files for license headers license-fix: ## Add missing license headers to Python files $(UV) run python $(SCRIPTS)/check_license_headers.py --fix +hooks: ## Install pre-commit hooks (run once after cloning) + $(UV) run pre-commit install + notice-check: ## Verify NOTICE file lists all packages in uv.lock @echo "Packages in uv.lock not mentioned in NOTICE:" @grep -E '^name = "' uv.lock | sed 's/name = "\(.*\)"/\1/' | \ diff --git a/pyproject.toml b/pyproject.toml index 2d663b1..5de8ad6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,7 @@ dev = [ "coverage", "build", "bandit[toml]", + "pre-commit", "tox", "tox-uv", ] diff --git a/uv.lock b/uv.lock index 917a958..695d8bb 100644 --- a/uv.lock +++ b/uv.lock @@ -79,6 +79,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" }, ] +[[package]] +name = "cfgv" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -273,6 +282,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, ] +[[package]] +name = "identify" +version = "2.6.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/46/c4/7fb4db12296cdb11893d61c92048fe617ee853f8523b9b296ac03b43757e/identify-2.6.18.tar.gz", hash = "sha256:873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd", size = 99580, upload-time = "2026-03-15T18:39:50.319Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl", hash = "sha256:8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737", size = 99394, upload-time = "2026-03-15T18:39:48.915Z" }, +] + [[package]] name = "idna" version = "3.11" @@ -316,6 +334,7 @@ dev = [ { name = "build" }, { name = "coverage" }, { name = "mypy" }, + { name = "pre-commit" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, @@ -333,6 +352,7 @@ dev = [ { name = "build" }, { name = "coverage" }, { name = "mypy" }, + { name = "pre-commit" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, @@ -502,6 +522,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] +[[package]] +name = "nodeenv" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, +] + [[package]] name = "packaging" version = "26.0" @@ -538,6 +567,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] +[[package]] +name = "pre-commit" +version = "4.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61", size = 198232, upload-time = "2025-12-16T21:14:33.552Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" }, +] + [[package]] name = "pygments" version = "2.19.2"