Last active
March 21, 2026 06:45
-
-
Save monperrus/e2fd9910348b8ccbe23dc85a41c565c7 to your computer and use it in GitHub Desktop.
Python script to enable GitHub sponsorships for all repositories in an organization using the GraphQL mutation API.
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 | |
| """Enable GitHub sponsorships for all repositories in an organization. | |
| This script: | |
| - Reads a GitHub personal access token from the local keyring | |
| - Lists all repositories in the configured organization | |
| - Skips archived repositories | |
| - Enables the sponsorship button on each remaining repository via the GitHub API | |
| Requirements: | |
| - A valid GitHub token stored in keyring under service "login2" and key "github_token" | |
| - Permissions to read organization repositories and update repository settings | |
| url: https://gist.github.com/monperrus/e2fd9910348b8ccbe23dc85a41c565c7 | |
| License: public domain | |
| """ | |
| import requests | |
| import json | |
| import keyring | |
| # --- CONFIGURATION --- | |
| GITHUB_TOKEN = keyring.get_password("login2", "github_token") | |
| ORG_NAME = "SpoonLabs" | |
| # --------------------- | |
| BASE_URL = "https://api.github.com" | |
| HEADERS = { | |
| "Authorization": f"Bearer {GITHUB_TOKEN}", | |
| "Accept": "application/vnd.github+json", | |
| } | |
| def get_all_repos(org): | |
| """Fetches all repositories for the organization using the REST API.""" | |
| repos = [] | |
| page = 1 | |
| while True: | |
| url = f"{BASE_URL}/orgs/{org}/repos?per_page=100&page={page}" | |
| response = requests.get(url, headers=HEADERS) | |
| if response.status_code != 200: | |
| print(f"Error fetching repos: {response.text}") | |
| break | |
| data = response.json() | |
| if not data: | |
| break | |
| repos.extend(data) | |
| page += 1 | |
| return repos | |
| def enable_sponsorship(node_id, repo_name): | |
| """Enables the sponsorship button via GraphQL mutation.""" | |
| query = """ | |
| mutation($input: UpdateRepositoryInput!) { | |
| updateRepository(input: $input) { | |
| repository { | |
| name | |
| hasSponsorshipsEnabled | |
| } | |
| } | |
| } | |
| """ | |
| variables = { | |
| "input": { | |
| "repositoryId": node_id, | |
| "hasSponsorshipsEnabled": True | |
| } | |
| } | |
| response = requests.post( | |
| f"{BASE_URL}/graphql", | |
| headers=HEADERS, | |
| json={"query": query, "variables": variables} | |
| ) | |
| if response.status_code == 200: | |
| res_data = response.json() | |
| if "errors" in res_data: | |
| print(f"❌ Failed to update {repo_name}: {res_data['errors'][0]['message']}") | |
| else: | |
| print(f"✅ Enabled sponsorship for: {repo_name}") | |
| else: | |
| print(f"❌ HTTP Error for {repo_name}: {response.status_code}") | |
| def main(): | |
| print(f"Fetching repositories for organization: {ORG_NAME}...") | |
| repos = get_all_repos(ORG_NAME) | |
| print(f"Found {len(repos)} repositories.\n") | |
| for repo in repos: | |
| # Skip archived repositories as they cannot be edited | |
| if repo.get('archived'): | |
| print(f"⏭️ Skipping archived repo: {repo['name']}") | |
| continue | |
| node_id = repo['node_id'] | |
| enable_sponsorship(node_id, repo['name']) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment