|
11 | 11 | from pathlib import Path |
12 | 12 | from collections import defaultdict |
13 | 13 |
|
14 | | -def check_unique_paths(projects): |
15 | | - # build paths *must* be unique, otherwise parallel compilation will overwrite build artifacts |
| 14 | +repopath = lambda path: Path(__file__).parents[2] / path |
| 15 | +relpath = lambda path: os.path.relpath(path, repopath(".")) |
| 16 | + |
| 17 | +def check_builds_paths(projects): |
| 18 | + # Get all build paths |
16 | 19 | paths = defaultdict(list) |
17 | 20 | for project in projects: |
18 | 21 | match = re.search(r"<option name=\".*?:build.path\">(.*?)</option>", project.read_text()) |
19 | 22 | if match: |
20 | | - match = match.group(1); |
| 23 | + path = match.group(1) |
| 24 | + match = (project.parent / match.group(1)).resolve(); |
21 | 25 | else: |
22 | | - match = "build" |
23 | | - paths[match].append(project) |
| 26 | + path = "build" |
| 27 | + match = path |
| 28 | + paths[match].append( (project, path) ) |
24 | 29 |
|
25 | 30 | result = 0 |
26 | 31 | for path, projects in paths.items(): |
| 32 | + # Check that all build paths are unique, otherwise parallel compilation will overwrite build artifacts |
27 | 33 | if path == "build": |
28 | | - for project in projects: |
29 | | - print("'{}' has no build path set!".format(project), file=sys.stderr) |
| 34 | + for project, _ in projects: |
| 35 | + print("\nProject '{}' has no build path set!".format(relpath(project)), file=sys.stderr) |
30 | 36 | result += 1 |
| 37 | + # Check that all build paths are unique |
31 | 38 | elif len(projects) > 1: |
32 | | - print("The build path '{}' is used by these projects:".format(path), file=sys.stderr) |
33 | | - for project in projects: |
34 | | - print(" - '{}'".format(project), file=sys.stderr) |
| 39 | + print("\nThe build path '{}' is used by multiple projects:".format(path), file=sys.stderr) |
| 40 | + for project, bpath in projects: |
| 41 | + print(" - '{}': '{}'".format(relpath(project), bpath), file=sys.stderr) |
| 42 | + result += 1 |
| 43 | + # Check that all build paths are actually inside the build folder |
| 44 | + if len(projects): |
| 45 | + relbuildpath = os.path.relpath(path, repopath("build")) |
| 46 | + if relbuildpath.startswith(".."): |
| 47 | + print("\nThe build path '{}' is outside of the 'modm/build' folder!" |
| 48 | + .format(relpath(path)), file=sys.stderr) |
| 49 | + for project, bpath in projects: |
| 50 | + print(" - '{}': '{}'".format(relpath(project), bpath), file=sys.stderr) |
35 | 51 | result += 1 |
36 | 52 |
|
37 | 53 | return result |
38 | 54 |
|
| 55 | +def _get_paths_from_ci(files): |
| 56 | + paths = set() |
| 57 | + for file in files: |
| 58 | + matches = re.findall(r"examples_compile.py (.*?)\)", file.read_text()) |
| 59 | + paths |= set(m for match in matches for m in match.split(" ")) |
| 60 | + return paths |
39 | 61 |
|
40 | | -if __name__ == "__main__": |
41 | | - # Find all project files |
42 | | - projects = [p for path in sys.argv[1:] for p in Path(path).glob("**/project.xml")] |
| 62 | +def check_is_part_of_ci(projects): |
| 63 | + folders = set(p.relative_to(repopath("examples")).parts[0] for p in projects) |
| 64 | + result = 0 |
| 65 | + # Linux files |
| 66 | + paths = _get_paths_from_ci([repopath(".github/workflows/linux.yml")]) |
| 67 | + paths = folders - paths - {'rpi'} |
| 68 | + if paths: |
| 69 | + print("\nLinux CI is missing examples: '{}'" |
| 70 | + .format("', '".join(sorted(list(paths)))), file=sys.stderr) |
| 71 | + print(" Please add these example folders to the appropriate CI job in\n" |
| 72 | + " '.github/workflows/linux.yml'!") |
43 | 73 |
|
44 | | - result = check_unique_paths(projects) |
| 74 | + return len(paths) |
45 | 75 |
|
| 76 | +if __name__ == "__main__": |
| 77 | + # Find all project files |
| 78 | + projects = list(repopath("examples").rglob("*/project.xml")) |
| 79 | + # Run a bunch of checks on them |
| 80 | + result = check_builds_paths(projects) |
| 81 | + result += check_is_part_of_ci(projects) |
| 82 | + # Return code if any |
46 | 83 | exit(result) |
47 | 84 |
|
48 | 85 |
|
0 commit comments