Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ jobs:
run: uv run poe test -A --junitxml=pytest.xml
working-directory: ./python

- name: Run changed-package routing tests
run: >-
uv run --locked --group dev --group tool-runtime
python -m pytest scripts/tests/test_run_tasks_in_changed_packages.py --import-mode=importlib -q
working-directory: ./python

# Surface failing tests
- name: Surface failing tests
if: always()
Expand Down
13 changes: 7 additions & 6 deletions python/scripts/run_tasks_in_changed_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from pathlib import Path

from rich import print

from scripts.task_runner import build_work_items, discover_projects, run_tasks

# Tasks that need to run in all packages when core changes (type info propagates)
Expand All @@ -24,15 +25,15 @@ def get_changed_packages(
core_package_changed = False

for file_path in changed_files:
# Strip 'python/' prefix if present (when git diff is run from repo root)
file_path_str = str(file_path)
if file_path_str.startswith("python/"):
file_path_str = file_path_str[7:] # Remove 'python/' prefix
# Strip the repository prefix using native separators so POSIX backslashes remain filename characters.
file_path_obj = Path(file_path)
if file_path_obj.parts and file_path_obj.parts[0] == "python":
file_path_obj = Path(*file_path_obj.parts[1:])

# Convert to absolute path if relative
abs_path = Path(file_path_str)
abs_path = file_path_obj
if not abs_path.is_absolute():
abs_path = workspace_root / file_path_str
abs_path = workspace_root / file_path_obj

# Check which package this file belongs to
for project in projects:
Expand Down
67 changes: 67 additions & 0 deletions python/scripts/tests/test_run_tasks_in_changed_packages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Copyright (c) Microsoft. All rights reserved.

"""Regression tests for changed-package path routing."""

from __future__ import annotations

import os
from pathlib import Path

import pytest

from scripts.run_tasks_in_changed_packages import get_changed_packages

PROJECTS = [Path("packages/core"), Path("packages/redis")]


@pytest.mark.parametrize("package", ["core", "redis"])
@pytest.mark.parametrize("spelling", ["forward", "native", "dot-forward", "dot-native"])
def test_repository_relative_paths_select_package(tmp_path: Path, package: str, spelling: str) -> None:
workspace_root = tmp_path / "python"
relative = Path("python") / "packages" / package / "example.py"
paths = {
"forward": f"python/packages/{package}/example.py",
"native": str(relative),
"dot-forward": f"./python/packages/{package}/example.py",
"dot-native": f".{os.sep}{relative}",
}

assert get_changed_packages(PROJECTS, [paths[spelling]], workspace_root) == (
{Path("packages") / package},
package == "core",
)


def test_existing_workspace_relative_and_absolute_paths_select_core(tmp_path: Path) -> None:
workspace_root = tmp_path / "python"
relative = Path("packages/core/example.py")
paths = [
relative.as_posix(),
str(relative),
f"./{relative.as_posix()}",
f".{os.sep}{relative}",
str(workspace_root / relative),
]

for file_path in paths:
assert get_changed_packages(PROJECTS, [file_path], workspace_root) == ({PROJECTS[0]}, True), file_path


@pytest.mark.skipif(os.name != "nt", reason="UNC paths use native Windows semantics.")
def test_unc_absolute_path_selects_core() -> None:
workspace_root = Path(r"\\server\share\repo\python")
file_path = workspace_root / PROJECTS[0] / "example.py"

assert get_changed_packages(PROJECTS, [str(file_path)], workspace_root) == ({PROJECTS[0]}, True)


@pytest.mark.skipif(os.name == "nt", reason="Backslash is a path separator on Windows.")
def test_posix_literal_backslash_package_keeps_its_identity(tmp_path: Path) -> None:
workspace_root = tmp_path / "python"
literal_package = Path(r"packages/core\notes")
file_path = Path("python") / literal_package / "example.py"

assert get_changed_packages([*PROJECTS, literal_package], [str(file_path)], workspace_root) == (
{literal_package},
False,
)
Loading