루비의 지속적인 통합

25971 단어 rubyrakeci
최근에 나는 루비에서 프로젝트를 처리해야만 했다. 나는 이 새로운 환경에 적응하려고 했다.개인적인 측면에서 이것은 내가 몇 달 후에 이 프로젝트로 돌아가야 할 때 인지적 부담이 줄어든다는 것을 의미한다. 특히 루비가 나의 전공 분야에서 멀리 떨어지기 때문이다.공교롭게도 충돌의 약속 때문에 나는 연속 통합을 실현할 때 약간의 번거로움을 만났다.그래도 해봤어요.
  • A simple project
  • A more complete project
  • 간단한 항목


    My website (which includes my blog)은 사실상 루비를 바탕으로 하는 것이다. 왜냐하면 이것은 Jekyll 프로젝트이기 때문에 GitHub Pages에 위탁 관리되고 있다(현재).물론 이것은 적당한 루비 프로젝트가 아니다. (예를 들어 목표 서버에 루비가 필요하지 않다.) 그러나 나는 그것이 관련 개념과 도구를 잘 소개한 것을 발견했다.

    마카토이사 / mcartoixa。github。io


    내 개인 사이트


    이 프로젝트의 주요 내용은 다음과 같습니다.

  • The build file ( Rakefile ).

  • The script file(build.sh)은 로컬에서 파일 생성을 수행하는 데 도움을 줍니다.

  • The CI configuration file ( .travis.yml ).
  • 파일 생성


    루비 환경에서 구축 도구를 사용하는 것은 선택이 많지 않다고 생각하기 때문에 Rake이 그렇다.다음은 전체 파일입니다.
    PROJECT_NAME ||= 'www.mcartoixa.me'
    PROJECT_VERSION ||= '0.0.0'
    
    import 'build/common.rake'
    
    좋아, 내가 부정행위를 했어.나는 build\ 폴더에서 구축과 관련된 모든 내용을 수집하는 것을 좋아한다. 나는 여기서 이렇게 했다.그러나 우리가 단도직입적으로 잃은 것은 일치성이다. a Rails project에서 많은 임무와 목표를 도입했기 때문에 나는 이것이 실제로 프로젝트에 더 많은 가독성을 가져왔다는 것을 발견했다.
    저 안에는 무엇이 있습니까?The build file은 다음과 같은 목표(즉 Rake speak에서의 임무)를 정의하고 전체적으로 우리가 다른 기술에서 본 것과 일치한다.

  • build:clean: 정리 생성(tmp\ 디렉터리).

  • 구축: 컴파일: 웹 사이트의 정적 버전(Jekyll 사용)을 만들고 배치를 준비합니다(tmp\obj\bin\ 폴더에서).

  • 구축: 테스트: 테스트 항목.
  • 저는 HTMLProofer으로 제 사이트의 링크를 검사하고 싶습니다.나는 a Jekyll plugin을 사용하여 이 점을 실현할 수 있지만, 테스트 링크가 상당히 소모되고 오류가 발생하기 쉽다는 것을 증명하기 때문에, 나는 차라리 그것을 나의 개발 작업 흐름에서 배제하고 싶다.

  • 구축: 분석: 비활성화 및 구성 문제 확인(Jekyll 사용).

  • 구축: 패키지: 사이트 정적 버전의 배포 가능한 압축 파일을 만듭니다(tmp\out\bin\​ 폴더에서).
  • 은 현재 거의 쓸모가 없다. 왜냐하면 모든 것이 GitHub 페이지에서 처리되고 배치를 포함하기 때문이다. 그러나 이것은 어느 정도에 개념을 증명했다.나는 내가 언제든지 다른 곳에서 나의 사이트를 진행할 수 있다는 자유를 알고 싶다.

  • 생성: 생성: 생성: 컴파일, 생성: 테스트와 생성: 분석 조합의 단축키.

  • 생성: 재구성: 생성: 정리와 생성: 조합을 생성하는 단축키입니다.

  • build:release:build:clean,build:build와build:package를 조합하는 단축키입니다.
  • 여기서 주의해야 할 것은 작업 이름에 이름 공간을 사용했다는 것이다.마찬가지로 이것은 a Rails project에서 유용하다는 것을 증명했다.따라서 컴파일 작업에 대한 설명은 간단합니다.
    namespace 'build' do
      task 'compile' do
        sh 'jekyll', 'build', '-dtmp/obj/bin/', 'JEKYLL_ENV=production', '--strict_front_matter'
      end
    end
    
    구축: 테스트 작업은 다소 복잡하지만 실제로는 HTMLProofer 구성이 주를 이룹니다.
    require 'html-proofer'
    namespace 'build' do
      task 'test' => %w[compile]
      task 'test' do
        options = {
          :allow_hash_href => true,
          :assume_extension => true,
          :check_favicon => true,
          :check_opengraph => true,
          :file_ignore => [
            /\/blog\/software-craftsmanship\/20[01]\d\//, # Do not check old blog posts
            /\/sections\//
          ],
          :root_dir => 'tmp/obj/bin/',
          :url_ignore => [
            'http://html5up.net', 'https://chrisbobbe.github.io/', # Included by the template
            'https://www.facebook.com/mathieu.cartoixa', # 404 only when checked...
            'https://www.linkedin.com/in/cartoixa/', 'https://www.linkedin.com/in/cartoixa/?trk=profile-badge' # 999 only when checked
          ]
        }
        HTMLProofer.check_directory('tmp/obj/bin/', options).run
      end
    end
    
    그리고build:package 작업은 압축 파일을 만들기 위한 외부 패키지가 필요합니다. 기본 PackageTask은 압축 파일 항목의 루트 디렉터리 이외의 파일을 지원하지 않는 것 같습니다.그러면 다음과 같은 결과가 발생합니다.
    require 'zip'
    namespace 'build' do
      namespace 'package' do
        PACKAGE_FILE = 'tmp/out/bin/www.mcartoixa.me-0.0.0.zip'
        file PACKAGE_FILE => %w[build:compile]
        file PACKAGE_FILE do
          FileUtils.mkdir_p('tmp/out/bin/')
          Zip::File.open(PACKAGE_FILE, Zip::File::CREATE) do |zf|
            Rake::FileList.new('tmp/obj/bin/**/*').each do |f|
              zf.add(f.delete_prefix('tmp/obj/bin/'), f)
            end
          end
        end
    
        task 'build' => PACKAGE_FILE
      end
      task 'package' => %w[package:build]
    end
    
    구축 도구의 주요 기능 중 하나는 목표 간의 의존 관계를 설명할 수 있다는 것을 주의하십시오.여기에는 다음과 같은 내용이 설명되어 있습니다.
  • 생성: 패키지 작업은 생성에 따라 달라집니다.​패키지: 구축.
  • 버전:​패키지: 구축 작업은 tmp/out/bin/www.cartoixa.me-0.0.0.zip을 구축하는 규칙에 달려 있습니다.
  • 구축 tmp/out/bin/www.mcartoixa.me-0.0.0.zip의 규칙은build:compile(정적 사이트는 포장을 시도하기 전에 만들어야 함)에 달려 있다.이것은 초보자에게는 약간 곤혹스러울 수도 있지만, 사실상 그것은 매우 강하다. (합리적으로 사용할 때)
  • 마지막으로 제가 보충하고 싶은 것은 HTMLProofer은 좋은 도구입니다. 하지만:
  • 내가 막 새로운 블로그 게시물을 추가했을 때, 나는 여전히 그것이 실제로 존재하지 않는다고 불평하지 않도록 방법을 찾아야 한다.
  • 은 때때로 사이트가... 원인으로 인해 실패할 수 있다. 이것은 나의 구축 성공을 막아서는 안 된다.나는 그것이 잘못이 아니라 경고만 불러일으킬 뿐이라는 것을 확보해야 한다고 생각한다.
  • 스크립트 파일


    Windows Server 2012와 IIS에서 Redmine을 실행한 실례를 보면 루비는 크로스플랫폼 기술이라고 생각합니다.사실, 나는 이미 이 컴퓨터가 컴파일해야 하는 의존 관계가 매우 나쁘게 유지되고 있다는 것을 많이 체험했다. (또는 전혀 없다.) 마리아 DB와 Redis로 연결하여 레일스 응용 프로그램을 실행하는 것은 악몽이다. (가능하면)build.bat은 면책 조항을 제외하고, build.sh 파일의 요점은 간단합니다(Bundler 사용).
    if bundle check > /dev/null; then
      bundle clean
    else
      bundle install --standalone --clean
    fi
    
    bundle exec rake build:${TASK}
    

    CI 구성 파일


    우리는 MacOS나 Linux를 실행하는 CI 플랫폼이 필요하기 때문에 Travis CI이면 된다.다시 한 번, 구축 파일의 모든 어려움을 처리한 후, .travis.yml은 단지
    before_install:
    - gem install bundler
    install:
    - bundle install --standalone --clean --jobs=3 --retry=3
    script:
    - bundle exec rake build:release
    

    더욱 완전한 항목


    이것이 바로 문제가 진정으로 시작된 곳이다.같은 원칙을 더 복잡한 Rails 프로젝트에 적용하려고 시도한 후에 나는 극복하기 어려울 것 같은 어려움을 만났다.환경 자체에 대한 이해가 부족하기 때문일 수도 있지만, 서로 충돌하는 관례 때문일 수도 있다.예를 들어 나는 모든 것이 개발자가 명령행에서 모든 것을 실현할 수 있도록 하기 위해서라고 생각한다.이것은 많은 것을 의미할 수 있다. 예를 들면,
  • 너는 다른 목록에서 일할 필요가 없다. 사실상 너는 이렇게 해서는 안 된다.다른 곳에서 원본 코드 사본을 처리하는 것은 상당히 번거로운 것 같습니다. (예를 들어 Javascript에 비해) 생산 의존 항목만 검색해서 포장하기 때문입니다.
  • 일부 도구에는 메모리가 있습니다.예를 들어, Bundler은 현재 환경(개발, 생산)을 기억합니다.
  • 더 심각한 것은 이른바 Deployment Mode이 당신의 개발 환경을 뚜렷하게 파괴할 것이다.
  • 이런 기능은 사용하기 어려워!...그러나 이것은 포효하는 것이 아니다. 만약 당신이 이 두 세계를 어떻게 조화시키는지에 대해 약간의 견해를 가지고 있다면, 공유하세요.
    비록 나는 이곳에서 진실하고 완전한 프로젝트를 공유할 수 없지만, 나는 유용한 Rakefile 요소를 보여줄 수 있다.
  • 에서 Ruby를 실행하여 소스 파일 구문을 확인하는 방법(구축: 컴파일 대상):
  • SOURCE_FILES = Rake::FileList.new('.ruby-*', 'config.ru', 'Gemfile*', 'Rakefile', 'app/ **/*', 'bin/** /*', 'config/ **/*', 'db/** /*', 'lib/ **/*', 'public/** /*', 'vendor/**/*') do |fl|
      fl.exclude(/^config\/app_parameters.yml$/)
      fl.exclude(/\.log$/)
    end
    RUBY_FILES = Rake::FileList.new(SOURCE_FILES.dup.to_a.select do |path|
      path.ends_with?('.rb')
    end) do |fl|
      fl.exclude(/^vendor\//)
    end
    
    namespace 'build' do
      rule '.rb.log' => [
        proc { |tn| tn.gsub(/\.rb\.log$/, '.rb').sub(/tmp\/obj\//, '') }
      ] do |t|
        FileUtils.mkdir_p(File.dirname(t.name))
        ruby "-wc #{t.source} > #{t.name}"
      end
      task 'compile' => RUBY_FILES.gsub(/\.rb$/, '.rb.log').sub(/^/, 'tmp/obj/')
    end
    
    우리는 *.rb.log 파일에 규칙을 정의했습니다. 이 파일들은 해당하는 *.rb 파일에서 루비를 실행하고 저장하여 생성합니다.그리고 우리가 정의한 임무는 이 파일들의 생성에 달려 있다.
  • 은 루비 파일에서 Reek을 실행하는 방법입니다.
  • require 'reek/rake/task'
    Reek::Rake::Task.new do |t|
      t.config_file = '.reek.yml'
      t.source_files = RUBY_FILES
      t.reek_opts = '-s --force-exclusion --no-progress'
    end
    
  • 이 루비 파일에서 Rubocop을 실행하는 방법(rubocop 대상을 만듭니다.
  • require 'rubocop/rake_task'
    RuboCop::RakeTask.new(:rubocop) do |t|
      t.formatters = ['clang', ['html', '-o', 'tmp/rubocop-results.html']]
      t.patterns = RUBY_FILES
    end
    
    앞서 설명한 바와 같이 Reek 및/또는 Rubocop과 같은 정적 분석 도구를 사용하려면 프로젝트 수명 주기 동안 수백 개의 경고를 한 번에 수정하지 않도록 최대한 빨리 해야 합니다.
    구축 과정에서 자산 (예를 들어 축소된 Javascript 파일) 을 생성할 때 이 파일을 생성한 후 file lists (target assets:precompile in a Rails project) 을 만들어야 하기 때문에 패키지는 더욱 도전적입니다.그러면 다음과 같은 결과가 발생합니다.
    require 'rake/packagetask'
    PACKAGED_FILES = Rake::FileList.new(SOURCE_FILES.dup) do |fl|
      fl.exclude(/^app\/assets\//)
    end
    namespace 'build' do
      namespace 'package' do
        pt = Rake::PackageTask.new('my_application', '0.0.0') do |t|
          t.need_tar_gz = true
          t.package_dir = 'tmp/obj/bin/'
          t.package_files = PACKAGED_FILES
        end
    
        file pt.package_dir_path + '/public/assets' => %w[assets:precompile]
        file pt.package_dir_path + '/public/assets' do
          pt.package_files = pt.package_files + Rake::FileList.new('public/assets/**/*')
        end
    
        task 'build' => pt.package_dir_path + '/public/assets'
        task 'build' => %w[package]
        task 'build' do
          FileUtils.mkdir_p('tmp/out/bin/')
          FileUtils.mv(File.join(pt.package_dir, pt.tar_gz_file), 'tmp/out/bin/')
        end
      end
      task 'package' => %w[package:build]
    end
    
    CI 구성에서 특정 명령행을 지정하면 전체 구축 유형이 작동합니다(로컬 구축의 일부가 될 수 없음).
    bundle install --standalone=test --deployment
    RAILS_ENV=test bundle exec rake build:release
    
    이것은 결코 이상적이지 않다. 왜냐하면 우리도 테스트 의존항(예를 들어 capybara 또는 RSpec Rails)을 포장할 것이다.하지만 허허: 일이 진행 중이야.

    좋은 웹페이지 즐겨찾기