summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelogs/unreleased/28807-search-for-milestone-by-title-in-rest-api.yml4
-rw-r--r--doc/api/milestones.md6
-rw-r--r--lib/api/helpers.rb4
-rw-r--r--lib/api/milestones.rb2
-rw-r--r--spec/requests/api/milestones_spec.rb21
5 files changed, 30 insertions, 7 deletions
diff --git a/changelogs/unreleased/28807-search-for-milestone-by-title-in-rest-api.yml b/changelogs/unreleased/28807-search-for-milestone-by-title-in-rest-api.yml
new file mode 100644
index 00000000000..0016253e32e
--- /dev/null
+++ b/changelogs/unreleased/28807-search-for-milestone-by-title-in-rest-api.yml
@@ -0,0 +1,4 @@
+---
+title: Enable filtering milestones by search criteria in the API
+merge_request: 9606
+author:
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index 63c5dc2c05d..9439db84e9b 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -10,6 +10,7 @@ GET /projects/:id/milestones?iid=42
GET /projects/:id/milestones?iid[]=42&iid[]=43
GET /projects/:id/milestones?state=active
GET /projects/:id/milestones?state=closed
+GET /projects/:id/milestones?search=version
```
Parameters:
@@ -18,7 +19,8 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID of a project |
| `iid` | Array[integer] | optional | Return only the milestone having the given `iid` |
-| `state` | string | optional | Return only `active` or `closed` milestones` |
+| `state` | string | optional | Return only `active` or `closed` milestones` |
+| `search` | string | optional | Return only milestones with a title or description matching the provided string |
```bash
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/5/milestones
@@ -115,4 +117,4 @@ GET /projects/:id/milestones/:milestone_id/merge_requests
Parameters:
- `id` (required) - The ID of a project
-- `milestone_id` (required) - The ID of a project milestone \ No newline at end of file
+- `milestone_id` (required) - The ID of a project milestone
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 72d2b320077..4600abc7dc7 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -164,6 +164,10 @@ module API
items.where(iid: iid)
end
+ def filter_by_search(items, text)
+ items.search(text)
+ end
+
# error helpers
def forbidden!(reason = nil)
diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb
index 0b4ed76b35c..44bdaea7fa4 100644
--- a/lib/api/milestones.rb
+++ b/lib/api/milestones.rb
@@ -31,6 +31,7 @@ module API
optional :state, type: String, values: %w[active closed all], default: 'all',
desc: 'Return "active", "closed", or "all" milestones'
optional :iid, type: Array[Integer], desc: 'The IID of the milestone'
+ optional :search, type: String, desc: 'The search criteria for the title or description of the milestone'
use :pagination
end
get ":id/milestones" do
@@ -39,6 +40,7 @@ module API
milestones = user_project.milestones
milestones = filter_milestones_state(milestones, params[:state])
milestones = filter_by_iid(milestones, params[:iid]) if params[:iid].present?
+ milestones = filter_by_search(milestones, params[:search]) if params[:search]
present paginate(milestones), with: Entities::Milestone
end
diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb
index 418bf5a507c..570651165ea 100644
--- a/spec/requests/api/milestones_spec.rb
+++ b/spec/requests/api/milestones_spec.rb
@@ -4,8 +4,8 @@ describe API::Milestones, api: true do
include ApiHelpers
let(:user) { create(:user) }
let!(:project) { create(:empty_project, namespace: user.namespace ) }
- let!(:closed_milestone) { create(:closed_milestone, project: project) }
- let!(:milestone) { create(:milestone, project: project) }
+ let!(:closed_milestone) { create(:closed_milestone, project: project, title: 'version1', description: 'closed milestone') }
+ let!(:milestone) { create(:milestone, project: project, title: 'version2', description: 'open milestone') }
before { project.team << [user, :developer] }
@@ -60,17 +60,28 @@ describe API::Milestones, api: true do
get api("/projects/#{project.id}/milestones", user), iid: [milestone.iid, closed_milestone.iid]
expect(response).to have_http_status(200)
+ expect(response).to include_pagination_headers
expect(json_response.size).to eq(2)
expect(json_response.first['title']).to eq milestone.title
expect(json_response.first['id']).to eq milestone.id
end
- it 'returns a project milestone by iid array' do
- get api("/projects/#{project.id}/milestones", user), iid: [milestone.iid, closed_milestone.iid]
+ it 'returns a project milestone by searching for title' do
+ get api("/projects/#{project.id}/milestones", user), search: 'version2'
expect(response).to have_http_status(200)
expect(response).to include_pagination_headers
- expect(json_response.size).to eq(2)
+ expect(json_response.size).to eq(1)
+ expect(json_response.first['title']).to eq milestone.title
+ expect(json_response.first['id']).to eq milestone.id
+ end
+
+ it 'returns a project milestones by searching for description' do
+ get api("/projects/#{project.id}/milestones", user), search: 'open'
+
+ expect(response).to have_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response.size).to eq(1)
expect(json_response.first['title']).to eq milestone.title
expect(json_response.first['id']).to eq milestone.id
end