[fix] solution/backend: Teams 카드 필수 필드 보완
웹훅 요청의 contentUrl 및 스키마 선언 누락을 공식 형식에 맞춤. HTTP 202와 채널 게시 성공을 구분하도록 검증 한계 기록. 검증: Teams 요청 형식 회귀 테스트 1건 통과. 워크플로 실제 수신은 별도 확인 필요.
This commit is contained in:
parent
3f47d5ecd2
commit
0f7d22750f
11
docs/TEAMS_WEBHOOK.md
Normal file
11
docs/TEAMS_WEBHOOK.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Teams 웹훅 확인 (2026-09-15)
|
||||||
|
|
||||||
|
- Adaptive Card 요청의 `contentUrl: null` 및 `$schema`를 공식 예제에 맞춰 보완했다.
|
||||||
|
- HTTP 202는 워크플로의 요청 접수다. Teams 채널 게시 성공을 뜻하지 않는다.
|
||||||
|
- 실제 전송 2건은 202였지만 사용자가 확인한 워크플로 실행은 실패였다.
|
||||||
|
상세 오류를 확인하지 못했으므로 누락 필드를 실제 실패 원인으로 단정하지 않는다.
|
||||||
|
- 운영 자동 알림 활성화 전, 채널 수신 또는 워크플로의 최종 게시 단계 성공을 확인해야 한다.
|
||||||
|
- 웹훅은 `.env`에만 보관하고 커밋하지 않는다.
|
||||||
|
|
||||||
|
검증: 백엔드에서 `APP_ENV=test PYTHONPATH=. .venv/bin/pytest tests/test_search_console_alerts.py --confcutdir=tests`.
|
||||||
|
공식 형식: https://learn.microsoft.com/en-us/connectors/teams/#adaptivecarditemschema
|
||||||
@ -26,7 +26,9 @@ async def send_alert(webhook_url: str, page_url: str, reason: str) -> bool:
|
|||||||
return False
|
return False
|
||||||
payload = {"type": "message", "attachments": [{
|
payload = {"type": "message", "attachments": [{
|
||||||
"contentType": "application/vnd.microsoft.card.adaptive",
|
"contentType": "application/vnd.microsoft.card.adaptive",
|
||||||
"content": {"type": "AdaptiveCard", "version": "1.2", "body": [
|
"contentUrl": None,
|
||||||
|
"content": {"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||||
|
"type": "AdaptiveCard", "version": "1.2", "body": [
|
||||||
{"type": "TextBlock", "text": "Google 색인 확인 필요", "weight": "Bolder"},
|
{"type": "TextBlock", "text": "Google 색인 확인 필요", "weight": "Bolder"},
|
||||||
{"type": "TextBlock", "text": page_url, "wrap": True},
|
{"type": "TextBlock", "text": page_url, "wrap": True},
|
||||||
{"type": "TextBlock", "text": reason, "wrap": True},
|
{"type": "TextBlock", "text": reason, "wrap": True},
|
||||||
|
|||||||
21
solution/backend/tests/test_search_console_alerts.py
Normal file
21
solution/backend/tests/test_search_console_alerts.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import httpx
|
||||||
|
from services import search_console_alerts as alerts
|
||||||
|
|
||||||
|
|
||||||
|
async def test_teams_payload_has_required_attachment_fields(monkeypatch):
|
||||||
|
requests = []
|
||||||
|
real_client = httpx.AsyncClient
|
||||||
|
|
||||||
|
def receive(request):
|
||||||
|
import json
|
||||||
|
requests.append(json.loads(request.content))
|
||||||
|
return httpx.Response(202)
|
||||||
|
|
||||||
|
monkeypatch.setattr(alerts.httpx, "AsyncClient", lambda **kw: real_client(
|
||||||
|
transport=httpx.MockTransport(receive), **kw,
|
||||||
|
))
|
||||||
|
assert await alerts.send_alert("https://example.test/webhook", "https://example.test/s/a", "test")
|
||||||
|
card = requests[0]["attachments"][0]
|
||||||
|
assert card["contentType"] == "application/vnd.microsoft.card.adaptive"
|
||||||
|
assert "contentUrl" in card and card["contentUrl"] is None
|
||||||
|
assert card["content"]["$schema"] == "http://adaptivecards.io/schemas/adaptive-card.json"
|
||||||
Loading…
Reference in New Issue
Block a user