Skip to content

Instantly share code, notes, and snippets.

@danielscholl
Last active November 17, 2024 15:43
Show Gist options
  • Save danielscholl/e4a31401d59216aaccd80e8f0254c08a to your computer and use it in GitHub Desktop.
Save danielscholl/e4a31401d59216aaccd80e8f0254c08a to your computer and use it in GitHub Desktop.
Retrieve list of Bicep Modules and versions.
import requests
class ACRVersionChecker:
def __init__(self, base_url: str = "https://mcr.microsoft.com"):
self.catalog_url = f"{base_url}/v2/_catalog"
self.tag_list_base_url = f"{base_url}/v2"
def fetch_catalog(self):
"""Fetch the list of repositories from MCR."""
print("Fetching repository catalog...")
try:
response = requests.get(self.catalog_url)
if response.status_code == 200:
return response.json().get("repositories", [])
print(f"Failed to fetch catalog. Status code: {response.status_code}")
return []
except Exception as e:
print(f"Failed to fetch catalog: {str(e)}")
return []
def fetch_tags(self, repo):
"""Fetch tags for a specific repository."""
tags_url = f"{self.tag_list_base_url}/{repo}/tags/list"
try:
response = requests.get(tags_url)
if response.status_code == 200:
return response.json().get("tags", [])
print(f"Failed to fetch tags. Status code: {response.status_code}")
return []
except Exception as e:
print(f"Failed to fetch tags for {repo}: {str(e)}")
return []
def parse_version(self, version_str):
"""Parse version string into tuple for proper sorting."""
try:
return tuple(map(int, version_str.split('.')))
except (ValueError, AttributeError):
return (0, 0, 0)
def get_latest_version(self, tags):
"""Get the latest version from a list of tags using semantic versioning."""
if not tags:
return None
try:
sorted_versions = sorted(tags, key=self.parse_version)
return sorted_versions[-1]
except Exception as e:
print(f"Error sorting versions: {str(e)}")
return None
def find_latest_module_versions(self, module_type="res"):
"""
Find the latest versions of all modules with the given type.
Args:
module_type (str): Type of modules to search for ('res' or 'ptn')
"""
prefix = f"bicep/avm/{module_type}/"
catalog = self.fetch_catalog()
if not catalog:
print("Failed to fetch catalog or catalog is empty")
return {}
matching_repos = [repo for repo in catalog if repo.startswith(prefix)]
if not matching_repos:
print(f"No repositories found matching prefix: {prefix}")
return {}
results = {}
total = len(matching_repos)
print(f"Found {total} matching repositories")
for index, repo in enumerate(matching_repos, 1):
print(f"Processing repository {index}/{total}: {repo}")
tags = self.fetch_tags(repo)
latest_version = self.get_latest_version(tags)
if latest_version:
# Just use the full repo path as the key
results[repo] = latest_version
else:
print(f"No valid version tags found for: {repo}")
return results
def main():
checker = ACRVersionChecker()
results = checker.find_latest_module_versions("res")
with open('modules.md', 'w') as f:
f.write("# Azure Verified Modules - Latest Versions\n\n")
if results:
f.write("## Resource Modules\n\n")
f.write("| Module | Version |\n")
f.write("|--------|----------|\n")
for repo, version in sorted(results.items()):
# Create the hyperlink URL by replacing the MCR path with GitHub path
github_url = f"https://github.com/Azure/bicep-registry-modules/tree/main/avm/{repo.replace('bicep/avm/', '')}"
f.write(f"| [{repo}]({github_url}) | {version} |\n")
else:
f.write("No results found\n")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment