Commit 7c36e856 authored by Sean McGivern's avatar Sean McGivern

Merge branch '41967_issue_api_closed_by_info' into 'master'

Add closed by information to issue API

See merge request gitlab-org/gitlab-ce!17042
parents 4e8bde96 b5987e62
...@@ -23,6 +23,7 @@ class Issue < ActiveRecord::Base ...@@ -23,6 +23,7 @@ class Issue < ActiveRecord::Base
belongs_to :project belongs_to :project
belongs_to :moved_to, class_name: 'Issue' belongs_to :moved_to, class_name: 'Issue'
belongs_to :closed_by, class_name: 'User'
has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.issues&.maximum(:iid) } has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.issues&.maximum(:iid) }
...@@ -78,6 +79,11 @@ class Issue < ActiveRecord::Base ...@@ -78,6 +79,11 @@ class Issue < ActiveRecord::Base
before_transition any => :closed do |issue| before_transition any => :closed do |issue|
issue.closed_at = Time.zone.now issue.closed_at = Time.zone.now
end end
before_transition closed: :opened do |issue|
issue.closed_at = nil
issue.closed_by = nil
end
end end
class << self class << self
......
...@@ -23,6 +23,7 @@ module Issues ...@@ -23,6 +23,7 @@ module Issues
end end
if project.issues_enabled? && issue.close if project.issues_enabled? && issue.close
issue.update(closed_by: current_user)
event_service.close_issue(issue, current_user) event_service.close_issue(issue, current_user)
create_note(issue, commit) if system_note create_note(issue, commit) if system_note
notification_service.close_issue(issue, current_user) if notifications notification_service.close_issue(issue, current_user) if notifications
......
---
title: adds closed by informations in issue api
merge_request: 17042
author: haseebeqx
type: added
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddClosedByToIssues < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def up
add_column :issues, :closed_by_id, :integer
add_concurrent_foreign_key :issues, :users, column: :closed_by_id, on_delete: :nullify
end
def down
remove_foreign_key :issues, column: :closed_by_id
remove_column :issues, :closed_by_id
end
end
...@@ -932,6 +932,7 @@ ActiveRecord::Schema.define(version: 20180327101207) do ...@@ -932,6 +932,7 @@ ActiveRecord::Schema.define(version: 20180327101207) do
t.integer "last_edited_by_id" t.integer "last_edited_by_id"
t.boolean "discussion_locked" t.boolean "discussion_locked"
t.datetime_with_timezone "closed_at" t.datetime_with_timezone "closed_at"
t.integer "closed_by_id"
end end
add_index "issues", ["author_id"], name: "index_issues_on_author_id", using: :btree add_index "issues", ["author_id"], name: "index_issues_on_author_id", using: :btree
...@@ -2095,6 +2096,7 @@ ActiveRecord::Schema.define(version: 20180327101207) do ...@@ -2095,6 +2096,7 @@ ActiveRecord::Schema.define(version: 20180327101207) do
add_foreign_key "issues", "milestones", name: "fk_96b1dd429c", on_delete: :nullify add_foreign_key "issues", "milestones", name: "fk_96b1dd429c", on_delete: :nullify
add_foreign_key "issues", "projects", name: "fk_899c8f3231", on_delete: :cascade add_foreign_key "issues", "projects", name: "fk_899c8f3231", on_delete: :cascade
add_foreign_key "issues", "users", column: "author_id", name: "fk_05f1e72feb", on_delete: :nullify add_foreign_key "issues", "users", column: "author_id", name: "fk_05f1e72feb", on_delete: :nullify
add_foreign_key "issues", "users", column: "closed_by_id", name: "fk_c63cbf6c25", on_delete: :nullify
add_foreign_key "issues", "users", column: "updated_by_id", name: "fk_ffed080f01", on_delete: :nullify add_foreign_key "issues", "users", column: "updated_by_id", name: "fk_ffed080f01", on_delete: :nullify
add_foreign_key "label_priorities", "labels", on_delete: :cascade add_foreign_key "label_priorities", "labels", on_delete: :cascade
add_foreign_key "label_priorities", "projects", on_delete: :cascade add_foreign_key "label_priorities", "projects", on_delete: :cascade
......
...@@ -100,6 +100,7 @@ Example response: ...@@ -100,6 +100,7 @@ Example response:
}, },
"updated_at" : "2016-01-04T15:31:51.081Z", "updated_at" : "2016-01-04T15:31:51.081Z",
"closed_at" : null, "closed_at" : null,
"closed_by" : null,
"id" : 76, "id" : 76,
"title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.", "title" : "Consequatur vero maxime deserunt laboriosam est voluptas dolorem.",
"created_at" : "2016-01-04T15:31:51.081Z", "created_at" : "2016-01-04T15:31:51.081Z",
...@@ -122,6 +123,8 @@ Example response: ...@@ -122,6 +123,8 @@ Example response:
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
**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.
## List group issues ## List group issues
Get a list of a group's issues. Get a list of a group's issues.
...@@ -216,6 +219,7 @@ Example response: ...@@ -216,6 +219,7 @@ Example response:
"updated_at" : "2016-01-04T15:31:46.176Z", "updated_at" : "2016-01-04T15:31:46.176Z",
"created_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z",
"closed_at" : null, "closed_at" : null,
"closed_by" : null,
"user_notes_count": 1, "user_notes_count": 1,
"due_date": null, "due_date": null,
"web_url": "http://example.com/example/example/issues/1", "web_url": "http://example.com/example/example/issues/1",
...@@ -233,6 +237,8 @@ Example response: ...@@ -233,6 +237,8 @@ Example response:
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
**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.
## List project issues ## List project issues
Get a list of a project's issues. Get a list of a project's issues.
...@@ -326,6 +332,14 @@ Example response: ...@@ -326,6 +332,14 @@ Example response:
"updated_at" : "2016-01-04T15:31:46.176Z", "updated_at" : "2016-01-04T15:31:46.176Z",
"created_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z",
"closed_at" : "2016-01-05T15:31:46.176Z", "closed_at" : "2016-01-05T15:31:46.176Z",
"closed_by" : {
"state" : "active",
"web_url" : "https://gitlab.example.com/root",
"avatar_url" : null,
"username" : "root",
"id" : 1,
"name" : "Administrator"
},
"user_notes_count": 1, "user_notes_count": 1,
"due_date": "2016-07-22", "due_date": "2016-07-22",
"web_url": "http://example.com/example/example/issues/1", "web_url": "http://example.com/example/example/issues/1",
...@@ -343,6 +357,8 @@ Example response: ...@@ -343,6 +357,8 @@ Example response:
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
**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.
## Single issue ## Single issue
Get a single project issue. Get a single project issue.
...@@ -409,6 +425,8 @@ Example response: ...@@ -409,6 +425,8 @@ Example response:
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z", "updated_at" : "2016-01-04T15:31:46.176Z",
"created_at" : "2016-01-04T15:31:46.176Z", "created_at" : "2016-01-04T15:31:46.176Z",
"closed_at" : null,
"closed_by" : null,
"subscribed": false, "subscribed": false,
"user_notes_count": 1, "user_notes_count": 1,
"due_date": null, "due_date": null,
...@@ -432,6 +450,8 @@ Example response: ...@@ -432,6 +450,8 @@ Example response:
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
**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.
## New issue ## New issue
Creates a new project issue. Creates a new project issue.
...@@ -484,6 +504,7 @@ Example response: ...@@ -484,6 +504,7 @@ Example response:
"description" : null, "description" : null,
"updated_at" : "2016-01-07T12:44:33.959Z", "updated_at" : "2016-01-07T12:44:33.959Z",
"closed_at" : null, "closed_at" : null,
"closed_by" : null,
"milestone" : null, "milestone" : null,
"subscribed" : true, "subscribed" : true,
"user_notes_count": 0, "user_notes_count": 0,
...@@ -508,6 +529,8 @@ Example response: ...@@ -508,6 +529,8 @@ Example response:
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
**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.
## Edit issue ## Edit issue
Updates an existing project issue. This call is also used to mark an issue as Updates an existing project issue. This call is also used to mark an issue as
...@@ -556,6 +579,14 @@ Example response: ...@@ -556,6 +579,14 @@ Example response:
"description" : null, "description" : null,
"updated_at" : "2016-01-07T12:55:16.213Z", "updated_at" : "2016-01-07T12:55:16.213Z",
"closed_at" : "2016-01-08T12:55:16.213Z", "closed_at" : "2016-01-08T12:55:16.213Z",
"closed_by" : {
"state" : "active",
"web_url" : "https://gitlab.example.com/root",
"avatar_url" : null,
"username" : "root",
"id" : 1,
"name" : "Administrator"
},
"iid" : 15, "iid" : 15,
"labels" : [ "labels" : [
"bug" "bug"
...@@ -587,6 +618,8 @@ Example response: ...@@ -587,6 +618,8 @@ Example response:
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
**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.
## Delete an issue ## Delete an issue
Only for admins and project owners. Soft deletes the issue in question. Only for admins and project owners. Soft deletes the issue in question.
...@@ -640,6 +673,7 @@ Example response: ...@@ -640,6 +673,7 @@ Example response:
"created_at": "2016-04-05T21:41:45.652Z", "created_at": "2016-04-05T21:41:45.652Z",
"updated_at": "2016-04-07T12:20:17.596Z", "updated_at": "2016-04-07T12:20:17.596Z",
"closed_at": null, "closed_at": null,
"closed_by": null,
"labels": [], "labels": [],
"milestone": null, "milestone": null,
"assignees": [{ "assignees": [{
...@@ -687,6 +721,8 @@ Example response: ...@@ -687,6 +721,8 @@ Example response:
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
**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.
## Subscribe to an issue ## Subscribe to an issue
Subscribes the authenticated user to an issue to receive notifications. Subscribes the authenticated user to an issue to receive notifications.
...@@ -719,6 +755,7 @@ Example response: ...@@ -719,6 +755,7 @@ Example response:
"created_at": "2016-04-05T21:41:45.652Z", "created_at": "2016-04-05T21:41:45.652Z",
"updated_at": "2016-04-07T12:20:17.596Z", "updated_at": "2016-04-07T12:20:17.596Z",
"closed_at": null, "closed_at": null,
"closed_by": null,
"labels": [], "labels": [],
"milestone": null, "milestone": null,
"assignees": [{ "assignees": [{
...@@ -766,6 +803,9 @@ Example response: ...@@ -766,6 +803,9 @@ Example response:
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
**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.
## Unsubscribe from an issue ## Unsubscribe from an issue
Unsubscribes the authenticated user from the issue to not receive notifications Unsubscribes the authenticated user from the issue to not receive notifications
...@@ -807,6 +847,8 @@ Example response: ...@@ -807,6 +847,8 @@ Example response:
"avatar_url": "http://www.gravatar.com/avatar/3e6f06a86cf27fa8b56f3f74f7615987?s=80&d=identicon", "avatar_url": "http://www.gravatar.com/avatar/3e6f06a86cf27fa8b56f3f74f7615987?s=80&d=identicon",
"web_url": "https://gitlab.example.com/keyon" "web_url": "https://gitlab.example.com/keyon"
}, },
"closed_at": null,
"closed_by": null,
"author": { "author": {
"name": "Vivian Hermann", "name": "Vivian Hermann",
"username": "orville", "username": "orville",
...@@ -927,6 +969,9 @@ Example response: ...@@ -927,6 +969,9 @@ Example response:
**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API. **Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
**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.
## Set a time estimate for an issue ## Set a time estimate for an issue
Sets an estimated time of work for this issue. Sets an estimated time of work for this issue.
...@@ -1112,6 +1157,8 @@ Example response: ...@@ -1112,6 +1157,8 @@ Example response:
"assignee": null, "assignee": null,
"source_project_id": 1, "source_project_id": 1,
"target_project_id": 1, "target_project_id": 1,
"closed_at": null,
"closed_by": null,
"labels": [], "labels": [],
"work_in_progress": false, "work_in_progress": false,
"milestone": null, "milestone": null,
...@@ -1206,3 +1253,4 @@ Example response: ...@@ -1206,3 +1253,4 @@ Example response:
[ce-13004]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13004 [ce-13004]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13004
[ce-14016]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14016 [ce-14016]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14016
[ce-17042]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17042
...@@ -405,6 +405,7 @@ module API ...@@ -405,6 +405,7 @@ module API
class IssueBasic < ProjectEntity class IssueBasic < ProjectEntity
expose :closed_at expose :closed_at
expose :closed_by, using: Entities::UserBasic
expose :labels do |issue, options| expose :labels do |issue, options|
# Avoids an N+1 query since labels are preloaded # Avoids an N+1 query since labels are preloaded
issue.labels.map(&:title).sort issue.labels.map(&:title).sort
......
...@@ -19,7 +19,7 @@ module Gitlab ...@@ -19,7 +19,7 @@ module Gitlab
custom_attributes: 'ProjectCustomAttribute', custom_attributes: 'ProjectCustomAttribute',
project_badges: 'Badge' }.freeze project_badges: 'Badge' }.freeze
USER_REFERENCES = %w[author_id assignee_id updated_by_id user_id created_by_id last_edited_by_id merge_user_id resolved_by_id].freeze USER_REFERENCES = %w[author_id assignee_id updated_by_id user_id created_by_id last_edited_by_id merge_user_id resolved_by_id closed_by_id].freeze
PROJECT_REFERENCES = %w[project_id source_project_id target_project_id].freeze PROJECT_REFERENCES = %w[project_id source_project_id target_project_id].freeze
......
...@@ -18,6 +18,7 @@ issues: ...@@ -18,6 +18,7 @@ issues:
- metrics - metrics
- timelogs - timelogs
- issue_assignees - issue_assignees
- closed_by
events: events:
- author - author
- project - project
......
...@@ -15,6 +15,7 @@ Issue: ...@@ -15,6 +15,7 @@ Issue:
- updated_by_id - updated_by_id
- confidential - confidential
- closed_at - closed_at
- closed_by_id
- due_date - due_date
- moved_to_id - moved_to_id
- lock_version - lock_version
......
...@@ -67,6 +67,10 @@ describe Issues::CloseService do ...@@ -67,6 +67,10 @@ describe Issues::CloseService do
expect(issue).to be_closed expect(issue).to be_closed
end end
it 'records closed user' do
expect(issue.closed_by_id).to be(user.id)
end
it 'sends email to user2 about assign of new issue' do it 'sends email to user2 about assign of new issue' do
email = ActionMailer::Base.deliveries.last email = ActionMailer::Base.deliveries.last
expect(email.to.first).to eq(user2.email) expect(email.to.first).to eq(user2.email)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment