Commit 1e66029e authored by Tetiana Chupryna's avatar Tetiana Chupryna Committed by Rémy Coutable

Add auto-fix worker

Run it in StoreReportService and automatically
create auto-fix MRs
parent 3c61465e
......@@ -304,6 +304,8 @@
- 1
- - requirements_management_process_requirements_reports
- 1
- - security_auto_fix
- 1
- - security_scans
- 2
- - self_monitoring_project_create
......
......@@ -21,6 +21,8 @@ module Security
vulnerability_ids = create_all_vulnerabilities!
mark_as_resolved_except(vulnerability_ids)
start_auto_fix
success
end
......@@ -219,5 +221,17 @@ module Security
def put_warning_for(finding)
Gitlab::AppLogger.warn(message: "Invalid vulnerability finding record found", finding: finding.to_hash)
end
def start_auto_fix
return unless auto_fix_enabled?
::Security::AutoFixWorker.perform_async(pipeline.id)
end
def auto_fix_enabled?
return false unless project.security_setting.auto_fix_enabled?
project.security_setting.auto_fix_enabled_types.include?(report.type.to_sym)
end
end
end
......@@ -838,6 +838,14 @@
:idempotent: true
:tags:
- :requires_disk_io
- :name: security_auto_fix
:feature_category: :vulnerability_management
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
- :name: set_user_status_based_on_user_cap_setting
:feature_category: :users
:has_external_dependencies:
......
# frozen_string_literal: true
module Security
class AutoFixWorker
include ApplicationWorker
feature_category :vulnerability_management
idempotent!
# rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)
return if Feature.disabled?(:security_auto_fix)
::Ci::Pipeline.find_by(id: pipeline_id).try do |pipeline|
project = pipeline.project
break unless project.security_setting.auto_fix_enabled?
Security::AutoFixService.new(project, pipeline).execute
end
end
# rubocop: enable CodeReuse/ActiveRecord
end
end
......@@ -25,6 +25,7 @@ RSpec.describe Security::StoreReportService, '#execute' do
before do
stub_licensed_features(sast: true, dependency_scanning: true, container_scanning: true, security_dashboard: true)
allow(Security::AutoFixWorker).to receive(:perform_async)
end
subject { described_class.new(pipeline, report).execute }
......@@ -223,4 +224,74 @@ RSpec.describe Security::StoreReportService, '#execute' do
})
end
end
context 'start auto_fix' do
before do
stub_licensed_features(vulnerability_auto_fix: true)
end
context 'with auto fix supported report type' do
let(:trait) { :dependency_scanning }
context 'when auto fix enabled' do
it 'start auto fix worker' do
expect(Security::AutoFixWorker).to receive(:perform_async).with(pipeline.id)
subject
end
end
context 'when auto fix disabled' do
context 'when feature flag is disabled' do
before do
stub_feature_flags(security_auto_fix: false)
end
it 'does not start auto fix worker' do
expect(Security::AutoFixWorker).not_to receive(:perform_async)
subject
end
end
context 'when auto fix feature is disabled' do
before do
project.security_setting.update!(auto_fix_dependency_scanning: false)
end
it 'does not start auto fix worker' do
expect(Security::AutoFixWorker).not_to receive(:perform_async)
subject
end
end
context 'when licensed feature is unavailable' do
before do
stub_licensed_features(vulnerability_auto_fix: false)
end
it 'does not start auto fix worker' do
expect(Security::AutoFixWorker).not_to receive(:perform_async)
subject
end
end
end
end
context 'with auto fix not supported report type' do
let(:trait) { :sast }
before do
stub_licensed_features(vulnerability_auto_fix: true)
end
it 'does not start auto fix worker' do
expect(Security::AutoFixWorker).not_to receive(:perform_async)
subject
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Security::AutoFixWorker do
describe '#perform' do
subject(:perform) { described_class.new.perform(pipeline.id) }
let_it_be(:pipeline) { create(:ci_pipeline, ref: 'master') }
let(:project) { pipeline.project }
before do
stub_licensed_features(vulnerability_auto_fix: true)
end
context 'when auto_fix feature is enabled' do
it 'run AutoFix Service' do
expect_any_instance_of(Security::AutoFixService).to receive(:execute)
perform
end
end
context 'when auto_fix feature is disabled' do
before do
project.security_setting.update!(auto_fix_dependency_scanning: false, auto_fix_container_scanning: false)
end
it 'does not run AutoFix Service' do
expect_any_instance_of(Security::AutoFixService).not_to receive(:execute)
perform
end
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(security_auto_fix: false )
end
it 'does not run AutoFix Service' do
expect_any_instance_of(Security::AutoFixService).not_to receive(:execute)
perform
end
end
end
end
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