[Ruby] rubocop을 커밋시 자동으로 달리게 한다 & 가능한 한 자동으로 수정한다

6609 단어 RuboCop루비Rails

배경



루비의 정적 코드 분석 도구로 매우 유용한 rubocop
  • git push 한 후에 CircleCi 등으로 대량으로 지적되고 있으면 고치는 것이 귀찮아져 점점 고쳐지지 않게 된다
  • 하나하나 로컬로 수동으로 rubocop을 실행하는 것도 번거 로움

  • 라는 문제가 있습니다.
    그래서 이번에는 git commit의 hook을 간단하게 설정할 수 있다 사전 커밋 젬

    커밋할 때 rubocop이 실행되도록



    a. 먼저 pre-commit gem이 포함되어 있지 않으면 rubocop을 설치합니다.

    Gemfile
    group :development do
      gem "pre-commit", require: false
      gem "rubocop", require: false
    end
    

    b. 그런 다음 pre-commit install을 실행합니다.
    bundle exec pre-commit install
    

    이렇게 하면
    {git_root_dir}/.git/hooks/pre-commit에 자동으로 쉘 스크립트가 생성됩니다. 이 pre-commit 파일이 커밋시에 실행되는 처리로, 내용으로서는 cmd 변수에 실행하는 ruby ​​command를 대입해 나중에는 ruby의 코드로서 실행하고 있는 것을 알 수 있습니다.

    사전 커밋
    ...
    cmd=`git config pre-commit.ruby 2>/dev/null`
    if   test -n "${cmd}"
    then true
    elif which rvm   >/dev/null 2>/dev/null
    then cmd="rvm default do ruby"
    elif which rbenv >/dev/null 2>/dev/null
    then cmd="rbenv exec ruby"
    else cmd="ruby"
    fi
    
    export rvm_silence_path_mismatch_check_flag=1
    
    ${cmd} -rrubygems -e '
      begin
        require "pre-commit"
        true
      rescue LoadError => e
        $stderr.puts <<-MESSAGE
    pre-commit: WARNING: Skipping checks because: #{e}
    pre-commit: Did you set your Ruby version?
    MESSAGE
        false
      end and PreCommit.run
    '
    

    c. 위의 ruby ​​command를 bundle exec로 변경합니다.
    git config pre-commit.ruby "bundle exec ruby"
    

    d. precommit checks에 rubocop를 추가합니다.
    git config pre-commit.checks "[rubocop]"
    

    여기까지 rubocop의 체크가 달리게 되었을 것이므로 뭔가 적당한 파일을 만들어 rubocop가 달리는지 체크해 보겠습니다.

    hoge.rb
    def hoge
      [1, 2, 3].each{
    |a| p a}
    end
    
    $ git commit -m 'hoge'                                                                                       土  8/11 23:07:25 2018
    pre-commit: Stopping commit because of errors.
    Inspecting 1 file
    C
    
    Offenses:
    
    hoge.rb:2:17: C: Layout/SpaceBeforeBlockBraces: Space missing to the left of {.
      [1, 2, 3].each{
                    ^
    hoge.rb:2:17: C: Style/BlockDelimiters: Avoid using {...} for multi-line blocks.
      [1, 2, 3].each{
                    ^
    hoge.rb:3:1: C: Layout/MultilineBlockLayout: Block argument expression is not on the same line as the block start.
    |a| p a}
    ^^^
    hoge.rb:3:8: C: Layout/BlockEndNewline: Expression at 3, 8 should be on its own line.
    |a| p a}
           ^
    
    1 file inspected, 4 offenses detected
    
    pre-commit: You can bypass this check using `git commit -n`
    

    네! 이제 rubocop의 규칙을 따르지 않는 코드는 용서없이 커밋 할 수 없습니다!

    가능한 한 자동으로 수정



    이어 커밋시 최대한 자동으로 수정되도록 합니다.
    그렇다고해도 간단하고 git config에서 rubocop 옵션을 설정하기만 하면 됩니다.
    git config pre-commit.rubocop.flags ["-a"]
    

    이제 커밋하면 위의 파일은 자동으로 수정되어 커밋을 통과합니다.
    $ git commit -m 'foo'                                                                                                  日  8/12 00:05:20 2018
    1 file inspected, no offenses detected
    [refactoring/rubocop 5c009d6] foo
     1 file changed, 2 deletions(-)
    

    물론 모두가 자동으로 수정되는 것은 아니기 때문에 손으로 수정하지 않으면 안되는 부분도 있습니다만, 처음으로 올린 문제가 해결되어 꽤 편해졌군요! 이것이라면 귀찮게하지 않고 할 수있을 것 같습니다!
    여러분도 좋은 rubocop life를

    (보충) 자동으로 수정은 하지만 staging에 올리지 않는다



    위의 마음대로 수정되어 거기서 모두 다닐 경우 그대로 커밋되는 것이 뭔가 기분 나쁘기 때문에 자신은 결국 pre-commit의 옵션은 제외하고 커밋이 통과하지 않은 후에 자동 수정을 한다 그렇게했습니다.

    사전 커밋
    ...
    MESSAGE
        false
      end and PreCommit.run
    ...
    
    # stagingされているファイルに対して自動修正をかける
    git diff --name-only --cached | xargs bundle exec rubocop -a
    

    이렇게 해 두면 커밋이 통과하지 않았을 경우에 자동 수정은 걸립니다만, 수정은 staging을 타지 않고 어디가 자동 수정되었는지 확인하고 나서 staging에 받아들여 다시 커밋할 수 있습니다.

    좋은 웹페이지 즐겨찾기