diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb index efe42fb29d50a7b1a6be00a6d20de2593cdaceb3..f982d66eb088ee0ef19c4758beac4b576bf58691 100644 --- a/app/services/issues/base_service.rb +++ b/app/services/issues/base_service.rb @@ -124,6 +124,10 @@ def execute_incident_hooks(issue, issue_data) def update_project_counter_caches?(issue) super || issue.confidential_changed? end + + def log_audit_event(issue, user, event_type, message) + # defined in EE + end end end diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb index e45033f2b916c1e5ac527f68b1a5186aed5f6dfc..f848a8db12a199e065edb286716efe579d009d19 100644 --- a/app/services/issues/close_service.rb +++ b/app/services/issues/close_service.rb @@ -28,6 +28,11 @@ def close_issue(issue, closed_via: nil, notifications: true, system_note: true) event_service.close_issue(issue, current_user) create_note(issue, closed_via) if system_note + if current_user.project_bot? + log_audit_event(issue, current_user, "#{issue.issue_type}_closed_by_project_bot", + "Closed #{issue.issue_type.humanize(capitalize: false)} #{issue.title}") + end + closed_via = _("commit %{commit_id}") % { commit_id: closed_via.id } if closed_via.is_a?(Commit) notification_service.async.close_issue(issue, current_user, { closed_via: closed_via }) if notifications diff --git a/app/services/issues/reopen_service.rb b/app/services/issues/reopen_service.rb index f4d229ecec7a594d6cde1c28209363b0b8c8d5f0..d71ba4e3414d805651a278d233fbd64445114659 100644 --- a/app/services/issues/reopen_service.rb +++ b/app/services/issues/reopen_service.rb @@ -7,6 +7,12 @@ def execute(issue, skip_authorization: false) if issue.reopen event_service.reopen_issue(issue, current_user) + + if current_user.project_bot? + log_audit_event(issue, current_user, "#{issue.issue_type}_reopened_by_project_bot", + "Reopened #{issue.issue_type.humanize(capitalize: false)} #{issue.title}") + end + create_note(issue, 'reopened') notification_service.async.reopen_issue(issue, current_user) perform_incident_management_actions(issue) diff --git a/app/workers/new_issue_worker.rb b/app/workers/new_issue_worker.rb index 07699a50e36e049bf048227191ed520e37c47154..0e7f11debd290e96b2600ed1c9f32e97638f03ee 100644 --- a/app/workers/new_issue_worker.rb +++ b/app/workers/new_issue_worker.rb @@ -28,5 +28,15 @@ def perform(issue_id, user_id, issuable_class = 'Issue') Issues::AfterCreateService .new(container: issuable.project, current_user: user) .execute(issuable) + + log_audit_event if user.project_bot? + end + + private + + def log_audit_event + # defined in EE end end + +NewIssueWorker.prepend_mod diff --git a/ee/app/services/ee/issues/base_service.rb b/ee/app/services/ee/issues/base_service.rb index 4cd141bb3e90da0359b788868fc8eb4b4618e3e0..b501620cca566ba47608f62c094106697200a30f 100644 --- a/ee/app/services/ee/issues/base_service.rb +++ b/ee/app/services/ee/issues/base_service.rb @@ -166,6 +166,19 @@ def process_iteration_id params[:iteration] = iteration if iteration end + + def log_audit_event(issue, user, event_type, message) + audit_context = { + name: event_type, + author: user, + scope: issue.respond_to?(:group) ? issue.group : issue.project, + target: issue, + message: message, + target_details: { iid: issue.iid, id: issue.id } + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end end end end diff --git a/ee/app/services/epics/base_service.rb b/ee/app/services/epics/base_service.rb index 758f66985e1bef584b992f98d862842d0e649429..061e2b5e2eb0a62c6dc9a7a8c78eb2be329d2cd6 100644 --- a/ee/app/services/epics/base_service.rb +++ b/ee/app/services/epics/base_service.rb @@ -188,5 +188,18 @@ def create_parent_notes(epic, new_parent, old_parent) def parent_param_present? params.key?(:parent) || params.key?(:parent_id) end + + def log_audit_event(epic, event_type, message) + audit_context = { + name: event_type, + author: current_user, + scope: epic.group, + target: epic, + message: message, + target_details: { iid: epic.iid, id: epic.id } + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end end end diff --git a/ee/app/services/epics/close_service.rb b/ee/app/services/epics/close_service.rb index f7eda3f441dbdaf7dfb439cf60a89dc6c6cf50ac..31904063baed2fb15f485fc525694a29f474c7e0 100644 --- a/ee/app/services/epics/close_service.rb +++ b/ee/app/services/epics/close_service.rb @@ -20,6 +20,7 @@ def close_epic(epic) author: current_user, namespace: epic.group ) + log_audit_event(epic, "epic_closed_by_project_bot", "Closed epic #{epic.title}") if current_user.project_bot? end end end diff --git a/ee/app/services/epics/reopen_service.rb b/ee/app/services/epics/reopen_service.rb index 2c76579f3654e693c84273d70f007336aaa5384a..8ab5cacfeba3d3b3b98d16780907d8df6d4d46e8 100644 --- a/ee/app/services/epics/reopen_service.rb +++ b/ee/app/services/epics/reopen_service.rb @@ -19,6 +19,10 @@ def reopen_epic(epic) author: current_user, namespace: epic.group ) + + if current_user.project_bot? + log_audit_event(epic, "epic_reopened_by_project_bot", "Reopened epic #{epic.title}") + end end end end diff --git a/ee/app/workers/ee/new_issue_worker.rb b/ee/app/workers/ee/new_issue_worker.rb new file mode 100644 index 0000000000000000000000000000000000000000..cff9014d1cd207d004eefaf450b716921a9bc2ee --- /dev/null +++ b/ee/app/workers/ee/new_issue_worker.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module EE + module NewIssueWorker + extend ::Gitlab::Utils::Override + + private + + def log_audit_event + audit_context = { + name: "#{issuable.issue_type}_created_by_project_bot", + author: user, + scope: issuable.respond_to?(:group) ? issuable.group : issuable.project, + target: issuable, + message: "Created #{issuable.issue_type.humanize(capitalize: false)} #{issuable.title}", + target_details: { iid: issuable.iid, id: issuable.id } + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end + end +end diff --git a/ee/app/workers/new_epic_worker.rb b/ee/app/workers/new_epic_worker.rb index e22ab28ba5d19d300c1bd23b0e33e38f49774b48..3bf68f8829303937031496b9aac8252618974c59 100644 --- a/ee/app/workers/new_epic_worker.rb +++ b/ee/app/workers/new_epic_worker.rb @@ -18,9 +18,25 @@ def perform(epic_id, user_id) EventCreateService.new.open_epic(issuable, user) NotificationService.new.new_epic(issuable, user) issuable.create_cross_references!(user) + log_audit_event if user.project_bot? end def issuable_class Epic end + + private + + def log_audit_event + audit_context = { + name: "epic_created_by_project_bot", + author: user, + scope: issuable.group, + target: issuable, + message: "Created epic #{issuable.title}", + target_details: { iid: issuable.iid, id: issuable.id } + } + + ::Gitlab::Audit::Auditor.audit(audit_context) + end end diff --git a/ee/config/audit_events/types/epic_closed_by_project_bot.yml b/ee/config/audit_events/types/epic_closed_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..1b469b6de035be7f9f2ee4ffb5abc3b6b8a03f61 --- /dev/null +++ b/ee/config/audit_events/types/epic_closed_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: epic_closed_by_project_bot +description: Triggered when an epic is closed by a group access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: portfolio_management +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/epic_created_by_project_bot.yml b/ee/config/audit_events/types/epic_created_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..57d1a3b0c5678ea3e529bf0ab4b322001a4efc46 --- /dev/null +++ b/ee/config/audit_events/types/epic_created_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: epic_created_by_project_bot +description: Triggered when an epic is created by a group access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: portfolio_management +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/epic_reopened_by_project_bot.yml b/ee/config/audit_events/types/epic_reopened_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..9457bd5265118a6609d221d8865ecf846f642961 --- /dev/null +++ b/ee/config/audit_events/types/epic_reopened_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: epic_reopened_by_project_bot +description: Triggered when an epic is reopened by a group access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: portfolio_management +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/incident_closed_by_project_bot.yml b/ee/config/audit_events/types/incident_closed_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..7c1f9caa50dec640e4ddc4f630452887a7467a1c --- /dev/null +++ b/ee/config/audit_events/types/incident_closed_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: incident_closed_by_project_bot +description: Triggered when an incident is closed using a project access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: incident_management +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/incident_created_by_project_bot.yml b/ee/config/audit_events/types/incident_created_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..c5240842f1c6c64e28c41a4e3432ce3977580183 --- /dev/null +++ b/ee/config/audit_events/types/incident_created_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: incident_created_by_project_bot +description: Triggered when an incident is created using a project access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: incident_management +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/incident_reopened_by_project_bot.yml b/ee/config/audit_events/types/incident_reopened_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..117cede775e764310fc88be5cb9bd688edc913be --- /dev/null +++ b/ee/config/audit_events/types/incident_reopened_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: incident_reopened_by_project_bot +description: Triggered when an incident is reopened using a project access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: incident_management +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/issue_closed_by_project_bot.yml b/ee/config/audit_events/types/issue_closed_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..e25bfa3ae98e5016534afd1572382f4938a2e6d1 --- /dev/null +++ b/ee/config/audit_events/types/issue_closed_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: issue_closed_by_project_bot +description: Triggered when an issue is closed using a project access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: team_planning +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/issue_created_by_project_bot.yml b/ee/config/audit_events/types/issue_created_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..a73968400bc72892a299ad6acce4573e49d96034 --- /dev/null +++ b/ee/config/audit_events/types/issue_created_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: issue_created_by_project_bot +description: Triggered when an issue is created using a project access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: team_planning +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/issue_reopened_by_project_bot.yml b/ee/config/audit_events/types/issue_reopened_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..2c4b8932e1efc3a95dd8f4568b61c5dd9203c84e --- /dev/null +++ b/ee/config/audit_events/types/issue_reopened_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: issue_reopened_by_project_bot +description: Triggered when an issue is reopened using a project access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: team_planning +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/test_case_closed_by_project_bot.yml b/ee/config/audit_events/types/test_case_closed_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..1eb4abab535f3e4a26d87abd8247bfce0ef02535 --- /dev/null +++ b/ee/config/audit_events/types/test_case_closed_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: test_case_closed_by_project_bot +description: Triggered when a test case is closed using a project access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: quality_management +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/test_case_created_by_project_bot.yml b/ee/config/audit_events/types/test_case_created_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..50032b4248713ea6a3ec39c53dd33d21643c326b --- /dev/null +++ b/ee/config/audit_events/types/test_case_created_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: test_case_created_by_project_bot +description: Triggered when a test case is created using a project access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: quality_management +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/config/audit_events/types/test_case_reopened_by_project_bot.yml b/ee/config/audit_events/types/test_case_reopened_by_project_bot.yml new file mode 100644 index 0000000000000000000000000000000000000000..dbb5c48053a8ded8f384e7dbd620ec229f98f7f6 --- /dev/null +++ b/ee/config/audit_events/types/test_case_reopened_by_project_bot.yml @@ -0,0 +1,9 @@ +--- +name: test_case_reopened_by_project_bot +description: Triggered when a test case is reopened using a project access token +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323299 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121485 +feature_category: quality_management +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/spec/services/ee/issues/close_service_spec.rb b/ee/spec/services/ee/issues/close_service_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..75f8e45093a97e54ca2f46a3f888664ad2012a3d --- /dev/null +++ b/ee/spec/services/ee/issues/close_service_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Issues::CloseService, feature_category: :team_planning do + let_it_be(:project) { create(:project, :repository) } + + before do + project.add_maintainer(project_bot) + end + + describe '#execute' do + let(:service) { described_class.new(container: project, current_user: project_bot) } + + context 'when project bot it logs audit events' do + let_it_be(:project_bot) { create(:user, :project_bot, email: "bot@example.com") } + + include_examples 'audit event logging' do + let(:issue) { create(:issue, title: "My issue", project: project, author: project_bot) } + let(:operation) { service.execute(issue) } + let(:event_type) { 'issue_closed_by_project_bot' } + let(:fail_condition!) { expect(project_bot).to receive(:project_bot?).and_return(false) } + let(:attributes) do + { + author_id: project_bot.id, + entity_id: issue.project.id, + entity_type: 'Project', + details: { + author_name: project_bot.name, + target_id: issue.id, + target_type: 'Issue', + target_details: { + iid: issue.iid, + id: issue.id + }.to_s, + author_class: project_bot.class.name, + custom_message: "Closed issue #{issue.title}" + } + } + end + end + end + end +end diff --git a/ee/spec/services/ee/issues/reopen_service_spec.rb b/ee/spec/services/ee/issues/reopen_service_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..a2fa54224e0be5ec52fa9cbb7c516cb8a04d9a11 --- /dev/null +++ b/ee/spec/services/ee/issues/reopen_service_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Issues::ReopenService, feature_category: :team_planning do + let_it_be(:project) { create(:project, :repository) } + + before do + project.add_maintainer(project_bot) + end + + describe '#execute' do + let(:service) { described_class.new(container: project, current_user: project_bot) } + + context 'when project bot it logs audit events' do + let_it_be(:project_bot) { create(:user, :project_bot, email: "bot@example.com") } + + include_examples 'audit event logging' do + let(:issue) { create(:issue, :closed, title: "My issue", project: project, author: project_bot) } + let(:operation) { service.execute(issue) } + let(:event_type) { 'issue_reopened_by_project_bot' } + let(:fail_condition!) { expect(project_bot).to receive(:project_bot?).and_return(false) } + let(:attributes) do + { + author_id: project_bot.id, + entity_id: issue.project.id, + entity_type: 'Project', + details: { + author_name: project_bot.name, + target_id: issue.id, + target_type: 'Issue', + target_details: { + iid: issue.iid, + id: issue.id + }.to_s, + author_class: project_bot.class.name, + custom_message: "Reopened issue #{issue.title}" + } + } + end + end + end + end +end diff --git a/ee/spec/services/epics/close_service_spec.rb b/ee/spec/services/epics/close_service_spec.rb index 5d1f74a36cf8342e655662b57a62c7e983b7c86e..f57321efa6aabfd8cb18cabe5b816ae3c5b2bcd5 100644 --- a/ee/spec/services/epics/close_service_spec.rb +++ b/ee/spec/services/epics/close_service_spec.rb @@ -69,6 +69,39 @@ subject.execute(epic) end + + context 'when project bot it logs audit events' do + let_it_be(:user) { create(:user, :project_bot, email: "bot@example.com") } + + before_all do + group.add_maintainer(user) + end + + include_examples 'audit event logging' do + let(:licensed_features_to_stub) { { epics: true } } + let(:operation) { subject.execute(epic) } + let(:event_type) { 'epic_closed_by_project_bot' } + let(:fail_condition!) { expect(user).to receive(:project_bot?).and_return(false) } + let(:attributes) do + { + author_id: user.id, + entity_id: epic.group.id, + entity_type: 'Group', + details: { + author_name: user.name, + target_id: epic.id, + target_type: 'Epic', + target_details: { + iid: epic.iid, + id: epic.id + }.to_s, + author_class: user.class.name, + custom_message: "Closed epic #{epic.title}" + } + } + end + end + end end context 'when trying to close a closed epic' do diff --git a/ee/spec/services/epics/reopen_service_spec.rb b/ee/spec/services/epics/reopen_service_spec.rb index 50fe51dfb5ef655d771545a311f17d22fd44a1e1..d791f8ead0a5925eb53716f6f46e6f52dd6a319a 100644 --- a/ee/spec/services/epics/reopen_service_spec.rb +++ b/ee/spec/services/epics/reopen_service_spec.rb @@ -69,6 +69,39 @@ subject.execute(epic) end + + context 'when project bot it logs audit events' do + let_it_be(:user) { create(:user, :project_bot, email: "bot@example.com") } + + before_all do + group.add_maintainer(user) + end + + include_examples 'audit event logging' do + let(:licensed_features_to_stub) { { epics: true } } + let(:operation) { subject.execute(epic) } + let(:event_type) { 'epic_reopened_by_project_bot' } + let(:fail_condition!) { expect(user).to receive(:project_bot?).and_return(false) } + let(:attributes) do + { + author_id: user.id, + entity_id: epic.group.id, + entity_type: 'Group', + details: { + author_name: user.name, + target_id: epic.id, + target_type: 'Epic', + target_details: { + iid: epic.iid, + id: epic.id + }.to_s, + author_class: user.class.name, + custom_message: "Reopened epic #{epic.title}" + } + } + end + end + end end context 'when trying to reopen an opened epic' do diff --git a/ee/spec/support/shared_examples/services/audit_event_logging_shared_examples.rb b/ee/spec/support/shared_examples/services/audit_event_logging_shared_examples.rb index a44124b65a3f988485e28f2963124045fc981116..6b29b65433768476a19ba2e22d84176f7f70e35d 100644 --- a/ee/spec/support/shared_examples/services/audit_event_logging_shared_examples.rb +++ b/ee/spec/support/shared_examples/services/audit_event_logging_shared_examples.rb @@ -3,7 +3,11 @@ RSpec.shared_examples 'audit event logging' do context 'when licensed' do before do - stub_licensed_features(extended_audit_events: true) + if defined?(licensed_features_to_stub) + stub_licensed_features(licensed_features_to_stub.merge(extended_audit_events: true)) + else + stub_licensed_features(extended_audit_events: true) + end end context 'when operation succeeds' do diff --git a/ee/spec/workers/ee/new_issue_worker_spec.rb b/ee/spec/workers/ee/new_issue_worker_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..29d5ba4b000357996ccdd56f57a797c0ed5cef35 --- /dev/null +++ b/ee/spec/workers/ee/new_issue_worker_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NewIssueWorker, feature_category: :team_planning do + let_it_be(:project) { create(:project, :repository) } + + before do + project.add_maintainer(project_bot) + end + + describe '#perform' do + let(:worker) { described_class.new } + + context 'when project bot it logs audit events' do + let_it_be(:project_bot) { create(:user, :project_bot, email: "bot@example.com") } + + include_examples 'audit event logging' do + let(:issue) { create(:issue, title: "My issue", project: project, author: project_bot) } + let(:operation) { worker.perform(issue.id, project_bot.id) } + let(:event_type) { 'issue_created_by_project_bot' } + let(:fail_condition!) { allow_any_instance_of(User).to receive(:project_bot?).and_return(false) } # rubocop:disable RSpec/AnyInstanceOf + let(:attributes) do + { + author_id: project_bot.id, + entity_id: issue.project.id, + entity_type: 'Project', + details: { + author_name: project_bot.name, + target_id: issue.id, + target_type: 'Issue', + target_details: { + iid: issue.iid, + id: issue.id + }.to_s, + author_class: project_bot.class.name, + custom_message: "Created issue #{issue.title}" + } + } + end + end + end + end +end diff --git a/ee/spec/workers/new_epic_worker_spec.rb b/ee/spec/workers/new_epic_worker_spec.rb index c687d450af85d5309bd8b0b4175e1f61f930230c..028d0cc56b80cd968b0daa06b7a1b717c7a0d649 100644 --- a/ee/spec/workers/new_epic_worker_spec.rb +++ b/ee/spec/workers/new_epic_worker_spec.rb @@ -104,6 +104,35 @@ worker.perform(epic.id, user.id) end end + + context 'when project bot it logs audit events' do + let_it_be(:project_bot) { create(:user, :project_bot, email: "bot@example.com") } + + include_examples 'audit event logging' do + let(:epic) { create(:epic, author: project_bot) } + let(:operation) { worker.perform(epic.id, project_bot.id) } + let(:event_type) { 'epic_created_by_project_bot' } + let(:fail_condition!) { allow_any_instance_of(User).to receive(:project_bot?).and_return(false) } # rubocop:disable RSpec/AnyInstanceOf + let(:attributes) do + { + author_id: project_bot.id, + entity_id: epic.group.id, + entity_type: 'Group', + details: { + author_name: project_bot.name, + target_id: epic.id, + target_type: 'Epic', + target_details: { + iid: epic.iid, + id: epic.id + }.to_s, + author_class: project_bot.class.name, + custom_message: "Created epic #{epic.title}" + } + } + end + end + end end end end