Skip to content

Allow resending failed webook requests with the API

Problem to solve

GitLab provides the ability to resend webhook requests in the UI. Documentation here

A customer would like the ability to be able to resend any failed requests using the API so they can resend them programmatically when they have many failures (hundred or more).

Proposal

Add API endpoints that would allow users to resend failed project and group webhook requests. In the UI we call these webhook events.

We can do this by providing two endpoints each to project hooks and group hooks that would add extra value in general to our API besides just resending failed webhook events:

  1. GET /{projects|groups}/:id/hooks/:hook_id/events - this would expose the same data as when you edit a webhook in the UI and select Recent events.
    1. It would allow filtering by the response status (to allow people to see only failures, for example)
    2. It would allow sorting by ascending or descending order
  2. POST /{projects|groups}/:id/hooks/:hook_id/events/:hook_log_id/resend - this would be the same functionality as in the controller when you resend any of the WebHookLog records (resend the webhook event).

This would allow people to resend failed webhook requests in the follow way:

  • See their webhook events in the API (parity with the UI).
  • Filter those events to see the failures.
  • Use the id of any event (including failures) to resend it (parity with the UI).
  • Control the rate at which those events are resent, and decide which order to send them in.

Implementation

Project hooks endpoints are defined in API::ProjectHooks (lib/api/project_hooks.rb). Group hooks endpoints are defined in API::GroupHooks (lib/api/group_hooks.rb).

GET /{projects|groups}/:id/hooks/:hook_id/events

This will expose web_hook_logs records for a webhook (WebHook#web_hook_logs).

It must allow filtering by a statuses argument.

statuses would be:

  • Any 3-digit integer that was an actual status codes, like 404, 200, etc.
  • Or else a string. Either:
    • "success" (which we would expand to all valid 2xx codes):
    • "failure", (which we would expand to all valid 4xx-5xx codes)
  • We could use Rack::Utils::HTTP_STATUS_CODES.keys to help us build sets of valid status codes for argument validation and for expanding strings to status codes.
  • statuses must allow multiple statuses passed in as comma-separated (like how people filter issues by labels).

To support this filtering we must first add a new database index to web_hook_logs.response_status. Note, the web_hook_logs table is very large on GitLab.com, so we may need close help/collaboration with Database reviewers.

We must allow sorting by a optional sort argument. This would sort by WebHookLog#create_at (there is an existing index in place).

sort would be either "desc" or "asc".

The default would be "desc".

POST /{projects|groups}/:id/hooks/:hook_id/events/:hook_log_id/resend

This will resend the WebHookLog record.

We must create a new service for resending a webhook event called WebHooks::Events::ResendService and refactor the existing controller logic to also use it.

Because the endpoint will execute a webhook in the request, which makes an external request to a server that might be slow to respond, the endpoint must queue a new worker WebHooks::Events::ResendWorker which would call the new service.

We must add documentation of these endpoints to:

Workaround

Use the UI to resend requests, but this can be cumbersome when there are hundreds of failures.

Edited by Luke Duncalfe