Skip to content
Snippets Groups Projects
Commit 6b2673bc authored by Robert Schilling's avatar Robert Schilling
Browse files

Add new to test bulk_update endpoint for issues and MRs

Add documentation for issues and MRs. Add shared tests
for both bulk updating issues and MRs.
parent 9e521ca7
No related branches found
No related tags found
No related merge requests found
---
title: 'API: Bulk update for issues and MRs'
merge_request:
author:
merge_request: 25201
author: Robert Schilling
type: added
Loading
Loading
@@ -635,6 +635,37 @@ Example response:
 
**Note**: The `closed_by` attribute was [introduced in GitLab 10.6][ce-17042]. This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
 
## Bulk update issues
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21368) in GitLab 11.8.
Update multiple issues using a single API call. Returns the number of successfully updated issues.
```
PUT /projects/:id/issues/bulk_update
```
| Attribute | Type | Required | Description **** |
|----------------|---------|----------|------------------------------------------------------------------------------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
| `issuable_ids` | Array[integer] | yes | The IDs of issues to be updated. |
| `assignee_ids` | Array[integer] | no | The ID of the user(s) to assign the issue to. Set to `0` or provide an empty value to unassign all assignees. |
| `milestone_id` | integer | no | The global ID of a milestone to assign the issue to. Set to `0` or provide an empty value to unassign a milestone.|
| `add_label_ids` | Array[integer] | no | Comma-separated label IDs to be added. |
| `remove_label_ids` | Array[integer] | no | Comma-separated label IDs to be added. |
| `state_event` | string | no | The state event of an issue. Set `close` to close the issue and `reopen` to reopen it. |
| `subscription_event` | string | no | The subscription_event event of an issue. Set `subscribe` to subscribe to the issue and `unsubscribe` to unsubscribe from it. |
```bash
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/issues/bulk_update?issuable_ids[]=1&issuable_ids[]=2&state_event=close
```
Example response:
```json
{ "message": "2 issues updated" }
```
## Delete an issue
 
Only for admins and project owners. Soft deletes the issue in question.
Loading
Loading
Loading
Loading
@@ -956,6 +956,37 @@ Must include at least one non-required attribute from above.
}
```
 
## Bulk update merge requests
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21368) in GitLab 11.8.
Update multiple merge requests using a single API call. Returns the number of successfully updated merge requests.
```
PUT /projects/:id/merge_requests/bulk_update
```
| Attribute | Type | Required | Description **** |
|----------------|---------|----------|------------------------------------------------------------------------------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
| `issuable_ids` | Array[integer] | yes | The IDs of merge requests to be updated. |
| `assignee_ids` | Array[integer] | no | The ID of the user(s) to assign the issue to. Set to `0` or provide an empty value to unassign all assignees. |
| `milestone_id` | integer | no | The global ID of a milestone to assign the issue to. Set to `0` or provide an empty value to unassign a milestone.|
| `add_label_ids` | Array[integer] | no | Comma-separated label IDs to be added. |
| `remove_label_ids` | Array[integer] | no | Comma-separated label IDs to be added. |
| `state_event` | string | no | The state event of an issue. Set `close` to close the issue and `reopen` to reopen it. |
| `subscription_event` | string | no | The subscription_event event of an issue. Set `subscribe` to subscribe to the issue and `unsubscribe` to unsubscribe from it. |
```bash
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/merge_requests/bulk_update?issuable_ids[]=1&issuable_ids[]=2&state_event=close
```
Example response:
```json
{ "message": "2 merge_requests updated" }
```
## Delete a merge request
 
Only for admins and project owners. Soft deletes the merge request in question.
Loading
Loading
Loading
Loading
@@ -11,6 +11,7 @@ module API
detail 'This feature was introduced in 11.9'
end
params do
requires :issuable_ids, type: Array[Integer], desc: "Array or #{issuable.pluralize} IDs to be updates"
optional :state_event, type: String, values: %w(reopen close), desc: 'Reopens or closes a resource'
optional :milestone_id, type: Integer, desc: 'The milestone ID number'
optional :add_label_ids, type: Array[Integer], desc: 'IDs of labels to be added'
Loading
Loading
@@ -28,16 +29,18 @@ module API
:subscription_event, :assignee_id
end
end
put ":id/#{issuable}/bulk_update" do
put ":id/#{issuable.pluralize}/bulk_update" do
authorize! :"admin_#{issuable}", user_project
update_params = declared_params(include_missing: false)
 
result = Issuable::BulkUpdateService.new(user_project, current_user, update_params)
.execute(issuable)
quantity = result[:count]
 
if result[:success]
status 200
{ notice: "#{quantity} #{issuable.pluralize(quantity)} updated" }
quantity = result[:count]
{ message: "#{quantity} #{issuable.pluralize(quantity)} updated" }
else
render_api_error!('Bulk update failed', 400)
end
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe API::IssuableBulkUpdate do
set(:user) { create(:user) }
set(:project) do
create(:project, :public, creator_id: user.id, namespace: user.namespace)
end
%w(issue merge_request).each do |issuable|
describe "PUT /projects/:id/#{issuable.pluralize}/bulk_update" do
let(:merge_request_1) { create(:merge_request, source_project: project) }
let(:merge_request_2) { create(:merge_request, :simple, source_project: project) }
let!(:issuables) { issuable == 'issue' ? create_list(:issue, 2, project: project) : [merge_request_1, merge_request_2] }
def bulk_update(issuable, issuables, params, update_user = user)
put api("/projects/#{project.id}/#{issuable.pluralize}/bulk_update", update_user),
params: { issuable_ids: Array(issuables).map(&:id) }.merge(params)
end
context 'with not enough permissions' do
it 'returns 403 for guest users' do
guest = create(:user)
project.add_guest(guest)
bulk_update(issuable, issuables, { state_event: 'close' }, guest)
expect(response).to have_gitlab_http_status(403)
end
end
context 'when modifying the state' do
it "closes #{issuable}" do
bulk_update(issuable, issuables, { state_event: 'close' })
expect(response).to have_gitlab_http_status(200)
expect(json_response['message']).to eq("#{issuables.count} #{issuable.pluralize(issuables.count)} updated")
expect(project.public_send(issuable.pluralize).opened).to be_empty
expect(project.public_send(issuable.pluralize).closed).not_to be_empty
end
it "opens #{issuable}" do
closed_issuables = create_list("closed_#{issuable}".to_sym, 2)
bulk_update(issuable, closed_issuables, { state_event: 'reopen' })
expect(response).to have_gitlab_http_status(200)
expect(project.public_send(issuable.pluralize).closed).to be_empty
end
end
context 'when modifying the milestone' do
let(:milestone) { create(:milestone, project: project) }
it "adds a milestone #{issuable}" do
bulk_update(issuable, issuables, { milestone_id: milestone.id })
expect(response).to have_gitlab_http_status(200)
issuables.each do |issuable|
expect(issuable.reload.milestone).to eq(milestone)
end
end
it 'removes a milestone' do
issuables.first.milestone = milestone
milestone_issuable = issuables.first
bulk_update(issuable, [milestone_issuable], { milestone_id: 0 })
expect(response).to have_gitlab_http_status(200)
expect(milestone_issuable.reload.milestone).to eq(nil)
end
end
context 'when modifying the subscription state' do
it "subscribes to #{issuable}" do
bulk_update(issuable, issuables, { subscription_event: 'subscribe' })
expect(response).to have_gitlab_http_status(200)
expect(issuables).to all(be_subscribed(user, project))
end
it 'unsubscribes from issues' do
issuables.each do |issuable|
issuable.subscriptions.create(user: user, project: project, subscribed: true)
end
bulk_update(issuable, issuables, { subscription_event: 'unsubscribe' })
expect(response).to have_gitlab_http_status(200)
issuables.each do |issuable|
expect(issuable).not_to be_subscribed(user, project)
end
end
end
context 'when modifying the assignee' do
it 'adds assignee to issues' do
params = issuable == 'issue' ? { assignee_ids: [user.id] } : { assignee_id: user.id }
bulk_update(issuable, issuables, params)
expect(response).to have_gitlab_http_status(200)
issuables.each do |issuable|
expect(issuable.reload.assignees).to eq([user])
end
end
it 'removes assignee' do
assigned_issuable = issuables.first
if issuable == 'issue'
params = { assignee_ids: 0 }
assigned_issuable.assignees << user
else
params = { assignee_id: 0 }
assigned_issuable.update_attribute(:assignee, user)
end
bulk_update(issuable, [assigned_issuable], params)
expect(assigned_issuable.reload.assignees).to eq([])
end
end
context 'when modifying labels' do
let(:bug) { create(:label, project: project) }
let(:regression) { create(:label, project: project) }
let(:feature) { create(:label, project: project) }
it 'adds new labels' do
bulk_update(issuable, issuables, { add_label_ids: [bug.id, regression.id, feature.id] })
issuables.each do |issusable|
expect(issusable.reload.label_ids).to contain_exactly(bug.id, regression.id, feature.id)
end
end
it 'removes labels' do
labled_issuable = issuables.first
labled_issuable.labels << bug
labled_issuable.labels << regression
labled_issuable.labels << feature
bulk_update(issuable, [labled_issuable], { remove_label_ids: [bug.id, regression.id] })
expect(labled_issuable.reload.label_ids).to contain_exactly(feature.id)
end
end
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment