From 82ae1097a2e07d233ff371872a34f7a073d1616e Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Tue, 10 Feb 2026 10:38:15 -0500 Subject: [PATCH 1/7] feat: Improve local dev experience with file-aware hooks and auto parallelization - Make precommit hooks file-aware: format and lint only changed Python files - Add conditional template hook that only runs when template files change - Update test-python-integration-local to use -n auto and --dist loadscope - Add new pytest markers: slow, cloud, local_only for better test selection - Add format-python-files and lint-python-files Makefile targets Co-Authored-By: Claude Opus 4.5 --- .pre-commit-config.yaml | 24 ++++++++++++++++-------- Makefile | 20 +++++++++++++++++++- sdk/python/pytest.ini | 3 +++ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af07798bf1f..de3fa5dad96 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,21 +3,29 @@ default_stages: [commit] repos: - repo: local hooks: - - id: format - name: Format + # File-aware format hook - only runs on changed Python files + - id: format-files + name: Format Changed Files stages: [commit] language: system - entry: make format-python - pass_filenames: false - - id: lint - name: Lint + types: [python] + entry: uv run ruff check --fix + pass_filenames: true + + # File-aware lint hook - only runs on changed Python files + - id: lint-files + name: Lint Changed Files stages: [commit] language: system - entry: make lint-python - pass_filenames: false + types: [python] + entry: uv run ruff check + pass_filenames: true + + # Conditional template hook - only runs when template files change - id: template name: Build Templates stages: [commit] language: system + files: ^infra/templates/|\.jinja2$ entry: make build-templates pass_filenames: false diff --git a/Makefile b/Makefile index 2ae9a07a246..4c196ffd2a6 100644 --- a/Makefile +++ b/Makefile @@ -58,11 +58,29 @@ format-python: ## Format Python code uv run ruff check --fix sdk/python/feast/ sdk/python/tests/ uv run ruff format sdk/python/feast/ sdk/python/tests/ +# File-aware format (for use with pre-commit, accepts file args) +format-python-files: ## Format specified Python files + @if [ -n "$(FILES)" ]; then \ + uv run ruff check --fix $(FILES); \ + uv run ruff format $(FILES); \ + else \ + echo "Usage: make format-python-files FILES='file1.py file2.py'"; \ + fi + lint-python: ## Lint Python code uv run ruff check sdk/python/feast/ sdk/python/tests/ uv run ruff format --check sdk/python/feast/ sdk/python/tests/ uv run bash -c "cd sdk/python && mypy feast" +# File-aware lint (for use with pre-commit, accepts file args) +lint-python-files: ## Lint specified Python files + @if [ -n "$(FILES)" ]; then \ + uv run ruff check $(FILES); \ + uv run ruff format --check $(FILES); \ + else \ + echo "Usage: make lint-python-files FILES='file1.py file2.py'"; \ + fi + # New combined target precommit-check: format-python lint-python ## Run all precommit checks @echo "✅ All precommit checks passed" @@ -209,7 +227,7 @@ test-python-integration-local: ## Run Python integration tests (local dev mode) HADOOP_HOME=$$HOME/hadoop \ CLASSPATH="$$( $$HADOOP_HOME/bin/hadoop classpath --glob ):$$CLASSPATH" \ HADOOP_USER_NAME=root \ - uv run python -m pytest --tb=short -v -n 8 --color=yes --integration --durations=10 --timeout=1200 --timeout_method=thread --dist loadgroup \ + uv run python -m pytest --tb=short -v -n auto --color=yes --integration --durations=10 --timeout=1200 --timeout_method=thread --dist loadscope \ -k "not test_lambda_materialization and not test_snowflake_materialization" \ -m "not rbac_remote_integration_test" \ --log-cli-level=INFO -s \ diff --git a/sdk/python/pytest.ini b/sdk/python/pytest.ini index 3182cd991f6..31640e509d7 100644 --- a/sdk/python/pytest.ini +++ b/sdk/python/pytest.ini @@ -17,6 +17,9 @@ markers = rbac_remote_integration_test: RBAC and remote functionality tests integration: Integration tests (slower, requires services) benchmark: Benchmark tests + slow: Tests taking >30 seconds + cloud: Tests requiring cloud credentials + local_only: Tests that run entirely locally timeout = 300 timeout_method = thread From d2c57c108148068819356491bdd3fcb11f5412b2 Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Tue, 10 Feb 2026 12:07:38 -0500 Subject: [PATCH 2/7] fix: Address review feedback on pre-commit hooks - Format hook now runs both ruff check --fix AND ruff format - Lint hook now runs both ruff check AND ruff format --check - Template hook file filter now includes docs/roadmap.md Co-Authored-By: Claude Opus 4.5 --- .pre-commit-config.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index de3fa5dad96..5d7a63c7f57 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,28 +4,30 @@ repos: - repo: local hooks: # File-aware format hook - only runs on changed Python files + # Runs both ruff check --fix and ruff format - id: format-files name: Format Changed Files stages: [commit] language: system types: [python] - entry: uv run ruff check --fix + entry: bash -c 'uv run ruff check --fix "$@" && uv run ruff format "$@"' -- pass_filenames: true # File-aware lint hook - only runs on changed Python files + # Runs both ruff check and ruff format --check - id: lint-files name: Lint Changed Files stages: [commit] language: system types: [python] - entry: uv run ruff check + entry: bash -c 'uv run ruff check "$@" && uv run ruff format --check "$@"' -- pass_filenames: true - # Conditional template hook - only runs when template files change + # Conditional template hook - only runs when template files or roadmap change - id: template name: Build Templates stages: [commit] language: system - files: ^infra/templates/|\.jinja2$ + files: ^infra/templates/|\.jinja2$|^docs/roadmap\.md$ entry: make build-templates pass_filenames: false From 6cf622ecb79463cae8f4653b5a80fff435dc602b Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Tue, 10 Feb 2026 13:57:15 -0500 Subject: [PATCH 3/7] fix: Restore --dist loadgroup to preserve xdist_group markers The codebase uses xdist_group markers extensively for test isolation (Ray OOM prevention, database registry tests, etc). The loadscope distribution mode ignores these markers, so restore loadgroup. Co-Authored-By: Claude Opus 4.5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4c196ffd2a6..a230a89cdb4 100644 --- a/Makefile +++ b/Makefile @@ -227,7 +227,7 @@ test-python-integration-local: ## Run Python integration tests (local dev mode) HADOOP_HOME=$$HOME/hadoop \ CLASSPATH="$$( $$HADOOP_HOME/bin/hadoop classpath --glob ):$$CLASSPATH" \ HADOOP_USER_NAME=root \ - uv run python -m pytest --tb=short -v -n auto --color=yes --integration --durations=10 --timeout=1200 --timeout_method=thread --dist loadscope \ + uv run python -m pytest --tb=short -v -n auto --color=yes --integration --durations=10 --timeout=1200 --timeout_method=thread --dist loadgroup \ -k "not test_lambda_materialization and not test_snowflake_materialization" \ -m "not rbac_remote_integration_test" \ --log-cli-level=INFO -s \ From a7b03b55f913cae4fe1e4e9fe762c17af83b6b39 Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Thu, 12 Feb 2026 12:10:17 -0500 Subject: [PATCH 4/7] Update Makefile Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a230a89cdb4..b2359ad0cf6 100644 --- a/Makefile +++ b/Makefile @@ -75,12 +75,13 @@ lint-python: ## Lint Python code # File-aware lint (for use with pre-commit, accepts file args) lint-python-files: ## Lint specified Python files @if [ -n "$(FILES)" ]; then \ - uv run ruff check $(FILES); \ + uv run ruff check $(FILES) && \ uv run ruff format --check $(FILES); \ else \ echo "Usage: make lint-python-files FILES='file1.py file2.py'"; \ fi + # New combined target precommit-check: format-python lint-python ## Run all precommit checks @echo "✅ All precommit checks passed" From cd398ca9ec49e909cf98b55971ff59e2531f9b1e Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Thu, 12 Feb 2026 12:10:44 -0500 Subject: [PATCH 5/7] Update Makefile Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b2359ad0cf6..755eb9820be 100644 --- a/Makefile +++ b/Makefile @@ -61,12 +61,13 @@ format-python: ## Format Python code # File-aware format (for use with pre-commit, accepts file args) format-python-files: ## Format specified Python files @if [ -n "$(FILES)" ]; then \ - uv run ruff check --fix $(FILES); \ + uv run ruff check --fix $(FILES) && \ uv run ruff format $(FILES); \ else \ echo "Usage: make format-python-files FILES='file1.py file2.py'"; \ fi + lint-python: ## Lint Python code uv run ruff check sdk/python/feast/ sdk/python/tests/ uv run ruff format --check sdk/python/feast/ sdk/python/tests/ From 7f10bcc3639f70079569b79fd56d6b791bc458eb Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Thu, 12 Feb 2026 13:51:27 -0500 Subject: [PATCH 6/7] fix: Use --dist loadgroup in test-python-integration-parallel Apply the same fix as test-python-integration-local to preserve xdist_group markers for test isolation (Ray OOM prevention, database registry conflicts, etc). Co-Authored-By: Claude Opus 4.5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 755eb9820be..c4e8dc71903 100644 --- a/Makefile +++ b/Makefile @@ -219,7 +219,7 @@ test-python-integration: ## Run Python integration tests (CI) # Integration tests with better parallelization test-python-integration-parallel: ## Run integration tests with enhanced parallelization uv run python -m pytest sdk/python/tests/integration \ - -n auto --dist loadscope \ + -n auto --dist loadgroup \ --timeout=300 --tb=short -v \ --integration --color=yes --durations=20 From 13dc09014d3b91de9e15bbecb0ac0f158209132c Mon Sep 17 00:00:00 2001 From: Francisco Javier Arceo Date: Thu, 12 Feb 2026 14:34:20 -0500 Subject: [PATCH 7/7] chore: Remove unused format-python-files and lint-python-files targets These Makefile targets were added but never wired up to pre-commit. Pre-commit passes filenames as positional arguments, but Make expects FILES="..." variable syntax. The inline bash commands in pre-commit work correctly, so these targets are dead code. Co-Authored-By: Claude Opus 4.5 --- Makefile | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/Makefile b/Makefile index c4e8dc71903..3360e88f6a2 100644 --- a/Makefile +++ b/Makefile @@ -58,31 +58,11 @@ format-python: ## Format Python code uv run ruff check --fix sdk/python/feast/ sdk/python/tests/ uv run ruff format sdk/python/feast/ sdk/python/tests/ -# File-aware format (for use with pre-commit, accepts file args) -format-python-files: ## Format specified Python files - @if [ -n "$(FILES)" ]; then \ - uv run ruff check --fix $(FILES) && \ - uv run ruff format $(FILES); \ - else \ - echo "Usage: make format-python-files FILES='file1.py file2.py'"; \ - fi - - lint-python: ## Lint Python code uv run ruff check sdk/python/feast/ sdk/python/tests/ uv run ruff format --check sdk/python/feast/ sdk/python/tests/ uv run bash -c "cd sdk/python && mypy feast" -# File-aware lint (for use with pre-commit, accepts file args) -lint-python-files: ## Lint specified Python files - @if [ -n "$(FILES)" ]; then \ - uv run ruff check $(FILES) && \ - uv run ruff format --check $(FILES); \ - else \ - echo "Usage: make lint-python-files FILES='file1.py file2.py'"; \ - fi - - # New combined target precommit-check: format-python lint-python ## Run all precommit checks @echo "✅ All precommit checks passed"