mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-26 06:16:56 +09:00
feat(api): add REST API endpoints for repository webhook delivery history (#38775)
Webhook delivery history (request/response, status, timestamp) was only
reachable through the repo settings UI, which shows the last ~10
deliveries with no filtering. There was no way to fetch this data
programmatically for debugging integrations or auditing webhook
activity.
This adds two read endpoints at the repository level:
- `GET /repos/{owner}/{repo}/hooks/{id}/deliveries` — paginated list of
a hook's deliveries, most recent first
- `GET /repos/{owner}/{repo}/hooks/{id}/deliveries/{uuid}` — a single
delivery, including request/response headers, body, and status
Both reuse the existing `hook_task` storage and retention policy (the
`CleanupHookTaskTable` cron job) that already back the "Recent
Deliveries" web UI, and are gated by the same `reqAdmin()` +
`reqWebhooksEnabled()` guard as the existing hook endpoints.
Org, user, and admin/system-level webhooks are intentionally out of
scope for this PR to keep it reviewable; they can follow as separate
PRs using the same pattern.
## Usage
```bash
curl -H "Authorization: token $TOKEN" \
https://gitea.example.com/api/v1/repos/{owner}/{repo}/hooks/{id}/deliveries
curl -H "Authorization: token $TOKEN" \
https://gitea.example.com/api/v1/repos/{owner}/{repo}/hooks/{id}/deliveries/{uuid}
```
## Testing
- Unit tests for the new model-layer query functions
(`ListHookTasks`, `GetHookTaskByUUID`)
- Integration tests covering: list + get, an undelivered task's response
is `null`, a hook/delivery UUID from another repository 404s instead
of leaking across repos, and pagination (`page`/`limit`, `Link` and
`X-Total-Count` headers, correct ordering/no overlap across pages)
- `make lint-go`, `make generate-swagger`
Fixes: https://github.com/go-gitea/gitea/issues/38463.
Co-authored-by: bircni <bircni@icloud.com>
Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
11 files changed
+824
-6
No files matched your search
@@ -46,6 +46,50 @@ type Hook struct {
|
||||
// HookList represents a list of API hook.
|
||||
type HookList []*Hook
|
||||
|
||||
// HookDeliveryRequest represents the request information of a webhook delivery
|
||||
type HookDeliveryRequest struct {
|
||||
// The URL the delivery was sent to
|
||||
URL string `json:"url"`
|
||||
// The HTTP method used for the delivery
|
||||
HTTPMethod string `json:"http_method"`
|
||||
// The headers sent with the delivery
|
||||
Headers map[string]string `json:"headers"`
|
||||
// The body sent with the delivery
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
// HookDeliveryResponse represents the response information of a webhook delivery
|
||||
type HookDeliveryResponse struct {
|
||||
// The HTTP status code of the response
|
||||
Status int `json:"status"`
|
||||
// The headers received in the response
|
||||
Headers map[string]string `json:"headers"`
|
||||
// The body received in the response
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
// HookDelivery represents a single delivery attempt for a webhook
|
||||
type HookDelivery struct {
|
||||
// The unique identifier of the delivery
|
||||
UUID string `json:"uuid"`
|
||||
// The event type that triggered this delivery
|
||||
EventType string `json:"event_type"`
|
||||
// Whether the delivery has been sent
|
||||
IsDelivered bool `json:"is_delivered"`
|
||||
// Whether the delivery was successful (2xx response)
|
||||
IsSucceeded bool `json:"is_succeeded"`
|
||||
// swagger:strfmt date-time
|
||||
// The date and time when the delivery was sent
|
||||
Delivered *time.Time `json:"delivered_at"`
|
||||
// The request that was sent
|
||||
Request *HookDeliveryRequest `json:"request"`
|
||||
// The response that was received
|
||||
Response *HookDeliveryResponse `json:"response"`
|
||||
}
|
||||
|
||||
// HookDeliveryList represents a list of API hook deliveries.
|
||||
type HookDeliveryList []*HookDelivery
|
||||
|
||||
// CreateHookOptionConfig has all config options in it
|
||||
// required are "content_type" and "url" Required
|
||||
type CreateHookOptionConfig map[string]string
|
||||
|
||||
Reference in new issue
Block a user