diff options
author | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2014-12-28 22:11:29 +0200 |
---|---|---|
committer | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2014-12-28 22:11:29 +0200 |
commit | 25a42a56cf4da95e8725b988f2b940d8b293a952 (patch) | |
tree | 232df952ea64eb75330e471fe4884a86e9e6af9f /app | |
parent | 19c6951cc21ba87b2e7a70a6d1a7272ef19e1b6b (diff) | |
parent | 1fa19401e969f79cbd737c55e63249ca9355791c (diff) | |
download | gitlab-ce-25a42a56cf4da95e8725b988f2b940d8b293a952.tar.gz |
Merge pull request #8439 from glasspelican/Teamcity
Teamcity integration using 8.1 rest api
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/projects/services_controller.rb | 2 | ||||
-rw-r--r-- | app/models/project.rb | 4 | ||||
-rw-r--r-- | app/models/project_services/teamcity_service.rb | 116 |
3 files changed, 120 insertions, 2 deletions
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index c50a1f1e75b..ef4d2609147 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -42,7 +42,7 @@ class Projects::ServicesController < Projects::ApplicationController :title, :token, :type, :active, :api_key, :subdomain, :room, :recipients, :project_url, :webhook, :user_key, :device, :priority, :sound, :bamboo_url, :username, :password, - :build_key, :server + :build_key, :server, :teamcity_url, :build_type ) end end diff --git a/app/models/project.rb b/app/models/project.rb index 32b0145ca24..f0a49b633fe 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -66,6 +66,7 @@ class Project < ActiveRecord::Base has_one :slack_service, dependent: :destroy has_one :buildbox_service, dependent: :destroy has_one :bamboo_service, dependent: :destroy + has_one :teamcity_service, dependent: :destroy has_one :pushover_service, dependent: :destroy has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id" has_one :forked_from_project, through: :forked_project_link @@ -314,7 +315,8 @@ class Project < ActiveRecord::Base end def available_services_names - %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack pushover buildbox bamboo) + %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla + emails_on_push gemnasium slack pushover buildbox bamboo teamcity) end def gitlab_ci? diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb new file mode 100644 index 00000000000..52b5862e4d1 --- /dev/null +++ b/app/models/project_services/teamcity_service.rb @@ -0,0 +1,116 @@ +class TeamcityService < CiService + include HTTParty + + prop_accessor :teamcity_url, :build_type, :username, :password + + validates :teamcity_url, presence: true, + format: { with: URI::regexp }, 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 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) + 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) + 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) + auth = { + username: username, + password: password, + } + + branch = 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 |