chore: fix ruff lint (webhooks v2) + Windows-safe test teardown
FlowDeck CI / lint (push) Successful in 1m21s
FlowDeck CI / test (push) Failing after 10m1s
FlowDeck CI / docker (push) Skipped

This commit is contained in:
2026-09-21 21:58:47 -04:00
parent 2fceed0da2
commit b56b181c3e
5 changed files with 40 additions and 44 deletions
+10 -10
View File
@@ -16,7 +16,6 @@ from fastapi import APIRouter, Header, HTTPException, Request
from fastapi.responses import JSONResponse, Response
from app.db import get_conn
from app.services.automations import fire_event as _fire_event
from app.services.api_v2_helpers import (
audit_log,
check_idempotency,
@@ -30,6 +29,7 @@ from app.services.api_v2_helpers import (
to_iso8601,
validate_scopes_input,
)
from app.services.automations import fire_event as _fire_event
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/v2", tags=["api-v2"])
@@ -2397,19 +2397,19 @@ async def retry_webhook_deliveries(webhook_id: int, request: Request,
_v2_rate_check(request, user)
if not has_scope(user.get("_token_scopes"), "write"):
raise HTTPException(403, "Insufficient scope. Required: write")
from app.services.webhook_outbound import retry_due_deliveries
with get_conn() as conn:
# Force retry by setting next_retry_at to the past
conn.execute(
"""UPDATE webhook_deliveries
"""UPDATE webhook_deliveries
SET next_retry_at = strftime('%s', 'now', '-1 second')
WHERE webhook_id = ? AND status = 'retrying'""",
(webhook_id,),
)
conn.commit()
retried = await retry_due_deliveries()
audit_log(user, "webhook.retry", "webhook", webhook_id, f"retried={retried}", request)
return {"webhook_id": webhook_id, "status": "retried", "retried_count": retried}
@@ -2421,19 +2421,19 @@ async def verify_webhook_signature(request: Request,
"""Verify a webhook signature (for debugging/testing)."""
user = get_bearer_user(request, authorization)
_v2_rate_check(request, user)
from app.services.webhook_outbound import verify_signature
try:
body = await request.json()
except Exception:
body = {}
secret = body.get("secret", "")
payload = body.get("payload", "{}")
signature = body.get("signature", "")
is_valid = verify_signature(secret, payload.encode(), signature)
audit_log(user, "webhook.signature_verify", "webhook", 0, f"valid={is_valid}", request)
return {"valid": is_valid, "secret": secret[:10] + "..." if len(secret) > 10 else secret}
+3 -1
View File
@@ -30,7 +30,9 @@ def _user(request: Request, authorization: str | None = None,
try:
user = get_bearer_user(request, authorization)
except HTTPException:
raise HTTPException(status_code=401, detail="Invalid or expired API token")
raise HTTPException(
status_code=401, detail="Invalid or expired API token"
) from None
if not has_scope(user.get("_token_scopes"), required_scope):
raise HTTPException(
status_code=403,
+2 -2
View File
@@ -112,7 +112,7 @@ def _log_delivery(webhook_id: int, event: str, status: str, http_code: int | Non
async def _deliver_once(client: httpx.AsyncClient, url: str, event: str,
payload: dict, secret: str) -> tuple[int | None, str]:
"""Single POST attempt. Returns (http_code, error).
Includes HMAC-SHA256 signature in X-FlowDeck-Signature header.
"""
body = json.dumps({"event": event, **payload}).encode()
@@ -144,7 +144,7 @@ async def deliver_to_sub(sub_id: int, url: str, event: str, payload: dict,
Returns True on success. Failures are re-queued via ``next_retry_at`` so
the background scheduler can pick them up even if this process restarts.
Retry schedule: 2s, 10s, 60s (3 retries total + initial attempt).
"""
own_client = _client is None