query_module_versions.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #!/usr/bin/env python3
  2. """Queries latest module versions from MODULE.bazel."""
  3. __copyright__ = """
  4. Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  5. Exceptions. See /LICENSE for license information.
  6. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. """
  8. import json
  9. import re
  10. import subprocess
  11. import urllib.error
  12. import urllib.request
  13. def _query_bazel_deps(module_text: str) -> None:
  14. """Query BCR for `bazel_dep` rule versions."""
  15. bazel_dep_re = re.compile(
  16. r'bazel_dep\([^)]*name\s*=\s*"([^"]+)"[^)]*version\s*='
  17. )
  18. packages = sorted([m[1] for m in bazel_dep_re.finditer(module_text)])
  19. print("- BCR:")
  20. for pkg in packages:
  21. try:
  22. url = f"https://bcr.bazel.build/modules/{pkg}/metadata.json"
  23. with urllib.request.urlopen(url) as response:
  24. data = json.loads(response.read().decode())
  25. versions = data.get("versions", [])
  26. print(f" - {pkg}: {versions[-1] if versions else 'Unknown'}")
  27. except Exception as e:
  28. print(f" - {pkg}: Error {e}")
  29. def _query_archive_overrides(module_text: str) -> None:
  30. """Query Git for `archive_override` rule versions."""
  31. archive_re = re.compile(
  32. r"archive_override\(\s*"
  33. r'module_name\s*=\s*"([^"]+)".*?'
  34. r'urls\s*=\s*\["[^"]*?github\.com/([^/]+/[^/]+?)/archive',
  35. re.DOTALL,
  36. )
  37. github_tags = sorted(
  38. [
  39. (m[1], f"https://github.com/{m[2]}.git")
  40. for m in archive_re.finditer(module_text)
  41. ]
  42. )
  43. print("- GitHub Tag:")
  44. for pkg, url in github_tags:
  45. try:
  46. output = subprocess.check_output(
  47. ["git", "ls-remote", "--tags", url], text=True
  48. )
  49. # Find the latest tag by sorting them (excluding the ^{}
  50. # dereferenced tags).
  51. tags = [
  52. line.split("/")[-1]
  53. for line in output.splitlines()
  54. if not line.endswith("^{}")
  55. ]
  56. # Simple version sort (git-style) using split by common delimiters.
  57. tags.sort(
  58. key=lambda tag: [
  59. int(x) if x.isdigit() else x
  60. for x in re.split(r"(\d+)", tag)
  61. ]
  62. )
  63. latest_tag = tags[-1] if tags else "Unknown"
  64. print(f" - {pkg}: {latest_tag}")
  65. except Exception as e:
  66. print(f" - {pkg}: Error {e}")
  67. def _query_git_overrides(module_text: str) -> None:
  68. """Query GitHub for `git_override` rule versions."""
  69. git_re = re.compile(
  70. r"git_override\(\s*"
  71. r'module_name\s*=\s*"([^"]+)".*?'
  72. r'remote\s*=\s*"([^"]+)"',
  73. re.DOTALL,
  74. )
  75. git_repos = sorted([(m[1], m[2]) for m in git_re.finditer(module_text)])
  76. print("- Git HEAD:")
  77. for pkg, url in git_repos:
  78. try:
  79. output = subprocess.check_output(
  80. ["git", "ls-remote", url, "HEAD"], text=True
  81. )
  82. commit = output.split()[0]
  83. print(f" - {pkg}: {commit}")
  84. except Exception as e:
  85. print(f" - {pkg}: Error {e}")
  86. def main() -> None:
  87. with open("MODULE.bazel", "r") as f:
  88. module_text = f.read()
  89. _query_bazel_deps(module_text)
  90. _query_archive_overrides(module_text)
  91. _query_git_overrides(module_text)
  92. if __name__ == "__main__":
  93. main()