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