forked from microsoft/agent-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun_tasks_in_changed_packages.py
More file actions
133 lines (105 loc) · 4.74 KB
/
run_tasks_in_changed_packages.py
File metadata and controls
133 lines (105 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Copyright (c) Microsoft. All rights reserved.
"""Run a task only in packages that have changed files."""
import argparse
import glob
import sys
from pathlib import Path
import tomli
from poethepoet.app import PoeThePoet
from rich import print
def discover_projects(workspace_pyproject_file: Path) -> list[Path]:
with workspace_pyproject_file.open("rb") as f:
data = tomli.load(f)
projects = data["tool"]["uv"]["workspace"]["members"]
exclude = data["tool"]["uv"]["workspace"].get("exclude", [])
all_projects: list[Path] = []
for project in projects:
if "*" in project:
globbed = glob.glob(str(project), root_dir=workspace_pyproject_file.parent)
globbed_paths = [Path(p) for p in globbed]
all_projects.extend(globbed_paths)
else:
all_projects.append(Path(project))
for project in exclude:
if "*" in project:
globbed = glob.glob(str(project), root_dir=workspace_pyproject_file.parent)
globbed_paths = [Path(p) for p in globbed]
all_projects = [p for p in all_projects if p not in globbed_paths]
else:
all_projects = [p for p in all_projects if p != Path(project)]
return all_projects
def extract_poe_tasks(file: Path) -> set[str]:
with file.open("rb") as f:
data = tomli.load(f)
tasks = set(data.get("tool", {}).get("poe", {}).get("tasks", {}).keys())
# Check if there is an include too
include: str | None = data.get("tool", {}).get("poe", {}).get("include", None)
if include:
include_file = file.parent / include
if include_file.exists():
tasks = tasks.union(extract_poe_tasks(include_file))
return tasks
def get_changed_packages(projects: list[Path], changed_files: list[str], workspace_root: Path) -> set[Path]:
"""Determine which packages have changed files."""
changed_packages: set[Path] = set()
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
# Convert to absolute path if relative
abs_path = Path(file_path_str)
if not abs_path.is_absolute():
abs_path = workspace_root / file_path_str
# Check which package this file belongs to
for project in projects:
project_abs = workspace_root / project
try:
# Check if the file is within this project directory
abs_path.relative_to(project_abs)
changed_packages.add(project)
# Check if the core package was changed
if project == Path("packages/core"):
core_package_changed = True
break
except ValueError:
# File is not in this project
continue
# If core package changed, check all packages
if core_package_changed:
print("[yellow]Core package changed - checking all packages[/yellow]")
return set(projects)
return changed_packages
def main() -> None:
parser = argparse.ArgumentParser(description="Run a task only in packages with changed files.")
parser.add_argument("task", help="The task name to run")
parser.add_argument("files", nargs="*", help="Changed files to determine which packages to run")
args = parser.parse_args()
pyproject_file = Path(__file__).parent / "pyproject.toml"
workspace_root = pyproject_file.parent
projects = discover_projects(pyproject_file)
# If no files specified, run in all packages (default behavior)
if not args.files or args.files == ["."]:
print(f"[yellow]No specific files provided, running {args.task} in all packages[/yellow]")
changed_packages = set(projects)
else:
changed_packages = get_changed_packages(projects, args.files, workspace_root)
if changed_packages:
print(f"[cyan]Detected changes in packages: {', '.join(str(p) for p in sorted(changed_packages))}[/cyan]")
else:
print(f"[yellow]No changes detected in any package, skipping {args.task}[/yellow]")
return
# Run the task in changed packages
for project in sorted(changed_packages):
tasks = extract_poe_tasks(project / "pyproject.toml")
if args.task in tasks:
print(f"Running task {args.task} in {project}")
app = PoeThePoet(cwd=project)
result = app(cli_args=[args.task])
if result:
sys.exit(result)
else:
print(f"Task {args.task} not found in {project}")
if __name__ == "__main__":
main()