diff options
Diffstat (limited to 'app/models/project_services')
27 files changed, 0 insertions, 2502 deletions
diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb deleted file mode 100644 index e6e16058d41..00000000000 --- a/app/models/project_services/asana_service.rb +++ /dev/null @@ -1,127 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# -require 'asana' - -class AsanaService < Service - prop_accessor :api_key, :restrict_to_branch - validates :api_key, presence: true, if: :activated? - - def title - 'Asana' - end - - def description - 'Asana - Teamwork without email' - end - - def help - 'This service adds commit messages as comments to Asana tasks. -Once enabled, commit messages are checked for Asana task URLs -(for example, `https://app.asana.com/0/123456/987654`) or task IDs -starting with # (for example, `#987654`). Every task ID found will -get the commit comment added to it. - -You can also close a task with a message containing: `fix #123456`. - -You can find your Api Keys here: -http://developer.asana.com/documentation/#api_keys' - end - - def to_param - 'asana' - end - - def fields - [ - { - type: 'text', - name: 'api_key', - placeholder: 'User API token. User must have access to task, -all comments will be attributed to this user.' - }, - { - type: 'text', - name: 'restrict_to_branch', - placeholder: 'Comma-separated list of branches which will be -automatically inspected. Leave blank to include all branches.' - } - ] - end - - def supported_events - %w(push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - Asana.configure do |client| - client.api_key = api_key - end - - user = data[:user_name] - branch = Gitlab::Git.ref_name(data[:ref]) - - branch_restriction = restrict_to_branch.to_s - - # check the branch restriction is poplulated and branch is not included - if branch_restriction.length > 0 && branch_restriction.index(branch).nil? - return - end - - project_name = project.name_with_namespace - push_msg = user + ' pushed to branch ' + branch + ' of ' + project_name - - data[:commits].each do |commit| - check_commit(' ( ' + commit[:url] + ' ): ' + commit[:message], push_msg) - end - end - - def check_commit(message, push_msg) - task_list = [] - close_list = [] - - message.split("\n").each do |line| - # look for a task ID or a full Asana url - task_list.concat(line.scan(/#(\d+)/)) - task_list.concat(line.scan(/https:\/\/app\.asana\.com\/\d+\/\d+\/(\d+)/)) - # look for a word starting with 'fix' followed by a task ID - close_list.concat(line.scan(/(fix\w*)\W*#(\d+)/i)) - end - - # post commit to every taskid found - task_list.each do |taskid| - task = Asana::Task.find(taskid[0]) - - if task - task.create_story(text: push_msg + ' ' + message) - end - end - - # close all tasks that had 'fix(ed/es/ing) #:id' in them - close_list.each do |taskid| - task = Asana::Task.find(taskid.last) - - if task - task.modify(completed: true) - end - end - end -end diff --git a/app/models/project_services/assembla_service.rb b/app/models/project_services/assembla_service.rb deleted file mode 100644 index fb7e0c0fb0d..00000000000 --- a/app/models/project_services/assembla_service.rb +++ /dev/null @@ -1,56 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -class AssemblaService < Service - include HTTParty - - prop_accessor :token, :subdomain - validates :token, presence: true, if: :activated? - - def title - 'Assembla' - end - - def description - 'Project Management Software (Source Commits Endpoint)' - end - - def to_param - 'assembla' - end - - def fields - [ - { type: 'text', name: 'token', placeholder: '' }, - { type: 'text', name: 'subdomain', placeholder: '' } - ] - end - - def supported_events - %w(push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - url = "https://atlas.assembla.com/spaces/#{subdomain}/github_tool?secret_key=#{token}" - AssemblaService.post(url, body: { payload: data }.to_json, headers: { 'Content-Type' => 'application/json' }) - end -end diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb deleted file mode 100644 index d8aedbd2ab4..00000000000 --- a/app/models/project_services/bamboo_service.rb +++ /dev/null @@ -1,137 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -class BambooService < CiService - include HTTParty - - prop_accessor :bamboo_url, :build_key, :username, :password - - validates :bamboo_url, - presence: true, - format: { with: /\A#{URI.regexp}\z/ }, - if: :activated? - validates :build_key, presence: true, if: :activated? - validates :username, - presence: true, - if: ->(service) { service.password? }, - if: :activated? - validates :password, - presence: true, - if: ->(service) { service.username? }, - if: :activated? - - attr_accessor :response - - after_save :compose_service_hook, if: :activated? - - def compose_service_hook - hook = service_hook || build_service_hook - hook.save - end - - def title - 'Atlassian Bamboo CI' - end - - def description - 'A continuous integration and build server' - end - - def help - 'You must set up automatic revision labeling and a repository trigger in Bamboo.' - end - - def to_param - 'bamboo' - end - - def fields - [ - { type: 'text', name: 'bamboo_url', - placeholder: 'Bamboo root URL like https://bamboo.example.com' }, - { type: 'text', name: 'build_key', - placeholder: 'Bamboo build plan key like KEY' }, - { type: 'text', name: 'username', - placeholder: 'A user with API access, if applicable' }, - { type: 'password', name: 'password' }, - ] - end - - def supported_events - %w(push) - end - - def build_info(sha) - url = URI.parse("#{bamboo_url}/rest/api/latest/result?label=#{sha}") - - if username.blank? && password.blank? - @response = HTTParty.get(parsed_url.to_s, verify: false) - else - get_url = "#{url}&os_authType=basic" - auth = { - username: username, - password: password, - } - @response = HTTParty.get(get_url, verify: false, basic_auth: auth) - end - end - - def build_page(sha, ref) - build_info(sha) if @response.nil? || !@response.code - - if @response.code != 200 || @response['results']['results']['size'] == '0' - # If actual build link can't be determined, send user to build summary page. - "#{bamboo_url}/browse/#{build_key}" - else - # If actual build link is available, go to build result page. - result_key = @response['results']['results']['result']['planResultKey']['key'] - "#{bamboo_url}/browse/#{result_key}" - end - end - - def commit_status(sha, ref) - build_info(sha) if @response.nil? || !@response.code - return :error unless @response.code == 200 || @response.code == 404 - - status = if @response.code == 404 || @response['results']['results']['size'] == '0' - 'Pending' - else - @response['results']['results']['result']['buildState'] - end - - if status.include?('Success') - 'success' - elsif status.include?('Failed') - 'failed' - elsif status.include?('Pending') - 'pending' - else - :error - end - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - # Bamboo requires a GET and does not take any data. - self.class.get("#{bamboo_url}/updateAndBuild.action?buildKey=#{build_key}", - verify: false) - end -end diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb deleted file mode 100644 index a714bc82246..00000000000 --- a/app/models/project_services/buildkite_service.rb +++ /dev/null @@ -1,135 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -require "addressable/uri" - -class BuildkiteService < CiService - ENDPOINT = "https://buildkite.com" - - prop_accessor :project_url, :token - - validates :project_url, presence: true, if: :activated? - validates :token, presence: true, if: :activated? - - after_save :compose_service_hook, if: :activated? - - def webhook_url - "#{buildkite_endpoint('webhook')}/deliver/#{webhook_token}" - end - - def compose_service_hook - hook = service_hook || build_service_hook - hook.url = webhook_url - hook.save - end - - def supported_events - %w(push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - service_hook.execute(data) - end - - def commit_status(sha, ref) - response = HTTParty.get(commit_status_path(sha), verify: false) - - if response.code == 200 && response['status'] - response['status'] - else - :error - end - end - - def commit_status_path(sha) - "#{buildkite_endpoint('gitlab')}/status/#{status_token}.json?commit=#{sha}" - end - - def build_page(sha, ref) - "#{project_url}/builds?commit=#{sha}" - end - - def builds_path - "#{project_url}/builds?branch=#{project.default_branch}" - end - - def status_img_path - "#{buildkite_endpoint('badge')}/#{status_token}.svg" - end - - def title - 'Buildkite' - end - - def description - 'Continuous integration and deployments' - end - - def to_param - 'buildkite' - end - - def fields - [ - { type: 'text', - name: 'token', - placeholder: 'Buildkite project GitLab token' }, - - { type: 'text', - name: 'project_url', - placeholder: "#{ENDPOINT}/example/project" } - ] - end - - private - - def webhook_token - token_parts.first - end - - def status_token - token_parts.second - end - - def token_parts - if token.present? - token.split(':') - else - [] - end - end - - def buildkite_endpoint(subdomain = nil) - if subdomain.present? - uri = Addressable::URI.parse(ENDPOINT) - new_endpoint = "#{uri.scheme || 'http'}://#{subdomain}.#{uri.host}" - - if uri.port.present? - "#{new_endpoint}:#{uri.port}" - else - new_endpoint - end - else - ENDPOINT - end - end -end diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb deleted file mode 100644 index e591afdda64..00000000000 --- a/app/models/project_services/campfire_service.rb +++ /dev/null @@ -1,86 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -class CampfireService < Service - prop_accessor :token, :subdomain, :room - validates :token, presence: true, if: :activated? - - def title - 'Campfire' - end - - def description - 'Simple web-based real-time group chat' - end - - def to_param - 'campfire' - end - - def fields - [ - { type: 'text', name: 'token', placeholder: '' }, - { type: 'text', name: 'subdomain', placeholder: '' }, - { type: 'text', name: 'room', placeholder: '' } - ] - end - - def supported_events - %w(push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - room = gate.find_room_by_name(self.room) - return true unless room - - message = build_message(data) - - room.speak(message) - end - - private - - def gate - @gate ||= Tinder::Campfire.new(subdomain, token: token) - end - - def build_message(push) - ref = Gitlab::Git.ref_name(push[:ref]) - before = push[:before] - after = push[:after] - - message = "" - message << "[#{project.name_with_namespace}] " - message << "#{push[:user_name]} " - - if Gitlab::Git.blank_ref?(before) - message << "pushed new branch #{ref} \n" - elsif Gitlab::Git.blank_ref?(after) - message << "removed branch #{ref} \n" - else - message << "pushed #{push[:total_commits_count]} commits to #{ref}. " - message << "#{project.web_url}/compare/#{before}...#{after}" - end - - message - end -end diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb deleted file mode 100644 index 1a36e439245..00000000000 --- a/app/models/project_services/ci_service.rb +++ /dev/null @@ -1,57 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# - -# Base class for CI services -# List methods you need to implement to get your CI service -# working with GitLab Merge Requests -class CiService < Service - def category - :ci - end - - def supported_events - %w(push) - end - - # Return complete url to build page - # - # Ex. - # http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c - # - def build_page(sha, ref) - # implement inside child - end - - # Return string with build status or :error symbol - # - # Allowed states: 'success', 'failed', 'running', 'pending' - # - # - # Ex. - # @service.commit_status('13be4ac') - # # => 'success' - # - # @service.commit_status('2abe4ac') - # # => 'running' - # - # - def commit_status(sha, ref) - # implement inside child - end -end diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb deleted file mode 100644 index 8d25f627870..00000000000 --- a/app/models/project_services/custom_issue_tracker_service.rb +++ /dev/null @@ -1,57 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# - -class CustomIssueTrackerService < IssueTrackerService - - prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url - - def title - if self.properties && self.properties['title'].present? - self.properties['title'] - else - 'Custom Issue Tracker' - end - end - - def description - if self.properties && self.properties['description'].present? - self.properties['description'] - else - 'Custom issue tracker' - end - end - - def to_param - 'custom_issue_tracker' - end - - def fields - [ - { type: 'text', name: 'title', placeholder: title }, - { type: 'text', name: 'description', placeholder: description }, - { type: 'text', name: 'project_url', placeholder: 'Project url' }, - { type: 'text', name: 'issues_url', placeholder: 'Issue url' }, - { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' } - ] - end - - def initialize_properties - self.properties = {} if properties.nil? - end -end diff --git a/app/models/project_services/emails_on_push_service.rb b/app/models/project_services/emails_on_push_service.rb deleted file mode 100644 index 6f6e5950aab..00000000000 --- a/app/models/project_services/emails_on_push_service.rb +++ /dev/null @@ -1,72 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# - -class EmailsOnPushService < Service - prop_accessor :send_from_committer_email - prop_accessor :disable_diffs - prop_accessor :recipients - validates :recipients, presence: true, if: :activated? - - def title - 'Emails on push' - end - - def description - 'Email the commits and diff of each push to a list of recipients.' - end - - def to_param - 'emails_on_push' - end - - def supported_events - %w(push tag_push) - end - - def execute(push_data) - return unless supported_events.include?(push_data[:object_kind]) - - EmailsOnPushWorker.perform_async( - project_id, - recipients, - push_data, - send_from_committer_email: send_from_committer_email?, - disable_diffs: disable_diffs? - ) - end - - def send_from_committer_email? - self.send_from_committer_email == "1" - end - - def disable_diffs? - self.disable_diffs == "1" - end - - def fields - domains = Notify.allowed_email_domains.map { |domain| "user@#{domain}" }.join(", ") - [ - { type: 'checkbox', name: 'send_from_committer_email', title: "Send from committer", - help: "Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. #{domains})." }, - { type: 'checkbox', name: 'disable_diffs', title: "Disable code diffs", - help: "Don't include possibly sensitive code diffs in notification body." }, - { type: 'textarea', name: 'recipients', placeholder: 'Emails separated by whitespace' }, - ] - end -end diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb deleted file mode 100644 index a199d0e86f2..00000000000 --- a/app/models/project_services/external_wiki_service.rb +++ /dev/null @@ -1,48 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# - -class ExternalWikiService < Service - include HTTParty - - prop_accessor :external_wiki_url - validates :external_wiki_url, - presence: true, - format: { with: /\A#{URI.regexp}\z/ }, - if: :activated? - - def title - 'External Wiki' - end - - def description - 'Replaces the link to the internal wiki with a link to an external wiki.' - end - - def to_param - 'external_wiki' - end - - def fields - [ - { type: 'text', name: 'external_wiki_url', placeholder: 'The URL of the external Wiki' }, - ] - end - - def execute(_data) - @response = HTTParty.get(properties['external_wiki_url'], verify: true) rescue nil - if @response !=200 - nil - end - end -end diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb deleted file mode 100644 index 99e361dd6ed..00000000000 --- a/app/models/project_services/flowdock_service.rb +++ /dev/null @@ -1,62 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# - -require "flowdock-git-hook" - -class FlowdockService < Service - prop_accessor :token - validates :token, presence: true, if: :activated? - - def title - 'Flowdock' - end - - def description - 'Flowdock is a collaboration web app for technical teams.' - end - - def to_param - 'flowdock' - end - - def fields - [ - { type: 'text', name: 'token', placeholder: '' } - ] - end - - def 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.path_to_repo, - repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}", - commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s", - diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s", - ) - end -end diff --git a/app/models/project_services/gemnasium_service.rb b/app/models/project_services/gemnasium_service.rb deleted file mode 100644 index 4e75bdfc953..00000000000 --- a/app/models/project_services/gemnasium_service.rb +++ /dev/null @@ -1,61 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# - -require "gemnasium/gitlab_service" - -class GemnasiumService < Service - prop_accessor :token, :api_key - validates :token, :api_key, presence: true, if: :activated? - - def title - 'Gemnasium' - end - - def description - 'Gemnasium monitors your project dependencies and alerts you about updates and security vulnerabilities.' - end - - def to_param - 'gemnasium' - end - - def fields - [ - { type: 'text', name: 'api_key', placeholder: 'Your personal API KEY on gemnasium.com ' }, - { type: 'text', name: 'token', placeholder: 'The project\'s slug on gemnasium.com' } - ] - end - - def supported_events - %w(push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - Gemnasium::GitlabService.execute( - ref: data[:ref], - before: data[:before], - after: data[:after], - token: token, - api_key: api_key, - repo: project.repository.path_to_repo - ) - end -end diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb deleted file mode 100644 index 0f9838a575d..00000000000 --- a/app/models/project_services/gitlab_ci_service.rb +++ /dev/null @@ -1,128 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# - -class GitlabCiService < CiService - API_PREFIX = "api/v1" - - prop_accessor :project_url, :token - validates :project_url, presence: true, if: :activated? - validates :token, presence: true, if: :activated? - - after_save :compose_service_hook, if: :activated? - - def compose_service_hook - hook = service_hook || build_service_hook - hook.url = [project_url, "/build", "?token=#{token}"].join("") - hook.save - end - - def supported_events - %w(push tag_push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - service_hook.execute(data) - end - - def commit_status_path(sha, ref) - project_url + "/refs/#{ref}/commits/#{sha}/status.json?token=#{token}" - end - - def get_ci_build(sha, ref) - @ci_builds ||= {} - @ci_builds[sha] ||= HTTParty.get(commit_status_path(sha, ref), verify: false) - end - - def commit_status(sha, ref) - response = get_ci_build(sha, ref) - - if response.code == 200 and response["status"] - response["status"] - else - :error - end - end - - def fork_registration(new_project, private_token) - params = { - id: new_project.id, - name_with_namespace: new_project.name_with_namespace, - web_url: new_project.web_url, - default_branch: new_project.default_branch, - ssh_url_to_repo: new_project.ssh_url_to_repo - } - - HTTParty.post( - fork_registration_path, - body: { - project_id: project.id, - project_token: token, - private_token: private_token, - data: params }, - verify: false - ) - end - - def commit_coverage(sha, ref) - response = get_ci_build(sha, ref) - - if response.code == 200 and response["coverage"] - response["coverage"] - end - end - - def build_page(sha, ref) - project_url + "/refs/#{ref}/commits/#{sha}" - end - - def builds_path - project_url + "?ref=" + project.default_branch - end - - def status_img_path - project_url + "/status.png?ref=" + project.default_branch - end - - def title - 'GitLab CI' - end - - def description - 'Continuous integration server from GitLab' - end - - def to_param - 'gitlab_ci' - end - - def fields - [ - { type: 'text', name: 'token', placeholder: 'GitLab CI project specific token' }, - { type: 'text', name: 'project_url', placeholder: 'http://ci.gitlabhq.com/projects/3' } - ] - end - - private - - def fork_registration_path - project_url.sub(/projects\/\d*/, "#{API_PREFIX}/forks") - end -end diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb deleted file mode 100644 index 5f0553f3b0b..00000000000 --- a/app/models/project_services/gitlab_issue_tracker_service.rb +++ /dev/null @@ -1,62 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -class GitlabIssueTrackerService < IssueTrackerService - include Rails.application.routes.url_helpers - - default_url_options[:host] = Gitlab.config.gitlab.host - default_url_options[:protocol] = Gitlab.config.gitlab.protocol - default_url_options[:port] = Gitlab.config.gitlab.port unless Gitlab.config.gitlab_on_standard_port? - default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root - - prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url - - def default? - true - end - - def to_param - 'gitlab' - end - - def project_url - namespace_project_issues_url(project.namespace, project) - end - - def new_issue_url - new_namespace_project_issue_url(namespace_id: project.namespace, project_id: project) - end - - def issue_url(iid) - namespace_project_issue_url(namespace_id: project.namespace, project_id: project, id: iid) - end - - def project_path - namespace_project_issues_path(project.namespace, project) - end - - def new_issue_path - new_namespace_project_issue_path(namespace_id: project.namespace, project_id: project) - end - - def issue_path(iid) - namespace_project_issue_path(namespace_id: project.namespace, project_id: project, id: iid) - end -end diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb deleted file mode 100644 index d264a56ebdf..00000000000 --- a/app/models/project_services/hipchat_service.rb +++ /dev/null @@ -1,238 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# - -class HipchatService < Service - MAX_COMMITS = 3 - - prop_accessor :token, :room, :server - validates :token, presence: true, if: :activated? - - def title - 'HipChat' - end - - def description - 'Private group chat and IM' - end - - def to_param - 'hipchat' - end - - def fields - [ - { type: 'text', name: 'token', placeholder: 'Room token' }, - { type: 'text', name: 'room', placeholder: 'Room name or ID' }, - { type: 'text', name: 'server', - placeholder: 'Leave blank for default. https://hipchat.example.com' } - ] - end - - def supported_events - %w(push issue merge_request note tag_push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - gate[room].send('GitLab', create_message(data)) - end - - private - - def gate - options = { api_version: 'v2' } - options[:server_url] = server unless server.blank? - @gate ||= HipChat::Client.new(token, options) - end - - def create_message(data) - object_kind = data[:object_kind] - - message = \ - case object_kind - when "push", "tag_push" - create_push_message(data) - when "issue" - create_issue_message(data) unless is_update?(data) - when "merge_request" - create_merge_request_message(data) unless is_update?(data) - when "note" - create_note_message(data) - end - end - - def create_push_message(push) - ref_type = Gitlab::Git.tag_ref?(push[:ref]) ? 'tag' : 'branch' - ref = Gitlab::Git.ref_name(push[:ref]) - - before = push[:before] - after = push[:after] - - message = "" - message << "#{push[:user_name]} " - if Gitlab::Git.blank_ref?(before) - message << "pushed new #{ref_type} <a href=\""\ - "#{project_url}/commits/#{URI.escape(ref)}\">#{ref}</a>"\ - " to #{project_link}\n" - elsif Gitlab::Git.blank_ref?(after) - message << "removed #{ref_type} <b>#{ref}</b> from <a href=\"#{project.web_url}\">#{project_name}</a> \n" - else - message << "pushed to #{ref_type} <a href=\""\ - "#{project.web_url}/commits/#{URI.escape(ref)}\">#{ref}</a> " - message << "of <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> " - message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)" - - push[:commits].take(MAX_COMMITS).each do |commit| - message << "<br /> - #{commit[:message].lines.first} (<a href=\"#{commit[:url]}\">#{commit[:id][0..5]}</a>)" - end - - if push[:commits].count > MAX_COMMITS - message << "<br />... #{push[:commits].count - MAX_COMMITS} more commits" - end - end - - message - end - - def format_body(body) - if body - body = body.truncate(200, separator: ' ', omission: '...') - end - - "<pre>#{body}</pre>" - end - - def create_issue_message(data) - user_name = data[:user][:name] - - obj_attr = data[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - title = obj_attr[:title] - state = obj_attr[:state] - issue_iid = obj_attr[:iid] - issue_url = obj_attr[:url] - description = obj_attr[:description] - - issue_link = "<a href=\"#{issue_url}\">issue ##{issue_iid}</a>" - message = "#{user_name} #{state} #{issue_link} in #{project_link}: <b>#{title}</b>" - - if description - description = format_body(description) - message << description - end - - message - end - - def create_merge_request_message(data) - user_name = data[:user][:name] - - obj_attr = data[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - merge_request_id = obj_attr[:iid] - source_branch = obj_attr[:source_branch] - target_branch = obj_attr[:target_branch] - state = obj_attr[:state] - description = obj_attr[:description] - title = obj_attr[:title] - - merge_request_url = "#{project_url}/merge_requests/#{merge_request_id}" - merge_request_link = "<a href=\"#{merge_request_url}\">merge request ##{merge_request_id}</a>" - message = "#{user_name} #{state} #{merge_request_link} in " \ - "#{project_link}: <b>#{title}</b>" - - if description - description = format_body(description) - message << description - end - - message - end - - def format_title(title) - "<b>" + title.lines.first.chomp + "</b>" - end - - def create_note_message(data) - data = HashWithIndifferentAccess.new(data) - user_name = data[:user][:name] - - repo_attr = HashWithIndifferentAccess.new(data[:repository]) - - obj_attr = HashWithIndifferentAccess.new(data[:object_attributes]) - note = obj_attr[:note] - note_url = obj_attr[:url] - noteable_type = obj_attr[:noteable_type] - - case noteable_type - when "Commit" - commit_attr = HashWithIndifferentAccess.new(data[:commit]) - subject_desc = commit_attr[:id] - subject_desc = Commit.truncate_sha(subject_desc) - subject_type = "commit" - title = format_title(commit_attr[:message]) - when "Issue" - subj_attr = HashWithIndifferentAccess.new(data[:issue]) - subject_id = subj_attr[:iid] - subject_desc = "##{subject_id}" - subject_type = "issue" - title = format_title(subj_attr[:title]) - when "MergeRequest" - subj_attr = HashWithIndifferentAccess.new(data[:merge_request]) - subject_id = subj_attr[:iid] - subject_desc = "##{subject_id}" - subject_type = "merge request" - title = format_title(subj_attr[:title]) - when "Snippet" - subj_attr = HashWithIndifferentAccess.new(data[:snippet]) - subject_id = subj_attr[:id] - subject_desc = "##{subject_id}" - subject_type = "snippet" - title = format_title(subj_attr[:title]) - end - - subject_html = "<a href=\"#{note_url}\">#{subject_type} #{subject_desc}</a>" - message = "#{user_name} commented on #{subject_html} in #{project_link}: " - message << title - - if note - note = format_body(note) - message << note - end - - message - end - - def project_name - project.name_with_namespace.gsub(/\s/, '') - end - - def project_url - project.web_url - end - - def project_link - "<a href=\"#{project_url}\">#{project_name}</a>" - end - - def is_update?(data) - data[:object_attributes][:action] == 'update' - end -end diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb deleted file mode 100644 index e9e1e276e7d..00000000000 --- a/app/models/project_services/irker_service.rb +++ /dev/null @@ -1,163 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# - -require 'uri' - -class IrkerService < Service - prop_accessor :colorize_messages, :recipients, :channels - validates :recipients, presence: true, if: :activated? - validate :check_recipients_count, if: :activated? - - before_validation :get_channels - after_initialize :initialize_settings - - # Writer for RSpec tests - attr_writer :settings - - def initialize_settings - # See the documentation (doc/project_services/irker.md) for possible values - # here - @settings ||= { - server_ip: 'localhost', - server_port: 6659, - max_channels: 3, - default_irc_uri: nil - } - end - - def title - 'Irker (IRC gateway)' - end - - def description - 'Send IRC messages, on update, to a list of recipients through an Irker '\ - 'gateway.' - end - - def help - msg = '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.' - - unless @settings[:default_irc].nil? - msg += ' Note that a default IRC URI is provided by this service\'s '\ - "administrator: #{default_irc}. You can thus just give a channel name." - end - msg - end - - def to_param - 'irker' - end - - def 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 fields - [ - { type: 'textarea', name: 'recipients', - placeholder: 'Recipients/channels separated by whitespaces' }, - { type: 'checkbox', name: 'colorize_messages' }, - ] - end - - private - - def check_recipients_count - return true if recipients.nil? || recipients.empty? - - if recipients.split(/\s+/).count > max_chans - errors.add(:recipients, "are limited to #{max_chans}") - end - end - - def max_chans - @settings[:max_channels] - end - - 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 default_irc_uri, recipient - end - channels.reject! &:nil? - end - - def default_irc_uri - default_irc = @settings[:default_irc_uri] - if !(default_irc.nil? || default_irc[-1] == '/') - default_irc += '/' - end - default_irc - end - - def format_channel(default_irc, recipient) - cnt = 0 - url = nil - - # Try to parse the chan as a full URI - begin - uri = URI.parse(recipient) - raise URI::InvalidURIError if uri.scheme.nil? && cnt == 0 - rescue URI::InvalidURIError - unless default_irc.nil? - cnt += 1 - recipient = "#{default_irc}#{recipient}" - retry if cnt == 1 - end - else - url = consider_uri uri - end - url - end - - def consider_uri(uri) - # Authorize both irc://domain.com/#chan and irc://domain.com/chan - if uri.is_a?(URI) && uri.scheme[/^ircs?\z/] && !uri.path.nil? - # Do not authorize irc://domain.com/ - if uri.fragment.nil? && uri.path.length > 1 - uri.to_s - else - # Authorize irc://domain.com/smthg#chan - # The irker daemon will deal with it by concatenating smthg and - # chan, thus sending messages on #smthgchan - uri.to_s - end - end - end -end diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb deleted file mode 100644 index c8ab9d63b74..00000000000 --- a/app/models/project_services/issue_tracker_service.rb +++ /dev/null @@ -1,125 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -class IssueTrackerService < Service - - validates :project_url, :issues_url, :new_issue_url, presence: true, if: :activated? - - def category - :issue_tracker - end - - def default? - false - end - - def issue_url(iid) - self.issues_url.gsub(':id', iid.to_s) - end - - def project_path - project_url - end - - def new_issue_path - new_issue_url - end - - def issue_path(iid) - issue_url(iid) - end - - def fields - [ - { type: 'text', name: 'description', placeholder: description }, - { type: 'text', name: 'project_url', placeholder: 'Project url' }, - { type: 'text', name: 'issues_url', placeholder: 'Issue url' }, - { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url' } - ] - end - - def initialize_properties - if properties.nil? - if enabled_in_gitlab_config - self.properties = { - title: issues_tracker['title'], - project_url: add_issues_tracker_id(issues_tracker['project_url']), - issues_url: add_issues_tracker_id(issues_tracker['issues_url']), - new_issue_url: add_issues_tracker_id(issues_tracker['new_issue_url']) - } - else - self.properties = {} - end - end - end - - def supported_events - %w(push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - message = "#{self.type} was unable to reach #{self.project_url}. Check the url and try again." - result = false - - begin - url = URI.parse(self.project_url) - - if url.host && url.port - http = Net::HTTP.start(url.host, url.port, { open_timeout: 5, read_timeout: 5 }) - response = http.head("/") - - if response - message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}" - result = true - end - end - rescue Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED => error - message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{error.message}" - end - Rails.logger.info(message) - result - end - - private - - def enabled_in_gitlab_config - Gitlab.config.issues_tracker && - Gitlab.config.issues_tracker.values.any? && - issues_tracker - end - - def issues_tracker - Gitlab.config.issues_tracker[to_param] - end - - def add_issues_tracker_id(url) - if self.project - id = self.project.issues_tracker_id - - if id - url = url.gsub(":issues_tracker_id", id) - end - end - - url - end -end diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb deleted file mode 100644 index fcd9dc2f336..00000000000 --- a/app/models/project_services/jira_service.rb +++ /dev/null @@ -1,58 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -class JiraService < IssueTrackerService - include Rails.application.routes.url_helpers - - prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url - - def help - issue_tracker_link = help_page_path("integration", "external-issue-tracker") - - line1 = "Setting `project_url`, `issues_url` and `new_issue_url` will "\ - "allow a user to easily navigate to the Jira issue tracker. "\ - "See the [integration doc](#{issue_tracker_link}) for details." - - line2 = 'Support for referencing commits and automatic closing of Jira issues directly ' \ - 'from GitLab is [available in GitLab EE.](http://doc.gitlab.com/ee/integration/jira.html)' - - [line1, line2].join("\n\n") - end - - def title - if self.properties && self.properties['title'].present? - self.properties['title'] - else - 'JIRA' - end - end - - def description - if self.properties && self.properties['description'].present? - self.properties['description'] - else - 'Jira issue tracker' - end - end - - def to_param - 'jira' - end -end diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb deleted file mode 100644 index ade9ee97873..00000000000 --- a/app/models/project_services/pivotaltracker_service.rb +++ /dev/null @@ -1,72 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -class PivotaltrackerService < Service - include HTTParty - - prop_accessor :token - validates :token, presence: true, if: :activated? - - def title - 'PivotalTracker' - end - - def description - 'Project Management Software (Source Commits Endpoint)' - end - - def to_param - 'pivotaltracker' - end - - def fields - [ - { type: 'text', name: 'token', placeholder: '' } - ] - end - - def supported_events - %w(push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - url = 'https://www.pivotaltracker.com/services/v5/source_commits' - data[:commits].each do |commit| - message = { - 'source_commit' => { - 'commit_id' => commit[:id], - 'author' => commit[:author][:name], - 'url' => commit[:url], - 'message' => commit[:message] - } - } - PivotaltrackerService.post( - url, - body: message.to_json, - headers: { - 'Content-Type' => 'application/json', - 'X-TrackerToken' => token - } - ) - end - end -end diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb deleted file mode 100644 index 53edf522e9a..00000000000 --- a/app/models/project_services/pushover_service.rb +++ /dev/null @@ -1,125 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -class PushoverService < Service - include HTTParty - 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? - - def title - 'Pushover' - end - - def description - 'Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop.' - end - - def to_param - 'pushover' - end - - def fields - [ - { type: 'text', name: 'api_key', placeholder: 'Your application key' }, - { type: 'text', name: 'user_key', placeholder: 'Your user key' }, - { type: 'text', name: 'device', placeholder: 'Leave blank for all active devices' }, - { type: 'select', name: 'priority', choices: - [ - ['Lowest Priority', -2], - ['Low Priority', -1], - ['Normal Priority', 0], - ['High Priority', 1] - ], - default_choice: 0 - }, - { type: 'select', name: 'sound', choices: - [ - ['Device default sound', nil], - ['Pushover (default)', 'pushover'], - ['Bike', 'bike'], - ['Bugle', 'bugle'], - ['Cash Register', 'cashregister'], - ['Classical', 'classical'], - ['Cosmic', 'cosmic'], - ['Falling', 'falling'], - ['Gamelan', 'gamelan'], - ['Incoming', 'incoming'], - ['Intermission', 'intermission'], - ['Magic', 'magic'], - ['Mechanical', 'mechanical'], - ['Piano Bar', 'pianobar'], - ['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 supported_events - %w(push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - ref = Gitlab::Git.ref_name(data[:ref]) - before = data[:before] - after = data[:after] - - if Gitlab::Git.blank_ref?(before) - message = "#{data[:user_name]} pushed new branch \"#{ref}\"." - elsif Gitlab::Git.blank_ref?(after) - message = "#{data[:user_name]} deleted branch \"#{ref}\"." - else - message = "#{data[:user_name]} push to branch \"#{ref}\"." - end - - if data[:total_commits_count] > 0 - message << "\nTotal commits count: #{data[:total_commits_count]}" - end - - pushover_data = { - token: api_key, - user: user_key, - device: device, - priority: priority, - title: "#{project.name_with_namespace}", - message: message, - url: data[:repository][:homepage], - url_title: "See project #{project.name_with_namespace}" - } - - # Sound parameter MUST NOT be sent to API if not selected - if sound - pushover_data.merge!(sound: sound) - end - - PushoverService.post('/messages.json', body: pushover_data) - end -end diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb deleted file mode 100644 index dd9ba97ee1f..00000000000 --- a/app/models/project_services/redmine_service.rb +++ /dev/null @@ -1,44 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -class RedmineService < IssueTrackerService - - prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url - - def title - if self.properties && self.properties['title'].present? - self.properties['title'] - else - 'Redmine' - end - end - - def description - if self.properties && self.properties['description'].present? - self.properties['description'] - else - 'Redmine issue tracker' - end - end - - def to_param - 'redmine' - end -end diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb deleted file mode 100644 index 36d9874edd3..00000000000 --- a/app/models/project_services/slack_service.rb +++ /dev/null @@ -1,105 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -class SlackService < Service - prop_accessor :webhook, :username, :channel - validates :webhook, presence: true, if: :activated? - - def title - 'Slack' - end - - def description - 'A team communication tool for the 21st century' - end - - def to_param - 'slack' - end - - def fields - [ - { type: 'text', name: 'webhook', - placeholder: 'https://hooks.slack.com/services/...' }, - { type: 'text', name: 'username', placeholder: 'username' }, - { type: 'text', name: 'channel', placeholder: '#channel' } - ] - end - - def supported_events - %w(push issue merge_request note tag_push) - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - return unless webhook.present? - - object_kind = data[:object_kind] - - data = data.merge( - project_url: project_url, - project_name: project_name - ) - - # WebHook events often have an 'update' event that follows a 'open' or - # 'close' action. Ignore update events for now to prevent duplicate - # messages from arriving. - - message = \ - case object_kind - when "push", "tag_push" - PushMessage.new(data) - when "issue" - IssueMessage.new(data) unless is_update?(data) - when "merge_request" - MergeMessage.new(data) unless is_update?(data) - when "note" - NoteMessage.new(data) - end - - opt = {} - opt[:channel] = channel if channel - opt[:username] = username if username - - if message - notifier = Slack::Notifier.new(webhook, opt) - notifier.ping(message.pretext, attachments: message.attachments) - end - end - - private - - def project_name - project.name_with_namespace.gsub(/\s/, '') - end - - def project_url - project.web_url - end - - def is_update?(data) - data[:object_attributes][:action] == 'update' - end -end - -require "slack_service/issue_message" -require "slack_service/push_message" -require "slack_service/merge_message" -require "slack_service/note_message" diff --git a/app/models/project_services/slack_service/base_message.rb b/app/models/project_services/slack_service/base_message.rb deleted file mode 100644 index aa00d6061a1..00000000000 --- a/app/models/project_services/slack_service/base_message.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'slack-notifier' - -class SlackService - class BaseMessage - def initialize(params) - raise NotImplementedError - end - - def pretext - format(message) - end - - def attachments - raise NotImplementedError - end - - private - - def message - raise NotImplementedError - end - - def format(string) - Slack::Notifier::LinkFormatter.format(string) - end - - def attachment_color - '#345' - end - end -end diff --git a/app/models/project_services/slack_service/issue_message.rb b/app/models/project_services/slack_service/issue_message.rb deleted file mode 100644 index 5af24a80609..00000000000 --- a/app/models/project_services/slack_service/issue_message.rb +++ /dev/null @@ -1,56 +0,0 @@ -class SlackService - class IssueMessage < BaseMessage - attr_reader :user_name - attr_reader :title - attr_reader :project_name - attr_reader :project_url - attr_reader :issue_iid - attr_reader :issue_url - attr_reader :action - attr_reader :state - attr_reader :description - - def initialize(params) - @user_name = params[:user][:name] - @project_name = params[:project_name] - @project_url = params[:project_url] - - obj_attr = params[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - @title = obj_attr[:title] - @issue_iid = obj_attr[:iid] - @issue_url = obj_attr[:url] - @action = obj_attr[:action] - @state = obj_attr[:state] - @description = obj_attr[:description] - end - - def attachments - return [] unless opened_issue? - - description_message - end - - private - - def message - "#{user_name} #{state} #{issue_link} in #{project_link}: *#{title}*" - end - - def opened_issue? - action == "open" - end - - def description_message - [{ text: format(description), color: attachment_color }] - end - - def project_link - "[#{project_name}](#{project_url})" - end - - def issue_link - "[issue ##{issue_iid}](#{issue_url})" - end - end -end diff --git a/app/models/project_services/slack_service/merge_message.rb b/app/models/project_services/slack_service/merge_message.rb deleted file mode 100644 index e792c258f73..00000000000 --- a/app/models/project_services/slack_service/merge_message.rb +++ /dev/null @@ -1,60 +0,0 @@ -class SlackService - class MergeMessage < BaseMessage - attr_reader :user_name - attr_reader :project_name - attr_reader :project_url - attr_reader :merge_request_id - attr_reader :source_branch - attr_reader :target_branch - attr_reader :state - attr_reader :title - - def initialize(params) - @user_name = params[:user][:name] - @project_name = params[:project_name] - @project_url = params[:project_url] - - obj_attr = params[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - @merge_request_id = obj_attr[:iid] - @source_branch = obj_attr[:source_branch] - @target_branch = obj_attr[:target_branch] - @state = obj_attr[:state] - @title = format_title(obj_attr[:title]) - end - - def pretext - format(message) - end - - def attachments - [] - end - - private - - def format_title(title) - '*' + title.lines.first.chomp + '*' - end - - def message - merge_request_message - end - - def project_link - "[#{project_name}](#{project_url})" - end - - def merge_request_message - "#{user_name} #{state} #{merge_request_link} in #{project_link}: #{title}" - end - - def merge_request_link - "[merge request ##{merge_request_id}](#{merge_request_url})" - end - - def merge_request_url - "#{project_url}/merge_requests/#{merge_request_id}" - end - end -end diff --git a/app/models/project_services/slack_service/note_message.rb b/app/models/project_services/slack_service/note_message.rb deleted file mode 100644 index 074478b292d..00000000000 --- a/app/models/project_services/slack_service/note_message.rb +++ /dev/null @@ -1,82 +0,0 @@ -class SlackService - class NoteMessage < BaseMessage - attr_reader :message - attr_reader :user_name - attr_reader :project_name - attr_reader :project_link - attr_reader :note - attr_reader :note_url - attr_reader :title - - def initialize(params) - params = HashWithIndifferentAccess.new(params) - @user_name = params[:user][:name] - @project_name = params[:project_name] - @project_url = params[:project_url] - - obj_attr = params[:object_attributes] - obj_attr = HashWithIndifferentAccess.new(obj_attr) - @note = obj_attr[:note] - @note_url = obj_attr[:url] - noteable_type = obj_attr[:noteable_type] - - case noteable_type - when "Commit" - create_commit_note(HashWithIndifferentAccess.new(params[:commit])) - when "Issue" - create_issue_note(HashWithIndifferentAccess.new(params[:issue])) - when "MergeRequest" - create_merge_note(HashWithIndifferentAccess.new(params[:merge_request])) - when "Snippet" - create_snippet_note(HashWithIndifferentAccess.new(params[:snippet])) - end - end - - def attachments - description_message - end - - private - - def format_title(title) - title.lines.first.chomp - end - - def create_commit_note(commit) - commit_sha = commit[:id] - commit_sha = Commit.truncate_sha(commit_sha) - commit_link = "[commit #{commit_sha}](#{@note_url})" - title = format_title(commit[:message]) - @message = "#{@user_name} commented on #{commit_link} in #{project_link}: *#{title}*" - end - - def create_issue_note(issue) - issue_iid = issue[:iid] - note_link = "[issue ##{issue_iid}](#{@note_url})" - title = format_title(issue[:title]) - @message = "#{@user_name} commented on #{note_link} in #{project_link}: *#{title}*" - end - - def create_merge_note(merge_request) - merge_request_id = merge_request[:iid] - merge_request_link = "[merge request ##{merge_request_id}](#{@note_url})" - title = format_title(merge_request[:title]) - @message = "#{@user_name} commented on #{merge_request_link} in #{project_link}: *#{title}*" - end - - def create_snippet_note(snippet) - snippet_id = snippet[:id] - snippet_link = "[snippet ##{snippet_id}](#{@note_url})" - title = format_title(snippet[:title]) - @message = "#{@user_name} commented on #{snippet_link} in #{project_link}: *#{title}*" - end - - def description_message - [{ text: format(@note), color: attachment_color }] - end - - def project_link - "[#{@project_name}](#{@project_url})" - end - end -end diff --git a/app/models/project_services/slack_service/push_message.rb b/app/models/project_services/slack_service/push_message.rb deleted file mode 100644 index b26f3e9ddce..00000000000 --- a/app/models/project_services/slack_service/push_message.rb +++ /dev/null @@ -1,110 +0,0 @@ -class SlackService - class PushMessage < BaseMessage - attr_reader :after - attr_reader :before - attr_reader :commits - attr_reader :project_name - attr_reader :project_url - attr_reader :ref - attr_reader :ref_type - attr_reader :user_name - - def initialize(params) - @after = params[:after] - @before = params[:before] - @commits = params.fetch(:commits, []) - @project_name = params[:project_name] - @project_url = params[:project_url] - @ref_type = Gitlab::Git.tag_ref?(params[:ref]) ? 'tag' : 'branch' - @ref = Gitlab::Git.ref_name(params[:ref]) - @user_name = params[:user_name] - end - - def pretext - format(message) - end - - def attachments - return [] if new_branch? || removed_branch? - - commit_message_attachments - end - - private - - def message - if new_branch? - new_branch_message - elsif removed_branch? - removed_branch_message - else - push_message - end - end - - def format(string) - Slack::Notifier::LinkFormatter.format(string) - end - - def new_branch_message - "#{user_name} pushed new #{ref_type} #{branch_link} to #{project_link}" - end - - def removed_branch_message - "#{user_name} removed #{ref_type} #{ref} from #{project_link}" - end - - def push_message - "#{user_name} pushed to #{ref_type} #{branch_link} of #{project_link} (#{compare_link})" - end - - def commit_messages - commits.map { |commit| compose_commit_message(commit) }.join("\n") - end - - def commit_message_attachments - [{ text: format(commit_messages), color: attachment_color }] - end - - def compose_commit_message(commit) - author = commit[:author][:name] - id = Commit.truncate_sha(commit[:id]) - message = commit[:message] - url = commit[:url] - - "[#{id}](#{url}): #{message} - #{author}" - end - - def new_branch? - Gitlab::Git.blank_ref?(before) - end - - def removed_branch? - Gitlab::Git.blank_ref?(after) - end - - def branch_url - "#{project_url}/commits/#{ref}" - end - - def compare_url - "#{project_url}/compare/#{before}...#{after}" - end - - def branch_link - "[#{ref}](#{branch_url})" - end - - def project_link - "[#{project_name}](#{project_url})" - end - - def compare_link - "[Compare changes](#{compare_url})" - end - - def attachment_color - '#345' - end - end -end diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb deleted file mode 100644 index 3c002a1634b..00000000000 --- a/app/models/project_services/teamcity_service.rb +++ /dev/null @@ -1,145 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# template :boolean default(FALSE) -# push_events :boolean default(TRUE) -# issues_events :boolean default(TRUE) -# merge_requests_events :boolean default(TRUE) -# tag_push_events :boolean default(TRUE) -# note_events :boolean default(TRUE), not null -# - -class TeamcityService < CiService - include HTTParty - - prop_accessor :teamcity_url, :build_type, :username, :password - - validates :teamcity_url, - presence: true, - format: { with: /\A#{URI.regexp}\z/ }, if: :activated? - validates :build_type, presence: true, if: :activated? - validates :username, - presence: true, - if: ->(service) { service.password? }, if: :activated? - validates :password, - presence: true, - if: ->(service) { service.username? }, if: :activated? - - attr_accessor :response - - after_save :compose_service_hook, if: :activated? - - def compose_service_hook - hook = service_hook || build_service_hook - hook.save - end - - def title - 'JetBrains TeamCity CI' - end - - def description - 'A continuous integration and build server' - end - - def help - 'The build configuration in Teamcity must use the build format '\ - 'number %build.vcs.number% '\ - 'you will also want to configure monitoring of all branches so merge '\ - 'requests build, that setting is in the vsc root advanced settings.' - end - - def to_param - 'teamcity' - end - - def supported_events - %w(push) - end - - def fields - [ - { type: 'text', name: 'teamcity_url', - placeholder: 'TeamCity root URL like https://teamcity.example.com' }, - { type: 'text', name: 'build_type', - placeholder: 'Build configuration ID' }, - { type: 'text', name: 'username', - placeholder: 'A user with permissions to trigger a manual build' }, - { type: 'password', name: 'password' }, - ] - end - - def build_info(sha) - url = URI.parse("#{teamcity_url}/httpAuth/app/rest/builds/"\ - "branch:unspecified:any,number:#{sha}") - auth = { - username: username, - password: password, - } - @response = HTTParty.get("#{url}", verify: false, basic_auth: auth) - end - - def build_page(sha, ref) - build_info(sha) if @response.nil? || !@response.code - - if @response.code != 200 - # If actual build link can't be determined, - # send user to build summary page. - "#{teamcity_url}/viewLog.html?buildTypeId=#{build_type}" - else - # If actual build link is available, go to build result page. - built_id = @response['build']['id'] - "#{teamcity_url}/viewLog.html?buildId=#{built_id}"\ - "&buildTypeId=#{build_type}" - end - end - - def commit_status(sha, ref) - build_info(sha) if @response.nil? || !@response.code - return :error unless @response.code == 200 || @response.code == 404 - - status = if @response.code == 404 - 'Pending' - else - @response['build']['status'] - end - - if status.include?('SUCCESS') - 'success' - elsif status.include?('FAILURE') - 'failed' - elsif status.include?('Pending') - 'pending' - else - :error - end - end - - def execute(data) - return unless supported_events.include?(data[:object_kind]) - - auth = { - username: username, - password: password, - } - - branch = Gitlab::Git.ref_name(data[:ref]) - - self.class.post("#{teamcity_url}/httpAuth/app/rest/buildQueue", - body: "<build branchName=\"#{branch}\">"\ - "<buildType id=\"#{build_type}\"/>"\ - '</build>', - headers: { 'Content-type' => 'application/xml' }, - basic_auth: auth - ) - end -end |