You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

quality_analysis_controller.rb 12 kB

10 years ago
10 years ago
10 years ago
10 years ago
​
10 years ago
​
​
​
10 years ago
​
​
​
10 years ago
10 years ago
10 years ago
​
​
​
​
​
​
​
​
​
10 years ago
10 years ago
10 years ago
10 years ago
​
10 years ago
​
10 years ago
10 years ago
​
10 years ago
​
​
​
​
10 years ago
​
​
​
10 years ago
​
10 years ago
10 years ago
​
​
​
​
​
​
10 years ago
10 years ago
​
​
​
​
​
​
10 years ago
10 years ago
​
​
​
​
10 years ago
​
​
​
​
​
10 years ago
10 years ago
10 years ago
10 years ago
​
​
10 years ago
10 years ago
​
​
​
​
​
​
10 years ago
​
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
​
​
​
​
​
10 years ago
​
​
​
10 years ago
​
10 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
10 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
10 years ago
​
​
​
​
​
​
​
​
​
​
​
​
​
10 years ago
​
10 years ago
10 years ago
​
​
​
​
​
​
​
​
​
​
​
10 years ago
​
​
​
​
10 years ago
​
​
​
​
​
​
​
10 years ago
​
​
​
​
​
​
​
10 years ago
​
​
​
​
​
​
​
​
​
​
10 years ago
​
10 years ago
10 years ago
10 years ago
​
​
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. class QualityAnalysisController < ApplicationController
  2. before_filter :find_project_by_project_id#, :except => [:getattachtype]
  3. before_filter :find_quality_analysis, :only => [:edit, :update_jenkins_job]
  4. before_filter :authorize
  5. before_filter :connect_jenkins, :only => [:create, :edit, :update_jenkins_job, :index, :delete]
  6. layout "base_projects"
  7. include ApplicationHelper
  8. include QualityAnalysisHelper
  9. require 'jenkins_api_client'
  10. require 'nokogiri'
  11. require 'json'
  12. require 'open-uri'
  13. def show
  14. end
  15. # params 说明:{identifier:版本库名}
  16. def create
  17. begin
  18. user_name = User.find(params[:user_id]).try(:login)
  19. identifier = params[:identifier]
  20. rep_id = params[:rep_id]
  21. # job_name and sonar_name 前者为job名字,后者为jenkins配置名
  22. job_name = "#{user_name}-#{rep_id}"
  23. sonar_name = "#{user_name}:#{rep_id}"
  24. # 考虑到历史数据:有些用户创建类job但是build失败,即sonar没有结果,这个时候需要把job删除,并且删掉quality_analyses表数据
  25. # 如果不要这句则需要迁移数据
  26. @sonar_address = Redmine::Configuration['sonar_address']
  27. projects_date = open(@sonar_address + "/api/projects/index").read
  28. arr = JSON.parse(projects_date).map {|m| m["nm"]} # eg: ["Hjqreturn:cc_rep", "Hjqreturn:putong", "Hjqreturn:sonar_rep2", "shitou:sonar_rep"]
  29. quality_an = QualityAnalysis.where(:sonar_name => sonar_name).first
  30. if @client.job.exists?(job_name) && QualityAnalysis.where(:sonar_name => sonar_name).select{|qa| arr.include?(qa.sonar_name)}.blank?
  31. aa = @client.job.delete("#{job_name}")
  32. quality_an.delete unless quality_an.blank?
  33. end
  34. # Checks if the given job exists in Jenkins.
  35. # unless @client.job.exists?(job_name)
  36. @g = Gitlab.client
  37. branch = params[:branch]
  38. language = swith_language_type(params[:language])
  39. path = params[:path].blank? ? "./" : params[:path]
  40. # qa = QualityAnalysis.where(:project_id => @project.id, :author_login => user_name).first
  41. version = quality_an.nil? ? 1 : quality_an.sonar_version + 1
  42. properties = "sonar.projectKey=#{sonar_name}
  43. sonar.projectName=#{sonar_name}
  44. sonar.projectVersion=#{version}
  45. sonar.sources=#{path}
  46. sonar.language=#{language.downcase}
  47. sonar.sourceEncoding=utf-8"
  48. git_url = @gitlab_address.to_s+"/"+@project.owner.to_s+"/"+ identifier + "."+"git"
  49. # 替换配置文件
  50. @doc = Nokogiri::XML(File.open(File.join(Rails.root, 'tmp', 'config.xml')))
  51. @doc.at_xpath("//hudson.plugins.git.UserRemoteConfig/url").content = git_url
  52. @doc.at_xpath("//hudson.plugins.git.BranchSpec/name").content = "*/#{branch}"
  53. @doc.at_xpath("//hudson.plugins.sonar.SonarRunnerBuilder/properties").content = properties # sonar-properties
  54. # jenkins job创建
  55. jenkins_job = @client.job.create("#{job_name}", @doc.to_xml)
  56. logger.info("Jenkins status of create ==> #{jenkins_job}")
  57. # 将地址作为hook值添加到gitlab
  58. @g.add_project_hook(@project.gpid, @jenkins_address + "/project/#{job_name}")
  59. # job创建完成后自动运行job,如果运行成功则返回‘200’
  60. code = @client.job.build("#{job_name}")
  61. logger.error("build result ==> #{code}")
  62. # 判断调用sonar分析是否成功
  63. # 等待启动时间处理, 最长时间为30分钟
  64. for i in 0..360 do
  65. sleep(5)
  66. @current_build_status = @client.job.get_current_build_status("#{job_name}")
  67. if (@current_build_status == "success" || @current_build_status == "failure")
  68. break
  69. if i == 360
  70. @build_console_result = false
  71. break
  72. end
  73. end
  74. end
  75. # sonar 缓冲,sonar生成数据
  76. sleep(10)
  77. # 获取sonar output结果
  78. console_build = @client.job.get_console_output("#{job_name}", build_num = 0, start = 0, mode = 'text')["output"]
  79. logger.info("@current_build_status is ==> #{@current_build_status}")
  80. # 两种情况需要删除job:
  81. # 1/创建成功但是build失败则删除job
  82. # 2/creat和build成功,调用sonar启动失败则删除job
  83. # 错误信息存储需存到Trustie数据库,否则一旦job删除则无法获取这些信息
  84. if jenkins_job == '200' && code != '201'
  85. @client.job.delete("#{job_name}")
  86. else
  87. if @current_build_status == "failure"
  88. reg_console = /Exception:.*?\r/.match(console_build)
  89. output = reg_console[0].gsub("\r", "") unless reg_console.nil?
  90. se = SonarError.where(:jenkins_job_name => job_name).first
  91. se.nil? ? SonarError.create(:project_id => @project.id, :jenkins_job_name => job_name, :output => output) : se.update_column(:output, output)
  92. @client.job.delete("#{job_name}")
  93. elsif @current_build_status == "success"
  94. if quality_an.blank?
  95. QualityAnalysis.create(:project_id => @project.id, :author_login => user_name, :rep_identifier => identifier,
  96. :sonar_version => version, :path => path, :branch => branch, :language => language, :sonar_name => "#{user_name}:#{rep_id}")
  97. else
  98. qa.update_attribute(:sonar_version, version)
  99. end
  100. end
  101. end
  102. # end
  103. rescue => e
  104. @message = e.message
  105. end
  106. respond_to do |format|
  107. if @current_build_status == "success"
  108. format.html{redirect_to project_quality_analysis_path(:project_id => @project.id, :resource_id => sonar_name, :branch => branch, :current_build_status => @current_build_status, :job_name => job_name)}
  109. elsif @current_build_status == "failure"
  110. format.html{redirect_to error_list_project_quality_analysi_path(:project_id => @project.id, :job_name => job_name)}
  111. end
  112. end
  113. end
  114. def error_list
  115. @error_list = SonarError.where(:jenkins_job_name => params[:job_name]).first
  116. respond_to do |format|
  117. format.html
  118. end
  119. end
  120. # get language type
  121. def swith_language_type language
  122. if language == "c#"
  123. "cs"
  124. elsif language == "python"
  125. "py"
  126. elsif language == "c"
  127. "c++"
  128. else
  129. language
  130. end
  131. end
  132. def edit
  133. @g = Gitlab.client
  134. gitlab_branches = @g.branches(@project.gpid)
  135. @branch_names = gitlab_branches.map{|b| b.name}
  136. @gitlab_default_branch = @g.project(@project.gpid).default_branch
  137. end
  138. # 删除的时候主要删除三方面数据:1/Trustie数据 2/jenkins数据 3/sonar数据
  139. # 如果只删除数据1,则新建的时候会有冲突
  140. def delete
  141. begin
  142. qa = QualityAnalysis.find(params[:id])
  143. rep_id = Repository.where(:project_id => @project.id, :identifier => qa.rep_identifier).first.try(:id)
  144. job_name = "#{qa.author_login}-#{rep_id}"
  145. logger.info("result: job_name ###################==>#{job_name}")
  146. logger.info("result: @client.job ###################==>#{@client.job}")
  147. d_job = @client.job.delete(job_name)
  148. logger.info("result: delete job ###################==>#{d_job}")
  149. qa.delete
  150. respond_to do |format|
  151. format.html{redirect_to :controller => 'repositories', :action => 'show', :id => @project, :repository_id => gitlab_repository(@project).identifier}
  152. end
  153. rescue Exception => e
  154. puts e
  155. end
  156. end
  157. # 更新Jenkins job,主要包括相关配置文件参数的更新,Trustie平台数据的更新
  158. def update_jenkins_job
  159. begin
  160. rep_id = Repository.where(:project_id => @project.id).first.try(:id)
  161. sonar_name = @quality_analysis.sonar_name
  162. job_name = "#{@quality_analysis.author_login}-#{rep_id}"
  163. version = @quality_analysis.sonar_version
  164. path = params[:path].blank? ? "./" : params[:path]
  165. language = swith_language_type(params[:language])
  166. branch = params[:branch]
  167. identifier = @quality_analysis.rep_identifier
  168. properties = "sonar.projectKey=#{sonar_name}
  169. sonar.projectName=#{sonar_name}
  170. sonar.projectVersion=#{version}
  171. sonar.sources=#{path}
  172. sonar.language=#{language.downcase}
  173. sonar.sourceEncoding=utf-8"
  174. git_url = @gitlab_address.to_s+"/"+@project.owner.to_s+"/"+ identifier + "."+"git"
  175. # modify config.yml
  176. @doc = Nokogiri::XML(File.open(File.join(Rails.root, 'tmp', 'config.xml')))
  177. @doc.at_xpath("//hudson.plugins.git.UserRemoteConfig/url").content = git_url
  178. @doc.at_xpath("//hudson.plugins.git.BranchSpec/name").content = "*/#{branch}"
  179. @doc.at_xpath("//hudson.plugins.sonar.SonarRunnerBuilder/properties").content = properties # sonar-properties
  180. # update成功则返回 ‘200’
  181. jenkins_job = @client.job.update("#{job_name}", @doc.to_xml)
  182. # 数据更新到Trustie数据
  183. if jenkins_job == '200'
  184. logger.info("quality_ananlysis will be updated: ==> #{jenkins_job}")
  185. @quality_analysis.path = path
  186. @quality_analysis.language = language
  187. @quality_analysis.branch = branch
  188. @quality_analysis.save
  189. end
  190. rescue Exception => e
  191. logger.error("Update jenkins job: #{e}")
  192. end
  193. respond_to do |format|
  194. format.html{redirect_to project_quality_analysis_path(:project_id => @project.id)}
  195. format.js
  196. end
  197. end
  198. # resource_id: login + @repository.id
  199. def index
  200. begin
  201. @branch = params[:branch]
  202. @resource_id = params[:resource_id]
  203. @sonar_address = Redmine::Configuration['sonar_address']
  204. if params[:resource_id].nil?
  205. @name_flag = true
  206. projects_date = open(@sonar_address + "/api/projects/index").read
  207. arr = JSON.parse(projects_date).map {|m| m["nm"]} # eg: ["Hjqreturn:cc_rep", "Hjqreturn:putong", "Hjqreturn:sonar_rep2", "shitou:sonar_rep"]
  208. @quality_analyses = QualityAnalysis.where(:project_id => @project.id).select{|qa| arr.include?(qa.sonar_name)}
  209. else
  210. filter = "sqale_rating,function_complexity,duplicated_lines_density,comment_lines_density,sqale_index,lines,files,functions,classes,directories,blocker_violations,critical_violations,major_violations,minor_violations,info_violations,violations"
  211. complexity_date = open(@sonar_address + "/api/resources/index?resource=#{@resource_id}&depth=0&metrics=#{filter}").read
  212. @complexity =JSON.parse(complexity_date).first
  213. # 按名称转换成hash键值对
  214. @ha = {}
  215. @complexity["msr"].each do |com|
  216. key = com["key"]
  217. if key == "sqale_index"
  218. value = com["frmt_val"]
  219. else
  220. value = com["val"]
  221. end
  222. @ha.store(key,value)
  223. end
  224. end
  225. rescue => e
  226. puts e
  227. end
  228. end
  229. # Find project of id params[:project_id]
  230. def find_project_by_project_id
  231. @project = Project.find(params[:project_id])
  232. rescue ActiveRecord::RecordNotFound
  233. render_404
  234. end
  235. def find_quality_analysis
  236. begin
  237. @quality_analysis = QualityAnalysis.find(params[:id])
  238. rescue
  239. render_404
  240. end
  241. end
  242. # Authorize the user for the requested action
  243. def authorize(ctrl = params[:controller], action = params[:action], global = false)
  244. unless @project.archived? && @project.gpid.nil?
  245. true
  246. else
  247. render_403 :message => :notice_not_authorized_archived_project
  248. end
  249. end
  250. def connect_jenkins
  251. @gitlab_address = Redmine::Configuration['gitlab_address']
  252. @jenkins_address = Redmine::Configuration['jenkins_address']
  253. jenkins_username = Redmine::Configuration['jenkins_username']
  254. jenkins_password = Redmine::Configuration['jenkins_password']
  255. # connect jenkins
  256. @client = JenkinsApi::Client.new(:server_url => @jenkins_address, :username => jenkins_username, :password => jenkins_password)
  257. rescue => e
  258. logger.error("failed to connect Jenkins ==> #{e}")
  259. end
  260. end

软件技术创新是当今国家整体创新能力的重要基础和发展引擎。近年来,大众参与的软件创新与创业活动已经成为网络时代软件开发和应用的新形态,正在快速改变着全球软件创新模式和软件产业格局。 ...