Repository: huggingface/huggingface_hub
Pull request #2169 (2024-03-29 13:35:46)

Add support for `updatedRefs` in WebhookPayload
Related to https://github.com/huggingface/hub-docs/pull/1252 cc @coyotte508 

Wehbook payload now sends a list of the updated refs. This is useful to react on new commits on specific pull requests, new tags and new branches. See https://huggingface.co/docs/hub/webhooks#code-changes for more details.

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/huggingface/huggingface_hub/pull/2169?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=huggingface) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 82.88%. Comparing base [(`9ced134`)](https://app.codecov.io/gh/huggingface/huggingface_hub/commit/9ced1346346bef0cabf9e51e8cbc20988b326cfb?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=huggingface) to head [(`60a3d4f`)](https://app.codecov.io/gh/huggingface/huggingface_hub/pull/2169?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=huggingface).

> :exclamation: Current head 60a3d4f differs from pull request most recent head d60936d. Consider uploading reports for the commit d60936d to get more accurate results


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #2169      +/-   ##
==========================================
- Coverage   82.90%   82.88%   -0.03%     
==========================================
  Files         103      103              
  Lines        9698     9703       +5     
==========================================
+ Hits         8040     8042       +2     
- Misses       1658     1661       +3     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/huggingface/huggingface_hub/pull/2169?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=huggingface).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=huggingface).

HuggingFaceDocBuilderDev: The docs for this PR live [here](https://moon-ci-docs.huggingface.co/docs/huggingface_hub/pr_2169). All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.
julien-c: let's try to grow the usage of webhook btw, i feel like this is powerful but under-exploited

Patch:
diff --git a/src/huggingface_hub/_webhooks_payload.py b/src/huggingface_hub/_webhooks_payload.py
index 6ea669fe..296e4251 100644
--- a/src/huggingface_hub/_webhooks_payload.py
+++ b/src/huggingface_hub/_webhooks_payload.py
@@ -107,6 +107,12 @@ class WebhookPayloadRepo(ObjectId):
     url: WebhookPayloadUrl
 
 
+class WebhookPayloadUpdatedRef(BaseModel):
+    ref: str
+    oldSha: Optional[str] = None
+    newSha: Optional[str] = None
+
+
 class WebhookPayload(BaseModel):
     event: WebhookPayloadEvent
     repo: WebhookPayloadRepo
@@ -114,3 +120,4 @@ class WebhookPayload(BaseModel):
     comment: Optional[WebhookPayloadComment] = None
     webhook: WebhookPayloadWebhook
     movedTo: Optional[WebhookPayloadMovedTo] = None
+    updatedRefs: Optional[List[WebhookPayloadUpdatedRef]] = None


Test patch:
diff --git a/tests/test_webhooks_server.py b/tests/test_webhooks_server.py
index 5d18af1f..f35efa27 100644
--- a/tests/test_webhooks_server.py
+++ b/tests/test_webhooks_server.py
@@ -79,10 +79,40 @@ WEBHOOK_PAYLOAD_UPDATE_DISCUSSION = {  # valid payload but doesn't have a "comme
     "webhook": {"id": "656a05348c99518820a4dd54", "version": 3},
 }
 
+WEBHOOK_PAYLOAD_WITH_UPDATED_REFS = {
+    "event": {"action": "update", "scope": "repo.content"},
+    "repo": {
+        "type": "space",
+        "name": "Wauplin/gradio-user-history",
+        "id": "651311c46de9c503f3f34a9e",
+        "private": False,
+        "subdomain": "wauplin-gradio-user-history",
+        "url": {
+            "web": "https://huggingface.co/spaces/Wauplin/gradio-user-history",
+            "api": "https://huggingface.co/api/spaces/Wauplin/gradio-user-history",
+        },
+        "headSha": "5e7f29fffcc579cb52539fddb14a1a4f85f39e44",
+        "owner": {
+            "id": "6273f303f6d63a28483fde12",
+        },
+    },
+    "webhook": {
+        "id": "65a14fd933eca76f4639fc84",
+        "version": 3,
+    },
+    "updatedRefs": [
+        {
+            "ref": "refs/pr/5",
+            "oldSha": None,
+            "newSha": "227c78346870a85e5de4fff8a585db68df975406",
+        }
+    ],
+}
+
 
 def test_deserialize_payload_example_with_comment() -> None:
     """Confirm that the test stub can actually be deserialized."""
-    payload = WebhookPayload.parse_obj(WEBHOOK_PAYLOAD_CREATE_DISCUSSION)
+    payload = WebhookPayload.model_validate(WEBHOOK_PAYLOAD_CREATE_DISCUSSION)
     assert payload.event.scope == WEBHOOK_PAYLOAD_CREATE_DISCUSSION["event"]["scope"]
     assert payload.comment is not None
     assert payload.comment.content == "Add co2 emissions information to the model card"
@@ -90,11 +120,20 @@ def test_deserialize_payload_example_with_comment() -> None:
 
 def test_deserialize_payload_example_without_comment() -> None:
     """Confirm that the test stub can actually be deserialized."""
-    payload = WebhookPayload.parse_obj(WEBHOOK_PAYLOAD_UPDATE_DISCUSSION)
+    payload = WebhookPayload.model_validate(WEBHOOK_PAYLOAD_UPDATE_DISCUSSION)
     assert payload.event.scope == WEBHOOK_PAYLOAD_UPDATE_DISCUSSION["event"]["scope"]
     assert payload.comment is None
 
 
+def test_deserialize_payload_example_with_updated_refs() -> None:
+    """Confirm that the test stub can actually be deserialized."""
+    payload = WebhookPayload.model_validate(WEBHOOK_PAYLOAD_WITH_UPDATED_REFS)
+    assert payload.updatedRefs is not None
+    assert payload.updatedRefs[0].ref == "refs/pr/5"
+    assert payload.updatedRefs[0].oldSha is None
+    assert payload.updatedRefs[0].newSha == "227c78346870a85e5de4fff8a585db68df975406"
+
+
 @requires("gradio")
 class TestWebhooksServerDontRun(unittest.TestCase):
     def test_add_webhook_implicit_path(self):