Commit 30e16d27 authored by Thong Kuah's avatar Thong Kuah

Merge branch 'epic-events-ee' into 'master'

[EE] Create an event on epic actions

See merge request gitlab-org/gitlab-ee!15649
parents 6898a225 55b747ee
......@@ -19,6 +19,7 @@ class Board < ApplicationRecord
def parent
@parent ||= group || project
end
alias_method :resource_parent, :parent
def group_board?
group_id.present?
......
......@@ -277,6 +277,10 @@ module Issuable
end
end
def resource_parent
project
end
def milestone_available?
project_id == milestone&.project_id || project.ancestors_upto.compact.include?(milestone&.group)
end
......
......@@ -51,6 +51,7 @@ class Event < ApplicationRecord
belongs_to :author, class_name: "User"
belongs_to :project
belongs_to :group
belongs_to :target, -> {
# If the association for "target" defines an "author" association we want to
......
......@@ -262,6 +262,7 @@ class Milestone < ApplicationRecord
def parent
group || project
end
alias_method :resource_parent, :parent
def group_milestone?
group_id.present?
......
......@@ -477,6 +477,7 @@ class Note < ApplicationRecord
def parent
project
end
alias_method :resource_parent, :parent
private
......
......@@ -146,6 +146,7 @@ class Todo < ApplicationRecord
def parent
project
end
alias_method :resource_parent, :parent
def unmergeable?
action == UNMERGEABLE
......
......@@ -95,16 +95,25 @@ class EventCreateService
private
def create_record_event(record, current_user, status)
create_event(record.project, current_user, status, target_id: record.id, target_type: record.class.name)
create_event(record.resource_parent, current_user, status, target_id: record.id, target_type: record.class.name)
end
def create_event(project, current_user, status, attributes = {})
def create_event(resource_parent, current_user, status, attributes = {})
attributes.reverse_merge!(
project: project,
action: status,
author_id: current_user.id
)
resource_parent_attr = case resource_parent
when Project
:project
when Group
:group
end
attributes[resource_parent_attr] = resource_parent if resource_parent_attr
Event.create!(attributes)
end
end
EventCreateService.prepend_if_ee('EE::EventCreateService')
# frozen_string_literal: true
class AddGroupColumnToEvents < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
add_reference :events, :group, index: true, foreign_key: { to_table: :namespaces, on_delete: :cascade }
end
end
......@@ -1310,9 +1310,11 @@ ActiveRecord::Schema.define(version: 2019_09_02_160015) do
t.datetime_with_timezone "updated_at", null: false
t.integer "action", limit: 2, null: false
t.string "target_type"
t.bigint "group_id"
t.index ["action"], name: "index_events_on_action"
t.index ["author_id", "project_id"], name: "index_events_on_author_id_and_project_id"
t.index ["created_at", "author_id"], name: "analytics_index_events_on_created_at_and_author_id"
t.index ["group_id"], name: "index_events_on_group_id"
t.index ["project_id", "created_at"], name: "index_events_on_project_id_and_created_at"
t.index ["project_id", "id"], name: "index_events_on_project_id_and_id"
t.index ["target_type", "target_id"], name: "index_events_on_target_type_and_target_id"
......@@ -3838,6 +3840,7 @@ ActiveRecord::Schema.define(version: 2019_09_02_160015) do
add_foreign_key "epics", "users", column: "assignee_id", name: "fk_dccd3f98fc", on_delete: :nullify
add_foreign_key "epics", "users", column: "author_id", name: "fk_3654b61b03", on_delete: :cascade
add_foreign_key "epics", "users", column: "closed_by_id", name: "fk_aa5798e761", on_delete: :nullify
add_foreign_key "events", "namespaces", column: "group_id", on_delete: :cascade
add_foreign_key "events", "projects", on_delete: :cascade
add_foreign_key "events", "users", column: "author_id", name: "fk_edfd187b6f", on_delete: :cascade
add_foreign_key "fork_network_members", "fork_networks", on_delete: :cascade
......
......@@ -37,6 +37,7 @@ module EE
belongs_to :due_date_sourcing_milestone, class_name: 'Milestone'
belongs_to :parent, class_name: "Epic"
has_many :children, class_name: "Epic", foreign_key: :parent_id
has_many :events, as: :target, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.epics&.maximum(:iid) }
......@@ -208,6 +209,10 @@ module EE
end
end
def resource_parent
group
end
def assignees
Array(assignee)
end
......
......@@ -58,6 +58,7 @@ module EE
def parent
for_epic? ? noteable.group : super
end
alias_method :resource_parent, :parent
def notify_after_create
noteable&.after_note_created(self)
......
......@@ -8,6 +8,7 @@ module EE
def parent
project || group
end
alias_method :resource_parent, :parent
def for_design?
target_type == DesignManagement::Design.name
......
# frozen_string_literal: true
module EE
module EventCreateService
def open_epic(epic, current_user)
create_record_event(epic, current_user, ::Event::CREATED)
end
def close_epic(epic, current_user)
create_record_event(epic, current_user, ::Event::CLOSED)
end
def reopen_epic(epic, current_user)
create_record_event(epic, current_user, ::Event::REOPENED)
end
end
end
......@@ -13,6 +13,7 @@ module Epics
def close_epic(epic)
if epic.close
epic.update(closed_by: current_user)
event_service.close_epic(epic, current_user)
SystemNoteService.change_status(epic, nil, current_user, epic.state)
notification_service.close_epic(epic, current_user)
end
......
......@@ -12,6 +12,7 @@ module Epics
def reopen_epic(epic)
if epic.reopen
event_service.reopen_epic(epic, current_user)
SystemNoteService.change_status(epic, nil, current_user, epic.state)
notification_service.reopen_epic(epic, current_user)
end
......
......@@ -7,6 +7,7 @@ class NewEpicWorker
def perform(epic_id, user_id)
return unless objects_found?(epic_id, user_id)
EventCreateService.new.open_epic(issuable, user)
NotificationService.new.new_epic(issuable)
issuable.create_cross_references!(user)
end
......
# frozen_string_literal: true
require 'spec_helper'
describe EventCreateService do
let(:service) { described_class.new }
describe 'Epics' do
let(:epic) { create(:epic) }
describe '#open_epic' do
it "creates new event" do
event = service.open_epic(epic, epic.author)
expect_event(event, Event::CREATED)
end
end
describe '#close_epic' do
it "creates new event" do
event = service.close_epic(epic, epic.author)
expect_event(event, Event::CLOSED)
end
end
describe '#reopen_epic' do
it "creates new event" do
event = service.reopen_epic(epic, epic.author)
expect_event(event, Event::REOPENED)
end
end
describe '#leave_note' do
it "creates new event" do
note = create(:note, noteable: epic)
event = service.leave_note(note, epic.author)
expect_event(event, Event::COMMENTED)
end
end
def expect_event(event, action)
expect(event).to be_persisted
expect(event.action).to eq action
expect(event.project_id).to be_nil
expect(event.group_id).to eq epic.group_id
end
end
end
......@@ -59,6 +59,10 @@ describe Epics::CloseService do
subject.execute(epic)
end
it "creates new event" do
expect { subject.execute(epic) }.to change { Event.count }
end
end
context 'when trying to close a closed epic' do
......@@ -87,6 +91,10 @@ describe Epics::CloseService do
subject.execute(epic)
end
it "does not create an event" do
expect { subject.execute(epic) }.not_to change { Event.count }
end
end
end
......
......@@ -59,6 +59,10 @@ describe Epics::ReopenService do
subject.execute(epic)
end
it "creates new event" do
expect { subject.execute(epic) }.to change { Event.count }
end
end
context 'when trying to reopen an opened epic' do
......@@ -87,6 +91,10 @@ describe Epics::ReopenService do
subject.execute(epic)
end
it "does not create an event" do
expect { subject.execute(epic) }.not_to change { Event.count }
end
end
end
......
......@@ -42,6 +42,10 @@ describe NewEpicWorker do
stub_licensed_features(epics: true)
end
it 'creates an event' do
expect { worker.perform(epic.id, user.id) }.to change { Event.count }.from(0).to(1)
end
context 'user watches group' do
before do
create(
......
......@@ -26,6 +26,7 @@ issues:
events:
- author
- project
- group
- target
- push_event_payload
notes:
......
......@@ -33,6 +33,7 @@ Event:
- target_type
- target_id
- project_id
- group_id
- created_at
- updated_at
- action
......
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