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 ...@@ -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_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_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? accepts_nested_attributes_for :variables, reject_if: :persisted?
delegate :id, to: :project, prefix: true delegate :id, to: :project, prefix: true
......
...@@ -22,6 +22,7 @@ module Ci ...@@ -22,6 +22,7 @@ module Ci
schedule: 4, schedule: 4,
api: 5, api: 5,
external: 6, external: 6,
chat: 8,
merge_request: 10 merge_request: 10
} }
end end
......
...@@ -22,11 +22,13 @@ class SlackSlashCommandsService < SlashCommandsService ...@@ -22,11 +22,13 @@ class SlackSlashCommandsService < SlashCommandsService
end end
end end
def chat_responder
::Gitlab::Chat::Responder::Slack
end
private private
def format(text) def format(text)
Slack::Notifier::LinkFormatter.format(text) if text Slack::Notifier::LinkFormatter.format(text) if text
end end
end end
SlackSlashCommandsService.prepend(EE::SlackSlashCommandsService)
...@@ -36,6 +36,7 @@ module Ci ...@@ -36,6 +36,7 @@ module Ci
project: project, project: project,
current_user: current_user, current_user: current_user,
push_options: params[:push_options], push_options: params[:push_options],
chat_data: params[:chat_data],
**extra_options(options)) **extra_options(options))
sequence = Gitlab::Ci::Pipeline::Chain::Sequence sequence = Gitlab::Ci::Pipeline::Chain::Sequence
......
...@@ -101,6 +101,7 @@ ...@@ -101,6 +101,7 @@
- authorized_projects - authorized_projects
- background_migration - background_migration
- chat_notification
- create_gpg_signature - create_gpg_signature
- delete_merged_branches - delete_merged_branches
- delete_user - delete_user
......
...@@ -30,6 +30,7 @@ class BuildFinishedWorker ...@@ -30,6 +30,7 @@ class BuildFinishedWorker
# We execute these async as these are independent operations. # We execute these async as these are independent operations.
BuildHooksWorker.perform_async(build.id) BuildHooksWorker.perform_async(build.id)
ArchiveTraceWorker.perform_async(build.id) ArchiveTraceWorker.perform_async(build.id)
ChatNotificationWorker.perform_async(build.id) if build.pipeline.chat?
end end
end end
......
---
title: Move ChatOps to Core
merge_request: 24780
author:
type: changed
...@@ -86,11 +86,11 @@ ...@@ -86,11 +86,11 @@
- [delete_stored_files, 1] - [delete_stored_files, 1]
- [remote_mirror_notification, 2] - [remote_mirror_notification, 2]
- [import_issues_csv, 2] - [import_issues_csv, 2]
- [chat_notification, 2]
# EE-specific queues # EE-specific queues
- [ldap_group_sync, 2] - [ldap_group_sync, 2]
- [create_github_webhook, 2] - [create_github_webhook, 2]
- [chat_notification, 2]
- [geo, 1] - [geo, 1]
- [repository_update_mirror, 1] - [repository_update_mirror, 1]
- [new_epic, 2] - [new_epic, 2]
......
...@@ -13,8 +13,6 @@ module EE ...@@ -13,8 +13,6 @@ module EE
}.freeze }.freeze
prepended do prepended do
has_one :chat_data, class_name: 'Ci::PipelineChatData'
has_many :job_artifacts, through: :builds has_many :job_artifacts, through: :builds
has_many :vulnerabilities_occurrence_pipelines, class_name: 'Vulnerabilities::OccurrencePipeline' has_many :vulnerabilities_occurrence_pipelines, class_name: 'Vulnerabilities::OccurrencePipeline'
has_many :vulnerabilities, source: :occurrence, through: :vulnerabilities_occurrence_pipelines, class_name: 'Vulnerabilities::Occurrence' has_many :vulnerabilities, source: :occurrence, through: :vulnerabilities_occurrence_pipelines, class_name: 'Vulnerabilities::Occurrence'
......
...@@ -15,7 +15,7 @@ module EE ...@@ -15,7 +15,7 @@ module EE
override :sources override :sources
def sources def sources
super.merge(pipeline: 7, chat: 8, webide: 9) super.merge(pipeline: 7, webide: 9)
end end
override :config_sources 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 ...@@ -87,7 +87,6 @@ class License < ActiveRecord::Base
cluster_health cluster_health
dast dast
epics epics
chatops
pod_logs pod_logs
pseudonymizer pseudonymizer
prometheus_alerts prometheus_alerts
...@@ -384,7 +383,6 @@ class License < ActiveRecord::Base ...@@ -384,7 +383,6 @@ class License < ActiveRecord::Base
def reset_current def reset_current
self.class.reset_current self.class.reset_current
Gitlab::Chat.flush_available_cache
end end
def reset_license def reset_license
......
...@@ -8,8 +8,7 @@ module EE ...@@ -8,8 +8,7 @@ module EE
override :extra_options override :extra_options
def extra_options(mirror_update: false) def extra_options(mirror_update: false)
{ {
allow_mirror_update: mirror_update, allow_mirror_update: mirror_update
chat_data: params[:chat_data]
} }
end end
end end
......
...@@ -46,7 +46,6 @@ ...@@ -46,7 +46,6 @@
- pipeline_default:ci_create_cross_project_pipeline - pipeline_default:ci_create_cross_project_pipeline
- admin_emails - admin_emails
- chat_notification
- create_github_webhook - create_github_webhook
- elastic_batch_project_indexer - elastic_batch_project_indexer
- elastic_commit_indexer - elastic_commit_indexer
......
...@@ -6,8 +6,6 @@ module EE ...@@ -6,8 +6,6 @@ module EE
UpdateBuildMinutesService.new(build.project, nil).execute(build) UpdateBuildMinutesService.new(build.project, nil).execute(build)
super super
ChatNotificationWorker.perform_async(build.id) if build.pipeline.chat?
end end
end 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: ...@@ -20,7 +20,6 @@ ci_pipelines:
- sourced_pipelines - sourced_pipelines
- triggered_by_pipeline - triggered_by_pipeline
- triggered_pipelines - triggered_pipelines
- chat_data
- job_artifacts - job_artifacts
- vulnerabilities_occurrence_pipelines - vulnerabilities_occurrence_pipelines
- vulnerabilities - 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 ...@@ -10,7 +10,6 @@ describe Ci::Pipeline do
create(:ci_empty_pipeline, status: :created, project: project) create(:ci_empty_pipeline, status: :created, project: project)
end 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(: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).through(:vulnerabilities_occurrence_pipelines).class_name('Vulnerabilities::Occurrence') }
it { is_expected.to have_many(:vulnerabilities_occurrence_pipelines).class_name('Vulnerabilities::OccurrencePipeline') } 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 ...@@ -11,10 +11,10 @@ module Gitlab
:trigger_request, :schedule, :merge_request, :trigger_request, :schedule, :merge_request,
:ignore_skip_ci, :save_incompleted, :ignore_skip_ci, :save_incompleted,
:seeds_block, :variables_attributes, :push_options, :seeds_block, :variables_attributes, :push_options,
:chat_data,
# EE specific # EE specific
:allow_mirror_update, :allow_mirror_update
:chat_data
) do ) do
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
......
...@@ -6,7 +6,13 @@ module Gitlab ...@@ -6,7 +6,13 @@ module Gitlab
module Chain module Chain
class RemoveUnwantedChatJobs < Chain::Base class RemoveUnwantedChatJobs < Chain::Base
def perform! 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 end
def break? def break?
...@@ -17,5 +23,3 @@ module Gitlab ...@@ -17,5 +23,3 @@ module Gitlab
end end
end end
end end
Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs.prepend(EE::Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs)
...@@ -11,7 +11,8 @@ module Gitlab ...@@ -11,7 +11,8 @@ module Gitlab
Gitlab::SlashCommands::IssueNew, Gitlab::SlashCommands::IssueNew,
Gitlab::SlashCommands::IssueSearch, Gitlab::SlashCommands::IssueSearch,
Gitlab::SlashCommands::IssueMove, Gitlab::SlashCommands::IssueMove,
Gitlab::SlashCommands::Deploy Gitlab::SlashCommands::Deploy,
Gitlab::SlashCommands::Run
] ]
end end
......
# frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
describe Gitlab::Chat::Command do describe Gitlab::Chat::Command do
......
# frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
describe Gitlab::Chat::Output do describe Gitlab::Chat::Output do
......
# frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
describe Gitlab::Chat::Responder::Base do describe Gitlab::Chat::Responder::Base do
......
# frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
describe Gitlab::Chat::Responder::Slack do describe Gitlab::Chat::Responder::Slack do
......
# frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
describe Gitlab::Chat::Responder do describe Gitlab::Chat::Responder do
......
...@@ -3,47 +3,21 @@ require 'spec_helper' ...@@ -3,47 +3,21 @@ require 'spec_helper'
describe Gitlab::Chat, :use_clean_rails_memory_store_caching do describe Gitlab::Chat, :use_clean_rails_memory_store_caching do
describe '.available?' do describe '.available?' do
it 'returns true when the chatops feature is available' do it 'returns true when the chatops feature is available' do
allow(License) allow(Feature)
.to receive(:feature_available?) .to receive(:enabled?)
.with(:chatops) .with(:chatops, default_enabled: true)
.and_return(true) .and_return(true)
expect(described_class).to be_available expect(described_class).to be_available
end end
it 'returns false when the chatops feature is not available' do it 'returns false when the chatops feature is not available' do
allow(License) allow(Feature)
.to receive(:feature_available?) .to receive(:enabled?)
.with(:chatops) .with(:chatops, default_enabled: true)
.and_return(false) .and_return(false)
expect(described_class).not_to be_available expect(described_class).not_to be_available
end 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
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: ...@@ -131,6 +131,7 @@ ci_pipelines:
- merge_request - merge_request
- deployments - deployments
- environments - environments
- chat_data
pipeline_variables: pipeline_variables:
- pipeline - pipeline
stages: stages:
......
# frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
describe Gitlab::SlashCommands::ApplicationHelp do describe Gitlab::SlashCommands::ApplicationHelp do
......
# frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
describe Gitlab::SlashCommands::Presenters::Error do describe Gitlab::SlashCommands::Presenters::Error do
......
# frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
describe Gitlab::SlashCommands::Presenters::Run do describe Gitlab::SlashCommands::Presenters::Run do
......
# frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
describe Gitlab::SlashCommands::Run do describe Gitlab::SlashCommands::Run do
......
...@@ -26,6 +26,7 @@ describe Ci::Pipeline, :mailer do ...@@ -26,6 +26,7 @@ describe Ci::Pipeline, :mailer do
it { is_expected.to have_many(:sourced_pipelines) } it { is_expected.to have_many(:sourced_pipelines) }
it { is_expected.to have_one(:triggered_by_pipeline) } it { is_expected.to have_one(:triggered_by_pipeline) }
it { is_expected.to have_many(:triggered_pipelines) } 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(:sha) }
it { is_expected.to validate_presence_of(:status) } it { is_expected.to validate_presence_of(:status) }
......
...@@ -38,4 +38,11 @@ describe SlackSlashCommandsService do ...@@ -38,4 +38,11 @@ describe SlackSlashCommandsService do
end end
end 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 end
...@@ -26,5 +26,24 @@ describe BuildFinishedWorker do ...@@ -26,5 +26,24 @@ describe BuildFinishedWorker do
.not_to raise_error .not_to raise_error
end end
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
end end
# frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
describe ChatNotificationWorker do 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