manifest_resource_summary.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import os
  2. import glob
  3. import json
  4. import base64
  5. import requests
  6. import xml.etree.ElementTree as ET
  7. from collections import defaultdict
  8. CONFIG_DIR = ".github/kernel-config"
  9. MANIFEST_URL_TEMPLATE = "https://android.googlesource.com/kernel/manifest/+/refs/heads/common-{branch}/default.xml?format=TEXT"
  10. # Gather all kernel versions from config files
  11. kernel_versions = set()
  12. config_map = {} # kernel_version -> config file
  13. for config_path in glob.glob(os.path.join(CONFIG_DIR, "*.json")):
  14. with open(config_path) as f:
  15. data = json.load(f)
  16. for entry in data.get("include", []):
  17. ver = entry.get("kernel_version")
  18. if ver:
  19. kernel_versions.add(ver)
  20. config_map[ver] = os.path.basename(config_path)
  21. # Map kernel_version to manifest branch name
  22. def kernel_version_to_branch(ver):
  23. # e.g. 6.1.25-android14-2023-06 -> android14-6.1-2023-06
  24. m = None
  25. import re
  26. m = re.match(r"([\d.]+)-android(\d+)-(\d{4}-\d{2}|lts|exp)", ver)
  27. if m:
  28. kver, android, date = m.groups()
  29. return f"android{android}-{kver}-{date}"
  30. return None
  31. manifest_details = defaultdict(lambda: defaultdict(dict))
  32. # manifest_details[(name, path)][kernel_version] = {"tool": ..., "revision": ...}
  33. for ver in sorted(kernel_versions):
  34. branch = kernel_version_to_branch(ver)
  35. if not branch:
  36. print(f"Could not parse branch for kernel version: {ver}")
  37. continue
  38. url = MANIFEST_URL_TEMPLATE.format(branch=branch)
  39. print(f"Fetching manifest for {ver} ({branch})")
  40. resp = requests.get(url)
  41. if resp.status_code != 200:
  42. print(f"Failed to fetch {url}")
  43. continue
  44. xml_content = base64.b64decode(resp.content).decode("utf-8")
  45. root = ET.fromstring(xml_content)
  46. for project in root.findall("project"):
  47. name = project.get("name")
  48. path = project.get("path", name)
  49. tool = project.get("tool", "")
  50. revision = project.get("revision", "")
  51. manifest_details[(name, path)][ver] = {"tool": tool, "revision": revision}
  52. # Output detailed table
  53. with open("manifest_resource_summary.md", "w") as f:
  54. f.write("| Resource Name | Path | Kernel Version | Tool | Revision |\n")
  55. f.write("|--------------|------|---------------|------|----------|\n")
  56. for (name, path), ver_map in sorted(manifest_details.items()):
  57. for ver, attrs in sorted(ver_map.items()):
  58. tool = attrs.get("tool", "")
  59. revision = attrs.get("revision", "")
  60. f.write(f"| `{name}` | `{path}` | `{ver}` | `{tool}` | `{revision}` |\n")
  61. # Optionally, add a summary for resources with differing tool/revision
  62. f.write("\n## Resources with differing tool or revision across kernel versions\n\n")
  63. for (name, path), ver_map in sorted(manifest_details.items()):
  64. tools = set(attrs.get("tool", "") for attrs in ver_map.values())
  65. revisions = set(attrs.get("revision", "") for attrs in ver_map.values())
  66. if len(tools) > 1 or len(revisions) > 1:
  67. f.write(f"- `{name}` (`{path}`):\n")
  68. for ver, attrs in sorted(ver_map.items()):
  69. tool = attrs.get("tool", "")
  70. revision = attrs.get("revision", "")
  71. f.write(f" - {ver}: tool=`{tool}` revision=`{revision}`\n")
  72. print("Summary written to manifest_resource_summary.md")