Ruby Policy 2.0: Difference between revisions

From ALT Linux Wiki
(Created page with "{{DraftPolicy |responsible=Малъ Скрылевъ |discussion_link=https://lists.altlinux.org/pipermail/devel/2019-February/206679.html |discuss...")
 
(redirect added)
Tag: New redirect
 
(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]]

Latest revision as of 14:47, 18 March 2019

Redirect to: