https://www.redmine.org/https://www.redmine.org/favicon.ico?16793021292017-12-31T16:43:58ZRedmineRedmine - Feature #27705: Gemify redmine pluginshttps://www.redmine.org/issues/27705?journal_id=828292017-12-31T16:43:58ZToshi MARUYAMA
<ul></ul><p>+100</p>
<p>I have a question.<br />"require initializer" is called twice. Is it correct?<br />One is in this patch and another is in original code.</p> Redmine - Feature #27705: Gemify redmine pluginshttps://www.redmine.org/issues/27705?journal_id=829192018-01-04T15:16:15ZSho HASHIMOTO
<ul></ul><blockquote>
<p>+100</p>
</blockquote>
<p>Thanks!</p>
<blockquote>
<p>"require initializer" is called twice. Is it correct?<br />One is in this patch and another is in original code.</p>
</blockquote>
<p>Oh... Maybe it's cause problem.</p>
<p>I left original code. Original code is for loading current structure plugins.</p>
<p>I think, there are below patterns.</p>
<ol>
<li>Same plugin and same version: Maybe, problem doesn't break to the surface.</li>
<li>Same plugin and different version: Cause problems. Both require will success. Overwritten by plugin dir's one halfway.</li>
<li>Different plugins and same ID: Cause problems. Both require will success. Each function will not be conflicted. But redmine will misunderstand only plugin dir's one was loaded.</li>
<li>Different plugins and different IDs: No problem.</li>
</ol>
<p>1., 2., 3. have same problem. @registered_plugins[id] was overwritten.<br />To fix this, for example, Redmine::Plugin.register(id) raises(or fails) if plugin was already installed.</p>
<pre><code class="diff syntaxhl"> def self.register(id, &block)
<span class="gi">+ raise ... if installed?(id) # or return
+
</span> p = new(id)
p.instance_eval(&block)
</code></pre>
<p>I think, it is difficult to find 2. by administrator if only return.</p> Redmine - Feature #27705: Gemify redmine pluginshttps://www.redmine.org/issues/27705?journal_id=831092018-01-15T02:13:00ZAkipii Oga
<ul></ul><p>+1 .<br />I agree.<br />I want all plugin and installation of Redmine main body to change to Gem. Also, I would like the installation work to be easy.</p> Redmine - Feature #27705: Gemify redmine pluginshttps://www.redmine.org/issues/27705?journal_id=834792018-02-03T10:44:09ZToshi MARUYAMA
<ul></ul><p>Sho HASHIMOTO wrote:</p>
<blockquote>
<p>I think, it is difficult to find 2. by administrator if only return.</p>
</blockquote>
<p>Can we raise exception if plugin name is duplicate?</p> Redmine - Feature #27705: Gemify redmine pluginshttps://www.redmine.org/issues/27705?journal_id=841132018-03-24T03:44:33ZSho HASHIMOTO
<ul></ul><blockquote><blockquote>
<p>I think, it is difficult to find 2. by administrator if only return.</p>
</blockquote>
<p>Can we raise exception if plugin name is duplicate?</p>
</blockquote>
<p>OK. I created another ticket. <a class="issue tracker-2 status-1 priority-4 priority-default" title="Feature: Reject plugin same ID with registered one (New)" href="https://www.redmine.org/issues/28412">#28412</a></p> Redmine - Feature #27705: Gemify redmine pluginshttps://www.redmine.org/issues/27705?journal_id=842322018-03-31T02:33:11ZGo MAEDA
<ul><li><strong>Category</strong> set to <i>Plugin API</i></li></ul> Redmine - Feature #27705: Gemify redmine pluginshttps://www.redmine.org/issues/27705?journal_id=1105942023-08-23T14:12:16ZTakashi Kato
<ul><li><strong>File</strong> <a href="/attachments/30863">0001-Enable-to-use-gem-as-a-Redmine-plugin.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/30863/0001-Enable-to-use-gem-as-a-Redmine-plugin.patch">0001-Enable-to-use-gem-as-a-Redmine-plugin.patch</a> added</li><li><strong>File</strong> <a href="/attachments/30864">0002-Add-redmine_plugin_gem-generator.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/30864/0002-Add-redmine_plugin_gem-generator.patch">0002-Add-redmine_plugin_gem-generator.patch</a> added</li><li><strong>File</strong> <a href="/attachments/30865">0003-Sohw-gems-badge-on-plugin-list.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/30865/0003-Sohw-gems-badge-on-plugin-list.patch">0003-Sohw-gems-badge-on-plugin-list.patch</a> added</li><li><strong>File</strong> <a href="/attachments/30866">0004-Add-dependency-test.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/30866/0004-Add-dependency-test.patch">0004-Add-dependency-test.patch</a> added</li></ul><p>Patches for Redmine 5.0 or later (Rails 6.1 or later) are available here(tested in <a class="changeset" title="Generate snake-case file name by redmine_plugin_migration (#38730). Patch by Haruka Asakura." href="https://www.redmine.org/projects/redmine/repository/svn/revisions/22282">r22282</a>).</p>
<p>Making plugins as gems allows you to install all plugins at once by listing them in the <code>Gemfile.extension</code> and running bundle install.<br />This can be especially useful in a Docker environment where you don't need to create a separate script to install plugins.<br />On the other hand, plugins placed under <code>plugins/</code> directory will still work. I will refer to current plugins as <strong>"filesystem plugin"</strong> and gemified plugins as <strong>"gem plugin"</strong>.</p>
<p>If there's a <strong>"filesystem plugin"</strong> and a <strong>"gem plugin"</strong> with the same ID, the <strong>"filesystem plugin"</strong> takes priority<br />To install a <strong>"gem plugin"</strong>, add its name to <code>Gemfile.extension</code>. Note that the reason why <code>Gemfile.extension</code> is not named <code>Gemfile.plugin</code> is that we assume that themes will also be gemmed in the future.</p>
<p>For a <strong>"gem plugin"</strong>, the plugin information is divided into two files: <code>init.rb</code> and <code>gemspec</code>. Basic information like plugin name and author goes in <code>gemspec</code>, while Redmine-specific information like menus and settings stays in <code>init.rb</code>.</p>
<p>As a trial, I converted <code>redmine-view-customize</code> into a <strong>"gem plugin"</strong>. It works well. <a class="external" href="https://github.com/tohosaku/redmine-view-customize/tree/rubygems">https://github.com/tohosaku/redmine-view-customize/tree/rubygems</a><br />The gem name, Redmine plugin ID, git repository name, and class names under the lib directory do not need to match. However, you can match all of them.</p>
<table>
<tr>
<td> gem name </td>
<td> redmine-view-cusomize </td>
</tr>
<tr>
<td> git repository name </td>
<td> redmine-view-cusomize </td>
</tr>
<tr>
<td> Redmine::Plugin#id </td>
<td> view_customize </td>
</tr>
<tr>
<td> class name </td>
<td> redmine_view_cusomize </td>
</tr>
</table>
<p>On the other hand, if you try to register a plugin with a different gem name and the same plugin id, an error will occur.</p>
<a name="Differences-from-the-previous-version"></a>
<h2 >Differences from the previous version<a href="#Differences-from-the-previous-version" class="wiki-anchor">¶</a></h2>
<p><strong>"filesystem plugin"</strong> allowed adding a gem to Redmine itself by adding the gem in the plugin's <code>Gemfile</code>. This is because Redmine was reading each plugin's Gemfile and requiring it as a dependent gem of redmine itself. gem plugin requires an <code>add_runtime_dependency</code> to be listed in each <code>gemspec</code>. The dependencies are automatically loaded when the plugin is registered with Redmine.</p>
<a name="Creating-a-new-plugin"></a>
<h2 >Creating a new plugin<a href="#Creating-a-new-plugin" class="wiki-anchor">¶</a></h2>
<pre>
bin/rails g redmine_plugin_gem foo
</pre><br />When creating a gem, it is common to use the <code>bundle gem</code> command to create a template, but since there is a difference between a normal gem and a <strong>"gem plugin"</strong> in the way the <code>gemspec</code> is described below, we recommend using bin/rails g to create the template.
<a name="Notes-on-gemspec-for-gem-plugin"></a>
<h2 >Notes on gemspec for "gem plugin"<a href="#Notes-on-gemspec-for-gem-plugin" class="wiki-anchor">¶</a></h2>
<ul>
<li>In the <code>gemspec</code> file, Do not use variables, constants, etc. defined by gem (eg. <code>Foo::VERSION</code>). <code>gemspec</code> is evaluated before rails initialization is completed. redmine plugin variables and constants are supposed to be managed by the zeitwerk autoloader after rails is started, so using them at initialization time will cause errors.</li>
<li>Redmine plugin dependencies can also be described in <code>gemspec</code> using "add_runtime_dependency".</li>
<li>The <code>spec.metadata["redmine_plugin_id"] = "plugin id"</code> is required as metadata in <code>gemspec</code>.</li>
<li>The following attributes that were previously listed in <code>init.rb</code> will be overwritten by the corresponding attributes in <code>gemspec</code>.</li>
</ul>
<table>
<tr>
<td> <strong>attributes of init.rb</strong> </td>
<td> <strong>attributes of gemspec</strong> </td>
</tr>
<tr>
<td> name </td>
<td> summary </td>
</tr>
<tr>
<td> author </td>
<td> authors </td>
</tr>
<tr>
<td> description </td>
<td> description </td>
</tr>
<tr>
<td> version </td>
<td> version </td>
</tr>
<tr>
<td> url </td>
<td> homepage </td>
</tr>
<tr>
<td> author_url </td>
<td> metadata['author_url'] </td>
</tr>
</table>
<a name="UI-Changes"></a>
<h2 >UI Changes<a href="#UI-Changes" class="wiki-anchor">¶</a></h2>
<p>Added the ability to distinguish <strong>"gem plugin"</strong> or not in the list of plugins.</p>
<a name="How-to-develop-filesystem-plugin-and-gem-plugin-in-one-development-branch"></a>
<h2 >How to develop “filesystem plugin” and “gem plugin” in one development branch<a href="#How-to-develop-filesystem-plugin-and-gem-plugin-in-one-development-branch" class="wiki-anchor">¶</a></h2>
<ul>
<li>Place the gem plugin directory in the plugins directory, and enter the gem information required by the <strong>"filesystem plugin"</strong> for Redmine 4.2 and Redmine 5.0 in the <code>PluginGemfile</code>. <code>Gemfile</code> is ignored. Dependent gem information must be included in both the <code>PluginGemfile</code> and <code>gemspec</code>.</li>
<li>To create a plugin that works with both Redmine 4.2 and Redmine 5.0 or later, the <code>init.rb</code> must look like this</li>
</ul>
<pre><code class="ruby syntaxhl"><span class="k">if</span> <span class="no">Rails</span><span class="p">.</span><span class="nf">version</span> <span class="o">></span> <span class="s1">'6.0'</span> <span class="o">&&</span> <span class="no">Rails</span><span class="p">.</span><span class="nf">autoloaders</span><span class="p">.</span><span class="nf">zeitwerk_enabled?</span>
<span class="c1"># for Redmine5.0 or later</span>
<span class="k">else</span>
<span class="no">Rails</span><span class="p">.</span><span class="nf">configuration</span><span class="p">.</span><span class="nf">to_prepare</span> <span class="k">do</span>
<span class="c1"># for Redmine4.*</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre> Redmine - Feature #27705: Gemify redmine pluginshttps://www.redmine.org/issues/27705?journal_id=1121532024-01-02T18:37:25ZTakashi Kato
<ul><li><strong>File</strong> <a href="/attachments/31749">0001v2-Enable-to-use-gem-as-a-Redmine-plugin.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/31749/0001v2-Enable-to-use-gem-as-a-Redmine-plugin.patch">0001v2-Enable-to-use-gem-as-a-Redmine-plugin.patch</a> added</li></ul><p>Updated patch 0001, can be applied to <a class="changeset" title="Fix "any" operator for text filters to exclude empty text values (#39991). Patch by Go MAEDA (@m..." href="https://www.redmine.org/projects/redmine/repository/svn/revisions/22583">r22583</a></p>