Commit 0ba4dc11 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'jenkins-service' into 'master'

Jenkins service

Show build status on MergeRequest page.
Requires GitLab Hook plugin to be installed in Jenkins
parents 0b259abe 90342c9e
...@@ -161,7 +161,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -161,7 +161,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def ci_status def ci_status
status = @merge_request.source_project.gitlab_ci_service.commit_status(merge_request.last_commit.sha) status = @merge_request.source_project.ci_service.commit_status(merge_request.last_commit.sha)
response = {status: status} response = {status: status}
render json: response render json: response
......
...@@ -32,7 +32,7 @@ module MergeRequestsHelper ...@@ -32,7 +32,7 @@ module MergeRequestsHelper
end end
def ci_build_details_path merge_request def ci_build_details_path merge_request
merge_request.source_project.gitlab_ci_service.build_page(merge_request.last_commit.sha) merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha)
end end
def merge_path_description(merge_request, separator) def merge_path_description(merge_request, separator)
......
...@@ -56,6 +56,9 @@ class Project < ActiveRecord::Base ...@@ -56,6 +56,9 @@ class Project < ActiveRecord::Base
has_one :git_hook, dependent: :destroy has_one :git_hook, dependent: :destroy
has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id' has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id'
# Project services
has_many :services
has_one :gitlab_ci_service, dependent: :destroy has_one :gitlab_ci_service, dependent: :destroy
has_one :campfire_service, dependent: :destroy has_one :campfire_service, dependent: :destroy
has_one :emails_on_push_service, dependent: :destroy has_one :emails_on_push_service, dependent: :destroy
...@@ -66,6 +69,8 @@ class Project < ActiveRecord::Base ...@@ -66,6 +69,8 @@ class Project < ActiveRecord::Base
has_one :gemnasium_service, dependent: :destroy has_one :gemnasium_service, dependent: :destroy
has_one :slack_service, dependent: :destroy has_one :slack_service, dependent: :destroy
has_one :jira_service, dependent: :destroy has_one :jira_service, dependent: :destroy
has_one :jenkins_service, dependent: :destroy
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id" has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
has_one :forked_from_project, through: :forked_project_link has_one :forked_from_project, through: :forked_project_link
# Merge Requests for target project should be removed with it # Merge Requests for target project should be removed with it
...@@ -318,13 +323,21 @@ class Project < ActiveRecord::Base ...@@ -318,13 +323,21 @@ class Project < ActiveRecord::Base
end end
def available_services_names def available_services_names
%w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack jira) %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack jira jenkins)
end end
def gitlab_ci? def gitlab_ci?
gitlab_ci_service && gitlab_ci_service.active gitlab_ci_service && gitlab_ci_service.active
end end
def ci_services
services.select { |service| service.category == :ci }
end
def ci_service
@ci_service ||= services.select(&:activated?).first
end
def jira_tracker? def jira_tracker?
self.issues_tracker == "jira" self.issues_tracker == "jira"
end end
......
# 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
# Return complete url to build page
#
# Ex.
# http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
#
def build_page(sha)
# 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)
# implement inside child
end
end
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
# api_key :string(255) # api_key :string(255)
# #
class GitlabCiService < Service class GitlabCiService < CiService
attr_accessible :project_url attr_accessible :project_url
validates :project_url, presence: true, if: :activated? validates :project_url, presence: true, if: :activated?
......
# == Schema Information
#
# Table name: services
#
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# token :string(255)
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# project_url :string(255)
# subdomain :string(255)
# room :string(255)
# recipients :text
# api_key :string(255)
#
class JenkinsService < CiService
attr_accessible :project_url
validates :project_url, presence: true, if: :activated?
delegate :execute, to: :service_hook, prefix: nil
after_save :compose_service_hook, if: :activated?
def compose_service_hook
hook = service_hook || build_service_hook
jenkins_url = project_url.sub(/job\/.*/, '')
hook.url = jenkins_url + "/gitlab/build_now"
hook.save
end
def title
'Jenkins CI'
end
def description
'An extendable open source continuous integration server'
end
def help
'You must have installed GitLab Hook plugin into Jenkins.'
end
def to_param
'jenkins'
end
def fields
[
{ type: 'text', name: 'project_url', placeholder: 'Jenkins project URL like http://jenkins.example.com/job/my-project/' }
]
end
def build_page sha
project_url + "/scm/bySHA1/#{sha}"
end
def commit_status sha
response = HTTParty.get(build_page(sha), verify: false)
if response.code == 200
if response.include?('alt="Success"')
'success'
elsif response.include?('alt="Failed"')
'failed'
elsif response.include?('alt="In progress"')
'running'
else
'pending'
end
else
:error
end
end
end
...@@ -33,6 +33,10 @@ class Service < ActiveRecord::Base ...@@ -33,6 +33,10 @@ class Service < ActiveRecord::Base
active active
end end
def category
:common
end
def title def title
# implement inside child # implement inside child
end end
...@@ -41,6 +45,10 @@ class Service < ActiveRecord::Base ...@@ -41,6 +45,10 @@ class Service < ActiveRecord::Base
# implement inside child # implement inside child
end end
def help
# implement inside child
end
def to_param def to_param
# implement inside child # implement inside child
end end
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
url_to_automerge_check: "#{automerge_check_project_merge_request_path(@project, @merge_request)}", url_to_automerge_check: "#{automerge_check_project_merge_request_path(@project, @merge_request)}",
check_enable: #{@merge_request.unchecked? ? "true" : "false"}, check_enable: #{@merge_request.unchecked? ? "true" : "false"},
url_to_ci_check: "#{ci_status_project_merge_request_path(@project, @merge_request)}", url_to_ci_check: "#{ci_status_project_merge_request_path(@project, @merge_request)}",
ci_enable: #{@project.gitlab_ci? ? "true" : "false"}, ci_enable: #{@project.ci_service ? "true" : "false"},
current_status: "#{@merge_request.merge_status_name}", current_status: "#{@merge_request.merge_status_name}",
action: "#{controller.action_name}" action: "#{controller.action_name}"
}); });
.panel.mr-state-widget.panel-default .panel.mr-state-widget.panel-default
- if @merge_request.source_project.gitlab_ci? && @commits.any? - if @merge_request.source_project.ci_service && @commits.any?
.panel-heading .panel-heading
= render "projects/merge_requests/show/mr_ci" = render "projects/merge_requests/show/mr_ci"
.panel-body .panel-body
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
%li= msg %li= msg
- if @service.help.present?
.bs-callout
= @service.help
.form-group .form-group
= f.label :active, "Active", class: "control-label" = f.label :active, "Active", class: "control-label"
.col-sm-10 .col-sm-10
......
...@@ -189,9 +189,9 @@ ActiveRecord::Schema.define(version: 20140513095908) do ...@@ -189,9 +189,9 @@ ActiveRecord::Schema.define(version: 20140513095908) do
t.datetime "updated_at" t.datetime "updated_at"
t.string "type" t.string "type"
t.string "description", default: "", null: false t.string "description", default: "", null: false
t.string "avatar"
t.string "ldap_cn" t.string "ldap_cn"
t.integer "ldap_access" t.integer "ldap_access"
t.string "avatar"
end end
add_index "namespaces", ["name"], name: "index_namespaces_on_name", using: :btree add_index "namespaces", ["name"], name: "index_namespaces_on_name", using: :btree
...@@ -238,20 +238,20 @@ ActiveRecord::Schema.define(version: 20140513095908) do ...@@ -238,20 +238,20 @@ ActiveRecord::Schema.define(version: 20140513095908) do
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.integer "creator_id" t.integer "creator_id"
t.boolean "issues_enabled", default: true, null: false t.boolean "issues_enabled", default: true, null: false
t.boolean "wall_enabled", default: true, null: false t.boolean "wall_enabled", default: true, null: false
t.boolean "merge_requests_enabled", default: true, null: false t.boolean "merge_requests_enabled", default: true, null: false
t.boolean "wiki_enabled", default: true, null: false t.boolean "wiki_enabled", default: true, null: false
t.integer "namespace_id" t.integer "namespace_id"
t.string "issues_tracker", default: "gitlab", null: false t.string "issues_tracker", default: "gitlab", null: false
t.string "issues_tracker_id" t.string "issues_tracker_id"
t.boolean "snippets_enabled", default: true, null: false t.boolean "snippets_enabled", default: true, null: false
t.datetime "last_activity_at" t.datetime "last_activity_at"
t.string "import_url" t.string "import_url"
t.integer "visibility_level", default: 0, null: false t.integer "visibility_level", default: 0, null: false
t.boolean "archived", default: false, null: false t.boolean "archived", default: false, null: false
t.string "import_status" t.string "import_status"
t.float "repository_size", default: 0.0 t.float "repository_size", default: 0.0
t.text "merge_requests_template" t.text "merge_requests_template"
end end
...@@ -357,6 +357,7 @@ ActiveRecord::Schema.define(version: 20140513095908) do ...@@ -357,6 +357,7 @@ ActiveRecord::Schema.define(version: 20140513095908) do
t.integer "notification_level", default: 1, null: false t.integer "notification_level", default: 1, null: false
t.datetime "password_expires_at" t.datetime "password_expires_at"
t.integer "created_by_id" t.integer "created_by_id"
t.datetime "last_credential_check_at"
t.string "avatar" t.string "avatar"
t.string "confirmation_token" t.string "confirmation_token"
t.datetime "confirmed_at" t.datetime "confirmed_at"
...@@ -364,7 +365,6 @@ ActiveRecord::Schema.define(version: 20140513095908) do ...@@ -364,7 +365,6 @@ ActiveRecord::Schema.define(version: 20140513095908) do
t.string "unconfirmed_email" t.string "unconfirmed_email"
t.boolean "hide_no_ssh_key", default: false t.boolean "hide_no_ssh_key", default: false
t.string "website_url", default: "", null: false t.string "website_url", default: "", null: false
t.datetime "last_credential_check_at"
end end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment