Commit fe40294d authored by James Fargher's avatar James Fargher

Port of move_chatops_to_core to EE

ChatOps used to be in the Ultimate tier.
parent df03c939
......@@ -47,6 +47,8 @@ module Ci
has_many :auto_canceled_pipelines, class_name: 'Ci::Pipeline', foreign_key: 'auto_canceled_by_id'
has_many :auto_canceled_jobs, class_name: 'CommitStatus', foreign_key: 'auto_canceled_by_id'
has_one :chat_data, class_name: 'Ci::PipelineChatData'
accepts_nested_attributes_for :variables, reject_if: :persisted?
delegate :id, to: :project, prefix: true
......
......@@ -22,6 +22,7 @@ module Ci
schedule: 4,
api: 5,
external: 6,
chat: 8,
merge_request: 10
}
end
......
......@@ -22,11 +22,13 @@ class SlackSlashCommandsService < SlashCommandsService
end
end
def chat_responder
::Gitlab::Chat::Responder::Slack
end
private
def format(text)
Slack::Notifier::LinkFormatter.format(text) if text
end
end
SlackSlashCommandsService.prepend(EE::SlackSlashCommandsService)
......@@ -36,6 +36,7 @@ module Ci
project: project,
current_user: current_user,
push_options: params[:push_options],
chat_data: params[:chat_data],
**extra_options(options))
sequence = Gitlab::Ci::Pipeline::Chain::Sequence
......
......@@ -101,6 +101,7 @@
- authorized_projects
- background_migration
- chat_notification
- create_gpg_signature
- delete_merged_branches
- delete_user
......
......@@ -30,6 +30,7 @@ class BuildFinishedWorker
# We execute these async as these are independent operations.
BuildHooksWorker.perform_async(build.id)
ArchiveTraceWorker.perform_async(build.id)
ChatNotificationWorker.perform_async(build.id) if build.pipeline.chat?
end
end
......
---
title: Move ChatOps to Core
merge_request: 24780
author:
type: changed
......@@ -86,11 +86,11 @@
- [delete_stored_files, 1]
- [remote_mirror_notification, 2]
- [import_issues_csv, 2]
- [chat_notification, 2]
# EE-specific queues
- [ldap_group_sync, 2]
- [create_github_webhook, 2]
- [chat_notification, 2]
- [geo, 1]
- [repository_update_mirror, 1]
- [new_epic, 2]
......
......@@ -13,8 +13,6 @@ module EE
}.freeze
prepended do
has_one :chat_data, class_name: 'Ci::PipelineChatData'
has_many :job_artifacts, through: :builds
has_many :vulnerabilities_occurrence_pipelines, class_name: 'Vulnerabilities::OccurrencePipeline'
has_many :vulnerabilities, source: :occurrence, through: :vulnerabilities_occurrence_pipelines, class_name: 'Vulnerabilities::Occurrence'
......
......@@ -15,7 +15,7 @@ module EE
override :sources
def sources
super.merge(pipeline: 7, chat: 8, webide: 9)
super.merge(pipeline: 7, webide: 9)
end
override :config_sources
......
# frozen_string_literal: true
module EE
module SlackSlashCommandsService
def chat_responder
::Gitlab::Chat::Responder::Slack
end
end
end
......@@ -87,7 +87,6 @@ class License < ActiveRecord::Base
cluster_health
dast
epics
chatops
pod_logs
pseudonymizer
prometheus_alerts
......@@ -384,7 +383,6 @@ class License < ActiveRecord::Base
def reset_current
self.class.reset_current
Gitlab::Chat.flush_available_cache
end
def reset_license
......
......@@ -8,8 +8,7 @@ module EE
override :extra_options
def extra_options(mirror_update: false)
{
allow_mirror_update: mirror_update,
chat_data: params[:chat_data]
allow_mirror_update: mirror_update
}
end
end
......
......@@ -46,7 +46,6 @@
- pipeline_default:ci_create_cross_project_pipeline
- admin_emails
- chat_notification
- create_github_webhook
- elastic_batch_project_indexer
- elastic_commit_indexer
......
......@@ -6,8 +6,6 @@ module EE
UpdateBuildMinutesService.new(build.project, nil).execute(build)
super
ChatNotificationWorker.perform_async(build.id) if build.pipeline.chat?
end
end
end
# frozen_string_literal: true
module EE
module Gitlab
module Ci
module Pipeline
module Chain
module RemoveUnwantedChatJobs
extend ::Gitlab::Utils::Override
override :perform!
def perform!
return unless pipeline.config_processor && pipeline.chat?
# When scheduling a chat pipeline we only want to run the build
# that matches the chat command.
pipeline.config_processor.jobs.select! do |name, _|
name.to_s == command.chat_data[:command].to_s
end
end
end
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module Chat
CACHE_TTL = 1.hour.to_i
AVAILABLE_CACHE_KEY = :gitlab_chat_available
# Returns `true` if Chatops is available for the current instance.
def self.available?
# We anticipate this code to be called rather frequently, especially on
# large instances such as GitLab.com. To reduce database load we cache the
# output for a while.
Rails.cache.fetch(AVAILABLE_CACHE_KEY, expires_in: CACHE_TTL) do
::License.feature_available?(:chatops)
end
end
def self.flush_available_cache
Rails.cache.delete(AVAILABLE_CACHE_KEY)
end
end
end
......@@ -20,7 +20,6 @@ ci_pipelines:
- sourced_pipelines
- triggered_by_pipeline
- triggered_pipelines
- chat_data
- job_artifacts
- vulnerabilities_occurrence_pipelines
- vulnerabilities
......
require 'spec_helper'
describe Gitlab::SlashCommands::Command do
describe '.commands' do
it 'includes EE specific commands' do
expect(described_class.commands).to include(Gitlab::SlashCommands::Run)
end
end
end
......@@ -10,7 +10,6 @@ describe Ci::Pipeline do
create(:ci_empty_pipeline, status: :created, project: project)
end
it { is_expected.to have_one(:chat_data) }
it { is_expected.to have_many(:job_artifacts).through(:builds) }
it { is_expected.to have_many(:vulnerabilities).through(:vulnerabilities_occurrence_pipelines).class_name('Vulnerabilities::Occurrence') }
it { is_expected.to have_many(:vulnerabilities_occurrence_pipelines).class_name('Vulnerabilities::OccurrencePipeline') }
......
require 'spec_helper'
describe SlackSlashCommandsService do
describe '#chat_responder' do
it 'returns the responder to use for Slack' do
expect(described_class.new.chat_responder)
.to eq(Gitlab::Chat::Responder::Slack)
end
end
end
require 'spec_helper'
describe BuildFinishedWorker do
describe '#perform' do
it 'schedules a ChatNotification job for a chat build' do
build = create(:ci_build, :success, pipeline: create(:ci_pipeline, source: :chat))
expect(ChatNotificationWorker)
.to receive(:perform_async)
.with(build.id)
described_class.new.perform(build.id)
end
it 'does not schedule a ChatNotification job for a regular build' do
build = create(:ci_build, :success, pipeline: create(:ci_pipeline))
expect(ChatNotificationWorker)
.not_to receive(:perform_async)
described_class.new.perform(build.id)
end
end
end
# frozen_string_literal: true
module Gitlab
module Chat
# Returns `true` if Chatops is available for the current instance.
def self.available?
::Feature.enabled?(:chatops, default_enabled: true)
end
end
end
......@@ -11,10 +11,10 @@ module Gitlab
:trigger_request, :schedule, :merge_request,
:ignore_skip_ci, :save_incompleted,
:seeds_block, :variables_attributes, :push_options,
:chat_data,
# EE specific
:allow_mirror_update,
:chat_data
:allow_mirror_update
) do
include Gitlab::Utils::StrongMemoize
......
......@@ -6,7 +6,13 @@ module Gitlab
module Chain
class RemoveUnwantedChatJobs < Chain::Base
def perform!
# to be overriden in EE
return unless pipeline.config_processor && pipeline.chat?
# When scheduling a chat pipeline we only want to run the build
# that matches the chat command.
pipeline.config_processor.jobs.select! do |name, _|
name.to_s == command.chat_data[:command].to_s
end
end
def break?
......@@ -17,5 +23,3 @@ module Gitlab
end
end
end
Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs.prepend(EE::Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs)
......@@ -11,7 +11,8 @@ module Gitlab
Gitlab::SlashCommands::IssueNew,
Gitlab::SlashCommands::IssueSearch,
Gitlab::SlashCommands::IssueMove,
Gitlab::SlashCommands::Deploy
Gitlab::SlashCommands::Deploy,
Gitlab::SlashCommands::Run
]
end
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Chat::Command do
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Chat::Output do
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Chat::Responder::Base do
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Chat::Responder::Slack do
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Chat::Responder do
......
......@@ -3,47 +3,21 @@ require 'spec_helper'
describe Gitlab::Chat, :use_clean_rails_memory_store_caching do
describe '.available?' do
it 'returns true when the chatops feature is available' do
allow(License)
.to receive(:feature_available?)
.with(:chatops)
allow(Feature)
.to receive(:enabled?)
.with(:chatops, default_enabled: true)
.and_return(true)
expect(described_class).to be_available
end
it 'returns false when the chatops feature is not available' do
allow(License)
.to receive(:feature_available?)
.with(:chatops)
allow(Feature)
.to receive(:enabled?)
.with(:chatops, default_enabled: true)
.and_return(false)
expect(described_class).not_to be_available
end
it 'caches the feature availability' do
expect(License)
.to receive(:feature_available?)
.once
.with(:chatops)
.and_return(true)
2.times do
described_class.available?
end
end
end
describe '.flush_available_cache' do
it 'flushes the feature availability cache' do
expect(License)
.to receive(:feature_available?)
.twice
.with(:chatops)
.and_return(true)
described_class.available?
described_class.flush_available_cache
described_class.available?
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs do
let(:project) { create(:project, :repository) }
let(:pipeline) do
build(:ci_pipeline_with_one_job, project: project, ref: 'master')
end
let(:command) do
double(:command, project: project, chat_data: { command: 'echo' })
end
describe '#perform!' do
it 'removes unwanted jobs for chat pipelines' do
allow(pipeline).to receive(:chat?).and_return(true)
pipeline.config_processor.jobs[:echo] = double(:job)
described_class.new(pipeline, command).perform!
expect(pipeline.config_processor.jobs.keys).to eq([:echo])
end
end
it 'does not remove any jobs for non-chat pipelines' do
described_class.new(pipeline, command).perform!
expect(pipeline.config_processor.jobs.keys).to eq([:rspec])
end
end
......@@ -131,6 +131,7 @@ ci_pipelines:
- merge_request
- deployments
- environments
- chat_data
pipeline_variables:
- pipeline
stages:
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::SlashCommands::ApplicationHelp do
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::SlashCommands::Presenters::Error do
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::SlashCommands::Presenters::Run do
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::SlashCommands::Run do
......
......@@ -26,6 +26,7 @@ describe Ci::Pipeline, :mailer do
it { is_expected.to have_many(:sourced_pipelines) }
it { is_expected.to have_one(:triggered_by_pipeline) }
it { is_expected.to have_many(:triggered_pipelines) }
it { is_expected.to have_one(:chat_data) }
it { is_expected.to validate_presence_of(:sha) }
it { is_expected.to validate_presence_of(:status) }
......
......@@ -38,4 +38,11 @@ describe SlackSlashCommandsService do
end
end
end
describe '#chat_responder' do
it 'returns the responder to use for Slack' do
expect(described_class.new.chat_responder)
.to eq(Gitlab::Chat::Responder::Slack)
end
end
end
......@@ -26,5 +26,24 @@ describe BuildFinishedWorker do
.not_to raise_error
end
end
it 'schedules a ChatNotification job for a chat build' do
build = create(:ci_build, :success, pipeline: create(:ci_pipeline, source: :chat))
expect(ChatNotificationWorker)
.to receive(:perform_async)
.with(build.id)
described_class.new.perform(build.id)
end
it 'does not schedule a ChatNotification job for a regular build' do
build = create(:ci_build, :success, pipeline: create(:ci_pipeline))
expect(ChatNotificationWorker)
.not_to receive(:perform_async)
described_class.new.perform(build.id)
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe ChatNotificationWorker do
......
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