Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
0a35aa9705
commit
1f5ca81aa6
|
@ -1654,11 +1654,8 @@ Gitlab/NamespacedClass:
|
|||
- 'app/models/project_services/ci_service.rb'
|
||||
- 'app/models/project_services/discord_service.rb'
|
||||
- 'app/models/project_services/drone_ci_service.rb'
|
||||
- 'app/models/project_services/external_wiki_service.rb'
|
||||
- 'app/models/project_services/flowdock_service.rb'
|
||||
- 'app/models/project_services/hangouts_chat_service.rb'
|
||||
- 'app/models/project_services/hipchat_service.rb'
|
||||
- 'app/models/project_services/irker_service.rb'
|
||||
- 'app/models/project_services/issue_tracker_data.rb'
|
||||
- 'app/models/project_services/jenkins_service.rb'
|
||||
- 'app/models/project_services/jira_tracker_data.rb'
|
||||
|
@ -1669,9 +1666,6 @@ Gitlab/NamespacedClass:
|
|||
- 'app/models/project_services/mock_monitoring_service.rb'
|
||||
- 'app/models/project_services/monitoring_service.rb'
|
||||
- 'app/models/project_services/open_project_tracker_data.rb'
|
||||
- 'app/models/project_services/packagist_service.rb'
|
||||
- 'app/models/project_services/pipelines_email_service.rb'
|
||||
- 'app/models/project_services/pivotaltracker_service.rb'
|
||||
- 'app/models/project_services/prometheus_service.rb'
|
||||
- 'app/models/project_services/pushover_service.rb'
|
||||
- 'app/models/project_services/slack_service.rb'
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Integrations
|
||||
class ExternalWiki < Integration
|
||||
include ActionView::Helpers::UrlHelper
|
||||
|
||||
prop_accessor :external_wiki_url
|
||||
validates :external_wiki_url, presence: true, public_url: true, if: :activated?
|
||||
|
||||
def title
|
||||
s_('ExternalWikiService|External wiki')
|
||||
end
|
||||
|
||||
def description
|
||||
s_('ExternalWikiService|Link to an external wiki from the sidebar.')
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'external_wiki'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{
|
||||
type: 'text',
|
||||
name: 'external_wiki_url',
|
||||
title: s_('ExternalWikiService|External wiki URL'),
|
||||
placeholder: s_('ExternalWikiService|https://example.com/xxx/wiki/...'),
|
||||
help: 'Enter the URL to the external wiki.',
|
||||
required: true
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
def help
|
||||
docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/wiki/index', anchor: 'link-an-external-wiki'), target: '_blank', rel: 'noopener noreferrer'
|
||||
|
||||
s_('Link an external wiki from the project\'s sidebar. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
|
||||
end
|
||||
|
||||
def execute(_data)
|
||||
response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true)
|
||||
response.body if response.code == 200
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w()
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,52 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Integrations
|
||||
class Flowdock < Integration
|
||||
include ActionView::Helpers::UrlHelper
|
||||
|
||||
prop_accessor :token
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
||||
def title
|
||||
'Flowdock'
|
||||
end
|
||||
|
||||
def description
|
||||
s_('FlowdockService|Send event notifications from GitLab to Flowdock flows.')
|
||||
end
|
||||
|
||||
def help
|
||||
docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('api/services', anchor: 'flowdock'), target: '_blank', rel: 'noopener noreferrer'
|
||||
s_('FlowdockService|Send event notifications from GitLab to Flowdock flows. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'flowdock'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'token', placeholder: s_('FlowdockService|1b609b52537...'), required: true, help: 'Enter your Flowdock token.' }
|
||||
]
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w(push)
|
||||
end
|
||||
|
||||
def execute(data)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
|
||||
::Flowdock::Git.post(
|
||||
data[:ref],
|
||||
data[:before],
|
||||
data[:after],
|
||||
token: token,
|
||||
repo: project.repository,
|
||||
repo_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}",
|
||||
commit_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/%s",
|
||||
diff_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/compare/%s...%s"
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,123 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'uri'
|
||||
|
||||
module Integrations
|
||||
class Irker < Integration
|
||||
prop_accessor :server_host, :server_port, :default_irc_uri
|
||||
prop_accessor :recipients, :channels
|
||||
boolean_accessor :colorize_messages
|
||||
validates :recipients, presence: true, if: :validate_recipients?
|
||||
|
||||
before_validation :get_channels
|
||||
|
||||
def title
|
||||
'Irker (IRC gateway)'
|
||||
end
|
||||
|
||||
def description
|
||||
'Send IRC messages.'
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'irker'
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w(push)
|
||||
end
|
||||
|
||||
def execute(data)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
|
||||
IrkerWorker.perform_async(project_id, channels,
|
||||
colorize_messages, data, settings)
|
||||
end
|
||||
|
||||
def settings
|
||||
{
|
||||
server_host: server_host.presence || 'localhost',
|
||||
server_port: server_port.presence || 6659
|
||||
}
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'server_host', placeholder: 'localhost',
|
||||
help: 'Irker daemon hostname (defaults to localhost)' },
|
||||
{ type: 'text', name: 'server_port', placeholder: 6659,
|
||||
help: 'Irker daemon port (defaults to 6659)' },
|
||||
{ type: 'text', name: 'default_irc_uri', title: 'Default IRC URI',
|
||||
help: 'A default IRC URI to prepend before each recipient (optional)',
|
||||
placeholder: 'irc://irc.network.net:6697/' },
|
||||
{ type: 'textarea', name: 'recipients',
|
||||
placeholder: 'Recipients/channels separated by whitespaces', required: true,
|
||||
help: 'Recipients have to be specified with a full URI: '\
|
||||
'irc[s]://irc.network.net[:port]/#channel. Special cases: if '\
|
||||
'you want the channel to be a nickname instead, append ",isnick" to ' \
|
||||
'the channel name; if the channel is protected by a secret password, ' \
|
||||
' append "?key=secretpassword" to the URI (Note that due to a bug, if you ' \
|
||||
' want to use a password, you have to omit the "#" on the channel). If you ' \
|
||||
' specify a default IRC URI to prepend before each recipient, you can just ' \
|
||||
' give a channel name.' },
|
||||
{ type: 'checkbox', name: 'colorize_messages' }
|
||||
]
|
||||
end
|
||||
|
||||
def help
|
||||
' NOTE: Irker does NOT have built-in authentication, which makes it' \
|
||||
' vulnerable to spamming IRC channels if it is hosted outside of a ' \
|
||||
' firewall. Please make sure you run the daemon within a secured network ' \
|
||||
' to prevent abuse. For more details, read: http://www.catb.org/~esr/irker/security.html.'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_channels
|
||||
return true unless activated?
|
||||
return true if recipients.nil? || recipients.empty?
|
||||
|
||||
map_recipients
|
||||
|
||||
errors.add(:recipients, 'are all invalid') if channels.empty?
|
||||
true
|
||||
end
|
||||
|
||||
def map_recipients
|
||||
self.channels = recipients.split(/\s+/).map do |recipient|
|
||||
format_channel(recipient)
|
||||
end
|
||||
channels.reject!(&:nil?)
|
||||
end
|
||||
|
||||
def format_channel(recipient)
|
||||
uri = nil
|
||||
|
||||
# Try to parse the chan as a full URI
|
||||
begin
|
||||
uri = consider_uri(URI.parse(recipient))
|
||||
rescue URI::InvalidURIError
|
||||
end
|
||||
|
||||
unless uri.present? && default_irc_uri.nil?
|
||||
begin
|
||||
new_recipient = URI.join(default_irc_uri, '/', recipient).to_s
|
||||
uri = consider_uri(URI.parse(new_recipient))
|
||||
rescue StandardError
|
||||
log_error("Unable to create a valid URL", default_irc_uri: default_irc_uri, recipient: recipient)
|
||||
end
|
||||
end
|
||||
|
||||
uri
|
||||
end
|
||||
|
||||
def consider_uri(uri)
|
||||
return if uri.scheme.nil?
|
||||
|
||||
# Authorize both irc://domain.com/#chan and irc://domain.com/chan
|
||||
if uri.is_a?(URI) && uri.scheme[/^ircs?\z/] && !uri.path.nil?
|
||||
uri.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,67 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Integrations
|
||||
class Packagist < Integration
|
||||
prop_accessor :username, :token, :server
|
||||
|
||||
validates :username, presence: true, if: :activated?
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
||||
default_value_for :push_events, true
|
||||
default_value_for :tag_push_events, true
|
||||
|
||||
after_save :compose_service_hook, if: :activated?
|
||||
|
||||
def title
|
||||
'Packagist'
|
||||
end
|
||||
|
||||
def description
|
||||
s_('Integrations|Update your Packagist projects.')
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'packagist'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'username', placeholder: '', required: true },
|
||||
{ type: 'text', name: 'token', placeholder: '', required: true },
|
||||
{ type: 'text', name: 'server', placeholder: 'https://packagist.org', required: false }
|
||||
]
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w(push merge_request tag_push)
|
||||
end
|
||||
|
||||
def execute(data)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
|
||||
service_hook.execute(data)
|
||||
end
|
||||
|
||||
def test(data)
|
||||
begin
|
||||
result = execute(data)
|
||||
return { success: false, result: result[:message] } if result[:http_status] != 202
|
||||
rescue StandardError => error
|
||||
return { success: false, result: error }
|
||||
end
|
||||
|
||||
{ success: true, result: result[:message] }
|
||||
end
|
||||
|
||||
def compose_service_hook
|
||||
hook = service_hook || build_service_hook
|
||||
hook.url = hook_url
|
||||
hook.save
|
||||
end
|
||||
|
||||
def hook_url
|
||||
base_url = server.presence || 'https://packagist.org'
|
||||
"#{base_url}/api/update-package?username=#{username}&apiToken=#{token}"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,105 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Integrations
|
||||
class PipelinesEmail < Integration
|
||||
include NotificationBranchSelection
|
||||
|
||||
prop_accessor :recipients, :branches_to_be_notified
|
||||
boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch
|
||||
validates :recipients, presence: true, if: :validate_recipients?
|
||||
|
||||
def initialize_properties
|
||||
if properties.nil?
|
||||
self.properties = {}
|
||||
self.notify_only_broken_pipelines = true
|
||||
self.branches_to_be_notified = "default"
|
||||
elsif !self.notify_only_default_branch.nil?
|
||||
# In older versions, there was only a boolean property named
|
||||
# `notify_only_default_branch`. Now we have a string property named
|
||||
# `branches_to_be_notified`. Instead of doing a background migration, we
|
||||
# opted to set a value for the new property based on the old one, if
|
||||
# users hasn't specified one already. When users edit the service and
|
||||
# selects a value for this new property, it will override everything.
|
||||
|
||||
self.branches_to_be_notified ||= notify_only_default_branch? ? "default" : "all"
|
||||
end
|
||||
end
|
||||
|
||||
def title
|
||||
_('Pipeline status emails')
|
||||
end
|
||||
|
||||
def description
|
||||
_('Email the pipeline status to a list of recipients.')
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'pipelines_email'
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w[pipeline]
|
||||
end
|
||||
|
||||
def self.default_test_event
|
||||
'pipeline'
|
||||
end
|
||||
|
||||
def execute(data, force: false)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
return unless force || should_pipeline_be_notified?(data)
|
||||
|
||||
all_recipients = retrieve_recipients(data)
|
||||
|
||||
return unless all_recipients.any?
|
||||
|
||||
pipeline_id = data[:object_attributes][:id]
|
||||
PipelineNotificationWorker.new.perform(pipeline_id, recipients: all_recipients)
|
||||
end
|
||||
|
||||
def can_test?
|
||||
project&.ci_pipelines&.any?
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'textarea',
|
||||
name: 'recipients',
|
||||
help: _('Comma-separated list of email addresses.'),
|
||||
required: true },
|
||||
{ type: 'checkbox',
|
||||
name: 'notify_only_broken_pipelines' },
|
||||
{ type: 'select',
|
||||
name: 'branches_to_be_notified',
|
||||
choices: branch_choices }
|
||||
]
|
||||
end
|
||||
|
||||
def test(data)
|
||||
result = execute(data, force: true)
|
||||
|
||||
{ success: true, result: result }
|
||||
rescue StandardError => error
|
||||
{ success: false, result: error }
|
||||
end
|
||||
|
||||
def should_pipeline_be_notified?(data)
|
||||
notify_for_branch?(data) && notify_for_pipeline?(data)
|
||||
end
|
||||
|
||||
def notify_for_pipeline?(data)
|
||||
case data[:object_attributes][:status]
|
||||
when 'success'
|
||||
!notify_only_broken_pipelines?
|
||||
when 'failed'
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def retrieve_recipients(data)
|
||||
recipients.to_s.split(/[,\r\n ]+/).reject(&:empty?)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,78 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Integrations
|
||||
class Pivotaltracker < Integration
|
||||
API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits'
|
||||
|
||||
prop_accessor :token, :restrict_to_branch
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
||||
def title
|
||||
'PivotalTracker'
|
||||
end
|
||||
|
||||
def description
|
||||
s_('PivotalTrackerService|Add commit messages as comments to PivotalTracker stories.')
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'pivotaltracker'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{
|
||||
type: 'text',
|
||||
name: 'token',
|
||||
placeholder: s_('PivotalTrackerService|Pivotal Tracker API token.'),
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'restrict_to_branch',
|
||||
placeholder: s_('PivotalTrackerService|Comma-separated list of branches which will be ' \
|
||||
'automatically inspected. Leave blank to include all branches.')
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w(push)
|
||||
end
|
||||
|
||||
def execute(data)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
return unless allowed_branch?(data[:ref])
|
||||
|
||||
data[:commits].each do |commit|
|
||||
message = {
|
||||
'source_commit' => {
|
||||
'commit_id' => commit[:id],
|
||||
'author' => commit[:author][:name],
|
||||
'url' => commit[:url],
|
||||
'message' => commit[:message]
|
||||
}
|
||||
}
|
||||
Gitlab::HTTP.post(
|
||||
API_ENDPOINT,
|
||||
body: message.to_json,
|
||||
headers: {
|
||||
'Content-Type' => 'application/json',
|
||||
'X-TrackerToken' => token
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def allowed_branch?(ref)
|
||||
return true unless ref.present? && restrict_to_branch.present?
|
||||
|
||||
branch = Gitlab::Git.ref_name(ref)
|
||||
allowed_branches = restrict_to_branch.split(',').map(&:strip)
|
||||
|
||||
branch.present? && allowed_branches.include?(branch)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -193,15 +193,17 @@ class Project < ApplicationRecord
|
|||
has_one :datadog_service, class_name: 'Integrations::Datadog'
|
||||
has_one :emails_on_push_service, class_name: 'Integrations::EmailsOnPush'
|
||||
has_one :ewm_service, class_name: 'Integrations::Ewm'
|
||||
has_one :external_wiki_service, class_name: 'Integrations::ExternalWiki'
|
||||
has_one :flowdock_service, class_name: 'Integrations::Flowdock'
|
||||
has_one :irker_service, class_name: 'Integrations::Irker'
|
||||
has_one :jira_service, class_name: 'Integrations::Jira'
|
||||
has_one :packagist_service, class_name: 'Integrations::Packagist'
|
||||
has_one :pipelines_email_service, class_name: 'Integrations::PipelinesEmail'
|
||||
has_one :pivotaltracker_service, class_name: 'Integrations::Pivotaltracker'
|
||||
has_one :redmine_service, class_name: 'Integrations::Redmine'
|
||||
has_one :youtrack_service, class_name: 'Integrations::Youtrack'
|
||||
has_one :discord_service
|
||||
has_one :drone_ci_service
|
||||
has_one :pipelines_email_service
|
||||
has_one :irker_service
|
||||
has_one :pivotaltracker_service
|
||||
has_one :flowdock_service
|
||||
has_one :mattermost_slash_commands_service
|
||||
has_one :mattermost_service
|
||||
has_one :slack_slash_commands_service
|
||||
|
@ -210,12 +212,10 @@ class Project < ApplicationRecord
|
|||
has_one :teamcity_service
|
||||
has_one :pushover_service
|
||||
has_one :jenkins_service
|
||||
has_one :external_wiki_service
|
||||
has_one :prometheus_service, inverse_of: :project
|
||||
has_one :mock_ci_service
|
||||
has_one :mock_monitoring_service
|
||||
has_one :microsoft_teams_service
|
||||
has_one :packagist_service
|
||||
has_one :hangouts_chat_service
|
||||
has_one :unify_circuit_service
|
||||
has_one :webex_teams_service
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ExternalWikiService < Integration
|
||||
include ActionView::Helpers::UrlHelper
|
||||
|
||||
prop_accessor :external_wiki_url
|
||||
validates :external_wiki_url, presence: true, public_url: true, if: :activated?
|
||||
|
||||
def title
|
||||
s_('ExternalWikiService|External wiki')
|
||||
end
|
||||
|
||||
def description
|
||||
s_('ExternalWikiService|Link to an external wiki from the sidebar.')
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'external_wiki'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{
|
||||
type: 'text',
|
||||
name: 'external_wiki_url',
|
||||
title: s_('ExternalWikiService|External wiki URL'),
|
||||
placeholder: s_('ExternalWikiService|https://example.com/xxx/wiki/...'),
|
||||
help: 'Enter the URL to the external wiki.',
|
||||
required: true
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
def help
|
||||
docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/wiki/index', anchor: 'link-an-external-wiki'), target: '_blank', rel: 'noopener noreferrer'
|
||||
|
||||
s_('Link an external wiki from the project\'s sidebar. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
|
||||
end
|
||||
|
||||
def execute(_data)
|
||||
response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true)
|
||||
response.body if response.code == 200
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w()
|
||||
end
|
||||
end
|
|
@ -1,50 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FlowdockService < Integration
|
||||
include ActionView::Helpers::UrlHelper
|
||||
|
||||
prop_accessor :token
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
||||
def title
|
||||
'Flowdock'
|
||||
end
|
||||
|
||||
def description
|
||||
s_('FlowdockService|Send event notifications from GitLab to Flowdock flows.')
|
||||
end
|
||||
|
||||
def help
|
||||
docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('api/services', anchor: 'flowdock'), target: '_blank', rel: 'noopener noreferrer'
|
||||
s_('FlowdockService|Send event notifications from GitLab to Flowdock flows. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'flowdock'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'token', placeholder: s_('FlowdockService|1b609b52537...'), required: true, help: 'Enter your Flowdock token.' }
|
||||
]
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w(push)
|
||||
end
|
||||
|
||||
def execute(data)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
|
||||
Flowdock::Git.post(
|
||||
data[:ref],
|
||||
data[:before],
|
||||
data[:after],
|
||||
token: token,
|
||||
repo: project.repository,
|
||||
repo_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}",
|
||||
commit_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/-/commit/%s",
|
||||
diff_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/compare/%s...%s"
|
||||
)
|
||||
end
|
||||
end
|
|
@ -1,121 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'uri'
|
||||
|
||||
class IrkerService < Integration
|
||||
prop_accessor :server_host, :server_port, :default_irc_uri
|
||||
prop_accessor :recipients, :channels
|
||||
boolean_accessor :colorize_messages
|
||||
validates :recipients, presence: true, if: :validate_recipients?
|
||||
|
||||
before_validation :get_channels
|
||||
|
||||
def title
|
||||
'Irker (IRC gateway)'
|
||||
end
|
||||
|
||||
def description
|
||||
'Send IRC messages.'
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'irker'
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w(push)
|
||||
end
|
||||
|
||||
def execute(data)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
|
||||
IrkerWorker.perform_async(project_id, channels,
|
||||
colorize_messages, data, settings)
|
||||
end
|
||||
|
||||
def settings
|
||||
{
|
||||
server_host: server_host.presence || 'localhost',
|
||||
server_port: server_port.presence || 6659
|
||||
}
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'server_host', placeholder: 'localhost',
|
||||
help: 'Irker daemon hostname (defaults to localhost)' },
|
||||
{ type: 'text', name: 'server_port', placeholder: 6659,
|
||||
help: 'Irker daemon port (defaults to 6659)' },
|
||||
{ type: 'text', name: 'default_irc_uri', title: 'Default IRC URI',
|
||||
help: 'A default IRC URI to prepend before each recipient (optional)',
|
||||
placeholder: 'irc://irc.network.net:6697/' },
|
||||
{ type: 'textarea', name: 'recipients',
|
||||
placeholder: 'Recipients/channels separated by whitespaces', required: true,
|
||||
help: 'Recipients have to be specified with a full URI: '\
|
||||
'irc[s]://irc.network.net[:port]/#channel. Special cases: if '\
|
||||
'you want the channel to be a nickname instead, append ",isnick" to ' \
|
||||
'the channel name; if the channel is protected by a secret password, ' \
|
||||
' append "?key=secretpassword" to the URI (Note that due to a bug, if you ' \
|
||||
' want to use a password, you have to omit the "#" on the channel). If you ' \
|
||||
' specify a default IRC URI to prepend before each recipient, you can just ' \
|
||||
' give a channel name.' },
|
||||
{ type: 'checkbox', name: 'colorize_messages' }
|
||||
]
|
||||
end
|
||||
|
||||
def help
|
||||
' NOTE: Irker does NOT have built-in authentication, which makes it' \
|
||||
' vulnerable to spamming IRC channels if it is hosted outside of a ' \
|
||||
' firewall. Please make sure you run the daemon within a secured network ' \
|
||||
' to prevent abuse. For more details, read: http://www.catb.org/~esr/irker/security.html.'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_channels
|
||||
return true unless activated?
|
||||
return true if recipients.nil? || recipients.empty?
|
||||
|
||||
map_recipients
|
||||
|
||||
errors.add(:recipients, 'are all invalid') if channels.empty?
|
||||
true
|
||||
end
|
||||
|
||||
def map_recipients
|
||||
self.channels = recipients.split(/\s+/).map do |recipient|
|
||||
format_channel(recipient)
|
||||
end
|
||||
channels.reject!(&:nil?)
|
||||
end
|
||||
|
||||
def format_channel(recipient)
|
||||
uri = nil
|
||||
|
||||
# Try to parse the chan as a full URI
|
||||
begin
|
||||
uri = consider_uri(URI.parse(recipient))
|
||||
rescue URI::InvalidURIError
|
||||
end
|
||||
|
||||
unless uri.present? && default_irc_uri.nil?
|
||||
begin
|
||||
new_recipient = URI.join(default_irc_uri, '/', recipient).to_s
|
||||
uri = consider_uri(URI.parse(new_recipient))
|
||||
rescue StandardError
|
||||
log_error("Unable to create a valid URL", default_irc_uri: default_irc_uri, recipient: recipient)
|
||||
end
|
||||
end
|
||||
|
||||
uri
|
||||
end
|
||||
|
||||
def consider_uri(uri)
|
||||
return if uri.scheme.nil?
|
||||
|
||||
# Authorize both irc://domain.com/#chan and irc://domain.com/chan
|
||||
if uri.is_a?(URI) && uri.scheme[/^ircs?\z/] && !uri.path.nil?
|
||||
uri.to_s
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,18 +2,6 @@
|
|||
|
||||
class JiraTrackerData < ApplicationRecord
|
||||
include Services::DataFields
|
||||
include IgnorableColumns
|
||||
|
||||
ignore_columns %i[
|
||||
encrypted_proxy_address
|
||||
encrypted_proxy_address_iv
|
||||
encrypted_proxy_port
|
||||
encrypted_proxy_port_iv
|
||||
encrypted_proxy_username
|
||||
encrypted_proxy_username_iv
|
||||
encrypted_proxy_password
|
||||
encrypted_proxy_password_iv
|
||||
], remove_with: '14.0', remove_after: '2021-05-22'
|
||||
|
||||
attr_encrypted :url, encryption_options
|
||||
attr_encrypted :api_url, encryption_options
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PackagistService < Integration
|
||||
prop_accessor :username, :token, :server
|
||||
|
||||
validates :username, presence: true, if: :activated?
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
||||
default_value_for :push_events, true
|
||||
default_value_for :tag_push_events, true
|
||||
|
||||
after_save :compose_service_hook, if: :activated?
|
||||
|
||||
def title
|
||||
'Packagist'
|
||||
end
|
||||
|
||||
def description
|
||||
s_('Integrations|Update your Packagist projects.')
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'packagist'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'username', placeholder: '', required: true },
|
||||
{ type: 'text', name: 'token', placeholder: '', required: true },
|
||||
{ type: 'text', name: 'server', placeholder: 'https://packagist.org', required: false }
|
||||
]
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w(push merge_request tag_push)
|
||||
end
|
||||
|
||||
def execute(data)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
|
||||
service_hook.execute(data)
|
||||
end
|
||||
|
||||
def test(data)
|
||||
begin
|
||||
result = execute(data)
|
||||
return { success: false, result: result[:message] } if result[:http_status] != 202
|
||||
rescue StandardError => error
|
||||
return { success: false, result: error }
|
||||
end
|
||||
|
||||
{ success: true, result: result[:message] }
|
||||
end
|
||||
|
||||
def compose_service_hook
|
||||
hook = service_hook || build_service_hook
|
||||
hook.url = hook_url
|
||||
hook.save
|
||||
end
|
||||
|
||||
def hook_url
|
||||
base_url = server.presence || 'https://packagist.org'
|
||||
"#{base_url}/api/update-package?username=#{username}&apiToken=#{token}"
|
||||
end
|
||||
end
|
|
@ -1,103 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PipelinesEmailService < Integration
|
||||
include NotificationBranchSelection
|
||||
|
||||
prop_accessor :recipients, :branches_to_be_notified
|
||||
boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch
|
||||
validates :recipients, presence: true, if: :validate_recipients?
|
||||
|
||||
def initialize_properties
|
||||
if properties.nil?
|
||||
self.properties = {}
|
||||
self.notify_only_broken_pipelines = true
|
||||
self.branches_to_be_notified = "default"
|
||||
elsif !self.notify_only_default_branch.nil?
|
||||
# In older versions, there was only a boolean property named
|
||||
# `notify_only_default_branch`. Now we have a string property named
|
||||
# `branches_to_be_notified`. Instead of doing a background migration, we
|
||||
# opted to set a value for the new property based on the old one, if
|
||||
# users hasn't specified one already. When users edit the service and
|
||||
# selects a value for this new property, it will override everything.
|
||||
|
||||
self.branches_to_be_notified ||= notify_only_default_branch? ? "default" : "all"
|
||||
end
|
||||
end
|
||||
|
||||
def title
|
||||
_('Pipeline status emails')
|
||||
end
|
||||
|
||||
def description
|
||||
_('Email the pipeline status to a list of recipients.')
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'pipelines_email'
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w[pipeline]
|
||||
end
|
||||
|
||||
def self.default_test_event
|
||||
'pipeline'
|
||||
end
|
||||
|
||||
def execute(data, force: false)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
return unless force || should_pipeline_be_notified?(data)
|
||||
|
||||
all_recipients = retrieve_recipients(data)
|
||||
|
||||
return unless all_recipients.any?
|
||||
|
||||
pipeline_id = data[:object_attributes][:id]
|
||||
PipelineNotificationWorker.new.perform(pipeline_id, recipients: all_recipients)
|
||||
end
|
||||
|
||||
def can_test?
|
||||
project&.ci_pipelines&.any?
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'textarea',
|
||||
name: 'recipients',
|
||||
help: _('Comma-separated list of email addresses.'),
|
||||
required: true },
|
||||
{ type: 'checkbox',
|
||||
name: 'notify_only_broken_pipelines' },
|
||||
{ type: 'select',
|
||||
name: 'branches_to_be_notified',
|
||||
choices: branch_choices }
|
||||
]
|
||||
end
|
||||
|
||||
def test(data)
|
||||
result = execute(data, force: true)
|
||||
|
||||
{ success: true, result: result }
|
||||
rescue StandardError => error
|
||||
{ success: false, result: error }
|
||||
end
|
||||
|
||||
def should_pipeline_be_notified?(data)
|
||||
notify_for_branch?(data) && notify_for_pipeline?(data)
|
||||
end
|
||||
|
||||
def notify_for_pipeline?(data)
|
||||
case data[:object_attributes][:status]
|
||||
when 'success'
|
||||
!notify_only_broken_pipelines?
|
||||
when 'failed'
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def retrieve_recipients(data)
|
||||
recipients.to_s.split(/[,\r\n ]+/).reject(&:empty?)
|
||||
end
|
||||
end
|
|
@ -1,76 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PivotaltrackerService < Integration
|
||||
API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits'
|
||||
|
||||
prop_accessor :token, :restrict_to_branch
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
||||
def title
|
||||
'PivotalTracker'
|
||||
end
|
||||
|
||||
def description
|
||||
s_('PivotalTrackerService|Add commit messages as comments to PivotalTracker stories.')
|
||||
end
|
||||
|
||||
def self.to_param
|
||||
'pivotaltracker'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{
|
||||
type: 'text',
|
||||
name: 'token',
|
||||
placeholder: s_('PivotalTrackerService|Pivotal Tracker API token.'),
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'restrict_to_branch',
|
||||
placeholder: s_('PivotalTrackerService|Comma-separated list of branches which will be ' \
|
||||
'automatically inspected. Leave blank to include all branches.')
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
def self.supported_events
|
||||
%w(push)
|
||||
end
|
||||
|
||||
def execute(data)
|
||||
return unless supported_events.include?(data[:object_kind])
|
||||
return unless allowed_branch?(data[:ref])
|
||||
|
||||
data[:commits].each do |commit|
|
||||
message = {
|
||||
'source_commit' => {
|
||||
'commit_id' => commit[:id],
|
||||
'author' => commit[:author][:name],
|
||||
'url' => commit[:url],
|
||||
'message' => commit[:message]
|
||||
}
|
||||
}
|
||||
Gitlab::HTTP.post(
|
||||
API_ENDPOINT,
|
||||
body: message.to_json,
|
||||
headers: {
|
||||
'Content-Type' => 'application/json',
|
||||
'X-TrackerToken' => token
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def allowed_branch?(ref)
|
||||
return true unless ref.present? && restrict_to_branch.present?
|
||||
|
||||
branch = Gitlab::Git.ref_name(ref)
|
||||
allowed_branches = restrict_to_branch.split(',').map(&:strip)
|
||||
|
||||
branch.present? && allowed_branches.include?(branch)
|
||||
end
|
||||
end
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: ci_needs_optional
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55468
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323891
|
||||
milestone: '13.10'
|
||||
type: development
|
||||
group: group::pipeline authoring
|
||||
default_enabled: true
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: usage_data_unique_users_committing_ciconfigfile
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52172
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299403
|
||||
milestone: '13.9'
|
||||
type: development
|
||||
group: group::pipeline authoring
|
||||
default_enabled: true
|
|
@ -14,4 +14,3 @@ distribution:
|
|||
- ee
|
||||
tier:
|
||||
- free
|
||||
skip_validation: true
|
||||
|
|
|
@ -2069,14 +2069,7 @@ To download artifacts from a job in the current pipeline, use the basic form of
|
|||
#### Optional `needs`
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30680) in GitLab 13.10.
|
||||
> - [Deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
|
||||
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/323891) in GitLab 13.11.
|
||||
> - Enabled on GitLab.com.
|
||||
> - Recommended for production use.
|
||||
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-optional-needs). **(FREE SELF)**
|
||||
|
||||
WARNING:
|
||||
This feature might not be available to you. Check the **version history** note above for details.
|
||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323891) in GitLab 14.0.
|
||||
|
||||
To need a job that sometimes does not exist in the pipeline, add `optional: true`
|
||||
to the `needs` configuration. If not defined, `optional: false` is the default.
|
||||
|
@ -2110,25 +2103,6 @@ rspec:
|
|||
optional: true
|
||||
```
|
||||
|
||||
#### Enable or disable optional needs **(FREE SELF)**
|
||||
|
||||
Optional needs is under development but ready for production use.
|
||||
It is deployed behind a feature flag that is **enabled by default**.
|
||||
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
|
||||
can opt to disable it.
|
||||
|
||||
To enable it:
|
||||
|
||||
```ruby
|
||||
Feature.enable(:ci_needs_optional)
|
||||
```
|
||||
|
||||
To disable it:
|
||||
|
||||
```ruby
|
||||
Feature.disable(:ci_needs_optional)
|
||||
```
|
||||
|
||||
### `tags`
|
||||
|
||||
Use `tags` to select a specific runner from the list of all runners that are
|
||||
|
|
|
@ -573,6 +573,20 @@ Snowplow Mini can be used for testing frontend and backend events on a productio
|
|||
|
||||
For GitLab.com, we're setting up a [QA and Testing environment](https://gitlab.com/gitlab-org/telemetry/-/issues/266) using Snowplow Mini.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
To control content security policy warnings when using an external host, you can allow or disallow them by modifying `config/gitlab.yml`. To allow them, add the relevant host for `connect_src`. For example, for `https://snowplow.trx.gitlab.net`:
|
||||
|
||||
```yaml
|
||||
development:
|
||||
<<: *base
|
||||
gitlab:
|
||||
content_security_policy:
|
||||
enabled: true
|
||||
directives:
|
||||
connect_src: "'self' http://localhost:* http://127.0.0.1:* ws://localhost:* wss://localhost:* ws://127.0.0.1:* https://snowplow.trx.gitlab.net/"
|
||||
```
|
||||
|
||||
## Snowplow Schemas
|
||||
|
||||
### `gitlab_standard`
|
||||
|
|
|
@ -784,22 +784,22 @@ module API
|
|||
::Integrations::Datadog,
|
||||
::Integrations::EmailsOnPush,
|
||||
::Integrations::Ewm,
|
||||
::Integrations::ExternalWiki,
|
||||
::Integrations::Flowdock,
|
||||
::Integrations::Irker,
|
||||
::Integrations::Jira,
|
||||
::Integrations::Packagist,
|
||||
::Integrations::PipelinesEmail,
|
||||
::Integrations::Pivotaltracker,
|
||||
::Integrations::Redmine,
|
||||
::Integrations::Youtrack,
|
||||
::BuildkiteService,
|
||||
::DiscordService,
|
||||
::DroneCiService,
|
||||
::ExternalWikiService,
|
||||
::FlowdockService,
|
||||
::HangoutsChatService,
|
||||
::IrkerService,
|
||||
::JenkinsService,
|
||||
::MattermostSlashCommandsService,
|
||||
::SlackSlashCommandsService,
|
||||
::PackagistService,
|
||||
::PipelinesEmailService,
|
||||
::PivotaltrackerService,
|
||||
::PrometheusService,
|
||||
::PushoverService,
|
||||
::SlackService,
|
||||
|
|
|
@ -34,7 +34,7 @@ module Flowdock
|
|||
# Send git push notification to Flowdock
|
||||
def post
|
||||
messages.each do |message|
|
||||
Flowdock::Client.new(flow_token: @token).post_to_thread(message)
|
||||
::Flowdock::Client.new(flow_token: @token).post_to_thread(message)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -35,14 +35,9 @@ module Gitlab
|
|||
end
|
||||
|
||||
def value
|
||||
if ::Feature.enabled?(:ci_needs_optional, default_enabled: :yaml)
|
||||
{ name: @config,
|
||||
artifacts: true,
|
||||
optional: false }
|
||||
else
|
||||
{ name: @config,
|
||||
artifacts: true }
|
||||
end
|
||||
{ name: @config,
|
||||
artifacts: true,
|
||||
optional: false }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -66,14 +61,9 @@ module Gitlab
|
|||
end
|
||||
|
||||
def value
|
||||
if ::Feature.enabled?(:ci_needs_optional, default_enabled: :yaml)
|
||||
{ name: job,
|
||||
artifacts: artifacts || artifacts.nil?,
|
||||
optional: !!optional }
|
||||
else
|
||||
{ name: job,
|
||||
artifacts: artifacts || artifacts.nil? }
|
||||
end
|
||||
{ name: job,
|
||||
artifacts: artifacts || artifacts.nil?,
|
||||
optional: !!optional }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
@needs_attributes.flat_map do |need|
|
||||
next if ::Feature.enabled?(:ci_needs_optional, default_enabled: :yaml) && need[:optional]
|
||||
next if need[:optional]
|
||||
|
||||
result = @previous_stages.any? do |stage|
|
||||
stage.seeds_names.include?(need[:name])
|
||||
|
|
|
@ -5,7 +5,8 @@ module Gitlab
|
|||
class StiType < ActiveRecord::Type::String
|
||||
NAMESPACED_INTEGRATIONS = Set.new(%w(
|
||||
Asana Assembla Bamboo Bugzilla Campfire Confluence CustomIssueTracker Datadog
|
||||
EmailsOnPush Ewm IssueTracker Jira Redmine Youtrack
|
||||
EmailsOnPush Ewm ExternalWiki Flowdock IssueTracker Irker Jira Packagist PipelinesEmail
|
||||
Pivotaltracker Redmine Youtrack
|
||||
)).freeze
|
||||
|
||||
def cast(value)
|
||||
|
|
|
@ -351,7 +351,6 @@
|
|||
category: pipeline_authoring
|
||||
redis_slot: pipeline_authoring
|
||||
aggregation: weekly
|
||||
feature_flag: usage_data_unique_users_committing_ciconfigfile
|
||||
- name: o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile
|
||||
category: pipeline_authoring
|
||||
redis_slot: pipeline_authoring
|
||||
|
|
|
@ -127,9 +127,9 @@ FactoryBot.define do
|
|||
end
|
||||
end
|
||||
|
||||
factory :external_wiki_service do
|
||||
factory :external_wiki_service, class: 'Integrations::ExternalWiki' do
|
||||
project
|
||||
type { ExternalWikiService }
|
||||
type { 'ExternalWikiService' }
|
||||
active { true }
|
||||
external_wiki_url { 'http://external-wiki-url.com' }
|
||||
end
|
||||
|
@ -167,7 +167,7 @@ FactoryBot.define do
|
|||
type { 'SlackService' }
|
||||
end
|
||||
|
||||
factory :pipelines_email_service do
|
||||
factory :pipelines_email_service, class: 'Integrations::PipelinesEmail' do
|
||||
project
|
||||
active { true }
|
||||
type { 'PipelinesEmailService' }
|
||||
|
|
|
@ -25,16 +25,6 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Need do
|
|||
it 'returns job needs configuration' do
|
||||
expect(need.value).to eq(name: 'job_name', artifacts: true, optional: false)
|
||||
end
|
||||
|
||||
context 'when the FF ci_needs_optional is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_needs_optional: false)
|
||||
end
|
||||
|
||||
it 'returns job needs configuration without `optional`' do
|
||||
expect(need.value).to eq(name: 'job_name', artifacts: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'job type'
|
||||
|
@ -134,16 +124,6 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Need do
|
|||
it 'returns job needs configuration' do
|
||||
expect(need.value).to eq(name: 'job_name', artifacts: true, optional: true)
|
||||
end
|
||||
|
||||
context 'when the FF ci_needs_optional is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_needs_optional: false)
|
||||
end
|
||||
|
||||
it 'returns job needs configuration without `optional`' do
|
||||
expect(need.value).to eq(name: 'job_name', artifacts: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1101,17 +1101,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
|
|||
it "does not return an error" do
|
||||
expect(subject.errors).to be_empty
|
||||
end
|
||||
|
||||
context 'when the FF ci_needs_optional is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_needs_optional: false)
|
||||
end
|
||||
|
||||
it "returns an error" do
|
||||
expect(subject.errors).to contain_exactly(
|
||||
"'rspec' job needs 'build' job, but it was not added to the pipeline")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -905,7 +905,7 @@ RSpec.describe Integration do
|
|||
|
||||
with_them do
|
||||
it 'returns the right result' do
|
||||
expect(build(:service, type: type, active: active).external_wiki?).to eq(result)
|
||||
expect(create(:service, type: type, active: active).external_wiki?).to eq(result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ExternalWikiService do
|
||||
RSpec.describe Integrations::ExternalWiki do
|
||||
describe "Associations" do
|
||||
it { is_expected.to belong_to :project }
|
||||
it { is_expected.to have_one :service_hook }
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe FlowdockService do
|
||||
RSpec.describe Integrations::Flowdock do
|
||||
describe "Associations" do
|
||||
it { is_expected.to belong_to :project }
|
||||
it { is_expected.to have_one :service_hook }
|
|
@ -4,7 +4,7 @@ require 'spec_helper'
|
|||
require 'socket'
|
||||
require 'json'
|
||||
|
||||
RSpec.describe IrkerService do
|
||||
RSpec.describe Integrations::Irker do
|
||||
describe 'Associations' do
|
||||
it { is_expected.to belong_to :project }
|
||||
it { is_expected.to have_one :service_hook }
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe PackagistService do
|
||||
RSpec.describe Integrations::Packagist do
|
||||
let(:packagist_params) do
|
||||
{
|
||||
active: true,
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe PipelinesEmailService, :mailer do
|
||||
RSpec.describe Integrations::PipelinesEmail, :mailer do
|
||||
let(:pipeline) do
|
||||
create(:ci_pipeline, :failed,
|
||||
project: project,
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe PivotaltrackerService do
|
||||
RSpec.describe Integrations::Pivotaltracker do
|
||||
include StubRequests
|
||||
|
||||
describe 'Associations' do
|
||||
|
@ -35,7 +35,7 @@ RSpec.describe PivotaltrackerService do
|
|||
end
|
||||
end
|
||||
|
||||
let(:url) { PivotaltrackerService::API_ENDPOINT }
|
||||
let(:url) { described_class::API_ENDPOINT }
|
||||
|
||||
def push_data(branch: 'master')
|
||||
{
|
|
@ -1158,7 +1158,7 @@ RSpec.describe Project, factory_default: :keep do
|
|||
it 'returns an active external wiki' do
|
||||
create(:service, project: project, type: 'ExternalWikiService', active: true)
|
||||
|
||||
is_expected.to be_kind_of(ExternalWikiService)
|
||||
is_expected.to be_kind_of(Integrations::ExternalWiki)
|
||||
end
|
||||
|
||||
it 'does not return an inactive external wiki' do
|
||||
|
|
Loading…
Reference in New Issue