如何在rails的gitlab中获取用户的提交历史

Posted

技术标签:

【中文标题】如何在rails的gitlab中获取用户的提交历史【英文标题】:How to get commit history of users in gitlab in rails 【发布时间】:2020-01-16 22:07:38 【问题描述】:

我正在尝试创建一个应用程序,该应用程序将获取用户的 gitlab/github 提交历史记录,我可以将其显示在侧面板中,并且可以根据我的标准进行检查。我想知道是否有办法获取当前登录用户的 gitlab/github 提交历史。我尝试使用 gem

https://github.com/libgit2/rugged

但找不到满足我需求的方法。如果有人知道如何实现这一点,那将非常有帮助。谢谢。

更新

我现在已经设法通过使用来获得用户:

Gitlab.endpoint = 'https://gitlab.com/api/v4'
Gitlab.private_token = 'token'
g = Gitlab.client(
  endpoint: 'https://gitlab.com/api/v4',
  private_token: 'token',
  httparty: 
    headers:  'Cookie' => 'gitlab_canary=true' 
  
)

通过使用命令g.user,我可以获取用户,但我需要获取用户在gitlab 中所做的提交。

【问题讨论】:

【参考方案1】:

    使用此 gitlab API GET /projects/:id/repository/commits 获取存储库 gitlab api 上的所有提交。详情请查看随附的代码。

    基本上,这个git log --author="user_name" 命令可以为您提供特定用户的 git 提交历史记录,您甚至可以在上述命令中仅使用名字或姓氏的电子邮件地址。

    通过 gitlab 进行身份验证后,您可以从 ruby​​ 运行以下命令。

    cmd = 'git log --author="user_name"'
    system(cmd)
使用私有令牌连接到 gitlab 的 ruby​​ 示例代码并不理想,只是一个示例
require 'json'
require 'curb'
require 'net/http'

begin

 def parseCoverageReport(report_text) 
   coverage_perc = report_text.match /All files\s+\|\s+(\d+\.?\d+).*\n/
   if not coverage_perc then
     coverage_perc = report_text.match /^TOTAL\s+\d+\s+\d+\s+(\d+)%$/
   end

   if coverage_perc then 
     #if we found coverage value in job trace
     #puts "coverage_perc[1]: #coverage_perc[1]"
     coverage_perc[1].to_i
   end
 end

 gen_config = YAML.load_file("config/general.yml")
 gitlab_config = YAML.load_file("config/gitlab.yml")

 SCHEDULER.every gen_config[:job_trigger_interval], :first_in => 0 do |job|

 table = 
     title: "Projects",
     hrows: Array.new.push(cols: [
       value: "Project name", 
       value: "Open Merge Requests",
       value: "Code coverage"
     ]),
     rows: Array.new
 

 instances = gitlab_config['instances']

 instances.each do |instance|

   gitlab_url = gitlab_config['instances'][instance.first]['url']
   # gitlab_token = gitlab_config['instances'][instance.first]['api_key']
   gitlab_token = ENV[gitlab_config['instances'][instance.first]['api_key']]
   red_threshold = gitlab_config['instances'][instance.first]['red_threshold']
   orange_threshold = gitlab_config['instances'][instance.first]['orange_threshold']
   cov_red_threshold = gitlab_config['instances'][instance.first]['cov_red_threshold']
   cov_orange_threshold = gitlab_config['instances'][instance.first]['cov_orange_threshold']
   projects = gitlab_config['instances'][instance.first]['projects']

   projects.each do |name, project|

       merge_reqs = JSON.parse(Curl.get("#gitlab_url/api/v4/projects/#project['id']/merge_requests?state=opened&private_token=#gitlab_token&per_page=200").body_str)
       git_project =  JSON.parse(Curl.get("#gitlab_url/api/v4/projects/#project['id']?private_token=#gitlab_token").body_str)
       opened_mrs = merge_reqs.select  |merge_reqs| %w[opened].include? merge_reqs['state'] 
       repo_name  = git_project['name']
       repo_url  = git_project['web_url']


       status = case
       when opened_mrs.size >= red_threshold then 'danger'
       when opened_mrs.size >= orange_threshold then 'warning'
       else
         'ok'
       end

       mrs_count = "#opened_mrs.size"
       send_event("#name_mr",  current: mrs_count, status: status )

       color = case
       when opened_mrs.size >= red_threshold then 'red'
       when opened_mrs.size >= orange_threshold then 'orange'
       else
         'green'
       end

       font_color = color == 'orange' ? 'black' : 'white'

       cov_color = color
       font_cov_color = 'white'

       code_coverage = "---"
       code_coverage_tag = "---"
       cov_job_url = ''

       jobs = JSON.parse(Curl.get("#gitlab_url/api/v4/projects/#project['id']/jobs?scope=success&private_token=#gitlab_token&per_page=30").body_str)
       code_cov_job = jobs.find  |gitlab_job| !gitlab_job['coverage'].nil? 

       if not code_cov_job then
         #if no job has 'coverage' feature set up in Gitlab try to parse 
         #'coverage' from jobs trace manually
         jobs.each do |job|
               trace_report = Curl.get("#gitlab_url/api/v4/projects/#project['id']/jobs/#job['id']/trace?private_token=#gitlab_token").body_str
               code_cov_percentage = parseCoverageReport(trace_report)
               if code_cov_percentage then
                 code_cov_job = job
                 code_cov_job['coverage'] = code_cov_percentage
                 break 
               end
         end
       end

       if code_cov_job then
         #found code coverage data => process them
         code_coverage = code_cov_job['coverage'].to_i
         cov_job_url = code_cov_job['web_url'].to_s

         #update code covergate SprintProgress widgets at the same job
         widget_title = "code_coverage_progress_#project['id']"
         send_event(widget_title,  
           title: "Code Coverage - #git_project['name']", 
           sprintboard_url: cov_job_url,
           min: 0, 
           max: 100, 
           value: code_coverage, 
           moreinfo: ''
         )

         cov_color = case
         when code_coverage <= cov_red_threshold then 'red'
         when code_coverage <= cov_orange_threshold then 'orange'
         else
           'green'
         end

         code_coverage = "#code_coverage%"
         code_coverage_tag = "<a href='#cov_job_url' target='_blank'>#code_coverage.to_s</a>"
       end

       repo_name_a_tag = "<a href='#repo_url' target='_blank'>#repo_name</a>"
       open_mrs_size = "<a href='#repo_url/merge_requests' target='_blank'>#opened_mrs.size</a>"

       table[:rows].push( 
         cols: [
            value: repo_name_a_tag, style: "color: #font_color; background-color: #color" , 
            value: open_mrs_size, style: "color: #font_color; background-color: #color" ,
            value: code_coverage_tag, style: "color: #cov_color == 'orange' ? 'black' : 'white'; background-color: #cov_color"  
         ]
       )

     end
   end

   send_event('open_merge_requests_table', table)

end
rescue Errno::ENOENT
 puts "No config file found for gitlab - not starting the Gitlab job"
end

在上面的 ruby​​ 例子中请看下面的代码 sn-p
merge_reqs = JSON.parse(Curl.get("#gitlab_url/api/v4/projects/#project['id']/merge_requests?state=opened&private_token=#gitlab_token&per_page=200").body_str)
       git_project =  JSON.parse(Curl.get("#gitlab_url/api/v4/projects/#project['id']?private_token=#gitlab_token").body_str)
       opened_mrs = merge_reqs.select  |merge_reqs| %w[opened].include? merge_reqs['state'] 
       repo_name  = git_project['name']
       repo_url  = git_project['web_url']

在这里,我要做的是使用 private_token 连接到我们的 gitlab 实例,然后针对特定的项目 ID(您可以从 gitlab 的 UI 中获取它)检查打开的合并请求。我还获得了 git_project,从中获得了名称和 web_url(这是我的用例)。

对于您的用例,您必须获取 project_id(用于 gitlab UI),然后使用一些适当的方法来获取提交。gitlab docs

【讨论】:

gitlab.Gitlab('https://git.xxx.xxx.xxx', private_token='xxxxxxxxxx') 是否与此 gem 相关联?我需要从所有项目中获取用户所有提交的日志,这是否适用? @amal 我已经更新了我的答案,它使用 ruby​​ 代码使用私有令牌连接到 gitlab。 JSON.parse(Curl.get("#gitlab_url/api/v4/projects/#project['id']/jobs?scope=success&private_token=#gitlab_token&per_page=30").body_str)跨度> 很抱歉,您能举一个更简单的例子吗? 在您的帮助下,我设法从 gitlab 获取用户,但我不知道如何获取用户的提交历史记录。您指定 cmd = 'git log --author="user_name"' system(cmd) 的这段代码适用于系统,但我无法操纵它来获取提交的内容。 @Amal 我已经更新了答案,希望最后2点对你有帮助

以上是关于如何在rails的gitlab中获取用户的提交历史的主要内容,如果未能解决你的问题,请参考以下文章

gitlab查看当前分支和master对比

如何在 git 分支中获取给定作者的提交消息历史记录? [复制]

git如何回滚远程仓库

GitLab获取人员参与项目-贡献项目列表

(转)通过gitlab统计git提交的代码量

Rails - 当用户单击提交按钮时如何更新表中的数据