如何仅对拉取请求中已更改的文件运行 Rubocop?

问题描述 投票:0回答:8

我创建了 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
8个回答
13
投票

你不必使用 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/ 获取更长的文章


5
投票

我通过查询 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

5
投票

一个更简单的解决方案:

git diff origin/master --name-only | xargs rubocop --force-exclusion

说明:我很少在本地更新

master
,但会进行
git fetch
更新
origin/master
,所以我想对此进行比较。我无法让其他建议的解决方案与
diff-tree
origin/master
一起工作。


4
投票

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


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 尊重其配置文件中的排除声明(此处使用默认的
./.rubocop.yml
)。你把这些声明放进去是有原因的,对吧?! ;)


1
投票

这是另一种替代方案,将当前分支与

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


0
投票

也许您可以利用CircleCI的动态配置功能

有一个关于如何根据修改的文件执行特定工作流程或步骤的具体指南(https://circleci.com/docs/using-dynamic-configuration/#execute-specific-workflows-or-steps-based -修改了哪些文件)。


0
投票

如果有人因为 Rubocop 在本地运行缓慢而发现此线程,请确保您没有关闭 Rubocop 的默认缓存。由于某种原因,我的

.rubocop.yml
文件有
UseCache: false
,一旦我删除该行,检查时间就提高了 10 倍(从 ~30 秒到 ~3 秒)。

© www.soinside.com 2019 - 2024. All rights reserved.