Initialer Commit
This commit is contained in:
commit
7d486554e8
130
gitea.py
Normal file
130
gitea.py
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
def setup_args():
|
||||||
|
parser = argparse.ArgumentParser(description="Gitea classroom helper")
|
||||||
|
parser.add_argument("--url", "-u", default="http://git.kinf.wiai.uni-bamberg.de", help="Gitea path")
|
||||||
|
parser.add_argument("--token", "-t", help="Gitea application token", required=True)
|
||||||
|
args = parser.parse_args()
|
||||||
|
return args
|
||||||
|
|
||||||
|
class GiteaClassRoom:
|
||||||
|
def __init__(self, host, token):
|
||||||
|
self.session = requests.Session()
|
||||||
|
self.session.headers.update({"accept": "application/json","Content-Type": "application/json"})
|
||||||
|
self.label_id = None
|
||||||
|
self.milestone_id = None
|
||||||
|
self.host = host
|
||||||
|
self.token = token
|
||||||
|
self.validate()
|
||||||
|
|
||||||
|
def url(self, url):
|
||||||
|
url = f"{self.host}/api/v1/{url}?token={self.token}"
|
||||||
|
#print(url)
|
||||||
|
return url
|
||||||
|
|
||||||
|
def post(self, endpoint, data):
|
||||||
|
return self.session.post(self.url(endpoint), data=json.dumps(data))
|
||||||
|
|
||||||
|
def get(self, endpoint):
|
||||||
|
return self.session.get(self.url(endpoint))
|
||||||
|
|
||||||
|
def put(self, endpoint):
|
||||||
|
return self.session.put(self.url(endpoint))
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
test = self.get("user/orgs")
|
||||||
|
if not test.ok:
|
||||||
|
raise ValueError("invalid token", test.status_code, test.text)
|
||||||
|
|
||||||
|
def filtered(self, endpoint, filters):
|
||||||
|
data = self.get(endpoint).json()
|
||||||
|
for entry in data:
|
||||||
|
if all([entry[name] == filters[name] for name in filters]):
|
||||||
|
return entry
|
||||||
|
return None
|
||||||
|
|
||||||
|
def add_label(self, repo, name="deliverables", color="#ff0000"):
|
||||||
|
label = self.filtered(f"repos/{repo}/labels", {"name": name})
|
||||||
|
if not label:
|
||||||
|
label = self.post(f"repos/{repo}/labels", {"name": name, "color":color}).json()
|
||||||
|
return label["id"]
|
||||||
|
|
||||||
|
def add_milestone(self, repo, title, description, due_on):
|
||||||
|
milestone = self.filtered(f"repos/{repo}/milestones", {"title": title, "due_on": due_on})
|
||||||
|
if not milestone:
|
||||||
|
data = {"title": title, "description": description, "due_on": due_on}
|
||||||
|
milestone = self.post(f"repos/{repo}/milestones", data).json()
|
||||||
|
return milestone["id"]
|
||||||
|
|
||||||
|
def add_issue(self, repo, title, body, milestone=None, labels=None):
|
||||||
|
issue = self.filtered(f"repos/{repo}/issues", {"title": title, "state": "open"})
|
||||||
|
if not issue:
|
||||||
|
data = {"title": title, "body": body}
|
||||||
|
if milestone:
|
||||||
|
data["milestone"] = milestone
|
||||||
|
if labels:
|
||||||
|
data["labels"] = labels
|
||||||
|
issue = self.post(f"repos/{repo}/issues", data).json()
|
||||||
|
return issue
|
||||||
|
|
||||||
|
def add_org(self, name):
|
||||||
|
print("don't forget to set the visibility to private (if you want)")
|
||||||
|
return self.post("orgs", {"username": name, "visibility": "private"}).json()
|
||||||
|
|
||||||
|
def add_org_repo(self, org, repo):
|
||||||
|
return self.post(f"org/{org}/repos", {"name": repo,"private":True}).json()
|
||||||
|
|
||||||
|
def add_team(self, org, name):
|
||||||
|
team = self.filtered(f"orgs/{org}/teams", {"name": name})
|
||||||
|
if not team:
|
||||||
|
team = self.post(f"orgs/{org}/teams", {"name": name, "permission": "write", "units":["repo.code","repo.issues","repo.pulls","repo.releases","repo.wiki"]}).json()
|
||||||
|
return team["id"]
|
||||||
|
|
||||||
|
def add_user_to_team(self, team_id, user):
|
||||||
|
return self.put(f"teams/{team_id}/members/{user}")
|
||||||
|
|
||||||
|
def add_repo_to_team(self, team_id, repo):
|
||||||
|
return self.put(f"teams/{team_id}/repos/{repo}")
|
||||||
|
|
||||||
|
def init_org(self, name, groups, labels={}, milestones={}, issues=[], **kwargs):
|
||||||
|
"""
|
||||||
|
name: name of the oranisation
|
||||||
|
groups: number of groups (int) or collection with group names
|
||||||
|
labels: map (key->props) for labels (name, color)
|
||||||
|
milestones: map (key->props) for milestones (title, description, due_on)
|
||||||
|
issues: list of issues (title, body, ([label_keys]), (milestone_key))
|
||||||
|
"""
|
||||||
|
self.add_org(name)
|
||||||
|
if isinstance(groups, int):
|
||||||
|
groups = {f"Group{i}":[] for i in range(groups)}
|
||||||
|
elif isinstance(groups, list):
|
||||||
|
groups = {f"Group{i}":v for i,v in enumerate(groups)}
|
||||||
|
for group in groups:
|
||||||
|
repo = f"{name}/{group}"
|
||||||
|
self.add_org_repo(name, group)
|
||||||
|
team = self.add_team(name, group)
|
||||||
|
for user in groups[group]:
|
||||||
|
self.add_user_to_team(team, user)
|
||||||
|
self.add_repo_to_team(team, repo)
|
||||||
|
added_labels = {label: self.add_label(repo, name=label, color=labels[label]) for label in list(labels)}
|
||||||
|
added_milestones = {milestone: self.add_milestone(repo, **milestones[milestone]) for milestone in dict(milestones)}
|
||||||
|
for issue in issues:
|
||||||
|
milestone = added_milestones[issue["milestone"]] if "milestone" in issue else None
|
||||||
|
label_ids = [added_labels[label] for label in issue["labels"]] if "labels" in issue else None
|
||||||
|
self.add_issue(repo, issue["title"], issue["body"], milestone, label_ids)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = setup_args()
|
||||||
|
gitea = GiteaClassRoom(host=args.url, token=args.token)
|
||||||
|
|
||||||
|
# config with json file
|
||||||
|
with open("sample.json") as src:
|
||||||
|
data = json.load(src)
|
||||||
|
gitea.init_org(**data)
|
||||||
|
|
||||||
|
# config with python class
|
||||||
|
#from sample import Testdata
|
||||||
|
#gitea.init_org(Testdata.name, Testdata.groups, Testdata.labels, Testdata.milestones, Testdata.issues)
|
||||||
63
sample.json
Normal file
63
sample.json
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"name": "ScriptTest",
|
||||||
|
"groups": 6,
|
||||||
|
"ALTERNATIVE_groups_with_names_and_users": {"admin": ["cklug", "mgoetz", "ckremitzl"]},
|
||||||
|
"ALTERNATIVE_groups_with_users": [["cklug", "mgoetz"]],
|
||||||
|
"labels": {
|
||||||
|
"deliverable": "#ff0000",
|
||||||
|
"hint": "#00f000"
|
||||||
|
},
|
||||||
|
"milestones": {
|
||||||
|
"ms1": {
|
||||||
|
"title": "Milestone 1",
|
||||||
|
"description": "The first milestone covers the game desgin basics (game design document), a firs architectural approach (e.g. UML diagram), and assignment of responsibilities",
|
||||||
|
"due_on": "2019-05-23T13:37:00Z"
|
||||||
|
},"ms2": {
|
||||||
|
"title": "Milestone 2",
|
||||||
|
"description": "Presentation of the final geogame (walktrough, demo, video,…)",
|
||||||
|
"due_on": "2019-07-22T13:37:00Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"issues": [
|
||||||
|
{
|
||||||
|
"title": "Game design document",
|
||||||
|
"body": "Write a game design document.\nYou can use the template in the VC as starting point.",
|
||||||
|
"labels": ["hint", "deliverable"],
|
||||||
|
"milestone": "ms1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Assign responsibilites",
|
||||||
|
"body": "Split the project into equal parts",
|
||||||
|
"labels": ["deliverable"],
|
||||||
|
"milestone": "ms1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Learn Android",
|
||||||
|
"body": "Get to know Android, especially Activites with their lifecycle and Services (Remote, Local, bind/unBind, start/stop)",
|
||||||
|
"labels": ["hint"],
|
||||||
|
"milestone": "ms1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Create Slides",
|
||||||
|
"body": "Presenting a word document (or A4 PDF) is cumbersome",
|
||||||
|
"labels": ["hint"],
|
||||||
|
"milestone": "ms1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Implement App",
|
||||||
|
"body": "Do it",
|
||||||
|
"labels": ["deliverable"],
|
||||||
|
"milestone": "ms2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Game design document",
|
||||||
|
"body": "Write a game design document.\nYou can use the template in the VC as starting point.",
|
||||||
|
"labels": ["hint", "deliverable"],
|
||||||
|
"milestone": "ms1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "have fun",
|
||||||
|
"body": "'nuff said"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
62
sample.py
Normal file
62
sample.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
class Testdata:
|
||||||
|
name = "ScriptTest"
|
||||||
|
groups = 5 # Group0, Group1, Group2
|
||||||
|
#groups = {"admin": ["cklug", "mgoetz", "ckremitzl"]} # "admin" with 3 members
|
||||||
|
#groups = [["cklug", "mgoetz"]] # Group0 with 2 members
|
||||||
|
labels = {
|
||||||
|
"deliverable": "#ff0000",
|
||||||
|
"hint": "#00f000"
|
||||||
|
}
|
||||||
|
milestones = {
|
||||||
|
"ms1": {
|
||||||
|
"title": "Milestone 1",
|
||||||
|
"description": "The first milestone covers the game desgin basics (game design document), a firs architectural approach (e.g. UML diagram), and assignment of responsibilities",
|
||||||
|
"due_on": "2019-05-23T13:37:00Z"
|
||||||
|
},"ms2": {
|
||||||
|
"title": "Milestone 2",
|
||||||
|
"description": "Presentation of the final geogame (walktrough, demo, video,…)",
|
||||||
|
"due_on": "2019-07-22T13:37:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
issues = [
|
||||||
|
{
|
||||||
|
"title": "Game design document",
|
||||||
|
"body": "Write a game design document.\nYou can use the template in the VC as starting point.",
|
||||||
|
"labels": ["hint", "deliverable"],
|
||||||
|
"milestone": "ms1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Assign responsibilites",
|
||||||
|
"body": "Split the project into equal parts",
|
||||||
|
"labels": ["deliverable"],
|
||||||
|
"milestone": "ms1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Learn Android",
|
||||||
|
"body": "Get to know Android, especially Activites with their lifecycle and Services (Remote, Local, bind/unBind, start/stop)",
|
||||||
|
"labels": ["hint"],
|
||||||
|
"milestone": "ms1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Create Slides",
|
||||||
|
"body": "Presenting a word document (or A4 PDF) is cumbersome",
|
||||||
|
"labels": ["hint"],
|
||||||
|
"milestone": "ms1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Implement App",
|
||||||
|
"body": "Do it",
|
||||||
|
"labels": ["deliverable"],
|
||||||
|
"milestone": "ms2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Game design document",
|
||||||
|
"body": "Write a game design document.\nYou can use the template in the VC as starting point.",
|
||||||
|
"labels": ["hint", "deliverable"],
|
||||||
|
"milestone": "ms1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "have fun",
|
||||||
|
"body": "'nuff said"
|
||||||
|
}
|
||||||
|
]
|
||||||
Loading…
x
Reference in New Issue
Block a user