Ruby Policy 2.0: различия между версиями
Зануда (обсуждение | вклад) мНет описания правки |
Ldv (обсуждение | вклад) (это проект правил, который ещё обсуждается) |
||
(не показаны 4 промежуточные версии 1 участника) | |||
Строка 1: | Строка 1: | ||
{{ | {{DraftPolicy | ||
|responsible=[[Участник:Зануда|Малъ Скрылевъ]] | |||
|discussion_link=https://lists.altlinux.org/pipermail/devel/2019-February/206679.html | |||
|discussion_since=05.02.2019 | |||
}} | |||
== Ruby Policy == | == Ruby Policy == | ||
Строка 23: | Строка 27: | ||
Если какая либо стороннаяя библиотека (модуль) должна была быть использована в рядовых программах руби, то ее библиотеки должны были быть положены в соотвестствующие папки в ''/usr/lib/ruby/site_ruby/'', которая является местом размещения библиотек руби не из числа стандартного набора. | Если какая либо стороннаяя библиотека (модуль) должна была быть использована в рядовых программах руби, то ее библиотеки должны были быть положены в соотвестствующие папки в ''/usr/lib/ruby/site_ruby/'', которая является местом размещения библиотек руби не из числа стандартного набора. | ||
В нынешней ситуации действительной на 2019 год, для развертывания дополнительных модулей используются модули '''rubygems''' и '''bundler''', ныне поставляющиеся в виде | В нынешней ситуации действительной на 2019 год, для развертывания дополнительных модулей используются модули '''rubygems''' и '''bundler''', ныне поставляющиеся в виде пакета вида с англоязычным назанием ''gem'' (русское название '''бисер''' будет употребляться далее), хотя первый был когда-то обычным сторонним модулем. | ||
Проект '''rubygems''' был начат в апреле 2009, '''bundler''' четырьмя месяцами позднее в августе того же года. На текущий момент пара этих | Проект '''rubygems''' был начат в апреле 2009, '''bundler''' четырьмя месяцами позднее в августе того же года. На текущий момент пара этих бисеров является по праву и на деле единственной системой определения зависимостей рубишной системы. | ||
Зависимости в текущих проектах руби бывают 2-х видов: | Зависимости в текущих проектах руби бывают 2-х видов: | ||
Строка 31: | Строка 35: | ||
* через ''Gemfile''. | * через ''Gemfile''. | ||
''.gemspec'' является единственным файлом описания зависимостей для rubygems | ''.gemspec'' является единственным файлом описания зависимостей для системы rubygems бисеров, зависимости в котором могут быть скучены в 2 группы, зависимости исполения (runtime), и зависимости разработки (development), и последние также используются для тестирования проектов. | ||
''Gemfile'' является файлом описания как зависимостей разработки для бисеров (в дополнение к .gemspec), а также зависимостей различного рода для иных проектов, напр. для окружений разработки, тестирования, боевого, и прочих, не являющихся собственно | ''Gemfile'' является файлом описания как зависимостей разработки для бисеров (в дополнение к .gemspec), а также зависимостей различного рода для иных проектов, напр. для окружений разработки, тестирования, боевого, и прочих, не являющихся собственно бисерами. В современных проектах для рельс (rails), или других напр. синатры (sinatra), файла требуемые для определенного окружения описываются практически полностью только файлом ''Gemfile'', то есть '''bundler''' сам решает в зависимости от писанного в том файле какие бисеры и их модули загружать для текущего окружения. Что во многих проектах приводит к тому, что явные вызовы метода '''require''' опускаются, например в проектах '''chef''', '''puppet''', или '''foreman''' современных версий. Типичный ''Gemfile'' можно найти [https://raw.githubusercontent.com/theforeman/foreman/develop/Gemfile тут]. | ||
Зависимости на версию ruby также определяется на основе ''Gemfile'' и ''.gemspec''. | Зависимости на версию ruby также определяется на основе ''Gemfile'' и ''.gemspec''. | ||
Строка 42: | Строка 46: | ||
=== Сравнение с предыдущей политикою === | === Сравнение с [[Ruby Policy|предыдущей политикою]] === | ||
Собственно подход с поиском зависимостей сугубо по вызовам метода '''require''' к текущему моменту существенно ограничивается следующими моментами: | Собственно подход с поиском зависимостей сугубо по вызовам метода '''require''' к текущему моменту существенно ограничивается следующими моментами: | ||
Строка 53: | Строка 57: | ||
Посему в нынешнюю пору намного надежнее использовать анализ пары ''Gemfile''/''.gemspec'' файлов для определения зависимостей. | Посему в нынешнюю пору намного надежнее использовать анализ пары ''Gemfile''/''.gemspec'' файлов для определения зависимостей. | ||
=== Пакет ruby === | === Пакет ruby === | ||
Строка 82: | Строка 85: | ||
<pre>%gem_replace_version '~> 1.1.7' '~> 1.7'</pre> | <pre>%gem_replace_version '~> 1.1.7' '~> 1.7'</pre> | ||
* поскольку '''bundler''' позволяет хранить в одном и том же дереве бисеров несколько версий для каждого из них, а система альта такого не позволяет делать, требуется создание пакета совместимости версии, который будет содержать заполненную дефисами версию бисера без заплаточного числа (patch number), в дополнение к его имени, напр. такой бисер '''compat-gem''' будет иметь имя пакета: <tt>gem-compat-gem-1-2-1.2.0.src.rpm</tt>. | * поскольку '''bundler''' позволяет хранить в одном и том же дереве бисеров несколько версий для каждого из них, а система альта такого не позволяет делать, требуется создание пакета совместимости версии, который будет содержать заполненную дефисами версию бисера без заплаточного числа (patch number), в дополнение к его имени, напр. такой бисер '''compat-gem''' будет иметь имя пакета: <tt>gem-compat-gem-1-2-1.2.0.src.rpm</tt>; | ||
* зависимость бисеров, в которых явным образом проводится сборка библиотек ''.so'' из исходников, автоматически проставляется зависимость на текущую версию руби, чтобы при пересборке самого руби с новой версиею, при ее изменении принудительно приходилось пересобирать и такие пакеты. | |||
=== Макросы RPM === | === Макросы RPM === |
Текущая версия от 01:38, 6 февраля 2019
Ruby Policy
Правила упаковки модулей и программ на языке Ruby
Введение
Руби и модульность
Для простоты употребления ссылок, они будут действительны для 2.6.1.
Язык разработки руби обладает модульностю начиная с зари его изобретения в 1993-м, так если все основные функции, описанные в ядре руби, находятся в libruby, и являются его неотъемлемой частью, то стандартная библиотека как раз модуляризирована, и ее модули расположены в папке /usr/lib/ruby/, в которой уже расположены руби интерпретируемые модули, в подпапках с соответствующим названием, напр. модуль parser находится в модуле racc:
/usr/lib/ruby/racc/parser.rb
В подпапке с названием <архитектура>-<ось>, находятся компилируемые части соответственных модулей, модуль 'cparse находится в модуле racc:
/usr/lib/ruby/x86_64-linux/racc/cparse.so
Если какая либо стороннаяя библиотека (модуль) должна была быть использована в рядовых программах руби, то ее библиотеки должны были быть положены в соотвестствующие папки в /usr/lib/ruby/site_ruby/, которая является местом размещения библиотек руби не из числа стандартного набора.
В нынешней ситуации действительной на 2019 год, для развертывания дополнительных модулей используются модули rubygems и bundler, ныне поставляющиеся в виде пакета вида с англоязычным назанием gem (русское название бисер будет употребляться далее), хотя первый был когда-то обычным сторонним модулем. Проект rubygems был начат в апреле 2009, bundler четырьмя месяцами позднее в августе того же года. На текущий момент пара этих бисеров является по праву и на деле единственной системой определения зависимостей рубишной системы.
Зависимости в текущих проектах руби бывают 2-х видов:
- через <gem>.gemspec;
- через Gemfile.
.gemspec является единственным файлом описания зависимостей для системы rubygems бисеров, зависимости в котором могут быть скучены в 2 группы, зависимости исполения (runtime), и зависимости разработки (development), и последние также используются для тестирования проектов.
Gemfile является файлом описания как зависимостей разработки для бисеров (в дополнение к .gemspec), а также зависимостей различного рода для иных проектов, напр. для окружений разработки, тестирования, боевого, и прочих, не являющихся собственно бисерами. В современных проектах для рельс (rails), или других напр. синатры (sinatra), файла требуемые для определенного окружения описываются практически полностью только файлом Gemfile, то есть bundler сам решает в зависимости от писанного в том файле какие бисеры и их модули загружать для текущего окружения. Что во многих проектах приводит к тому, что явные вызовы метода require опускаются, например в проектах chef, puppet, или foreman современных версий. Типичный Gemfile можно найти тут.
Зависимости на версию ruby также определяется на основе Gemfile и .gemspec.
Версионирование
В руби и подсистеме бисеров для изменения правок бисеров применяется так называемый подход семантического версионирования, при котором первое число отражает "великое" изменение в библиотеке, когда меняется скажем API, второе число - "малое" изменение, при добавлении функциональности без ломки обратной совместимости, а третье - заплаточное изменение (patch number).
Сравнение с предыдущей политикою
Собственно подход с поиском зависимостей сугубо по вызовам метода require к текущему моменту существенно ограничивается следующими моментами:
- вызовы этого метода не всегда являются определяющими для точного обнаружения и составления списка зависимостей, для бисеров, а в большей мере для проектов на основе Gemfile, поскольку в коде могут быть фиктивные вызовы обрамленные некоторым кодом, который делает этот вызов не обязательным, но возможным для работы бисера;
- для Gemfile проектов потому, что вызовы require являются неявными и выполняются bundler-ом опосредованно на основе анализа Gemfile и .gemspec если таковой присутствует. также bundler следит за тем, чтобы среда и окружение разработки таких проектов были целостными, это приводит к том, что вызов require к внешнему модулю при необъявленная зависимость на него в Gemfile, приведет к критическому затруднения разработки проекта;
- имя внешнего модуля не всегда может быть извлечено из анализа вызова require, из-за нестанрдартного объявления имен модулей в таких библиотеках, напр. бисер имеет имя 'foo-bar', модули в нем могу быть вида: FooBar, FooBar, или Foo/Bar, с файловыми соответствиями foo_bar, foo/bar, последний вызовет ложное срабатывание на модуль с именем foo;
- из-за неявности загрузки как внешних модулей проекта, поскольку вызовы require к внешним библиотекам делает сам bundler;
- методика определения зависимостей из require не способна проконтролировать версии API зависимого пакета при смене оного, особенно в случае, когда под зависимостям на деле пакету требуется старое, и необновленное API.
Посему в нынешнюю пору намного надежнее использовать анализ пары Gemfile/.gemspec файлов для определения зависимостей.
Пакет ruby
В системе может быть только единственная библиотека libruby, с единственным набором модулей stdlibs.
При сборке новой версии libruby должны быть пересобраны все модули stdlibs, также все бисеры, которые содержат подгружаемые .so библиотеки, и все модули, для которых в файлах Gemfile/.gemspec прописано явное требование к версии руби, которое удовлетворяет новая версия libruby.
Внешний вид пакета
- пакеты собранные на основе бисера имеют префикс gem-;
- исходные пакеты с приложениями на рельсах, синатре или подобных средах могут быть без префикса, при конфликтах возможен префикс rubyapp-;
- модули stdlibs, а также иные проекты, не попадающие в предыдущие два пункта, и библиотеки которых кладутся в папку site_ruby, должны иметь префикс ruby-;
- символы подчёркивания "_" заменяются в имени пакета на символы дефиса "-".
Зависимости
Зависимости теперь отслеживаются на основе анализа пары Gemfile/.gemspec.
Экспорт зависимостей на бисеры имеет вид gem(gemname) = version и rubygem(gemname) = version, для совместимости с пакетами rpm от redhat.
Конфликт зависимостей
В случае конфликта зависимостей применяются один из двух способов их разрешения:
- в случае сохранения работоспособности бисера следует применять схему с явным объявлением макроса подмены версии требуемой библиотеки, имеющим имя gem_replace_version, напр. с ~> 1.1.7 на ~> 1.7:
%gem_replace_version '~> 1.1.7' '~> 1.7'
- поскольку bundler позволяет хранить в одном и том же дереве бисеров несколько версий для каждого из них, а система альта такого не позволяет делать, требуется создание пакета совместимости версии, который будет содержать заполненную дефисами версию бисера без заплаточного числа (patch number), в дополнение к его имени, напр. такой бисер compat-gem будет иметь имя пакета: gem-compat-gem-1-2-1.2.0.src.rpm;
- зависимость бисеров, в которых явным образом проводится сборка библиотек .so из исходников, автоматически проставляется зависимость на текущую версию руби, чтобы при пересборке самого руби с новой версиею, при ее изменении принудительно приходилось пересобирать и такие пакеты.
Макросы RPM
Макросы, требуемые для опакечивания бисеров и приложений руби, определены в rpm-, который советуем объявить в спецификации пакета в сборочном требовании в пометой (pre), так BuildRequires(pre): rpm-build-ruby:
Сборочные макросы таковы:
%__ruby %_bindir/ruby %__setup_rb %_bindir/setup.rb %ruby_func() %__ruby -rrubygems -rrbconfig -e %* %ruby_rubyconf_func() %__ruby -rrubygems -rrbconfig -e 'print RbConfig::CONFIG["%*"]' %ruby_gemspecdir %(%ruby_func 'print File.join( Gem.dir, "specifications" )') %ruby_gemextdir %(%ruby_func 'print File.join( Gem.dir, "extensions", RbConfig::CONFIG["sitearch"], RbConfig::CONFIG["ruby_version"] )') %ruby_gemlibdir %(%ruby_func 'print File.join( Gem.dir, "gems" )') %ruby_ridir %(%ruby_rubyconf_func ridir) %gem_build %__setup_rb build %gem_install %__setup_rb install --install_prefix=%buildroot %gem_test %__setup_rb test %gem_show %__setup_rb show --install_prefix=%buildroot
Расположение файлов
Файлы бисеров будут располагаться в соответствующих подпапках для бисеров папки /usr/lib/ruby/gems/2.5.0/, где 2.5.0 версия руби без учета заплаточного числа.
Заметки по спецификации пакета
- также пакеты содержащие основной код бисера, должны иметь группу Development/Ruby. А пакеты содержащие исполняемый код из того или иного бисера, должны иметь группу соответствующую назначению пакета;
- пакеты, не содержащие двоичного исполняемого кода модуля, должны содержать явное объявление архитектуры noarch.
Типовой .spec
Для исправления старых или сломанных пактов, а также создания новых можно использовать такой типовой файл спецификации:
%define pkgname gemmodule Name: ruby-%pkgname Version: 0.0.0 Release: alt1 Summary: summary Group: Development/Ruby License: <LICENSE> URL: https://site.org/ # VCS: https://github.com/user/gemmodule.git Source: %pkgname-%version.tar BuildRequires(pre): rpm-build-ruby BuildRequires: gem(another_gem) %description %summary %package -n %pkgname Summary: summary Group: Development/Other BuildArch: noarch %description -n %pkgname %summary %package doc Summary: Documentation for <package> Group: Development/Documentation BuildArch: noarch %description doc Documentation for <package>. %prep %setup -q -n %pkgname-%version %build %gem_build %install %gem_show %gem_install %check %gem_test %files %rubygem_gemdir/* %rubygem_extdir/* %rubygem_specdir/* %files -n %pkgname %_bindir/* %files doc %ruby_ridir/* %changelog
Тестирование
Тестирование пакетов руби подсистемы проводится с помощью пакета gem-setup, который определяет и запускает необходимые для проверки руби пакета тесты, определенные в Gemspec/.gemspec. Для включения тестирования пакета необходимо включать в .spec пакета явные требования к зависимым пакетам на этапе сборки, напр.:
BuildRequires: gem(another_gem) >= 1.0
Правила перехода на схему сию
- Все зависимости Requires для всех подпакетов определяются автоматически, посему все такие зависимости должны быть отвержены;
- Зависимости BuildRequires для пакета в случае, если проводится тестиование (раздел %check) или если это является крайне необходимым, должны быть прописаны явно, получены они могут быть с помощью приложения setup.rb;
- Также в случае, если пакет был переименован, требуется явным образом прописать в Provides старое имя пакета;
- В разделе %prep отвергаются все макросы указывающие на ruby, в частности %update_setup_rb;
- В разделе %build все макросы указывающие на ruby, например %ruby_build, %ruby_config заменяются на %gem_build;
- В разделе %install все макросы указывающие на ruby заменяются на %gem_install;
- В разделе %check все макросы указывающие на ruby заменяются на %gem_test, хотя при крайней и неотложной необходимсти этот макрос может быть засерен;
- В разделе %files для корневого пакета заменяются следующие макросы %[ruby]gem_specdir на %ruby_gemspecdir, %ruby_sitelibdir на %ruby_gemlibdir, %ruby_sitearchdir на %ruby_gemextdir;
- В разделе %files для пакета документации %ruby_ri_sitedir макрос заменяется на %ruby_ridir.
Автоматизация
Для автоматизации надзора и обновления рубишных пакетов используется бисер gem-rubobot, который будет выполнять следующие функции:
- проводить надзор за новыми версиями пакетов и уведомлять об их появлении на rubygems.org;
- проводить надзор за новыми версиями руби и уведомлять об их появлении;
- осуществлять контроль целостности подсистемы бисеров с помощью специально созданного Gemfile;
- при достижении числа скачиваний бисера более определенного значения (по умолчанию 1 миллион), в автоматизированном пытаться опакечивать такой бисер, и уведомлять в случае как успеха, так и обратном случае;
- в автоматическом режиме пытаться обновить бисеры с учётом сохранения целостности бисерной подсистемы и уведомлять в случае невозможности обновить бисерный пакет;
- в автоматическом режиме пытаться обновить пакеты с приложениями на руби, который здесь также подразумевает попытку собирать приложение с заменой версии с помощью макроса, и уведомлять при невозможности собрать пакеты с приведенными правками;
- в полуавтоматическом режиме (то есть по прямой указивке оператора) собирать приложения руби с автоматическим созданием пакетов совместимости.
- в полуавтоматическом режиме (то есть по прямой указивке оператора) собирать руби с автоматическою пересборкою необходимых пакетов по зависимостям.