|
|
(13 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.
| |
| | |
| The the modern context, which is valid for 2019, in order to deploy additional modules, the '''rubygems''' and '''bundler''' modules are used, which kind of the modules is called as ''gem'' (russian ''''бисер'''), and the first of them previously treated as usual ruby side module. The '''rubygems''' has begun in 2009 Apr., '''bundler''' in four months last than '''rubygems''' in Aug the same year. In present, the pair of the gems is de-facto an de-jure the only dynamically working system of dependencies of ruby modules system.
| |
| | |
| In modern projects the ruby gem dependencies can be provided with two ways:
| |
| * via ''<gem>.gemspec'';
| |
| * via ''Gemfile''.
| |
| | |
| The ''.gemspec'' is the only file to declare dependencies for '''rubygems''' between the gems themselves. The dependencies in the file can be joined into two groups separately: runtime, and development, and the least can be used also to test the gem project.
| |
| | |
| The ''Gemfile'' is the file to define local dependencies (additionally to ''.gemspec'') from the other gems. The project containing the ''Gemfile'' counkl not be exactly the ''gem'', but it can be one of the modern ruby application type as: rails or sinatra application, ruby script application. The dependencies can be joined into various kinds of groups along the ''default'' one like ''production'', ''development'', ''test'', ''assets'' etc. Based on the current environment and written in the '''Gemfile''' scheme, the '''bundler''' makes a decision itself, which the gems shall be loaded, and which must be hidden that leads to situation when explicit declaration to call a module from a gem will be avoided. For example it can be observed in rails application like '''chef''' or '''foreman''', or script application '''opennebula'''.
| |
| | |
| Typical ''Gemfile'' can be found [https://raw.githubusercontent.com/theforeman/foreman/develop/Gemfile here].
| |
| | |
| Dependencies to ruby also can be defined in '''Gemfile''' or '''.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]]
| |