Changeset View
Changeset View
Standalone View
Standalone View
swh/web/save_origin_webhooks/generic_receiver.py
- This file was added.
# Copyright (C) 2022 The Software Heritage developers | ||||||||||||
# See the AUTHORS file at the top-level directory of this distribution | ||||||||||||
# License: GNU Affero General Public License version 3, or any later version | ||||||||||||
# See top-level LICENSE file for more information | ||||||||||||
from typing import Any, Callable, Dict, Tuple | ||||||||||||
from rest_framework.request import Request | ||||||||||||
from swh.web.save_code_now.origin_save import create_save_origin_request | ||||||||||||
from swh.web.utils.exc import BadInputExc | ||||||||||||
def origin_save_webhook_receiver( | ||||||||||||
request: Request, | ||||||||||||
forge_type: str, | ||||||||||||
is_forge_request: Callable[[Request], bool], | ||||||||||||
is_push_event: Callable[[Request], bool], | ||||||||||||
extract_repo_url_and_visit_type: Callable[[Request], Tuple[str, str]], | ||||||||||||
) -> Dict[str, Any]: | ||||||||||||
""" | ||||||||||||
.. http:post:: /api/1/origin/save/webhook/{forge_type_lower}/ | ||||||||||||
Webhook receiver for {forge_type} to request or update the archival of a repository | ||||||||||||
when new commits are pushed to it. | ||||||||||||
To add such webhook to one of your {repo_types} repository hosted on {forge_type}, | ||||||||||||
please follow that `guide <{webhook_guide_url}>`_. | ||||||||||||
Please note that the expected content type for the webhook payload should be | ||||||||||||
``application/json``. | ||||||||||||
:>json string origin_url: the url of the origin to save | ||||||||||||
:>json string visit_type: the type of visit to perform | ||||||||||||
:>json string save_request_date: the date (in iso format) the save | ||||||||||||
request was issued | ||||||||||||
:>json string save_request_status: the status of the save request, | ||||||||||||
either **accepted**, **rejected** or **pending** | ||||||||||||
:statuscode 200: save request for repository has been successfully created from | ||||||||||||
the webhook payload. | ||||||||||||
:statuscode 400: no save request has been created due to invalid POST request | ||||||||||||
vlorentz: it's best to make link text self-descriptive | ||||||||||||
or missing data in webhook payload | ||||||||||||
""" | ||||||||||||
Done Inline Actions
vlorentz: | ||||||||||||
if not is_forge_request(request): | ||||||||||||
raise BadInputExc( | ||||||||||||
f"POST request has not been sent by a {forge_type} webhook and has " | ||||||||||||
"not been processed." | ||||||||||||
) | ||||||||||||
if not is_push_event(request): | ||||||||||||
Done Inline ActionsShouldn't it return the same values as https://archive.softwareheritage.org/1/origin/save/doc/ , for the sake of consistency? vlorentz: Shouldn't it return the same values as https://archive.softwareheritage.org/1/origin/save/doc/… | ||||||||||||
Not Done Inline ActionsI do not think we should return the other fields as most of them will be null (visit date and status for instance) so it is quite pointless to include them imho. anlambert: I do not think we should return the other fields as most of them will be null (visit date and… | ||||||||||||
raise BadInputExc( | ||||||||||||
f"Event sent by {forge_type} webhook is not a push one, request has " | ||||||||||||
"not been processed." | ||||||||||||
) | ||||||||||||
content_type = request.headers.get("Content-Type") | ||||||||||||
if content_type != "application/json": | ||||||||||||
raise BadInputExc( | ||||||||||||
f"Invalid content type '{content_type}' for the POST request sent by " | ||||||||||||
f"{forge_type} webhook, it should be 'application/json'." | ||||||||||||
) | ||||||||||||
repo_url, visit_type = extract_repo_url_and_visit_type(request) | ||||||||||||
if not repo_url: | ||||||||||||
raise BadInputExc( | ||||||||||||
f"Repository URL could not be extracted from {forge_type} webhook payload." | ||||||||||||
) | ||||||||||||
if not visit_type: | ||||||||||||
raise BadInputExc( | ||||||||||||
f"Visit type could not be determined for repository {repo_url}." | ||||||||||||
) | ||||||||||||
save_request = create_save_origin_request( | ||||||||||||
visit_type=visit_type, origin_url=repo_url | ||||||||||||
) | ||||||||||||
Done Inline Actions
Preterit feels more correct than present perfect here. It's also consistent with other errors below vlorentz: Preterit feels more correct than present perfect here. It's also consistent with other errors… | ||||||||||||
return { | ||||||||||||
"origin_url": save_request["origin_url"], | ||||||||||||
"visit_type": save_request["visit_type"], | ||||||||||||
"save_request_date": save_request["save_request_date"], | ||||||||||||
"save_request_status": save_request["save_request_status"], | ||||||||||||
} |
it's best to make link text self-descriptive