Rig up git repo creation, webhooks

This commit is contained in:
Drew DeVault 2020-03-31 11:17:19 -04:00
parent 74d8068b44
commit c47f6ff49a
4 changed files with 104 additions and 38 deletions

View File

@ -117,27 +117,34 @@ def sources_git_new_POST(owner, project_name):
owner, project = get_project(owner, project_name, ProjectAccess.write)
valid = Validation(request)
if "create" in valid:
assert False # TODO: Create repo
git_repo = git.create_repo(owner, valid)
if not valid.ok:
repos = git.get_repos(owner)
return render_template("project-sources-select.html",
view="new-resource", vcs="git",
owner=owner, project=project, repos=repos,
existing=[], **valid.kwargs)
else:
repo_name = None
for field in valid.source:
if field.startswith("existing-"):
repo_name = field[len("existing-"):]
break
repo_name = None
for field in valid.source:
if field.startswith("existing-"):
repo_name = field[len("existing-"):]
break
if not repo_name:
search = valid.optional("search")
repos = git.get_repos(owner)
# TODO: Search properly
repos = filter(lambda r: search.lower() in r["name"].lower(), repos)
repos = sorted(repos, key=lambda r: r["updated"], reverse=True)
# TODO: Fetch existing repos for this project
return render_template("project-sources-select.html",
view="new-resource", vcs="git",
owner=owner, project=project, repos=repos,
existing=[], search=search)
if not repo_name:
search = valid.optional("search")
repos = git.get_repos(owner)
# TODO: Search properly
repos = filter(lambda r: search.lower() in r["name"].lower(), repos)
repos = sorted(repos, key=lambda r: r["updated"], reverse=True)
# TODO: Fetch existing repos for this project
return render_template("project-sources-select.html",
view="new-resource", vcs="git",
owner=owner, project=project, repos=repos,
existing=[], search=search)
git_repo = git.get_repo(owner, repo_name)
git_repo = git.get_repo(owner, repo_name)
repo = SourceRepo()
repo.remote_id = git_repo["id"]
repo.project_id = project.id
@ -155,8 +162,10 @@ def sources_git_new_POST(owner, project_name):
event.user_id = project.owner_id
db.session.add(event)
# TODO: repo webhooks for rigging up commit events
git.ensure_user_webhooks(owner, {
url_for("webhooks.git_repo_update"): ["repo:update", "repo:delete"],
origin + url_for("webhooks.git_repo_update"):
["repo:update", "repo:delete"],
})
db.session.commit()
@ -234,8 +243,10 @@ def mailing_lists_new_POST(owner, project_name):
event.user_id = project.owner_id
db.session.add(event)
# TODO: lists webhooks for rigging up new mail events
lists.ensure_mailing_list_webhooks(owner, list_name, {
url_for("webhooks.mailing_list_update"): ["list:update", "list:delete"],
origin + url_for("webhooks.mailing_list_update"):
["list:update", "list:delete"],
})
db.session.commit()

View File

@ -1,11 +1,44 @@
from flask import Blueprint
import json
from flask import Blueprint, request
from hubsrht.types import MailingList, SourceRepo, RepoType
from srht.database import db
from srht.flask import csrf_bypass
webhooks = Blueprint("webhooks", __name__)
@webhooks.route("/webhooks/git-repo")
@csrf_bypass
@webhooks.route("/webhooks/git-repo", methods=["POST"])
def git_repo_update():
pass # TODO
event = request.headers.get("X-Webhook-Event")
payload = json.loads(request.data.decode("utf-8"))
if event == "repo:update":
repo = (SourceRepo.query
.filter(SourceRepo.remote_id == payload["id"])
.filter(SourceRepo.repo_type == RepoType.git)
.one_or_none())
if not repo:
return "I don't recognize that repository.", 404
repo.name = payload["name"]
repo.description = payload["description"]
db.session.commit()
return f"Updated local:{repo.id}/remote:{repo.remote_id}. Thanks!", 200
elif event == "repo:delete":
raise NotImplementedError()
@webhooks.route("/webhooks/mailing-list")
@csrf_bypass
@webhooks.route("/webhooks/mailing-list", methods=["POST"])
def mailing_list_update():
pass # TODO
event = request.headers.get("X-Webhook-Event")
payload = json.loads(request.data.decode("utf-8"))
if event == "list:update":
ml = (MailingList.query
.filter(MailingList.remote_id == payload["id"])
.one_or_none())
if not ml:
return "I don't recognize that mailing list.", 404
ml.name = payload["name"]
ml.description = payload["description"]
db.session.commit()
return f"Updated local:{ml.id}/remote:{ml.remote_id}. Thanks!", 200
elif event == "list:delete":
raise NotImplementedError()

View File

@ -13,7 +13,7 @@ class GitService:
r = requests.get(f"{_gitsrht}/api/repos/{repo_name}",
headers=get_authorization(user))
if r.status_code != 200:
raise Exception(r.json())
raise Exception(r.text)
return r.json()
def get_readme(self, user, repo_name):
@ -21,10 +21,32 @@ class GitService:
# TODO: Use default branch
r = requests.get(f"{_gitsrht}/api/repos/{repo_name}/blob/master/README.md",
headers=get_authorization(user))
if r.status_code != 200:
if r.status_code == 404:
return ""
elif r.status_code != 200:
raise Exception(r.text)
return r.text
def create_repo(self, user, valid):
name = valid.require("name")
description = valid.require("description")
if not valid.ok:
return None
r = requests.post(f"{_gitsrht}/api/repos",
headers=get_authorization(user),
json={
"name": name,
"description": description,
"visibility": "public", # TODO: Should this be different?
})
if r.status_code == 400:
for error in r.json()["errors"]:
valid.error(error["reason"], field=error.get("field"))
return None
elif r.status_code != 201:
raise Exception(r.text)
return r.json()
def ensure_user_webhooks(self, user, config):
ensure_webhooks(user, f"{_gitsrht}/api/user/webhooks", config)

View File

@ -13,23 +13,23 @@
<label for="{{ typename }}">Name</label>
<input
type="text"
name="repo_name"
name="name"
id="name"
class="form-control {{ valid.cls("repo_name") }}"
value="{{ repo_name or project.name }}" />
{{ valid.summary("repo_name") }}
class="form-control {{ valid.cls("name") }}"
value="{{ name or project.name }}" />
{{ valid.summary("name") }}
<div class="form-group">
<label for="repo_description">Description</label>
<label for="description">Description</label>
<input
type="text"
name="repo_description"
id="repo_description"
class="form-control {{valid.cls("repo_description")}}"
value="{{ repo_description or project.description }}" />
{{valid.summary("repo_description")}}
name="description"
id="description"
class="form-control {{valid.cls("description")}}"
value="{{ description or project.description }}" />
{{valid.summary("description")}}
</div>
</div>
<button type="submit" class="btn btn-primary" name="new">
<button type="submit" class="btn btn-primary" name="create">
Create new {{vcs}} repository {{ icon("caret-right") }}
</button>
</div>