|
|
(14 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
| {{DraftPolicy
| | #REDIRECT [[Ruby/Policy_2.0]] |
| |responsible=[[Участник:majioa|Малъ Скрылевъ]]
| |
| |discussion_link=https://lists.altlinux.org/pipermail/devel/2019-February/206679.html
| |
| |discussion_since=05.02.2019
| |
| }}
| |
| | |
| == Ruby Policy ==
| |
| | |
| __TOC__
| |
| | |
| '''''Rules for ruby module and application packages'''''
| |
| | |
| === Introduction ===
| |
| | |
| ==== Ruby and modularity ====
| |
| | |
| NOTE: To simplify link usage, they will be treated as for 2.6.1 ruby version.
| |
| | |
| The ruby language have the modularity feature begginging with the day-spring of its invention in 1993th, so if we have [http://ruby-doc.org/core-2.6.1/all the core functions of ruby] are placed into the ''libruby.so'', are built-in part of the language, then [http://ruby-doc.org/stdlib-2.6.1/ ruby's standard library] is modularized, and its modules are resided in the <tt>/usr/lib/ruby/</tt> folder that has the interpreted modules inside the consequently named folders. For example: '''parser''' module is placed in the ''racc'' module:
| |
| | |
| <tt>/usr/lib/ruby/racc/parser.rb</tt>
| |
| | |
| Inside the folder named as <arch>-<os>, there are some compiled parts for the respective modules, so ''''cparse''' modules is placed in ''racc'' module:
| |
| | |
| <tt>/usr/lib/ruby/x86_64-linux/racc/cparse.so</tt>
| |
| | |
| Therefore the when a side library (module) ought to be be used in ordinal ruby applications, then its library modules must be placed into the respective folders in ''/usr/lib/ruby/site_ruby/'', and the last is the only place to reside libraries not from the ruby standard set.
| |
| | |
| В нынешней ситуации действительной на 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'' можно найти [https://raw.githubusercontent.com/theforeman/foreman/develop/Gemfile тут].
| |
| | |
| Зависимости на версию ruby также определяется на основе ''Gemfile'' и ''.gemspec''.
| |
| | |
| ==== Версионирование ====
| |
| | |
| В руби и подсистеме бисеров для изменения правок бисеров применяется так называемый подход [https://semver.org/lang/ru/ семантического версионирования], при котором первое число отражает "великое" изменение в библиотеке, когда меняется скажем API, второе число - "малое" изменение, при добавлении функциональности без ломки обратной совместимости, а третье - заплаточное изменение (patch number).
| |
| | |
| | |
| === Сравнение с [[Ruby Policy|предыдущей политикою]] ===
| |
| | |
| Собственно подход с поиском зависимостей сугубо по вызовам метода '''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''':
| |
| | |
| <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>;
| |
| | |
| * зависимость бисеров, в которых явным образом проводится сборка библиотек ''.so'' из исходников, автоматически проставляется зависимость на текущую версию руби, чтобы при пересборке самого руби с новой версиею, при ее изменении принудительно приходилось пересобирать и такие пакеты.
| |
| | |
| === Макросы RPM ===
| |
| | |
| Макросы, требуемые для опакечивания бисеров и приложений руби, определены в ''rpm-'', который советуем объявить в спецификации пакета в сборочном требовании в пометой ''(pre)'', так <tt>BuildRequires(pre): rpm-build-ruby</tt>:
| |
| | |
| Сборочные макросы таковы:
| |
| | |
| <pre>
| |
| %__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
| |
| </pre>
| |
| | |
| | |
| === Расположение файлов ===
| |
| | |
| Файлы бисеров будут располагаться в соответствующих подпапках для бисеров папки ''/usr/lib/ruby/gems/2.5.0/'', где 2.5.0 версия руби без учета заплаточного числа.
| |
| | |
| === Заметки по спецификации пакета ===
| |
| | |
| # также пакеты содержащие основной код бисера, должны иметь группу ''Development/Ruby''. А пакеты содержащие исполняемый код из того или иного бисера, должны иметь группу соответствующую назначению пакета;
| |
| # пакеты, не содержащие двоичного исполняемого кода модуля, должны содержать явное объявление архитектуры noarch.
| |
| | |
| ==== Типовой .spec ====
| |
| | |
| Для исправления старых или сломанных пактов, а также создания новых можно использовать такой типовой файл спецификации:
| |
| | |
| <pre>
| |
| %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
| |
| | |
| </pre>
| |
| | |
| === Тестирование ===
| |
| | |
| Тестирование пакетов руби подсистемы проводится с помощью пакета '''gem-setup''', который определяет и запускает необходимые для проверки руби пакета тесты, определенные в '''Gemspec'''/'''.gemspec'''. Для включения тестирования пакета необходимо включать в '''.spec''' пакета явные требования к зависимым пакетам на этапе сборки, напр.:
| |
| | |
| <pre>BuildRequires: gem(another_gem) >= 1.0 </pre>
| |
| | |
| === Правила перехода на схему сию ===
| |
| | |
| # Все зависимости '''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 миллион), в автоматизированном пытаться опакечивать такой бисер, и уведомлять в случае как успеха, так и обратном случае;
| |
| * в автоматическом режиме пытаться обновить бисеры с учётом сохранения целостности бисерной подсистемы и уведомлять в случае невозможности обновить бисерный пакет;
| |
| * в автоматическом режиме пытаться обновить пакеты с приложениями на руби, который здесь также подразумевает попытку собирать приложение с заменой версии с помощью макроса, и уведомлять при невозможности собрать пакеты с приведенными правками;
| |
| * в полуавтоматическом режиме (то есть по прямой указивке оператора) собирать приложения руби с автоматическим созданием пакетов совместимости.
| |
| * в полуавтоматическом режиме (то есть по прямой указивке оператора) собирать руби с автоматическою пересборкою необходимых пакетов по зависимостям.
| |
| | |
| [[Категория:Ruby]]
| |