Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/integrations')
-rw-r--r--app/models/integrations/asana.rb37
-rw-r--r--app/models/integrations/assembla.rb29
-rw-r--r--app/models/integrations/bamboo.rb1
-rw-r--r--app/models/integrations/base_chat_notification.rb46
-rw-r--r--app/models/integrations/base_issue_tracker.rb2
-rw-r--r--app/models/integrations/campfire.rb63
-rw-r--r--app/models/integrations/confluence.rb19
-rw-r--r--app/models/integrations/datadog.rb157
-rw-r--r--app/models/integrations/discord.rb6
-rw-r--r--app/models/integrations/drone_ci.rb3
-rw-r--r--app/models/integrations/emails_on_push.rb51
-rw-r--r--app/models/integrations/external_wiki.rb22
-rw-r--r--app/models/integrations/field.rb27
-rw-r--r--app/models/integrations/flowdock.rb23
-rw-r--r--app/models/integrations/hangouts_chat.rb5
-rw-r--r--app/models/integrations/harbor.rb2
-rw-r--r--app/models/integrations/irker.rb93
-rw-r--r--app/models/integrations/jira.rb3
-rw-r--r--app/models/integrations/mattermost.rb6
-rw-r--r--app/models/integrations/microsoft_teams.rb5
-rw-r--r--app/models/integrations/mock_ci.rb2
-rw-r--r--app/models/integrations/packagist.rb51
-rw-r--r--app/models/integrations/pipelines_email.rb34
-rw-r--r--app/models/integrations/pivotaltracker.rb35
-rw-r--r--app/models/integrations/prometheus.rb66
-rw-r--r--app/models/integrations/pushover.rb141
-rw-r--r--app/models/integrations/shimo.rb18
-rw-r--r--app/models/integrations/slack.rb5
-rw-r--r--app/models/integrations/teamcity.rb5
-rw-r--r--app/models/integrations/unify_circuit.rb8
-rw-r--r--app/models/integrations/webex_teams.rb7
-rw-r--r--app/models/integrations/youtrack.rb5
-rw-r--r--app/models/integrations/zentao.rb56
33 files changed, 464 insertions, 569 deletions
diff --git a/app/models/integrations/asana.rb b/app/models/integrations/asana.rb
index d25bf8b1b1e..2cfd71c9eb2 100644
--- a/app/models/integrations/asana.rb
+++ b/app/models/integrations/asana.rb
@@ -4,9 +4,22 @@ require 'asana'
module Integrations
class Asana < Integration
- prop_accessor :api_key, :restrict_to_branch
validates :api_key, presence: true, if: :activated?
+ field :api_key,
+ type: 'password',
+ title: 'API key',
+ help: -> { s_('AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user.') },
+ non_empty_password_title: -> { s_('ProjectService|Enter new API key') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current API key.') },
+ # Example Personal Access Token from Asana docs
+ placeholder: '0/68a9e79b868c6789e79a124c30b0',
+ required: true
+
+ field :restrict_to_branch,
+ title: -> { s_('Integrations|Restrict to branch (optional)') },
+ help: -> { s_('AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches.') }
+
def title
'Asana'
end
@@ -24,28 +37,6 @@ module Integrations
'asana'
end
- def fields
- [
- {
- type: 'password',
- name: 'api_key',
- title: 'API key',
- help: s_('AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user.'),
- non_empty_password_title: s_('ProjectService|Enter new API key'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current API key.'),
- # Example Personal Access Token from Asana docs
- placeholder: '0/68a9e79b868c6789e79a124c30b0',
- required: true
- },
- {
- type: 'text',
- name: 'restrict_to_branch',
- title: 'Restrict to branch (optional)',
- help: s_('AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches.')
- }
- ]
- end
-
def self.supported_events
%w(push)
end
diff --git a/app/models/integrations/assembla.rb b/app/models/integrations/assembla.rb
index ccd24c1fb2c..88dbf2915ef 100644
--- a/app/models/integrations/assembla.rb
+++ b/app/models/integrations/assembla.rb
@@ -2,9 +2,18 @@
module Integrations
class Assembla < Integration
- prop_accessor :token, :subdomain
validates :token, presence: true, if: :activated?
+ field :token,
+ type: 'password',
+ non_empty_password_title: -> { s_('ProjectService|Enter new token') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') },
+ placeholder: '',
+ required: true
+
+ field :subdomain,
+ placeholder: ''
+
def title
'Assembla'
end
@@ -17,24 +26,6 @@ module Integrations
'assembla'
end
- def fields
- [
- {
- type: 'password',
- name: 'token',
- non_empty_password_title: s_('ProjectService|Enter new token'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'),
- placeholder: '',
- required: true
- },
- {
- type: 'text',
- name: 'subdomain',
- placeholder: ''
- }
- ]
- end
-
def self.supported_events
%w(push)
end
diff --git a/app/models/integrations/bamboo.rb b/app/models/integrations/bamboo.rb
index 4e30c1ccc69..230dc6bb336 100644
--- a/app/models/integrations/bamboo.rb
+++ b/app/models/integrations/bamboo.rb
@@ -155,7 +155,6 @@ module Integrations
query_params[:os_authType] = 'basic'
params[:basic_auth] = basic_auth
- params[:use_read_total_timeout] = true
params
end
diff --git a/app/models/integrations/base_chat_notification.rb b/app/models/integrations/base_chat_notification.rb
index 33d4eecbf49..c7992e4083c 100644
--- a/app/models/integrations/base_chat_notification.rb
+++ b/app/models/integrations/base_chat_notification.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-# Base class for Chat notifications services
+# Base class for Chat notifications integrations
# This class is not meant to be used directly, but only to inherit from.
module Integrations
@@ -46,7 +46,7 @@ module Integrations
# `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 haven't specified one already. When users edit the service and
+ # users haven't specified one already. When users edit the integration and
# select a value for this new property, it will override everything.
self.branches_to_be_notified ||= notify_only_default_branch? ? "default" : "all"
@@ -78,7 +78,7 @@ module Integrations
type: 'select',
name: 'branches_to_be_notified',
title: s_('Integrations|Branches for which notifications are to be sent'),
- choices: branch_choices
+ choices: self.class.branch_choices
}.freeze,
{
type: 'text',
@@ -118,7 +118,7 @@ module Integrations
event_type = data[:event_type] || object_kind
- channel_names = get_channel_field(event_type).presence || channel.presence
+ channel_names = event_channel_value(event_type).presence || channel.presence
channels = channel_names&.split(',')&.map(&:strip)
opts = {}
@@ -134,15 +134,13 @@ module Integrations
end
def event_channel_names
- supported_events.map { |event| event_channel_name(event) }
- end
+ return [] unless configurable_channels?
- def event_field(event)
- fields.find { |field| field[:name] == event_channel_name(event) }
+ supported_events.map { |event| event_channel_name(event) }
end
- def global_fields
- fields.reject { |field| field[:name].end_with?('channel') }
+ def form_fields
+ super.reject { |field| field[:name].end_with?('channel') }
end
def default_channel_placeholder
@@ -153,6 +151,21 @@ module Integrations
raise NotImplementedError
end
+ # With some integrations the webhook is already tied to a specific channel,
+ # for others the channels are configurable for each event.
+ def configurable_channels?
+ false
+ end
+
+ def event_channel_name(event)
+ EVENT_CHANNEL[event]
+ end
+
+ def event_channel_value(event)
+ field_name = event_channel_name(event)
+ self.public_send(field_name) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
private
def log_usage(_, _)
@@ -213,21 +226,12 @@ module Integrations
end
end
- def get_channel_field(event)
- field_name = event_channel_name(event)
- self.public_send(field_name) # rubocop:disable GitlabSecurity/PublicSend
- end
-
def build_event_channels
- supported_events.reduce([]) do |channels, event|
- channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel_placeholder }
+ event_channel_names.map do |channel_field|
+ { type: 'text', name: channel_field, placeholder: default_channel_placeholder }
end
end
- def event_channel_name(event)
- EVENT_CHANNEL[event]
- end
-
def project_name
project.full_name
end
diff --git a/app/models/integrations/base_issue_tracker.rb b/app/models/integrations/base_issue_tracker.rb
index bffe87c21ee..fe4a2f43b13 100644
--- a/app/models/integrations/base_issue_tracker.rb
+++ b/app/models/integrations/base_issue_tracker.rb
@@ -94,7 +94,7 @@ module Integrations
result = false
begin
- response = Gitlab::HTTP.head(self.project_url, verify: true, use_read_total_timeout: true)
+ response = Gitlab::HTTP.head(self.project_url, verify: true)
if response
message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}"
diff --git a/app/models/integrations/campfire.rb b/app/models/integrations/campfire.rb
index 7889cd8f9a9..bf1358ac0f6 100644
--- a/app/models/integrations/campfire.rb
+++ b/app/models/integrations/campfire.rb
@@ -2,9 +2,34 @@
module Integrations
class Campfire < Integration
- prop_accessor :token, :subdomain, :room
validates :token, presence: true, if: :activated?
+ field :token,
+ type: 'password',
+ title: -> { _('Campfire token') },
+ help: -> { s_('CampfireService|API authentication token from Campfire.') },
+ non_empty_password_title: -> { s_('ProjectService|Enter new token') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') },
+ placeholder: '',
+ required: true
+
+ field :subdomain,
+ title: -> { _('Campfire subdomain (optional)') },
+ placeholder: '',
+ help: -> do
+ ERB::Util.html_escape(
+ s_('CampfireService|The %{code_open}.campfirenow.com%{code_close} subdomain.')
+ ) % {
+ code_open: '<code>'.html_safe,
+ code_close: '</code>'.html_safe
+ }
+ end
+
+ field :room,
+ title: -> { _('Campfire room ID (optional)') },
+ placeholder: '123456',
+ help: -> { s_('CampfireService|From the end of the room URL.') }
+
def title
'Campfire'
end
@@ -15,42 +40,18 @@ module Integrations
def help
docs_link = ActionController::Base.helpers.link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('api/services', anchor: 'campfire'), target: '_blank', rel: 'noopener noreferrer'
- s_('CampfireService|Send notifications about push events to Campfire chat rooms. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
+
+ ERB::Util.html_escape(
+ s_('CampfireService|Send notifications about push events to Campfire chat rooms. %{docs_link}')
+ ) % {
+ docs_link: docs_link.html_safe
+ }
end
def self.to_param
'campfire'
end
- def fields
- [
- {
- type: 'password',
- name: 'token',
- title: _('Campfire token'),
- help: s_('CampfireService|API authentication token from Campfire.'),
- non_empty_password_title: s_('ProjectService|Enter new token'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'),
- placeholder: '',
- required: true
- },
- {
- type: 'text',
- name: 'subdomain',
- title: _('Campfire subdomain (optional)'),
- placeholder: '',
- help: s_('CampfireService|The %{code_open}.campfirenow.com%{code_close} subdomain.') % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- },
- {
- type: 'text',
- name: 'room',
- title: _('Campfire room ID (optional)'),
- placeholder: '123456',
- help: s_('CampfireService|From the end of the room URL.')
- }
- ]
- end
-
def self.supported_events
%w(push)
end
diff --git a/app/models/integrations/confluence.rb b/app/models/integrations/confluence.rb
index 4e1d1993d02..c1c43af99bf 100644
--- a/app/models/integrations/confluence.rb
+++ b/app/models/integrations/confluence.rb
@@ -6,11 +6,14 @@ module Integrations
VALID_HOST_MATCH = %r{\A.+\.atlassian\.net\Z}.freeze
VALID_PATH_MATCH = %r{\A/wiki(/|\Z)}.freeze
- prop_accessor :confluence_url
-
validates :confluence_url, presence: true, if: :activated?
validate :validate_confluence_url_is_cloud, if: :activated?
+ field :confluence_url,
+ title: -> { s_('Confluence Cloud Workspace URL') },
+ placeholder: 'https://example.atlassian.net/wiki',
+ required: true
+
def self.to_param
'confluence'
end
@@ -38,18 +41,6 @@ module Integrations
end
end
- def fields
- [
- {
- type: 'text',
- name: 'confluence_url',
- title: s_('Confluence Cloud Workspace URL'),
- placeholder: 'https://example.atlassian.net/wiki',
- required: true
- }
- ]
- end
-
def testable?
false
end
diff --git a/app/models/integrations/datadog.rb b/app/models/integrations/datadog.rb
index bb0fb6b9079..97e586c0662 100644
--- a/app/models/integrations/datadog.rb
+++ b/app/models/integrations/datadog.rb
@@ -15,7 +15,75 @@ module Integrations
TAG_KEY_VALUE_RE = %r{\A [\w-]+ : .*\S.* \z}x.freeze
- prop_accessor :datadog_site, :api_url, :api_key, :datadog_service, :datadog_env, :datadog_tags
+ field :datadog_site,
+ placeholder: DEFAULT_DOMAIN,
+ help: -> do
+ ERB::Util.html_escape(
+ s_('DatadogIntegration|The Datadog site to send data to. To send data to the EU site, use %{codeOpen}datadoghq.eu%{codeClose}.')
+ ) % {
+ codeOpen: '<code>'.html_safe,
+ codeClose: '</code>'.html_safe
+ }
+ end
+
+ field :api_url,
+ title: -> { s_('DatadogIntegration|API URL') },
+ help: -> { s_('DatadogIntegration|(Advanced) The full URL for your Datadog site.') }
+
+ field :api_key,
+ type: 'password',
+ title: -> { _('API key') },
+ non_empty_password_title: -> { s_('ProjectService|Enter new API key') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current API key') },
+ help: -> do
+ ERB::Util.html_escape(
+ s_('DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog.')
+ ) % {
+ linkOpen: %Q{<a href="#{URL_API_KEYS_DOCS}" target="_blank" rel="noopener noreferrer">}.html_safe,
+ linkClose: '</a>'.html_safe
+ }
+ end,
+ required: true
+
+ field :archive_trace_events,
+ type: 'checkbox',
+ title: -> { s_('Logs') },
+ checkbox_label: -> { s_('Enable logs collection') },
+ help: -> { s_('When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces.') }
+
+ field :datadog_service,
+ title: -> { s_('DatadogIntegration|Service') },
+ placeholder: 'gitlab-ci',
+ help: -> { s_('DatadogIntegration|Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments.') }
+
+ field :datadog_env,
+ title: -> { s_('DatadogIntegration|Environment') },
+ placeholder: 'ci',
+ help: -> do
+ ERB::Util.html_escape(
+ s_('DatadogIntegration|For self-managed deployments, set the %{codeOpen}env%{codeClose} tag for all the data sent to Datadog. %{linkOpen}How do I use tags?%{linkClose}')
+ ) % {
+ codeOpen: '<code>'.html_safe,
+ codeClose: '</code>'.html_safe,
+ linkOpen: '<a href="https://docs.datadoghq.com/getting_started/tagging/#using-tags" target="_blank" rel="noopener noreferrer">'.html_safe,
+ linkClose: '</a>'.html_safe
+ }
+ end
+
+ field :datadog_tags,
+ type: 'textarea',
+ title: -> { s_('DatadogIntegration|Tags') },
+ placeholder: "tag:value\nanother_tag:value",
+ help: -> do
+ ERB::Util.html_escape(
+ s_('DatadogIntegration|Custom tags in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}')
+ ) % {
+ codeOpen: '<code>'.html_safe,
+ codeClose: '</code>'.html_safe,
+ linkOpen: '<a href="https://docs.datadoghq.com/getting_started/tagging/#using-tags" target="_blank" rel="noopener noreferrer">'.html_safe,
+ linkClose: '</a>'.html_safe
+ }
+ end
before_validation :strip_properties
@@ -77,92 +145,11 @@ module Integrations
end
def fields
- f = [
- {
- type: 'text',
- name: 'datadog_site',
- placeholder: DEFAULT_DOMAIN,
- help: ERB::Util.html_escape(
- s_('DatadogIntegration|The Datadog site to send data to. To send data to the EU site, use %{codeOpen}datadoghq.eu%{codeClose}.')
- ) % {
- codeOpen: '<code>'.html_safe,
- codeClose: '</code>'.html_safe
- },
- required: false
- },
- {
- type: 'text',
- name: 'api_url',
- title: s_('DatadogIntegration|API URL'),
- help: s_('DatadogIntegration|(Advanced) The full URL for your Datadog site.'),
- required: false
- },
- {
- type: 'password',
- name: 'api_key',
- title: _('API key'),
- non_empty_password_title: s_('ProjectService|Enter new API key'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current API key'),
- help: ERB::Util.html_escape(
- s_('DatadogIntegration|%{linkOpen}API key%{linkClose} used for authentication with Datadog.')
- ) % {
- linkOpen: %Q{<a href="#{URL_API_KEYS_DOCS}" target="_blank" rel="noopener noreferrer">}.html_safe,
- linkClose: '</a>'.html_safe
- },
- required: true
- }
- ]
-
if Feature.enabled?(:datadog_integration_logs_collection, parent)
- f.append({
- type: 'checkbox',
- name: 'archive_trace_events',
- title: s_('Logs'),
- checkbox_label: s_('Enable logs collection'),
- help: s_('When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces.'),
- required: false
- })
+ super
+ else
+ super.reject { _1.name == 'archive_trace_events' }
end
-
- f += [
- {
- type: 'text',
- name: 'datadog_service',
- title: s_('DatadogIntegration|Service'),
- placeholder: 'gitlab-ci',
- help: s_('DatadogIntegration|Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments.')
- },
- {
- type: 'text',
- name: 'datadog_env',
- title: s_('DatadogIntegration|Environment'),
- placeholder: 'ci',
- help: ERB::Util.html_escape(
- s_('DatadogIntegration|For self-managed deployments, set the %{codeOpen}env%{codeClose} tag for all the data sent to Datadog. %{linkOpen}How do I use tags?%{linkClose}')
- ) % {
- codeOpen: '<code>'.html_safe,
- codeClose: '</code>'.html_safe,
- linkOpen: '<a href="https://docs.datadoghq.com/getting_started/tagging/#using-tags" target="_blank" rel="noopener noreferrer">'.html_safe,
- linkClose: '</a>'.html_safe
- }
- },
- {
- type: 'textarea',
- name: 'datadog_tags',
- title: s_('DatadogIntegration|Tags'),
- placeholder: "tag:value\nanother_tag:value",
- help: ERB::Util.html_escape(
- s_('DatadogIntegration|Custom tags in Datadog. Enter one tag per line in the %{codeOpen}key:value%{codeClose} format. %{linkOpen}How do I use tags?%{linkClose}')
- ) % {
- codeOpen: '<code>'.html_safe,
- codeClose: '</code>'.html_safe,
- linkOpen: '<a href="https://docs.datadoghq.com/getting_started/tagging/#using-tags" target="_blank" rel="noopener noreferrer">'.html_safe,
- linkClose: '</a>'.html_safe
- }
- }
- ]
-
- f
end
override :hook_url
diff --git a/app/models/integrations/discord.rb b/app/models/integrations/discord.rb
index 790e41e5a2a..ecabf23c90b 100644
--- a/app/models/integrations/discord.rb
+++ b/app/models/integrations/discord.rb
@@ -23,10 +23,6 @@ module Integrations
s_('Send notifications about project events to a Discord channel. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
end
- def event_field(event)
- # No-op.
- end
-
def default_channel_placeholder
# No-op.
end
@@ -43,7 +39,7 @@ module Integrations
type: 'select',
name: 'branches_to_be_notified',
title: s_('Integrations|Branches for which notifications are to be sent'),
- choices: branch_choices
+ choices: self.class.branch_choices
}
]
end
diff --git a/app/models/integrations/drone_ci.rb b/app/models/integrations/drone_ci.rb
index 35524503dea..b1f72b7144e 100644
--- a/app/models/integrations/drone_ci.rb
+++ b/app/models/integrations/drone_ci.rb
@@ -60,8 +60,7 @@ module Integrations
response = Gitlab::HTTP.try_get(
commit_status_path(sha, ref),
verify: enable_ssl_verification,
- extra_log_info: { project_id: project_id },
- use_read_total_timeout: true
+ extra_log_info: { project_id: project_id }
)
status =
diff --git a/app/models/integrations/emails_on_push.rb b/app/models/integrations/emails_on_push.rb
index ab458bb2c27..ed12a3a8d63 100644
--- a/app/models/integrations/emails_on_push.rb
+++ b/app/models/integrations/emails_on_push.rb
@@ -6,12 +6,35 @@ module Integrations
RECIPIENTS_LIMIT = 750
- boolean_accessor :send_from_committer_email
- boolean_accessor :disable_diffs
- prop_accessor :recipients, :branches_to_be_notified
validates :recipients, presence: true, if: :validate_recipients?
validate :number_of_recipients_within_limit, if: :validate_recipients?
+ field :send_from_committer_email,
+ type: 'checkbox',
+ title: -> { s_("EmailsOnPushService|Send from committer") },
+ help: -> do
+ @help ||= begin
+ domains = Notify.allowed_email_domains.map { |domain| "user@#{domain}" }.join(", ")
+
+ s_("EmailsOnPushService|Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance (such as %{domains}).") % { domains: domains }
+ end
+ end
+
+ field :disable_diffs,
+ type: 'checkbox',
+ title: -> { s_("EmailsOnPushService|Disable code diffs") },
+ help: -> { s_("EmailsOnPushService|Don't include possibly sensitive code diffs in notification body.") }
+
+ field :branches_to_be_notified,
+ type: 'select',
+ title: -> { s_('Integrations|Branches for which notifications are to be sent') },
+ choices: branch_choices
+
+ field :recipients,
+ type: 'textarea',
+ placeholder: -> { s_('EmailsOnPushService|tanuki@example.com gitlab@example.com') },
+ help: -> { s_('EmailsOnPushService|Emails separated by whitespace.') }
+
def self.valid_recipients(recipients)
recipients.split.grep(Devise.email_regexp).uniq(&:downcase)
end
@@ -67,28 +90,6 @@ module Integrations
Gitlab::Utils.to_boolean(self.disable_diffs)
end
- def fields
- domains = Notify.allowed_email_domains.map { |domain| "user@#{domain}" }.join(", ")
- [
- { type: 'checkbox', name: 'send_from_committer_email', title: s_("EmailsOnPushService|Send from committer"),
- help: s_("EmailsOnPushService|Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance (such as %{domains}).") % { domains: domains } },
- { type: 'checkbox', name: 'disable_diffs', title: s_("EmailsOnPushService|Disable code diffs"),
- help: s_("EmailsOnPushService|Don't include possibly sensitive code diffs in notification body.") },
- {
- type: 'select',
- name: 'branches_to_be_notified',
- title: s_('Integrations|Branches for which notifications are to be sent'),
- choices: branch_choices
- },
- {
- type: 'textarea',
- name: 'recipients',
- placeholder: s_('EmailsOnPushService|tanuki@example.com gitlab@example.com'),
- help: s_('EmailsOnPushService|Emails separated by whitespace.')
- }
- ]
- end
-
private
def number_of_recipients_within_limit
diff --git a/app/models/integrations/external_wiki.rb b/app/models/integrations/external_wiki.rb
index 18c48411e30..bc2ea193a84 100644
--- a/app/models/integrations/external_wiki.rb
+++ b/app/models/integrations/external_wiki.rb
@@ -2,9 +2,14 @@
module Integrations
class ExternalWiki < Integration
- prop_accessor :external_wiki_url
validates :external_wiki_url, presence: true, public_url: true, if: :activated?
+ field :external_wiki_url,
+ title: -> { s_('ExternalWikiService|External wiki URL') },
+ placeholder: -> { s_('ExternalWikiService|https://example.com/xxx/wiki/...') },
+ help: -> { s_('ExternalWikiService|Enter the URL to the external wiki.') },
+ required: true
+
def title
s_('ExternalWikiService|External wiki')
end
@@ -17,19 +22,6 @@ module Integrations
'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 = ActionController::Base.helpers.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'
@@ -37,7 +29,7 @@ module Integrations
end
def execute(_data)
- response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true, use_read_total_timeout: true)
+ response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true)
response.body if response.code == 200
rescue StandardError
nil
diff --git a/app/models/integrations/field.rb b/app/models/integrations/field.rb
index cbda418755b..53c8f5f623e 100644
--- a/app/models/integrations/field.rb
+++ b/app/models/integrations/field.rb
@@ -4,14 +4,16 @@ module Integrations
class Field
SECRET_NAME = %r/token|key|password|passphrase|secret/.freeze
+ BOOLEAN_ATTRIBUTES = %i[required api_only exposes_secrets].freeze
+
ATTRIBUTES = %i[
- section type placeholder required choices value checkbox_label
+ section type placeholder choices value checkbox_label
title help
non_empty_password_help
non_empty_password_title
- api_only
- exposes_secrets
- ].freeze
+ ].concat(BOOLEAN_ATTRIBUTES).freeze
+
+ TYPES = %w[text textarea password checkbox select].freeze
attr_reader :name, :integration_class
@@ -22,6 +24,13 @@ module Integrations
attributes[:type] = SECRET_NAME.match?(@name) ? 'password' : type
attributes[:api_only] = api_only
@attributes = attributes.freeze
+
+ invalid_attributes = attributes.keys - ATTRIBUTES
+ if invalid_attributes.present?
+ raise ArgumentError, "Invalid attributes #{invalid_attributes.inspect}"
+ elsif !TYPES.include?(self[:type])
+ raise ArgumentError, "Invalid type #{self[:type].inspect}"
+ end
end
def [](key)
@@ -34,11 +43,19 @@ module Integrations
end
def secret?
- @attributes[:type] == 'password'
+ self[:type] == 'password'
end
ATTRIBUTES.each do |name|
define_method(name) { self[name] }
end
+
+ BOOLEAN_ATTRIBUTES.each do |name|
+ define_method("#{name}?") { !!self[name] }
+ end
+
+ TYPES.each do |type|
+ define_method("#{type}?") { self[:type] == type }
+ end
end
end
diff --git a/app/models/integrations/flowdock.rb b/app/models/integrations/flowdock.rb
index 703d8013bab..52efb29f2c1 100644
--- a/app/models/integrations/flowdock.rb
+++ b/app/models/integrations/flowdock.rb
@@ -2,9 +2,16 @@
module Integrations
class Flowdock < Integration
- prop_accessor :token
validates :token, presence: true, if: :activated?
+ field :token,
+ type: 'password',
+ help: -> { s_('FlowdockService|Enter your Flowdock token.') },
+ non_empty_password_title: -> { s_('ProjectService|Enter new token') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') },
+ placeholder: '1b609b52537...',
+ required: true
+
def title
'Flowdock'
end
@@ -22,20 +29,6 @@ module Integrations
'flowdock'
end
- def fields
- [
- {
- type: 'password',
- name: 'token',
- help: s_('FlowdockService|Enter your Flowdock token.'),
- non_empty_password_title: s_('ProjectService|Enter new token'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'),
- placeholder: '1b609b52537...',
- required: true
- }
- ]
- end
-
def self.supported_events
%w(push)
end
diff --git a/app/models/integrations/hangouts_chat.rb b/app/models/integrations/hangouts_chat.rb
index 8c68c9ff95a..df112ad6ca8 100644
--- a/app/models/integrations/hangouts_chat.rb
+++ b/app/models/integrations/hangouts_chat.rb
@@ -19,9 +19,6 @@ module Integrations
s_('Before enabling this integration, create a webhook for the room in Google Chat where you want to receive notifications from this project. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
end
- def event_field(event)
- end
-
def default_channel_placeholder
end
@@ -42,7 +39,7 @@ module Integrations
type: 'select',
name: 'branches_to_be_notified',
title: s_('Integrations|Branches for which notifications are to be sent'),
- choices: branch_choices
+ choices: self.class.branch_choices
}
]
end
diff --git a/app/models/integrations/harbor.rb b/app/models/integrations/harbor.rb
index 44813795fc0..82981493822 100644
--- a/app/models/integrations/harbor.rb
+++ b/app/models/integrations/harbor.rb
@@ -4,7 +4,7 @@ module Integrations
class Harbor < Integration
prop_accessor :url, :project_name, :username, :password
- validates :url, public_url: true, presence: true, if: :activated?
+ validates :url, public_url: true, presence: true, addressable_url: { allow_localhost: false, allow_local_network: false }, if: :activated?
validates :project_name, presence: true, if: :activated?
validates :username, presence: true, if: :activated?
validates :password, format: { with: ::Ci::Maskable::REGEX }, if: :activated?
diff --git a/app/models/integrations/irker.rb b/app/models/integrations/irker.rb
index 780f4bef0c9..3f3e321f45e 100644
--- a/app/models/integrations/irker.rb
+++ b/app/models/integrations/irker.rb
@@ -4,13 +4,55 @@ 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
+ field :server_host,
+ placeholder: 'localhost',
+ title: -> { s_('IrkerService|Server host (optional)') },
+ help: -> { s_('IrkerService|irker daemon hostname (defaults to localhost).') }
+
+ field :server_port,
+ placeholder: 6659,
+ title: -> { s_('IrkerService|Server port (optional)') },
+ help: -> { s_('IrkerService|irker daemon port (defaults to 6659).') }
+
+ field :default_irc_uri,
+ title: -> { s_('IrkerService|Default IRC URI (optional)') },
+ help: -> { s_('IrkerService|URI to add before each recipient.') },
+ placeholder: 'irc://irc.network.net:6697/'
+
+ field :recipients,
+ type: 'textarea',
+ title: -> { s_('IrkerService|Recipients') },
+ placeholder: 'irc[s]://irc.network.net[:port]/#channel',
+ required: true,
+ help: -> do
+ recipients_docs_link = ActionController::Base.helpers.link_to(
+ s_('IrkerService|How to enter channels or users?'),
+ Rails.application.routes.url_helpers.help_page_url(
+ 'user/project/integrations/irker',
+ anchor: 'enter-irker-recipients'
+ ),
+ target: '_blank', rel: 'noopener noreferrer'
+ )
+
+ ERB::Util.html_escape(
+ s_('IrkerService|Channels and users separated by whitespaces. %{recipients_docs_link}')
+ ) % {
+ recipients_docs_link: recipients_docs_link.html_safe
+ }
+ end
+
+ field :colorize_messages,
+ type: 'checkbox',
+ title: -> { _('Colorize messages') }
+
+ # NOTE: This field is only used internally to store the parsed
+ # channels from the `recipients` field, it should not be exposed
+ # in the UI or API.
+ prop_accessor :channels
+
def title
s_('IrkerService|irker (IRC gateway)')
end
@@ -30,17 +72,10 @@ module Integrations
def execute(data)
return unless supported_events.include?(data[:object_kind])
- if Feature.enabled?(:rename_integrations_workers)
- Integrations::IrkerWorker.perform_async(
- project_id, channels,
- colorize_messages, data, settings
- )
- else
- ::IrkerWorker.perform_async(
- project_id, channels,
- colorize_messages, data, settings
- )
- end
+ Integrations::IrkerWorker.perform_async(
+ project_id, channels,
+ colorize_messages, data, settings
+ )
end
def settings
@@ -50,34 +85,6 @@ module Integrations
}
end
- def fields
- recipients_docs_link = ActionController::Base.helpers.link_to(
- s_('IrkerService|How to enter channels or users?'),
- Rails.application.routes.url_helpers.help_page_url(
- 'user/project/integrations/irker',
- anchor: 'enter-irker-recipients'
- ),
- target: '_blank', rel: 'noopener noreferrer'
- )
-
- [
- { type: 'text', name: 'server_host', placeholder: 'localhost', title: s_('IrkerService|Server host (optional)'),
- help: s_('IrkerService|irker daemon hostname (defaults to localhost).') },
- { type: 'text', name: 'server_port', placeholder: 6659, title: s_('IrkerService|Server port (optional)'),
- help: s_('IrkerService|irker daemon port (defaults to 6659).') },
- { type: 'text', name: 'default_irc_uri', title: s_('IrkerService|Default IRC URI (optional)'),
- help: s_('IrkerService|URI to add before each recipient.'),
- placeholder: 'irc://irc.network.net:6697/' },
- { type: 'textarea', name: 'recipients', title: s_('IrkerService|Recipients'),
- placeholder: 'irc[s]://irc.network.net[:port]/#channel', required: true,
- help: format(
- s_('IrkerService|Channels and users separated by whitespaces. %{recipients_docs_link}').html_safe,
- recipients_docs_link: recipients_docs_link.html_safe
- ) },
- { type: 'checkbox', name: 'colorize_messages', title: _('Colorize messages') }
- ]
- end
-
def help
docs_link = ActionController::Base.helpers.link_to(
_('Learn more.'),
diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb
index 125f52104d4..c9c9b9d59d6 100644
--- a/app/models/integrations/jira.rb
+++ b/app/models/integrations/jira.rb
@@ -71,11 +71,12 @@ module Integrations
non_empty_password_help: -> { s_('JiraService|Leave blank to use your current password or API token.') },
help: -> { s_('JiraService|Use a password for server version and an API token for cloud version.') }
+ field :jira_issue_transition_id, api_only: true
+
# TODO: we can probably just delegate as part of
# https://gitlab.com/gitlab-org/gitlab/issues/29404
# These fields are API only, so no field definition is required.
data_field :jira_issue_transition_automatic
- data_field :jira_issue_transition_id
data_field :project_key
data_field :issues_enabled
data_field :vulnerabilities_enabled
diff --git a/app/models/integrations/mattermost.rb b/app/models/integrations/mattermost.rb
index d9ccbb7ea34..dae11b99bc5 100644
--- a/app/models/integrations/mattermost.rb
+++ b/app/models/integrations/mattermost.rb
@@ -3,6 +3,7 @@
module Integrations
class Mattermost < BaseChatNotification
include SlackMattermostNotifier
+ extend ::Gitlab::Utils::Override
def title
s_('Mattermost notifications')
@@ -28,5 +29,10 @@ module Integrations
def webhook_placeholder
'http://mattermost.example.com/hooks/'
end
+
+ override :configurable_channels?
+ def configurable_channels?
+ true
+ end
end
end
diff --git a/app/models/integrations/microsoft_teams.rb b/app/models/integrations/microsoft_teams.rb
index 625ee0bc522..69863f164cd 100644
--- a/app/models/integrations/microsoft_teams.rb
+++ b/app/models/integrations/microsoft_teams.rb
@@ -22,9 +22,6 @@ module Integrations
'https://outlook.office.com/webhook/…'
end
- def event_field(event)
- end
-
def default_channel_placeholder
end
@@ -47,7 +44,7 @@ module Integrations
section: SECTION_TYPE_CONFIGURATION,
name: 'branches_to_be_notified',
title: s_('Integrations|Branches for which notifications are to be sent'),
- choices: branch_choices
+ choices: self.class.branch_choices
}
]
end
diff --git a/app/models/integrations/mock_ci.rb b/app/models/integrations/mock_ci.rb
index 0b3a9bc5405..2d8e26d409f 100644
--- a/app/models/integrations/mock_ci.rb
+++ b/app/models/integrations/mock_ci.rb
@@ -49,7 +49,7 @@ module Integrations
# # => 'running'
#
def commit_status(sha, ref)
- response = Gitlab::HTTP.get(commit_status_path(sha), verify: enable_ssl_verification, use_read_total_timeout: true)
+ response = Gitlab::HTTP.get(commit_status_path(sha), verify: enable_ssl_verification)
read_commit_status(response)
rescue Errno::ECONNREFUSED
:error
diff --git a/app/models/integrations/packagist.rb b/app/models/integrations/packagist.rb
index 758c9e4761b..05ee919892d 100644
--- a/app/models/integrations/packagist.rb
+++ b/app/models/integrations/packagist.rb
@@ -5,7 +5,25 @@ module Integrations
include HasWebHook
extend Gitlab::Utils::Override
- prop_accessor :username, :token, :server
+ field :username,
+ title: -> { _('Username') },
+ help: -> { s_('Enter your Packagist username.') },
+ placeholder: '',
+ required: true
+
+ field :token,
+ type: 'password',
+ title: -> { _('Token') },
+ help: -> { s_('Enter your Packagist token.') },
+ non_empty_password_title: -> { s_('ProjectService|Enter new token') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') },
+ placeholder: '',
+ required: true
+
+ field :server,
+ title: -> { _('Server (optional)') },
+ help: -> { s_('Enter your Packagist server. Defaults to https://packagist.org.') },
+ placeholder: 'https://packagist.org'
validates :username, presence: true, if: :activated?
validates :token, presence: true, if: :activated?
@@ -22,37 +40,6 @@ module Integrations
'packagist'
end
- def fields
- [
- {
- type: 'text',
- name: 'username',
- title: _('Username'),
- help: s_('Enter your Packagist username.'),
- placeholder: '',
- required: true
- },
- {
- type: 'password',
- name: 'token',
- title: _('Token'),
- help: s_('Enter your Packagist token.'),
- non_empty_password_title: s_('ProjectService|Enter new token'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'),
- placeholder: '',
- required: true
- },
- {
- type: 'text',
- name: 'server',
- title: _('Server (optional)'),
- help: s_('Enter your Packagist server. Defaults to https://packagist.org.'),
- placeholder: 'https://packagist.org',
- required: false
- }
- ]
- end
-
def self.supported_events
%w(push merge_request tag_push)
end
diff --git a/app/models/integrations/pipelines_email.rb b/app/models/integrations/pipelines_email.rb
index f15482dc2e1..77cbba25f2c 100644
--- a/app/models/integrations/pipelines_email.rb
+++ b/app/models/integrations/pipelines_email.rb
@@ -6,11 +6,26 @@ module Integrations
RECIPIENTS_LIMIT = 30
- prop_accessor :recipients, :branches_to_be_notified
- boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch
validates :recipients, presence: true, if: :validate_recipients?
validate :number_of_recipients_within_limit, if: :validate_recipients?
+ field :recipients,
+ type: 'textarea',
+ help: -> { _('Comma-separated list of email addresses.') },
+ required: true
+
+ field :notify_only_broken_pipelines,
+ type: 'checkbox'
+
+ field :notify_only_default_branch,
+ type: 'checkbox',
+ api_only: true
+
+ field :branches_to_be_notified,
+ type: 'select',
+ title: -> { s_('Integrations|Branches for which notifications are to be sent') },
+ choices: branch_choices
+
def initialize_properties
super
@@ -65,21 +80,6 @@ module Integrations
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',
- title: s_('Integrations|Branches for which notifications are to be sent'),
- choices: branch_choices }
- ]
- end
-
def test(data)
result = execute(data, force: true)
diff --git a/app/models/integrations/pivotaltracker.rb b/app/models/integrations/pivotaltracker.rb
index 931ccf46655..d32fb974339 100644
--- a/app/models/integrations/pivotaltracker.rb
+++ b/app/models/integrations/pivotaltracker.rb
@@ -4,9 +4,22 @@ 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?
+ field :token,
+ type: 'password',
+ help: -> { s_('PivotalTrackerService|Pivotal Tracker API token. User must have access to the story. All comments are attributed to this user.') },
+ non_empty_password_title: -> { s_('ProjectService|Enter new token') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') },
+ required: true
+
+ field :restrict_to_branch,
+ title: -> { s_('Integrations|Restrict to branch (optional)') },
+ help: -> do
+ s_('PivotalTrackerService|Comma-separated list of branches to ' \
+ 'automatically inspect. Leave blank to include all branches.')
+ end
+
def title
'Pivotal Tracker'
end
@@ -24,26 +37,6 @@ module Integrations
'pivotaltracker'
end
- def fields
- [
- {
- type: 'password',
- name: 'token',
- help: s_('PivotalTrackerService|Pivotal Tracker API token. User must have access to the story. All comments are attributed to this user.'),
- non_empty_password_title: s_('ProjectService|Enter new token'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'),
- required: true
- },
- {
- type: 'text',
- name: 'restrict_to_branch',
- title: 'Restrict to branch (optional)',
- help: s_('PivotalTrackerService|Comma-separated list of branches to ' \
- 'automatically inspect. Leave blank to include all branches.')
- }
- ]
- end
-
def self.supported_events
%w(push)
end
diff --git a/app/models/integrations/prometheus.rb b/app/models/integrations/prometheus.rb
index 36060565317..e672a985810 100644
--- a/app/models/integrations/prometheus.rb
+++ b/app/models/integrations/prometheus.rb
@@ -4,11 +4,30 @@ module Integrations
class Prometheus < BaseMonitoring
include PrometheusAdapter
- # Access to prometheus is directly through the API
- prop_accessor :api_url
- prop_accessor :google_iap_service_account_json
- prop_accessor :google_iap_audience_client_id
- boolean_accessor :manual_configuration
+ field :manual_configuration,
+ type: 'checkbox',
+ title: -> { s_('PrometheusService|Active') },
+ help: -> { s_('PrometheusService|Select this checkbox to override the auto configuration settings with your own settings.') },
+ required: true
+
+ field :api_url,
+ title: 'API URL',
+ placeholder: -> { s_('PrometheusService|https://prometheus.example.com/') },
+ help: -> { s_('PrometheusService|The Prometheus API base URL.') },
+ required: true
+
+ field :google_iap_audience_client_id,
+ title: 'Google IAP Audience Client ID',
+ placeholder: -> { s_('PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com') },
+ help: -> { s_('PrometheusService|The ID of the IAP-secured resource.') },
+ required: false
+
+ field :google_iap_service_account_json,
+ type: 'textarea',
+ title: 'Google IAP Service Account JSON',
+ placeholder: -> { s_('PrometheusService|{ "type": "service_account", "project_id": ... }') },
+ help: -> { s_('PrometheusService|The contents of the credentials.json file of your service account.') },
+ required: false
# We need to allow the self-monitoring project to connect to the internal
# Prometheus instance.
@@ -45,43 +64,6 @@ module Integrations
'prometheus'
end
- def fields
- [
- {
- type: 'checkbox',
- name: 'manual_configuration',
- title: s_('PrometheusService|Active'),
- help: s_('PrometheusService|Select this checkbox to override the auto configuration settings with your own settings.'),
- required: true
- },
- {
- type: 'text',
- name: 'api_url',
- title: 'API URL',
- placeholder: s_('PrometheusService|https://prometheus.example.com/'),
- help: s_('PrometheusService|The Prometheus API base URL.'),
- required: true
- },
- {
- type: 'text',
- name: 'google_iap_audience_client_id',
- title: 'Google IAP Audience Client ID',
- placeholder: s_('PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com'),
- help: s_('PrometheusService|The ID of the IAP-secured resource.'),
- autocomplete: 'off',
- required: false
- },
- {
- type: 'textarea',
- name: 'google_iap_service_account_json',
- title: 'Google IAP Service Account JSON',
- placeholder: s_('PrometheusService|{ "type": "service_account", "project_id": ... }'),
- help: s_('PrometheusService|The contents of the credentials.json file of your service account.'),
- required: false
- }
- ]
- end
-
# Check we can connect to the Prometheus API
def test(*args)
return { success: false, result: 'Prometheus configuration error' } unless prometheus_client
diff --git a/app/models/integrations/pushover.rb b/app/models/integrations/pushover.rb
index 7fd5efa8765..791e27c5db7 100644
--- a/app/models/integrations/pushover.rb
+++ b/app/models/integrations/pushover.rb
@@ -4,9 +4,73 @@ module Integrations
class Pushover < Integration
BASE_URI = 'https://api.pushover.net/1'
- prop_accessor :api_key, :user_key, :device, :priority, :sound
validates :api_key, :user_key, :priority, presence: true, if: :activated?
+ field :api_key,
+ type: 'password',
+ title: -> { _('API key') },
+ help: -> { s_('PushoverService|Enter your application key.') },
+ non_empty_password_title: -> { s_('ProjectService|Enter new API key') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current API key.') },
+ placeholder: '',
+ required: true
+
+ field :user_key,
+ type: 'password',
+ title: -> { _('User key') },
+ help: -> { s_('PushoverService|Enter your user key.') },
+ non_empty_password_title: -> { s_('PushoverService|Enter new user key') },
+ non_empty_password_help: -> { s_('PushoverService|Leave blank to use your current user key.') },
+ placeholder: '',
+ required: true
+
+ field :device,
+ title: -> { _('Devices (optional)') },
+ help: -> { s_('PushoverService|Leave blank for all active devices.') },
+ placeholder: ''
+
+ field :priority,
+ type: 'select',
+ required: true,
+ choices: -> do
+ [
+ [s_('PushoverService|Lowest priority'), -2],
+ [s_('PushoverService|Low priority'), -1],
+ [s_('PushoverService|Normal priority'), 0],
+ [s_('PushoverService|High priority'), 1]
+ ]
+ end
+
+ field :sound,
+ type: 'select',
+ choices: -> do
+ [
+ ['Device default sound', nil],
+ ['Pushover (default)', 'pushover'],
+ %w(Bike bike),
+ %w(Bugle bugle),
+ ['Cash Register', 'cashregister'],
+ %w(Classical classical),
+ %w(Cosmic cosmic),
+ %w(Falling falling),
+ %w(Gamelan gamelan),
+ %w(Incoming incoming),
+ %w(Intermission intermission),
+ %w(Magic magic),
+ %w(Mechanical mechanical),
+ ['Piano Bar', 'pianobar'],
+ %w(Siren siren),
+ ['Space Alarm', 'spacealarm'],
+ ['Tug Boat', 'tugboat'],
+ ['Alien Alarm (long)', 'alien'],
+ ['Climb (long)', 'climb'],
+ ['Persistent (long)', 'persistent'],
+ ['Pushover Echo (long)', 'echo'],
+ ['Up Down (long)', 'updown'],
+ ['None (silent)', 'none']
+ ]
+ end
+
def title
'Pushover'
end
@@ -19,81 +83,6 @@ module Integrations
'pushover'
end
- def fields
- [
- {
- type: 'password',
- name: 'api_key',
- title: _('API key'),
- help: s_('PushoverService|Enter your application key.'),
- non_empty_password_title: s_('ProjectService|Enter new API key'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current API key.'),
- placeholder: '',
- required: true
- },
- {
- type: 'password',
- name: 'user_key',
- title: _('User key'),
- help: s_('PushoverService|Enter your user key.'),
- non_empty_password_title: s_('PushoverService|Enter new user key'),
- non_empty_password_help: s_('PushoverService|Leave blank to use your current user key.'),
- placeholder: '',
- required: true
- },
- {
- type: 'text',
- name: 'device',
- title: _('Devices (optional)'),
- help: s_('PushoverService|Leave blank for all active devices.'),
- placeholder: ''
- },
- {
- type: 'select',
- name: 'priority',
- required: true,
- choices:
- [
- [s_('PushoverService|Lowest priority'), -2],
- [s_('PushoverService|Low priority'), -1],
- [s_('PushoverService|Normal priority'), 0],
- [s_('PushoverService|High priority'), 1]
- ],
- default_choice: 0
- },
- {
- type: 'select',
- name: 'sound',
- choices:
- [
- ['Device default sound', nil],
- ['Pushover (default)', 'pushover'],
- %w(Bike bike),
- %w(Bugle bugle),
- ['Cash Register', 'cashregister'],
- %w(Classical classical),
- %w(Cosmic cosmic),
- %w(Falling falling),
- %w(Gamelan gamelan),
- %w(Incoming incoming),
- %w(Intermission intermission),
- %w(Magic magic),
- %w(Mechanical mechanical),
- ['Piano Bar', 'pianobar'],
- %w(Siren siren),
- ['Space Alarm', 'spacealarm'],
- ['Tug Boat', 'tugboat'],
- ['Alien Alarm (long)', 'alien'],
- ['Climb (long)', 'climb'],
- ['Persistent (long)', 'persistent'],
- ['Pushover Echo (long)', 'echo'],
- ['Up Down (long)', 'updown'],
- ['None (silent)', 'none']
- ]
- }
- ]
- end
-
def self.supported_events
%w(push)
end
diff --git a/app/models/integrations/shimo.rb b/app/models/integrations/shimo.rb
index dd25a0bc558..8bc296e0320 100644
--- a/app/models/integrations/shimo.rb
+++ b/app/models/integrations/shimo.rb
@@ -2,9 +2,12 @@
module Integrations
class Shimo < BaseThirdPartyWiki
- prop_accessor :external_wiki_url
validates :external_wiki_url, presence: true, public_url: true, if: :activated?
+ field :external_wiki_url,
+ title: -> { s_('Shimo|Shimo Workspace URL') },
+ required: true
+
def render?
return false unless Feature.enabled?(:shimo_integration, project)
@@ -25,21 +28,10 @@ module Integrations
# support for `test` method
def execute(_data)
- response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true, use_read_total_timeout: true)
+ response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true)
response.body if response.code == 200
rescue StandardError
nil
end
-
- def fields
- [
- {
- type: 'text',
- name: 'external_wiki_url',
- title: s_('Shimo|Shimo Workspace URL'),
- required: true
- }
- ]
- end
end
end
diff --git a/app/models/integrations/slack.rb b/app/models/integrations/slack.rb
index 0381db3a67e..93263229109 100644
--- a/app/models/integrations/slack.rb
+++ b/app/models/integrations/slack.rb
@@ -55,5 +55,10 @@ module Integrations
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(key, values: user_id)
end
+
+ override :configurable_channels?
+ def configurable_channels?
+ true
+ end
end
end
diff --git a/app/models/integrations/teamcity.rb b/app/models/integrations/teamcity.rb
index a23aa5f783d..e0299c9ac5f 100644
--- a/app/models/integrations/teamcity.rb
+++ b/app/models/integrations/teamcity.rb
@@ -156,7 +156,7 @@ module Integrations
end
def get_path(path)
- Gitlab::HTTP.try_get(build_url(path), verify: enable_ssl_verification, basic_auth: basic_auth, extra_log_info: { project_id: project_id }, use_read_total_timeout: true)
+ Gitlab::HTTP.try_get(build_url(path), verify: enable_ssl_verification, basic_auth: basic_auth, extra_log_info: { project_id: project_id })
end
def post_to_build_queue(data, branch)
@@ -167,8 +167,7 @@ module Integrations
'</build>',
headers: { 'Content-type' => 'application/xml' },
verify: enable_ssl_verification,
- basic_auth: basic_auth,
- use_read_total_timeout: true
+ basic_auth: basic_auth
)
end
diff --git a/app/models/integrations/unify_circuit.rb b/app/models/integrations/unify_circuit.rb
index f085423d229..f10a75fac5d 100644
--- a/app/models/integrations/unify_circuit.rb
+++ b/app/models/integrations/unify_circuit.rb
@@ -19,9 +19,6 @@ module Integrations
s_('Integrations|Send notifications about project events to a Unify Circuit conversation. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
end
- def event_field(event)
- end
-
def default_channel_placeholder
end
@@ -38,7 +35,7 @@ module Integrations
type: 'select',
name: 'branches_to_be_notified',
title: s_('Integrations|Branches for which notifications are to be sent'),
- choices: branch_choices
+ choices: self.class.branch_choices
}
]
end
@@ -49,8 +46,7 @@ module Integrations
response = Gitlab::HTTP.post(webhook, body: {
subject: message.project_name,
text: message.summary,
- markdown: true,
- use_read_total_timeout: true
+ markdown: true
}.to_json)
response if response.success?
diff --git a/app/models/integrations/webex_teams.rb b/app/models/integrations/webex_teams.rb
index 345dd98cbc1..75be457dcf5 100644
--- a/app/models/integrations/webex_teams.rb
+++ b/app/models/integrations/webex_teams.rb
@@ -19,9 +19,6 @@ module Integrations
s_("WebexTeamsService|Send notifications about project events to a Webex Teams conversation. %{docs_link}") % { docs_link: docs_link.html_safe }
end
- def event_field(event)
- end
-
def default_channel_placeholder
end
@@ -38,7 +35,7 @@ module Integrations
type: 'select',
name: 'branches_to_be_notified',
title: s_('Integrations|Branches for which notifications are to be sent'),
- choices: branch_choices
+ choices: self.class.branch_choices
}
]
end
@@ -47,7 +44,7 @@ module Integrations
def notify(message, opts)
header = { 'Content-Type' => 'application/json' }
- response = Gitlab::HTTP.post(webhook, headers: header, body: { markdown: message.summary }.to_json, use_read_total_timeout: true)
+ response = Gitlab::HTTP.post(webhook, headers: header, body: { markdown: message.summary }.to_json)
response if response.success?
end
diff --git a/app/models/integrations/youtrack.rb b/app/models/integrations/youtrack.rb
index ab6e1da27f8..fa719f925ed 100644
--- a/app/models/integrations/youtrack.rb
+++ b/app/models/integrations/youtrack.rb
@@ -33,10 +33,7 @@ module Integrations
end
def fields
- [
- { type: 'text', name: 'project_url', title: _('Project URL'), help: s_('IssueTracker|The URL to the project in YouTrack.'), required: true },
- { type: 'text', name: 'issues_url', title: s_('ProjectService|Issue URL'), help: s_('IssueTracker|The URL to view an issue in the YouTrack project. Must contain %{colon_id}.') % { colon_id: '<code>:id</code>'.html_safe }, required: true }
- ]
+ super.select { _1.name.in?(%w[project_url issues_url]) }
end
end
end
diff --git a/app/models/integrations/zentao.rb b/app/models/integrations/zentao.rb
index c33df465fde..11db469f7ee 100644
--- a/app/models/integrations/zentao.rb
+++ b/app/models/integrations/zentao.rb
@@ -4,7 +4,28 @@ module Integrations
class Zentao < Integration
include Gitlab::Routing
- data_field :url, :api_url, :api_token, :zentao_product_xid
+ self.field_storage = :data_fields
+
+ field :url,
+ title: -> { s_('ZentaoIntegration|ZenTao Web URL') },
+ placeholder: 'https://www.zentao.net',
+ help: -> { s_('ZentaoIntegration|Base URL of the ZenTao instance.') },
+ required: true
+
+ field :api_url,
+ title: -> { s_('ZentaoIntegration|ZenTao API URL (optional)') },
+ help: -> { s_('ZentaoIntegration|If different from Web URL.') }
+
+ field :api_token,
+ type: 'password',
+ title: -> { s_('ZentaoIntegration|ZenTao API token') },
+ non_empty_password_title: -> { s_('ZentaoIntegration|Enter new ZenTao API token') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') },
+ required: true
+
+ field :zentao_product_xid,
+ title: -> { s_('ZentaoIntegration|ZenTao Product ID') },
+ required: true
validates :url, public_url: true, presence: true, if: :activated?
validates :api_url, public_url: true, allow_blank: true
@@ -47,39 +68,6 @@ module Integrations
%w()
end
- def fields
- [
- {
- type: 'text',
- name: 'url',
- title: s_('ZentaoIntegration|ZenTao Web URL'),
- placeholder: 'https://www.zentao.net',
- help: s_('ZentaoIntegration|Base URL of the ZenTao instance.'),
- required: true
- },
- {
- type: 'text',
- name: 'api_url',
- title: s_('ZentaoIntegration|ZenTao API URL (optional)'),
- help: s_('ZentaoIntegration|If different from Web URL.')
- },
- {
- type: 'password',
- name: 'api_token',
- title: s_('ZentaoIntegration|ZenTao API token'),
- non_empty_password_title: s_('ZentaoIntegration|Enter new ZenTao API token'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'),
- required: true
- },
- {
- type: 'text',
- name: 'zentao_product_xid',
- title: s_('ZentaoIntegration|ZenTao Product ID'),
- required: true
- }
- ]
- end
-
private
def client