Запустите Vagrant+Chef, если файлы шаблонов были извлечены с окончаниями строки CRLF.

Меня постоянно раздражает досадная ошибка, которая возникает, когда разработчики Windows проверяют кулинарные книги из моего репозитория Git с autocrlf Git, установленным на true. . Когда они запускают vagrant up для запуска виртуальной машины Linux, файлы поваренной книги сопоставляются с виртуальной машиной с окончаниями строк CRLF, что приводит к бесконечным неясным ошибкам, когда оболочка и другие утилиты POSIX пытаются работать на виртуальной машине. (теперь недействительные) файлы шаблонов, которые были скопированы на виртуальную машину.

Исправить это достаточно просто: повторно клонируйте репозиторий после изменения параметра autocrlf на input или false.

Моя проблема в том, что когда у вас неправильные окончания строк, единственными симптомами являются ошибки в странных местах, которые никоим образом не указывают на наличие проблемы с окончаниями строк.

Как сделать так, чтобы Chef† проверял неправильные окончания строк, скажем, в файлах шаблонов поваренной книги и выдавал ошибку, если находил их? Я думаю, простой фрагмент Ruby, который проверяет окончания строк в данном файле, который я могу поместить в начало рецепта, будет работать.

Примечание: в конкретном случае моего репо последовательность шагов такова:

  1. Разработчик проверяет репозиторий
  2. Разработчик запускает vagrant up
  3. Vagrant запускает запуск Chef в виртуальной машине
  4. Наконец, скрипт сборки репо запускается на виртуальной машине.

† Или что-нибудь еще, включенное в репозиторий.


person Michael Kropat    schedule 23.07.2015    source источник


Ответы (2)


Rubocop можно использовать для принудительного применения окончания строк в стиле unix (среди многих другие вещи).

Например (из командной строки, в гостевой системе):

gem install rubocop
rubocop --only Style/EndOfLine  # only check line endings

Или это можно сделать из контекста самого шеф-повара с помощью следующего рецепта:

chef_gem 'rubocop'

ruby_block 'check line endings' do
  block do
    # It's probably better to call rubo cop code directly, rather than
    # shelling out, but that can be an exercise for the reader ;-)
    rubocop_cmd = Mixlib::ShellOut.new(
      'rubocop --only Style/EndOfLine',
      :cwd => 'dir_to_check'
    )
    rubocop_cmd.run_command

    # Raise an exception if it didn't exit with 0.
    rubocop_cmd.error!
  end
end

Неперехваченное исключение заставит шеф-повара выручить.

person Jon Burgess    schedule 24.07.2015
comment
+1 Хороший ответ. В моем случае я не уверен, что смогу применить это, поскольку сценарии локальной сборки запускаются на виртуальной машине только после запуска Chef. Извините, что изначально не включил все детали в вопрос. - person Michael Kropat; 24.07.2015
comment
Независимо от того, работает ли он в контексте шеф-повара или нет, например. после, не имеет большого значения. Пока у вас есть ruby/bundler, все вышеперечисленное будет работать. - person Jon Burgess; 26.07.2015
comment
Сказав это, я бы порекомендовал запустить что-то подобное до того, как окончания строк DOS попадут в главную ветку (или что-то еще) в scm. Иначе там будет только шум. - person Jon Burgess; 26.07.2015
comment
Все хорошие моменты, но чтобы немного лучше объяснить мою ситуацию: отчасти я использую Vagrant, потому что разработчику не нужен ruby/bundler на хост-компьютере - все, что им нужно сделать, это vagrant up и необходимые зависимости и процессы сборки происходят внутри виртуальной машины. Я полностью согласен с окончанием строк DOS, но вот что интересно: msysgit в Windows по умолчанию имеет значение autocrlf = true, что означает, что даже если файлы в репозитории имеют окончания строк unix, они будут извлечены на хост-компьютер с строкой DOS. окончания. - person Michael Kropat; 26.07.2015
comment
Я все еще не совсем уверен, что правильно понимаю ваш вариант использования. Я обновил свой ответ, чтобы было ясно, что пример командной строки можно запустить из гостевой виртуальной машины, а также указать, как то же самое можно запустить из шеф-повара. - person Jon Burgess; 27.07.2015
comment
Имеет смысл. Шаг chef_gem был тем, чего мне концептуально не хватало. Наконец-то я попытался реализовать это, но, похоже, это не работает, потому что rubocop не хочет проверять файлы .erb (файлы моих шаблонов). Не является частью первоначального вопроса, но теперь я также хотел бы проверить файлы кулинарных книг, и я не думаю, что rubocop с ними тоже будет работать. Хотя спасибо за идею. - person Michael Kropat; 11.09.2015

Вот фрагмент Ruby, который вы можете добавить в любой рецепт Chef:

def cookbook_supporting_files(*cookbooks)
  cookbooks = cookbooks.map {|name| run_context.cookbook_collection[name]}

  cookbooks.flat_map do |cb|
    (cb.manifest[:files] + cb.manifest[:templates]) \
      .map {|f| ::File.join(cb.root_dir, f['path']) }
  end
end

def dos_eol?(f)
  ::File.open(f, 'rb').read(4096).include? "\r\n"
end

cookbook_supporting_files(cookbook_name).each do |f|
  if dos_eol? f
    raise "Cookbook template '#{f}' contains CRLF line endings"
  end
end

Это проверит окончания строк файлов и шаблонов поваренной книги, которые существуют в любой поваренной книге, в которую помещен приведенный выше фрагмент.

Если вы хотите, чтобы тот же фрагмент проверял другие поваренные книги, просто замените:

cookbook_supporting_files(cookbook_name)

Со списком кулинарных книг, которые вы хотите проверить:

cookbook_supporting_files('some_cookbook', 'another_cookbook')
person Michael Kropat    schedule 24.07.2015