forked from grizz/ghmeta
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ghmeta.py
executable file
·118 lines (90 loc) · 3.4 KB
/
ghmeta.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/bin/env python
import os
import getpass
import click
from github import Github
from github.GithubException import UnknownObjectException
import github.GithubObject
import yaml
def auth():
token = os.environ.get("GHMETA_TOKEN", None)
if not token:
raise Exception(
"requires environment variable GHMETA_TOKEN to be set to a github personal access token"
)
return Github(token)
def load_local(filename="data.yml"):
""" Loads local metadata from file. """
with open(filename) as f:
docs = list(yaml.load_all(f, Loader=yaml.FullLoader))
if len(docs) != 1:
raise Exception("only supports single document yaml files")
return docs[0]
def load_github(repo):
data = dict(ghmeta={"push_to": []}, labels=[], milestones=[])
for each in repo.get_labels():
data["labels"].append(
dict(name=each.name, color=each.color, description=each.description)
)
for each in repo.get_milestones(state="open"):
data["milestones"].append(dict(title=each.title, description=each.description))
return data
def push_data(repo, data):
""" Pushes data to github repos. """
overwrite = True
# milestaones need to be referenced by id, so we need to get the full list first
existing_milestones = {}
for each in repo.get_milestones():
existing_milestones[each.title] = each
for milestone in data["milestones"]:
title = milestone["title"]
# TODO add state
if overwrite and title in existing_milestones:
print(f"updating milestone `{title}` to `{milestone['description']}`")
existing_milestones[title].edit(title, "open", milestone["description"])
else:
repo.create_milestone(title, "open", milestone["description"])
for label in data["labels"]:
name = label["name"]
# github fails on None, so make sure it's at least an empty string
description = label.get("description", "") or ""
try:
existing_label = repo.get_label(label["name"])
if overwrite:
print(f"updating label `{name}` to #{label['color']} `{description}`")
existing_label.edit(name, label["color"], description)
continue
except UnknownObjectException:
pass
repo.create_label(name, label["color"], description)
@click.command()
@click.option(
"--pull-from",
help="Read metadata from here, default is none meaning local file (`data.yml`).",
)
@click.option(
"--push-to", help="Push metadata to these repos (may be a comma separated list"
)
@click.argument("command", default="display")
def ghmeta(command, pull_from, push_to):
ghobj = auth()
if pull_from:
data = load_github(ghobj.get_repo(pull_from))
else:
data = load_local()
# if push_to is passed, overwrite file data
if push_to:
data["ghmeta"]["push_to"] = push_to.split(",")
if command == "display":
print(yaml.dump(data))
elif command == "push":
push_to = data["ghmeta"]["push_to"]
if not push_to:
raise Exception("nothing to push to, set push_to in data or command line")
for repo_url in push_to:
print(f"syncing {repo_url}")
push_data(ghobj.get_repo(repo_url), data)
else:
raise Exception(f"unknown command {command}")
if __name__ == "__main__":
ghmeta()