For those working with circleCI and GitHub, here is a script we did today
QuickStart
python main.py list-ctx
python main.py list-env
python main.py list-keys
python main.py replace-keys
with the following main.py file
import requests
import argparse
from config import API_TOKEN, GH_TOKEN, ORG # CircleCi api Token, Github api token, Github organisation name
ORG_SLUG = f"github/{ORG}"
auth_header = { 'Circle-Token': API_TOKEN }
github_headers = {
"X-GitHub-Api-Version": "2022-11-28",
"Accept": "application/vnd.github+json",
"Authorization": f"Bearer {GH_TOKEN}"
}
def list_contexts():
url = "https://circleci.com/api/v2/context"
req_params = {
"owner-slug": ORG_SLUG,
"owner-type": "organization",
}
page_token = ""
contexts = []
while True:
params = {**req_params, "page-token": page_token}
response = requests.get(url, params=params, headers=auth_header).json()
contexts += response.get("items", [])
page_token = response.get("next_page_token", None)
if page_token is None:
return contexts
def list_context_variables(context_id):
url = f"https://circleci.com/api/v2/context/{context_id}/environment-variable"
req_params = {}
page_token = ""
env_vars = []
while True:
params = {**req_params, "page-token": page_token}
response = requests.get(url, params=params, headers=auth_header).json()
env_vars += response.get("items", [])
page_token = response.get("next_page_token", None)
if page_token is None:
return env_vars
def list_github_repositories():
url = f"https://api.github.com/orgs/{ORG}/repos"
req_params = {
"per_page": 100
}
page_idx = 1
repos = []
while True:
params = {**req_params, "page": page_idx}
response = requests.get(url, params=params, headers=github_headers).json()
repos += response
if len(response) == 0:
return repos
page_idx += 1
def list_project_env_variables(project):
url = f"https://circleci.com/api/v2/project/gh/{ORG}/{project}/envvar"
req_params = {}
page_token = ""
env_vars = []
while True:
params = {**req_params, "page-token": page_token}
response = requests.get(url, params=params, headers=auth_header).json()
env_vars += response.get("items", [])
page_token = response.get("next_page_token", None)
if page_token is None:
return env_vars
def list_project_keys(project):
url = f"https://circleci.com/api/v2/project/gh/{ORG}/{project}/checkout-key"
req_params = {}
page_token = ""
keys = []
while True:
params = {**req_params, "page-token": page_token}
response = requests.get(url, params=params, headers=auth_header).json()
keys += response.get("items", [])
page_token = response.get("next_page_token", None)
if page_token is None:
return keys
def list_github_deploy_keys(project):
url = f"https://api.github.com/repos/{ORG}/{project}/keys"
req_params = {
"per_page": 100
}
page_idx = 1
keys = []
while True:
params = {**req_params, "page": page_idx}
response = requests.get(url, params=params, headers=github_headers).json()
keys += response
if len(response) == 0:
return keys
page_idx += 1
def delete_github_deploy_key(project, key):
url = f"https://api.github.com/repos/{ORG}/{project}/keys/{key['id']}"
response = requests.delete(url, headers=github_headers)
if response.status_code != 204:
print("Could not delete github key", key['title'], response.json())
def get_project_checkout_keys(project, fingerprint):
url = f"https://circleci.com/api/v2/project/gh/{ORG}/{project}/checkout-key/{fingerprint}"
response = requests.get(url, headers=auth_header).json()
return response
def delete_project_checkout_keys(project, fingerprint):
url = f"https://circleci.com/api/v2/project/gh/{ORG}/{project}/checkout-key/{fingerprint}"
response = requests.delete(url, headers=auth_header)
if response.status_code != 200:
print("Could not delete circleci key for project", project)
def create_project_checkout_keys(project, key_type):
url = f"https://circleci.com/api/v2/project/gh/{ORG}/{project}/checkout-key"
response = requests.post(url, headers=auth_header, json={"type": key_type})
if response.status_code != 201:
print("Could not create circleci key for project", project, response.json())
def main_list_project_env_var():
repos = list_github_repositories()
print("project;var")
for repo in repos:
env_vars = list_project_env_variables(repo["name"])
for var in env_vars:
print(f'{repo["name"]};{var["name"]}')
def main_list_project_checkout_keys():
repos = list_github_repositories()
print("project;type;fingerprint;created_at")
for repo in repos:
keys = list_project_keys(repo["name"])
for key in keys:
print(f'{repo["name"]};{key["type"]};{key["fingerprint"]};{key["created_at"]}')
def main_list_contexts():
contexts = list_contexts()
print("context;var;last_modified")
for ctx in contexts:
env_vars = list_context_variables(ctx["id"])
for var in env_vars:
print(f'{ctx["name"]};{var["variable"]};{var["created_at"]}')
def main_replace_project_checkout_keys():
repos = list_github_repositories()
for repo in repos:
project = repo["name"]
gh_keys = list_github_deploy_keys(project)
for key in gh_keys:
delete_github_deploy_key(project, key)
ci_keys = list_project_keys(project)
for key in ci_keys:
delete_project_checkout_keys(project, key["fingerprint"])
create_project_checkout_keys(project, key_type=key['type'])
command_dict = {
"list-ctx": main_list_contexts,
"list-env": main_list_project_env_var,
"list-keys": main_list_project_checkout_keys,
"replace-keys": main_replace_project_checkout_keys
}
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("cmd", choices=list(command_dict.keys()))
args = parser.parse_args()
command_dict[args.cmd]()