Merge branch '41616-api-issues-between-date' into 'master'
Resolve "API support for selecting only updated issues before/after a given date" Closes #41616 See merge request gitlab-org/gitlab-ce!17417
This commit is contained in:
commit
5a1da682a7
14 changed files with 219 additions and 14 deletions
|
@ -19,6 +19,10 @@
|
|||
# non_archived: boolean
|
||||
# iids: integer[]
|
||||
# my_reaction_emoji: string
|
||||
# created_after: datetime
|
||||
# created_before: datetime
|
||||
# updated_after: datetime
|
||||
# updated_before: datetime
|
||||
#
|
||||
class IssuableFinder
|
||||
prepend FinderWithCrossProjectAccess
|
||||
|
@ -79,6 +83,7 @@ class IssuableFinder
|
|||
def filter_items(items)
|
||||
items = by_scope(items)
|
||||
items = by_created_at(items)
|
||||
items = by_updated_at(items)
|
||||
items = by_state(items)
|
||||
items = by_group(items)
|
||||
items = by_search(items)
|
||||
|
@ -283,6 +288,13 @@ class IssuableFinder
|
|||
end
|
||||
end
|
||||
|
||||
def by_updated_at(items)
|
||||
items = items.updated_after(params[:updated_after]) if params[:updated_after].present?
|
||||
items = items.updated_before(params[:updated_before]) if params[:updated_before].present?
|
||||
|
||||
items
|
||||
end
|
||||
|
||||
def by_state(items)
|
||||
case params[:state].to_s
|
||||
when 'closed'
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
# my_reaction_emoji: string
|
||||
# public_only: boolean
|
||||
# due_date: date or '0', '', 'overdue', 'week', or 'month'
|
||||
# created_after: datetime
|
||||
# created_before: datetime
|
||||
# updated_after: datetime
|
||||
# updated_before: datetime
|
||||
#
|
||||
class IssuesFinder < IssuableFinder
|
||||
CONFIDENTIAL_ACCESS_LEVEL = Gitlab::Access::REPORTER
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
# my_reaction_emoji: string
|
||||
# source_branch: string
|
||||
# target_branch: string
|
||||
# created_after: datetime
|
||||
# created_before: datetime
|
||||
# updated_after: datetime
|
||||
# updated_before: datetime
|
||||
#
|
||||
class MergeRequestsFinder < IssuableFinder
|
||||
def klass
|
||||
|
|
|
@ -19,6 +19,7 @@ module Issuable
|
|||
include AfterCommitQueue
|
||||
include Sortable
|
||||
include CreatedAtFilterable
|
||||
include UpdatedAtFilterable
|
||||
|
||||
# This object is used to gather issuable meta data for displaying
|
||||
# upvotes, downvotes, notes and closing merge requests count for issues and merge requests
|
||||
|
|
12
app/models/concerns/updated_at_filterable.rb
Normal file
12
app/models/concerns/updated_at_filterable.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
module UpdatedAtFilterable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
scope :updated_before, ->(date) { where(scoped_table[:updated_at].lteq(date)) }
|
||||
scope :updated_after, ->(date) { where(scoped_table[:updated_at].gteq(date)) }
|
||||
|
||||
def self.scoped_table
|
||||
arel_table.alias(table_name)
|
||||
end
|
||||
end
|
||||
end
|
5
changelogs/unreleased/41616-api-issues-between-date.yml
Normal file
5
changelogs/unreleased/41616-api-issues-between-date.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Adds updated_at filter to issues and merge_requests API
|
||||
merge_request: 17417
|
||||
author: Jacopo Beschi @jacopo-beschi
|
||||
type: added
|
|
@ -46,6 +46,10 @@ GET /issues?my_reaction_emoji=star
|
|||
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
|
||||
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
|
||||
| `search` | string | no | Search issues against their `title` and `description` |
|
||||
| `created_after` | datetime | no | Return issues created on or after the given time |
|
||||
| `created_before` | datetime | no | Return issues created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return issues updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return issues updated on or before the given time |
|
||||
|
||||
```bash
|
||||
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/issues
|
||||
|
@ -152,6 +156,10 @@ GET /groups/:id/issues?my_reaction_emoji=star
|
|||
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
|
||||
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
|
||||
| `search` | string | no | Search group issues against their `title` and `description` |
|
||||
| `created_after` | datetime | no | Return issues created on or after the given time |
|
||||
| `created_before` | datetime | no | Return issues created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return issues updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return issues updated on or before the given time |
|
||||
|
||||
|
||||
```bash
|
||||
|
@ -259,8 +267,10 @@ GET /projects/:id/issues?my_reaction_emoji=star
|
|||
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
|
||||
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
|
||||
| `search` | string | no | Search project issues against their `title` and `description` |
|
||||
| `created_after` | datetime | no | Return issues created after the given time (inclusive) |
|
||||
| `created_before` | datetime | no | Return issues created before the given time (inclusive) |
|
||||
| `created_after` | datetime | no | Return issues created on or after the given time |
|
||||
| `created_before` | datetime | no | Return issues created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return issues updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return issues updated on or before the given time |
|
||||
|
||||
```bash
|
||||
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/4/issues
|
||||
|
|
|
@ -41,8 +41,10 @@ Parameters:
|
|||
| `milestone` | string | no | Return merge requests for a specific milestone |
|
||||
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |
|
||||
| `labels` | string | no | Return merge requests matching a comma separated list of labels |
|
||||
| `created_after` | datetime | no | Return merge requests created after the given time (inclusive) |
|
||||
| `created_before` | datetime | no | Return merge requests created before the given time (inclusive) |
|
||||
| `created_after` | datetime | no | Return merge requests created on or after the given time |
|
||||
| `created_before` | datetime | no | Return merge requests created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return merge requests updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return merge requests updated on or before the given time |
|
||||
| `scope` | string | no | Return merge requests for the given scope: `created-by-me`, `assigned-to-me` or `all`. Defaults to `created-by-me` |
|
||||
| `author_id` | integer | no | Returns merge requests created by the given user `id`. Combine with `scope=all` or `scope=assigned-to-me` |
|
||||
| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id` |
|
||||
|
@ -158,8 +160,10 @@ Parameters:
|
|||
| `milestone` | string | no | Return merge requests for a specific milestone |
|
||||
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |
|
||||
| `labels` | string | no | Return merge requests matching a comma separated list of labels |
|
||||
| `created_after` | datetime | no | Return merge requests created after the given time (inclusive) |
|
||||
| `created_before` | datetime | no | Return merge requests created before the given time (inclusive) |
|
||||
| `created_after` | datetime | no | Return merge requests created on or after the given time |
|
||||
| `created_before` | datetime | no | Return merge requests created on or before the given time |
|
||||
| `updated_after` | datetime | no | Return merge requests updated on or after the given time |
|
||||
| `updated_before` | datetime | no | Return merge requests updated on or before the given time |
|
||||
| `scope` | string | no | Return merge requests for the given scope: `created-by-me`, `assigned-to-me` or `all` _([Introduced][ce-13060] in GitLab 9.5)_ |
|
||||
| `author_id` | integer | no | Returns merge requests created by the given user `id` _([Introduced][ce-13060] in GitLab 9.5)_ |
|
||||
| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id` _([Introduced][ce-13060] in GitLab 9.5)_ |
|
||||
|
|
|
@ -32,6 +32,8 @@ module API
|
|||
optional :search, type: String, desc: 'Search issues for text present in the title or description'
|
||||
optional :created_after, type: DateTime, desc: 'Return issues created after the specified time'
|
||||
optional :created_before, type: DateTime, desc: 'Return issues created before the specified time'
|
||||
optional :updated_after, type: DateTime, desc: 'Return issues updated after the specified time'
|
||||
optional :updated_before, type: DateTime, desc: 'Return issues updated before the specified time'
|
||||
optional :author_id, type: Integer, desc: 'Return issues which are authored by the user with the given ID'
|
||||
optional :assignee_id, type: Integer, desc: 'Return issues which are assigned to the user with the given ID'
|
||||
optional :scope, type: String, values: %w[created-by-me assigned-to-me all],
|
||||
|
|
|
@ -42,6 +42,8 @@ module API
|
|||
optional :labels, type: String, desc: 'Comma-separated list of label names'
|
||||
optional :created_after, type: DateTime, desc: 'Return merge requests created after the specified time'
|
||||
optional :created_before, type: DateTime, desc: 'Return merge requests created before the specified time'
|
||||
optional :updated_after, type: DateTime, desc: 'Return merge requests updated after the specified time'
|
||||
optional :updated_before, type: DateTime, desc: 'Return merge requests updated before the specified time'
|
||||
optional :view, type: String, values: %w[simple], desc: 'If simple, returns the `iid`, URL, title, description, and basic state of merge request'
|
||||
optional :author_id, type: Integer, desc: 'Return merge requests which are authored by the user with the given ID'
|
||||
optional :assignee_id, type: Integer, desc: 'Return merge requests which are assigned to the user with the given ID'
|
||||
|
|
|
@ -10,9 +10,9 @@ describe IssuesFinder do
|
|||
set(:project3) { create(:project, group: subgroup) }
|
||||
set(:milestone) { create(:milestone, project: project1) }
|
||||
set(:label) { create(:label, project: project2) }
|
||||
set(:issue1) { create(:issue, author: user, assignees: [user], project: project1, milestone: milestone, title: 'gitlab', created_at: 1.week.ago) }
|
||||
set(:issue2) { create(:issue, author: user, assignees: [user], project: project2, description: 'gitlab') }
|
||||
set(:issue3) { create(:issue, author: user2, assignees: [user2], project: project2, title: 'tanuki', description: 'tanuki', created_at: 1.week.from_now) }
|
||||
set(:issue1) { create(:issue, author: user, assignees: [user], project: project1, milestone: milestone, title: 'gitlab', created_at: 1.week.ago, updated_at: 1.week.ago) }
|
||||
set(:issue2) { create(:issue, author: user, assignees: [user], project: project2, description: 'gitlab', created_at: 1.week.from_now, updated_at: 1.week.from_now) }
|
||||
set(:issue3) { create(:issue, author: user2, assignees: [user2], project: project2, title: 'tanuki', description: 'tanuki', created_at: 2.weeks.from_now, updated_at: 2.weeks.from_now) }
|
||||
set(:issue4) { create(:issue, project: project3) }
|
||||
set(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue1) }
|
||||
set(:award_emoji2) { create(:award_emoji, name: 'thumbsup', user: user2, awardable: issue2) }
|
||||
|
@ -275,12 +275,46 @@ describe IssuesFinder do
|
|||
end
|
||||
|
||||
context 'through created_before' do
|
||||
let(:params) { { created_before: issue1.created_at + 1.second } }
|
||||
let(:params) { { created_before: issue1.created_at } }
|
||||
|
||||
it 'returns issues created on or before the given date' do
|
||||
expect(issues).to contain_exactly(issue1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'through created_after and created_before' do
|
||||
let(:params) { { created_after: issue2.created_at, created_before: issue3.created_at } }
|
||||
|
||||
it 'returns issues created between the given dates' do
|
||||
expect(issues).to contain_exactly(issue2, issue3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'filtering by updated_at' do
|
||||
context 'through updated_after' do
|
||||
let(:params) { { updated_after: issue3.updated_at } }
|
||||
|
||||
it 'returns issues updated on or after the given date' do
|
||||
expect(issues).to contain_exactly(issue3)
|
||||
end
|
||||
end
|
||||
|
||||
context 'through updated_before' do
|
||||
let(:params) { { updated_before: issue1.updated_at } }
|
||||
|
||||
it 'returns issues updated on or before the given date' do
|
||||
expect(issues).to contain_exactly(issue1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'through updated_after and updated_before' do
|
||||
let(:params) { { updated_after: issue2.updated_at, updated_before: issue3.updated_at } }
|
||||
|
||||
it 'returns issues updated between the given dates' do
|
||||
expect(issues).to contain_exactly(issue2, issue3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'filtering by reaction name' do
|
||||
|
|
|
@ -109,7 +109,7 @@ describe MergeRequestsFinder do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with created_after and created_before params' do
|
||||
context 'filtering by created_at/updated_at' do
|
||||
let(:new_project) { create(:project, forked_from_project: project1) }
|
||||
|
||||
let!(:new_merge_request) do
|
||||
|
@ -117,15 +117,18 @@ describe MergeRequestsFinder do
|
|||
:simple,
|
||||
author: user,
|
||||
created_at: 1.week.from_now,
|
||||
updated_at: 1.week.from_now,
|
||||
source_project: new_project,
|
||||
target_project: project1)
|
||||
target_project: new_project)
|
||||
end
|
||||
|
||||
let!(:old_merge_request) do
|
||||
create(:merge_request,
|
||||
:simple,
|
||||
author: user,
|
||||
source_branch: 'feature_1',
|
||||
created_at: 1.week.ago,
|
||||
updated_at: 1.week.ago,
|
||||
source_project: new_project,
|
||||
target_project: new_project)
|
||||
end
|
||||
|
@ -135,7 +138,7 @@ describe MergeRequestsFinder do
|
|||
end
|
||||
|
||||
it 'filters by created_after' do
|
||||
params = { project_id: project1.id, created_after: new_merge_request.created_at }
|
||||
params = { project_id: new_project.id, created_after: new_merge_request.created_at }
|
||||
|
||||
merge_requests = described_class.new(user, params).execute
|
||||
|
||||
|
@ -143,12 +146,52 @@ describe MergeRequestsFinder do
|
|||
end
|
||||
|
||||
it 'filters by created_before' do
|
||||
params = { project_id: new_project.id, created_before: old_merge_request.created_at + 1.second }
|
||||
params = { project_id: new_project.id, created_before: old_merge_request.created_at }
|
||||
|
||||
merge_requests = described_class.new(user, params).execute
|
||||
|
||||
expect(merge_requests).to contain_exactly(old_merge_request)
|
||||
end
|
||||
|
||||
it 'filters by created_after and created_before' do
|
||||
params = {
|
||||
project_id: new_project.id,
|
||||
created_after: old_merge_request.created_at,
|
||||
created_before: new_merge_request.created_at
|
||||
}
|
||||
|
||||
merge_requests = described_class.new(user, params).execute
|
||||
|
||||
expect(merge_requests).to contain_exactly(old_merge_request, new_merge_request)
|
||||
end
|
||||
|
||||
it 'filters by updated_after' do
|
||||
params = { project_id: new_project.id, updated_after: new_merge_request.updated_at }
|
||||
|
||||
merge_requests = described_class.new(user, params).execute
|
||||
|
||||
expect(merge_requests).to contain_exactly(new_merge_request)
|
||||
end
|
||||
|
||||
it 'filters by updated_before' do
|
||||
params = { project_id: new_project.id, updated_before: old_merge_request.updated_at }
|
||||
|
||||
merge_requests = described_class.new(user, params).execute
|
||||
|
||||
expect(merge_requests).to contain_exactly(old_merge_request)
|
||||
end
|
||||
|
||||
it 'filters by updated_after and updated_before' do
|
||||
params = {
|
||||
project_id: new_project.id,
|
||||
updated_after: old_merge_request.updated_at,
|
||||
updated_before: new_merge_request.updated_at
|
||||
}
|
||||
|
||||
merge_requests = described_class.new(user, params).execute
|
||||
|
||||
expect(merge_requests).to contain_exactly(old_merge_request, new_merge_request)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -163,6 +163,42 @@ describe API::Issues do
|
|||
expect(first_issue['id']).to eq(issue.id)
|
||||
end
|
||||
|
||||
context 'filtering before a specific date' do
|
||||
let!(:issue2) { create(:issue, project: project, author: user, created_at: Date.new(2000, 1, 1), updated_at: Date.new(2000, 1, 1)) }
|
||||
|
||||
it 'returns issues created before a specific date' do
|
||||
get api('/issues?created_before=2000-01-02T00:00:00.060Z', user)
|
||||
|
||||
expect(json_response.size).to eq(1)
|
||||
expect(first_issue['id']).to eq(issue2.id)
|
||||
end
|
||||
|
||||
it 'returns issues updated before a specific date' do
|
||||
get api('/issues?updated_before=2000-01-02T00:00:00.060Z', user)
|
||||
|
||||
expect(json_response.size).to eq(1)
|
||||
expect(first_issue['id']).to eq(issue2.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'filtering after a specific date' do
|
||||
let!(:issue2) { create(:issue, project: project, author: user, created_at: 1.week.from_now, updated_at: 1.week.from_now) }
|
||||
|
||||
it 'returns issues created after a specific date' do
|
||||
get api("/issues?created_after=#{issue2.created_at}", user)
|
||||
|
||||
expect(json_response.size).to eq(1)
|
||||
expect(first_issue['id']).to eq(issue2.id)
|
||||
end
|
||||
|
||||
it 'returns issues updated after a specific date' do
|
||||
get api("/issues?updated_after=#{issue2.updated_at}", user)
|
||||
|
||||
expect(json_response.size).to eq(1)
|
||||
expect(first_issue['id']).to eq(issue2.id)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns an array of labeled issues' do
|
||||
get api("/issues", user), labels: label.title
|
||||
|
||||
|
|
|
@ -172,6 +172,42 @@ describe API::MergeRequests do
|
|||
end
|
||||
end
|
||||
|
||||
it 'returns merge requests created before a specific date' do
|
||||
merge_request2 = create(:merge_request, :simple, source_project: project, target_project: project, source_branch: 'feature_1', created_at: Date.new(2000, 1, 1))
|
||||
|
||||
get api('/merge_requests?created_before=2000-01-02T00:00:00.060Z', user)
|
||||
|
||||
expect(json_response.size).to eq(1)
|
||||
expect(json_response.first['id']).to eq(merge_request2.id)
|
||||
end
|
||||
|
||||
it 'returns merge requests created after a specific date' do
|
||||
merge_request2 = create(:merge_request, :simple, source_project: project, target_project: project, source_branch: 'feature_1', created_at: 1.week.from_now)
|
||||
|
||||
get api("/merge_requests?created_after=#{merge_request2.created_at}", user)
|
||||
|
||||
expect(json_response.size).to eq(1)
|
||||
expect(json_response.first['id']).to eq(merge_request2.id)
|
||||
end
|
||||
|
||||
it 'returns merge requests updated before a specific date' do
|
||||
merge_request2 = create(:merge_request, :simple, source_project: project, target_project: project, source_branch: 'feature_1', updated_at: Date.new(2000, 1, 1))
|
||||
|
||||
get api('/merge_requests?updated_before=2000-01-02T00:00:00.060Z', user)
|
||||
|
||||
expect(json_response.size).to eq(1)
|
||||
expect(json_response.first['id']).to eq(merge_request2.id)
|
||||
end
|
||||
|
||||
it 'returns merge requests updated after a specific date' do
|
||||
merge_request2 = create(:merge_request, :simple, source_project: project, target_project: project, source_branch: 'feature_1', updated_at: 1.week.from_now)
|
||||
|
||||
get api("/merge_requests?updated_after=#{merge_request2.updated_at}", user)
|
||||
|
||||
expect(json_response.size).to eq(1)
|
||||
expect(json_response.first['id']).to eq(merge_request2.id)
|
||||
end
|
||||
|
||||
context 'search params' do
|
||||
before do
|
||||
merge_request.update(title: 'Search title', description: 'Search description')
|
||||
|
|
Loading…
Reference in a new issue