Rate limit context commit writes per user
What does this MR do and why?
Merge request context commits are previously merged commits that you add to a merge request for context. You add and remove them with the REST API, or with the Add or remove previously merged commits modal, which calls the same API. Neither endpoint has a rate limit.
This MR adds a per-user rate limit of 10 requests per minute, shared between:
POST /projects/:id/merge_requests/:merge_request_iid/context_commitsDELETE /projects/:id/merge_requests/:merge_request_iid/context_commits
Over the limit, both endpoints return 429 Too Many Requests.
- One unit per request, however many commits it lists. The modal sends all removed commits in one
DELETE, andPOSTalready accepts at most 20 commits per request. - The check runs after the authorization check, so requests from users who can't update the merge request don't count toward the limit.
- Behind the
rate_limit_context_commits_writefeature flag (gitlab_com_derisk, disabled by default, user actor). - As with other application rate limits, requests that send the rate limit bypass header aren't limited.
References
- https://gitlab.com/gitlab-org/gitlab/-/work_items/636123
- Rollout issue:
rate_limit_context_commits_write
Screenshots or screen recordings
Not applicable: no UI change. When a save is rate limited, the modal shows its existing "Please try again" alert. If a save both adds and removes commits and only one of the two requests is limited, the page reloads without an alert, as it already does for any partial failure.
How to set up and validate locally
-
In the Rails console, enable the flag for your user:
Feature.enable(:rate_limit_context_commits_write, User.find_by_username('<your username>')) -
Pick a merge request you can update, and a commit SHA from its target branch that isn't in the merge request.
-
Add and remove that commit 6 times within a minute (12 requests):
for i in $(seq 6); do curl --request POST --header "PRIVATE-TOKEN: <token>" --header "Content-Type: application/json" \ --data '{"commits": ["<sha>"]}' \ --url "http://gdk.test:3000/api/v4/projects/<project id>/merge_requests/<iid>/context_commits" \ --output /dev/null --write-out "POST %{http_code}\n" curl --request DELETE --header "PRIVATE-TOKEN: <token>" --header "Content-Type: application/json" \ --data '{"commits": ["<sha>"]}' \ --url "http://gdk.test:3000/api/v4/projects/<project id>/merge_requests/<iid>/context_commits" \ --output /dev/null --write-out "DELETE %{http_code}\n" doneThe first 10 requests return
201or204. The last 2 return429. -
Disable the flag and repeat. No request returns
429.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.