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)