Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,21 +1,24 @@
|
|
| 1 |
import os
|
| 2 |
import requests
|
| 3 |
import uvicorn
|
|
|
|
| 4 |
from fastapi import FastAPI, Request, Header, HTTPException
|
| 5 |
from typing import Optional
|
| 6 |
|
|
|
|
|
|
|
|
|
|
| 7 |
app = FastAPI()
|
| 8 |
|
| 9 |
TEAMS_WEBHOOK_URL = os.getenv("TEAMS_WEBHOOK_URL")
|
| 10 |
WEBHOOK_SECRET = os.getenv("WEBHOOK_SECRET")
|
| 11 |
-
HF_TOKEN = os.getenv("HF_TOKEN")
|
| 12 |
|
| 13 |
@app.get("/")
|
| 14 |
def root():
|
| 15 |
return {"status": "running"}
|
| 16 |
|
| 17 |
def get_commit_info(repo_type, repo_name, head_sha):
|
| 18 |
-
"""HF API๋ก ์ปค๋ฐ ๋ฉ์์ง์ ๋ณ๊ฒฝ ํ์ผ ๋ชฉ๋ก ์กฐํ"""
|
| 19 |
type_map = {"model": "models", "dataset": "datasets", "space": "spaces"}
|
| 20 |
api_type = type_map.get(repo_type, "models")
|
| 21 |
|
|
@@ -23,36 +26,63 @@ def get_commit_info(repo_type, repo_name, head_sha):
|
|
| 23 |
if HF_TOKEN:
|
| 24 |
headers["Authorization"] = f"Bearer {HF_TOKEN}"
|
| 25 |
|
| 26 |
-
# ์ต๊ทผ ์ปค๋ฐ ๋ชฉ๋ก ์กฐํ
|
| 27 |
-
commits_url = f"https://huggingface.co/api/{api_type}/{repo_name}/commits/main"
|
| 28 |
-
resp = requests.get(commits_url, headers=headers)
|
| 29 |
-
|
| 30 |
commit_title = head_sha[:8]
|
| 31 |
commit_author = "unknown"
|
| 32 |
-
if resp.ok:
|
| 33 |
-
for commit in resp.json():
|
| 34 |
-
if commit.get("id", "").startswith(head_sha[:8]):
|
| 35 |
-
commit_title = commit.get("title", head_sha[:8])
|
| 36 |
-
commit_author = commit.get("authors", [{}])[0].get("user", "unknown") if commit.get("authors") else "unknown"
|
| 37 |
-
break
|
| 38 |
-
|
| 39 |
-
# ๋ณ๊ฒฝ ํ์ผ ๋ชฉ๋ก ์กฐํ
|
| 40 |
-
diff_url = f"https://huggingface.co/api/{api_type}/{repo_name}/diff/{head_sha}"
|
| 41 |
-
diff_resp = requests.get(diff_url, headers=headers)
|
| 42 |
-
|
| 43 |
changed_files = []
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
|
| 57 |
return commit_title, commit_author, changed_files
|
| 58 |
|
|
@@ -66,6 +96,13 @@ async def handle_webhook(
|
|
| 66 |
raise HTTPException(status_code=403, detail="Invalid secret")
|
| 67 |
|
| 68 |
payload = await request.json()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
event = payload.get("event", {})
|
| 70 |
repo = payload.get("repo", {})
|
| 71 |
|
|
@@ -74,16 +111,14 @@ async def handle_webhook(
|
|
| 74 |
repo_type = repo.get("type", "model")
|
| 75 |
head_sha = repo.get("headSha", "")
|
| 76 |
|
| 77 |
-
# HF API๋ก ์์ธ ์ ๋ณด ์กฐํ
|
| 78 |
commit_title, commit_author, changed_files = get_commit_info(repo_type, repo_name, head_sha)
|
| 79 |
|
| 80 |
-
# ํ์ผ ๋ชฉ๋ก ํ
์คํธ ์์ฑ
|
| 81 |
if changed_files:
|
| 82 |
-
files_text = "\n".join(changed_files[:15])
|
| 83 |
if len(changed_files) > 15:
|
| 84 |
files_text += f"\n...์ธ {len(changed_files) - 15}๊ฐ ํ์ผ"
|
| 85 |
else:
|
| 86 |
-
files_text = "(ํ์ผ
|
| 87 |
|
| 88 |
card = {
|
| 89 |
"type": "message",
|
|
@@ -98,9 +133,7 @@ async def handle_webhook(
|
|
| 98 |
{
|
| 99 |
"type": "TextBlock",
|
| 100 |
"text": f"๐ฆ {repo_name}",
|
| 101 |
-
"wrap": True,
|
| 102 |
-
"weight": "Bolder",
|
| 103 |
-
"size": "Large"
|
| 104 |
},
|
| 105 |
{
|
| 106 |
"type": "FactSet",
|
|
@@ -113,22 +146,19 @@ async def handle_webhook(
|
|
| 113 |
{
|
| 114 |
"type": "TextBlock",
|
| 115 |
"text": "**๋ณ๊ฒฝ๋ ํ์ผ:**",
|
| 116 |
-
"wrap": True,
|
| 117 |
-
"spacing": "Medium"
|
| 118 |
},
|
| 119 |
{
|
| 120 |
"type": "TextBlock",
|
| 121 |
"text": files_text,
|
| 122 |
-
"wrap": True,
|
| 123 |
-
"fontType": "Monospace",
|
| 124 |
-
"size": "Small"
|
| 125 |
},
|
| 126 |
{
|
| 127 |
"type": "ActionSet",
|
| 128 |
"actions": [{
|
| 129 |
"type": "Action.OpenUrl",
|
| 130 |
-
"title": "
|
| 131 |
-
"url": f"https://huggingface.co/{repo_name}"
|
| 132 |
}]
|
| 133 |
}
|
| 134 |
]
|
|
|
|
| 1 |
import os
|
| 2 |
import requests
|
| 3 |
import uvicorn
|
| 4 |
+
import logging
|
| 5 |
from fastapi import FastAPI, Request, Header, HTTPException
|
| 6 |
from typing import Optional
|
| 7 |
|
| 8 |
+
logging.basicConfig(level=logging.INFO)
|
| 9 |
+
logger = logging.getLogger(__name__)
|
| 10 |
+
|
| 11 |
app = FastAPI()
|
| 12 |
|
| 13 |
TEAMS_WEBHOOK_URL = os.getenv("TEAMS_WEBHOOK_URL")
|
| 14 |
WEBHOOK_SECRET = os.getenv("WEBHOOK_SECRET")
|
| 15 |
+
HF_TOKEN = os.getenv("HF_TOKEN")
|
| 16 |
|
| 17 |
@app.get("/")
|
| 18 |
def root():
|
| 19 |
return {"status": "running"}
|
| 20 |
|
| 21 |
def get_commit_info(repo_type, repo_name, head_sha):
|
|
|
|
| 22 |
type_map = {"model": "models", "dataset": "datasets", "space": "spaces"}
|
| 23 |
api_type = type_map.get(repo_type, "models")
|
| 24 |
|
|
|
|
| 26 |
if HF_TOKEN:
|
| 27 |
headers["Authorization"] = f"Bearer {HF_TOKEN}"
|
| 28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
commit_title = head_sha[:8]
|
| 30 |
commit_author = "unknown"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
changed_files = []
|
| 32 |
+
|
| 33 |
+
# 1) ์ปค๋ฐ ๋ชฉ๋ก์์ ์ปค๋ฐ ๋ฉ์์ง, ์์ฑ์ ์กฐํ
|
| 34 |
+
try:
|
| 35 |
+
commits_url = f"https://huggingface.co/api/{api_type}/{repo_name}/commits/main"
|
| 36 |
+
logger.info(f"Fetching commits: {commits_url}")
|
| 37 |
+
resp = requests.get(commits_url, headers=headers, timeout=10)
|
| 38 |
+
logger.info(f"Commits API status: {resp.status_code}")
|
| 39 |
+
if resp.ok:
|
| 40 |
+
for commit in resp.json():
|
| 41 |
+
if commit.get("id", "").startswith(head_sha[:8]):
|
| 42 |
+
commit_title = commit.get("title", head_sha[:8])
|
| 43 |
+
authors = commit.get("authors", [])
|
| 44 |
+
if authors:
|
| 45 |
+
commit_author = authors[0].get("user", "unknown")
|
| 46 |
+
break
|
| 47 |
+
except Exception as e:
|
| 48 |
+
logger.error(f"Commits API error: {e}")
|
| 49 |
+
|
| 50 |
+
# 2) ์ปค๋ฐ ์์ธ (๋ณ๊ฒฝ ํ์ผ) - ์ฌ๋ฌ ์๋ํฌ์ธํธ ์๋
|
| 51 |
+
endpoints_to_try = [
|
| 52 |
+
f"https://huggingface.co/api/{api_type}/{repo_name}/commit/{head_sha}",
|
| 53 |
+
f"https://huggingface.co/api/{api_type}/{repo_name}/diff/{head_sha}",
|
| 54 |
+
f"https://huggingface.co/{repo_name}/resolve/{head_sha}/.commit_info",
|
| 55 |
+
]
|
| 56 |
+
|
| 57 |
+
for url in endpoints_to_try:
|
| 58 |
+
try:
|
| 59 |
+
logger.info(f"Trying: {url}")
|
| 60 |
+
resp = requests.get(url, headers=headers, timeout=10)
|
| 61 |
+
logger.info(f" Status: {resp.status_code}")
|
| 62 |
+
logger.info(f" Body (first 500): {resp.text[:500]}")
|
| 63 |
+
if resp.ok:
|
| 64 |
+
data = resp.json() if resp.headers.get("content-type", "").startswith("application/json") else {}
|
| 65 |
+
# dict ํํ์ธ ๊ฒฝ์ฐ
|
| 66 |
+
if isinstance(data, dict):
|
| 67 |
+
for f in data.get("files", []):
|
| 68 |
+
path = f.get("filename", f.get("path", f.get("rfilename", "")))
|
| 69 |
+
status = f.get("status", "changed")
|
| 70 |
+
changed_files.append(f"{status}: {path}")
|
| 71 |
+
if not changed_files and "siblings" in data:
|
| 72 |
+
for f in data["siblings"]:
|
| 73 |
+
changed_files.append(f.get("rfilename", ""))
|
| 74 |
+
# list ํํ์ธ ๊ฒฝ์ฐ
|
| 75 |
+
elif isinstance(data, list):
|
| 76 |
+
for item in data:
|
| 77 |
+
if isinstance(item, dict):
|
| 78 |
+
path = item.get("path", item.get("filename", item.get("rfilename", "")))
|
| 79 |
+
status = item.get("status", "")
|
| 80 |
+
changed_files.append(f"{'๐ ' if status == 'added' else 'โ๏ธ ' if status == 'modified' else '๐๏ธ ' if status == 'removed' else '๐ '}{path}")
|
| 81 |
+
if changed_files:
|
| 82 |
+
logger.info(f" Found {len(changed_files)} files!")
|
| 83 |
+
break
|
| 84 |
+
except Exception as e:
|
| 85 |
+
logger.error(f" Error: {e}")
|
| 86 |
|
| 87 |
return commit_title, commit_author, changed_files
|
| 88 |
|
|
|
|
| 96 |
raise HTTPException(status_code=403, detail="Invalid secret")
|
| 97 |
|
| 98 |
payload = await request.json()
|
| 99 |
+
|
| 100 |
+
# ์ ์ฒด payload ๋ก๊น
(๋๋ฒ๊น
์ฉ)
|
| 101 |
+
logger.info(f"=== WEBHOOK RECEIVED ===")
|
| 102 |
+
logger.info(f"Full payload keys: {list(payload.keys())}")
|
| 103 |
+
logger.info(f"Event: {payload.get('event')}")
|
| 104 |
+
logger.info(f"Repo: {payload.get('repo')}")
|
| 105 |
+
|
| 106 |
event = payload.get("event", {})
|
| 107 |
repo = payload.get("repo", {})
|
| 108 |
|
|
|
|
| 111 |
repo_type = repo.get("type", "model")
|
| 112 |
head_sha = repo.get("headSha", "")
|
| 113 |
|
|
|
|
| 114 |
commit_title, commit_author, changed_files = get_commit_info(repo_type, repo_name, head_sha)
|
| 115 |
|
|
|
|
| 116 |
if changed_files:
|
| 117 |
+
files_text = "\n".join(changed_files[:15])
|
| 118 |
if len(changed_files) > 15:
|
| 119 |
files_text += f"\n...์ธ {len(changed_files) - 15}๊ฐ ํ์ผ"
|
| 120 |
else:
|
| 121 |
+
files_text = "(๋ณ๊ฒฝ ํ์ผ ์กฐํ ์คํจ - Space ๋ก๊ทธ๋ฅผ ํ์ธํ์ธ์)"
|
| 122 |
|
| 123 |
card = {
|
| 124 |
"type": "message",
|
|
|
|
| 133 |
{
|
| 134 |
"type": "TextBlock",
|
| 135 |
"text": f"๐ฆ {repo_name}",
|
| 136 |
+
"wrap": True, "weight": "Bolder", "size": "Large"
|
|
|
|
|
|
|
| 137 |
},
|
| 138 |
{
|
| 139 |
"type": "FactSet",
|
|
|
|
| 146 |
{
|
| 147 |
"type": "TextBlock",
|
| 148 |
"text": "**๋ณ๊ฒฝ๋ ํ์ผ:**",
|
| 149 |
+
"wrap": True, "spacing": "Medium"
|
|
|
|
| 150 |
},
|
| 151 |
{
|
| 152 |
"type": "TextBlock",
|
| 153 |
"text": files_text,
|
| 154 |
+
"wrap": True, "fontType": "Monospace", "size": "Small"
|
|
|
|
|
|
|
| 155 |
},
|
| 156 |
{
|
| 157 |
"type": "ActionSet",
|
| 158 |
"actions": [{
|
| 159 |
"type": "Action.OpenUrl",
|
| 160 |
+
"title": "์ปค๋ฐ ๋ณด๊ธฐ",
|
| 161 |
+
"url": f"https://huggingface.co/{repo_name}/commit/{head_sha}"
|
| 162 |
}]
|
| 163 |
}
|
| 164 |
]
|