Created
January 15, 2025 00:08
-
-
Save npwolf/d5acd0d2312a83714d85bb1c664cff1a to your computer and use it in GitHub Desktop.
Copy github autolinks from one repo to all repos in an organization
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import argparse | |
import subprocess | |
import requests | |
API_URL = "https://api.github.com" | |
def get_github_token(): | |
"""Fetch the GitHub token using 'gh auth token'.""" | |
try: | |
token = subprocess.check_output(["gh", "auth", "token"], text=True).strip() | |
if not token: | |
raise Exception("No token returned by 'gh auth token'") | |
return token | |
except subprocess.CalledProcessError as e: | |
print( | |
"Error fetching GitHub token. Ensure you're logged in using 'gh auth login'." | |
) | |
raise e | |
def get_repos(org, headers): | |
"""Fetch all repositories in the organization.""" | |
url = f"{API_URL}/orgs/{org}/repos" | |
repos = [] | |
params = {"per_page": 100} | |
while url: | |
response = requests.get(url, headers=headers, params=params) | |
response.raise_for_status() | |
repos.extend(response.json()) | |
url = response.links.get("next", {}).get("url") | |
return [repo["full_name"] for repo in repos] | |
def get_autolinks(repo, headers): | |
"""Fetch all autolinks for a repository.""" | |
url = f"{API_URL}/repos/{repo}/autolinks" | |
response = requests.get(url, headers=headers) | |
response.raise_for_status() | |
return response.json() | |
def add_autolink(repo, key_prefix, url_template, headers, dry_run): | |
"""Add an autolink to a repository.""" | |
if dry_run: | |
print( | |
f"[Dry Run] Would add autolink to {repo}: Prefix={key_prefix}, Template={url_template}" | |
) | |
return | |
url = f"{API_URL}/repos/{repo}/autolinks" | |
payload = {"key_prefix": key_prefix, "url_template": url_template} | |
response = requests.post(url, headers=headers, json=payload) | |
if response.status_code == 201: | |
print(f"Successfully added autolink to {repo}: Prefix={key_prefix}") | |
elif response.status_code == 422: | |
print(f"Autolink already exists in {repo}: Prefix={key_prefix}") | |
else: | |
print(f"Failed to add autolink to {repo}: Prefix={key_prefix}") | |
print(f"Error: {response.status_code} - {response.text}") | |
def main(): | |
parser = argparse.ArgumentParser( | |
description="Copy autolinks from one repo to all repos in an organization." | |
) | |
parser.add_argument("--org", required=True, help="The GitHub organization name.") | |
parser.add_argument( | |
"--source-repo", | |
required=True, | |
help="The source repository containing autolinks (in the given org).", | |
) | |
parser.add_argument( | |
"--dry-run", | |
action="store_true", | |
help="Simulate the process without making changes.", | |
) | |
args = parser.parse_args() | |
# Fetch GitHub token | |
token = get_github_token() | |
headers = { | |
"Authorization": f"Bearer {token}", | |
"Accept": "application/vnd.github+json", | |
} | |
# Fetch repositories in the organization | |
print(f"Fetching repositories for organization: {args.org}...") | |
repos = get_repos(args.org, headers) | |
# Fetch autolinks from the source repository | |
source_repo = f"{args.org}/{args.source_repo}" | |
print(f"Fetching autolinks from source repository: {source_repo}...") | |
source_autolinks = get_autolinks(source_repo, headers) | |
if not source_autolinks: | |
print("No autolinks found in the source repository.") | |
return | |
# Copy autolinks to all repositories | |
print("Copying autolinks to all repositories in the organization...") | |
for repo in repos: | |
print(f"Processing repository: {repo}") | |
existing_autolinks = get_autolinks(repo, headers) | |
existing_key_prefixes = { | |
autolink["key_prefix"] for autolink in existing_autolinks | |
} | |
for autolink in source_autolinks: | |
key_prefix = autolink["key_prefix"] | |
url_template = autolink["url_template"] | |
if key_prefix in existing_key_prefixes: | |
print( | |
f"Autolink with prefix {key_prefix} already exists in {repo}. Skipping." | |
) | |
else: | |
add_autolink(repo, key_prefix, url_template, headers, args.dry_run) | |
print("Autolink copying completed.") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment