Spaces:
Sleeping
Sleeping
basic commands
Browse files- src/gradio_space_ci/webhook.py +60 -10
src/gradio_space_ci/webhook.py
CHANGED
@@ -28,6 +28,9 @@ from huggingface_hub import (
|
|
28 |
snapshot_download,
|
29 |
space_info,
|
30 |
upload_folder,
|
|
|
|
|
|
|
31 |
)
|
32 |
from huggingface_hub.repocard import RepoCard
|
33 |
from huggingface_hub.utils import (
|
@@ -248,16 +251,7 @@ async def trigger_ci_on_pr(payload: WebhookPayload, task_queue: BackgroundTasks)
|
|
248 |
|
249 |
pr_num = payload.discussion.num
|
250 |
details = get_discussion_details(repo_id=space_id, repo_type="space", discussion_num=pr_num)
|
251 |
-
event_author = details.events[-1]._event["author"]["name"]
|
252 |
-
if (
|
253 |
-
# Means comment by a trusted author
|
254 |
-
payload.event.scope == "discussion.comment"
|
255 |
-
and payload.event.action == "create"
|
256 |
-
and payload.discussion.isPullRequest
|
257 |
-
and payload.discussion.status == "open"
|
258 |
-
and event_author in EPHEMERAL_SPACES_CONFIG["trusted_authors"]
|
259 |
-
):
|
260 |
-
print("Comment detected with content:\n ", payload.comment.content)
|
261 |
|
262 |
if (
|
263 |
# Means "a new PR has been opened"
|
@@ -295,8 +289,28 @@ async def trigger_ci_on_pr(payload: WebhookPayload, task_queue: BackgroundTasks)
|
|
295 |
if discussion.is_pull_request and discussion.status == "open":
|
296 |
if not is_pr_synced(space_id=space_id, pr_num=discussion.num):
|
297 |
# Found a PR that is not yet synced
|
|
|
|
|
|
|
298 |
task_queue.add_task(sync_ci_space, space_id=space_id, pr_num=discussion.num)
|
299 |
has_task = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
300 |
|
301 |
if has_task:
|
302 |
return Response("Task scheduled to sync/delete Space", status_code=status.HTTP_202_ACCEPTED)
|
@@ -463,6 +477,42 @@ def _get_ci_space_id(space_id: str, pr_num: int) -> str:
|
|
463 |
return f"{space_id}-ci-pr-{pr_num}"
|
464 |
|
465 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
466 |
NOTIFICATION_TEMPLATE_CREATED_AND_CONFIGURED = """\
|
467 |
Following the creation of this PR, an ephemeral Space [{ci_space_id}](https://huggingface.co/spaces/{ci_space_id}) has been started. Any changes pushed to this PR will be synced with the test Space.
|
468 |
Since this PR has been created by a trusted author, the ephemeral Space has been configured with the correct hardware, storage, and secrets.
|
|
|
28 |
snapshot_download,
|
29 |
space_info,
|
30 |
upload_folder,
|
31 |
+
delete_space_secret,
|
32 |
+
delete_space_variable,
|
33 |
+
delete_space_storage
|
34 |
)
|
35 |
from huggingface_hub.repocard import RepoCard
|
36 |
from huggingface_hub.utils import (
|
|
|
251 |
|
252 |
pr_num = payload.discussion.num
|
253 |
details = get_discussion_details(repo_id=space_id, repo_type="space", discussion_num=pr_num)
|
254 |
+
event_author = details.events[-1]._event["author"]["name"] # username of that event
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
|
256 |
if (
|
257 |
# Means "a new PR has been opened"
|
|
|
289 |
if discussion.is_pull_request and discussion.status == "open":
|
290 |
if not is_pr_synced(space_id=space_id, pr_num=discussion.num):
|
291 |
# Found a PR that is not yet synced
|
292 |
+
if event_author not in EPHEMERAL_SPACES_CONFIG["trusted_authors"] :
|
293 |
+
# if change by untrusted author unset config
|
294 |
+
unset_config(space_id=space_id,pr_num=pr_num)
|
295 |
task_queue.add_task(sync_ci_space, space_id=space_id, pr_num=discussion.num)
|
296 |
has_task = True
|
297 |
+
if (
|
298 |
+
# Means comment by a trusted author
|
299 |
+
payload.event.scope == "discussion.comment"
|
300 |
+
and payload.event.action == "create"
|
301 |
+
and payload.discussion.isPullRequest
|
302 |
+
and payload.discussion.status == "open"
|
303 |
+
and event_author in EPHEMERAL_SPACES_CONFIG["trusted_authors"]
|
304 |
+
):
|
305 |
+
print("Comment detected with content:\n", payload.comment.content)
|
306 |
+
if payload.comment.content == "/trust_pr":
|
307 |
+
print("trusting pr ...")
|
308 |
+
set_config(space_id=space_id,pr_num=pr_num)
|
309 |
+
print("pr has been trusted")
|
310 |
+
elif payload.comment.content == "/untrust_pr":
|
311 |
+
print("untrusting pr ...")
|
312 |
+
unset_config(space_id=space_id,pr_num=pr_num)
|
313 |
+
print("pr has been untrusted")
|
314 |
|
315 |
if has_task:
|
316 |
return Response("Task scheduled to sync/delete Space", status_code=status.HTTP_202_ACCEPTED)
|
|
|
477 |
return f"{space_id}-ci-pr-{pr_num}"
|
478 |
|
479 |
|
480 |
+
def set_config(space_id: str, pr_num: str) -> None:
|
481 |
+
"""a function to set the ephemerial space config"""
|
482 |
+
variables: Dict[str, str] = EPHEMERAL_SPACES_CONFIG["variables"]
|
483 |
+
secrets: Dict[str, str] = EPHEMERAL_SPACES_CONFIG["secrets"]
|
484 |
+
hardware: Optional[SpaceHardware] = EPHEMERAL_SPACES_CONFIG["hardware"]
|
485 |
+
storage: Optional[SpaceHardware] = EPHEMERAL_SPACES_CONFIG["storage"]
|
486 |
+
ci_space_id = _get_ci_space_id(space_id=space_id, pr_num=pr_num)
|
487 |
+
# Configure space
|
488 |
+
for key, value in variables.items():
|
489 |
+
add_space_variable(ci_space_id, key, value)
|
490 |
+
for key, value in secrets.items():
|
491 |
+
add_space_secret(ci_space_id, key, value)
|
492 |
+
|
493 |
+
# Request hardware/storage for space
|
494 |
+
if hardware is not None and hardware != SpaceHardware.CPU_BASIC:
|
495 |
+
request_space_hardware(ci_space_id, hardware, sleep_time=5 * 60) # sleep after 5min on PR Spaces with GPU
|
496 |
+
if storage is not None:
|
497 |
+
request_space_storage(ci_space_id, storage)
|
498 |
+
|
499 |
+
|
500 |
+
def unset_config(space_id: str, pr_num: int) -> None:
|
501 |
+
"a function to unset the configuration of an ephemeral space"
|
502 |
+
ci_space_id = _get_ci_space_id(space_id=space_id, pr_num=pr_num)
|
503 |
+
variables: Dict[str, str] = EPHEMERAL_SPACES_CONFIG["variables"]
|
504 |
+
secrets: Dict[str, str] = EPHEMERAL_SPACES_CONFIG["secrets"]
|
505 |
+
# Unset space variables and secrets
|
506 |
+
for key in variables.keys():
|
507 |
+
delete_space_variable(ci_space_id, key)
|
508 |
+
for key in secrets.keys():
|
509 |
+
delete_space_secret(ci_space_id, key)
|
510 |
+
# Reset hardware
|
511 |
+
request_space_hardware(ci_space_id,SpaceHardware.CPU_BASIC)
|
512 |
+
delete_space_storage(ci_space_id)
|
513 |
+
|
514 |
+
|
515 |
+
|
516 |
NOTIFICATION_TEMPLATE_CREATED_AND_CONFIGURED = """\
|
517 |
Following the creation of this PR, an ephemeral Space [{ci_space_id}](https://huggingface.co/spaces/{ci_space_id}) has been started. Any changes pushed to this PR will be synced with the test Space.
|
518 |
Since this PR has been created by a trusted author, the ephemeral Space has been configured with the correct hardware, storage, and secrets.
|