【问题标题】:How to run Rubocop only on the changed files in a pull request?如何仅在拉取请求中更改的文件上运行 Rubocop?
【发布时间】:2015-12-09 19:26:21
【问题描述】:

我创建了 spec/lint/rubocop_spec.rb,它在当前分支和主分支之间更改的文件上运行 Rubocop 样式检查器。这在我本地测试时有效,但在构建服务器 Circle.ci 上运行时无效。 我怀疑是因为只下载了有问题的分支,所以它没有发现master之间的任何差异。有没有比git co master && git pull origin master 更好的方法? 我可以查询 Github API 以列出更改的文件吗?

require 'spec_helper'

describe 'Check that the files we have changed have correct syntax' do
  before do
    current_sha = `git rev-parse --verify HEAD`.strip!
    files = `git diff master #{current_sha} --name-only | grep .rb`
    files.tr!("\n", ' ')
    @report = 'nada'
    if files.present?
      puts "Changed files: #{files}"

      @report = `rubocop #{files}`
      puts "Report: #{@report}"
    end
  end

  it { @report.match('Offenses').should_not be true }
end

【问题讨论】:

    标签: ruby-on-rails git continuous-deployment circleci rubocop


    【解决方案1】:

    您不必使用 github api,甚至可以运行 ruby​​(除非您想包装响应):

    git fetch && git diff-tree -r --no-commit-id --name-only master@\{u\} head | xargs ls -1 2>/dev/null | xargs rubocop --force-exclusion
    

    请参阅http://www.red56.uk/2017/03/26/running-rubocop-on-changed-files/ 以了解更长的文章

    【讨论】:

    • 如果本地主服务器没有更新,这将如何工作?使用 github api 可确保在最新版本的 master 上检查差异。 :)
    • @martins 这有两个原因:1)它首先执行 git fetch 和 2)它使用 master@{u},因此差异树正在比较 master 正在跟踪的获取的远程分支(通常是 origin/大师,但你可能有一个奇怪的设置)而不是本地版本。 (我认为 git 是 github 的一种 api,但具有自动缓存功能!)
    • 为我工作。很有用!
    • git fetch && git diff-tree -r --no-commit-id --name-only master@\{u\} HEAD | xargs ls -1 2>/dev/null | grep '\.rb$' | xargs bundle exec rubocop 为我工作,head 模棱两可
    • rubocop --force-exclusion 考虑 .rubocop.yml 排除项
    【解决方案2】:

    我没有足够高的声誉来评论答案,所以我发布一个答案以添加我认为有用的改进:

    git fetch && git diff-tree -r --no-commit-id --name-only master@\{u\} HEAD | xargs ls -1 2>/dev/null | grep '\.rb$' | xargs bundle exec rubocop --force-exclusion
    

    --force-exclusion 的添加使 RuboCop 尊重其配置文件中的 Exclude 声明(此处使用默认的 ./.rubocop.yml)。你把这些声明放进去是有原因的,对吧?! ;)

    【讨论】:

      【解决方案3】:

      您可以使用https://github.com/AtakamaLLC/lint-diffs

      除了 ruby​​ 之外,它还适用于您的 repo 中的任何语言(甚至是 bash 脚本和 README 文件),并且适用于任何类型的源代码控制,而不仅仅是 git。

      这样您就可以在任何地方使用相同的工具。

      您必须在配置中启用 rubocop 扩展。

      【讨论】:

        【解决方案4】:

        这是另一个将当前分支与origin/master 进行比较的替代方案(应该适用于任何存储库托管 - 只需在带有 bitbucket 存储库的 circleci 上尝试过)。它还传递了一个.rubocop.yml 配置文件选项(如果不需要,可以删除该部分)。

        require 'spec_helper'
        
        RSpec.describe 'Check that the files we have changed have correct syntax' do
          before do
            current_sha = 'origin/master..HEAD'
            @files = `git diff-tree --no-commit-id --name-only -r #{current_sha} | grep .rb`
            @files.tr!("\n", ' ')
          end
        
          it 'runs rubocop on changed ruby files' do
            if @files.empty?
              puts "Linting not performed. No ruby files changed."
            else
              puts "Running rubocop for changed files: #{@files}"
              result = system "bundle exec rubocop --config .rubocop.yml --fail-level warn #{@files}"
              expect(result).to be(true)
            end
          end
        end
        

        原文要点:https://gist.github.com/djburdick/5104d15f612c15dde65f#gistcomment-2029606

        【讨论】:

          【解决方案5】:

          我发现https://github.com/m4i/rubocop-git 效果很好。但是它适用于您的 git diff(可选 --cached),因此它不允许您比较分支。

          【讨论】:

          • 您能否详细说明如何使用它来仅检查特定 PR 发生了什么变化?谢谢。
          • 尝试rubocop-git <first_commit> <last_commit>,例如:rubocop-git master master~5 检查master中的最后5次提交。你需要一个额外的 git 调用来找出分支中的第一个提交。
          【解决方案6】:

          我通过查询 api.github.com 修复了它。 这将在 current_sha 和 master 分支之间更改的所有文件上运行 rubocop。

          require 'spec_helper'
          
          describe 'Check that the files we have changed have correct syntax' do
            before do
              current_sha = `git rev-parse --verify HEAD`.strip!
              token = 'YOUR GITHUB TOKEN'
              url = 'https://api.github.com/repos/orwapp/orwapp/compare/' \
                    "master...#{current_sha}?access_token=#{token}"
              files = `curl -i #{url} | grep filename | cut -f2 -d: | grep \.rb | tr '"', '\ '`
              files.tr!("\n", ' ')
              @report = 'nada'
              if files.present?
                puts "Changed files: #{files}"
          
                @report = `rubocop #{files}`
                puts "Report: #{@report}"
              end
            end
          
            it { expect(@report.match('Offenses')).to be_falsey }
          end
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-23
            • 2021-05-15
            • 2021-05-01
            • 1970-01-01
            相关资源
            最近更新 更多