Make optional plugin gems truly optional with require_optional - #145
Merged
Merged
Conversation
Installing the framework installed a database, an HTML parser and a feed autodiscovery client, because the store plugins, the plugins that read HTML and two CLI subcommands had their gems in the gemspec's runtime dependencies. A Recipe that stores nothing and parses no HTML paid for all of it, which is not what "small core plus independent plugins" means. The runtime dependencies are now what lib/ requires and nothing else: activesupport, hashie, rexml and rss. activerecord, sqlite3, nokogiri and feedbag are optional plugin dependencies, declared in the Gemfile's optional groups and required inside the plugin that uses them. An optional gem is required through Automatic.require_optional, which names the gem, what needed it and how to install it when it is absent; the CLI reports that as a message and exit status 1 rather than a backtrace. PublishMarkdown, which the Quick Start publishes with, now reduces an HTML body to text with nokogiri where it is installed and with its own substitution where it is not, so the documented first workflow runs on a plain `gem install automatic`; the specs hold the two to the same output. The shipped Quick Start Recipe drops StorePermalink, which is now the documented next step, taken together with its gems. Each optional gem is in two groups: `plugins`, which is all of them, and one named for what it is for, which selects it alone. That gives the three documented ways to set up a checkout -- minimal, all supported plugins, and one dependency at a time -- and DEPLOYMENT.md carries the single table of which plugin needs which gem. The plugins whose specs need a running service stay outside `plugins`, so installing that group leaves the suite runnable. The default suite passes with no optional gem installed and the required workflow installs none, which is what keeps the split honest; a separate non-required workflow installs the `plugins` group and runs the same suite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019J9jKyHkYSFzPY7xiXLwSc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This change restructures how Automatic Ruby handles optional plugin dependencies, making them genuinely optional by introducing a new
Automatic.require_optionalmethod and reorganizing the Gemfile to use fine-grained optional groups instead of a monolithic:pluginsgroup.Key Changes
New
Automatic.require_optionalmethod inlib/automatic.rb: Replaces barerequirestatements for optional gems with a method that provides helpful error messages naming the gem, the plugin that needs it, and installation instructions when a gem is missing.Reorganized Gemfile: Replaced the single optional
:pluginsgroup with multiple fine-grained groups (store,html,sanitize,nkf,autodiscovery) so operators can install only what they need. Thepluginsgroup still exists as a convenience that includes all of them.Updated plugin files to use
Automatic.require_optional:FilterSanitize,FilterDescriptionLink,FilterFullFeed,FilterImageSource,SubscriptionTwitternow use the new methodPublishMarkdownmade truly optional by implementing HTML-to-text conversion without nokogiri as a fallbackPublishMarkdown enhancement: Added built-in HTML entity decoding and markup reduction without requiring nokogiri, allowing the Quick Start to run on a plain
gem install automatic. When nokogiri is installed, it uses the parser for better handling of malformed markup.Documentation updates across DEPLOYMENT.md, PLUGINS.md, POLICY.md, README.md, and QUICKSTART.md to explain the new optional dependency model and how to install gems for specific plugins.
New CI workflow (
.github/workflows/plugins.yml): Tests that the optionalpluginsgroup resolves and that plugin specs pass when optional gems are installed.Updated test infrastructure: Modified spec helpers and individual plugin specs to properly guard optional dependency tests and clarify the distinction between the default suite and optional plugin coverage.
Notable Implementation Details
Automatic.require_optionalacceptsgem_nameparameter for gems where the require path differs from the gem name (e.g.,xml-simplegem vsxmlsimplerequire path)feed2markdown.yml) was simplified to not require StorePermalink by default, with instructions to add it as an optional stepLoadErrorseparately to provide user-friendly messages for missing optional gems rather than backtraceshttps://claude.ai/code/session_019J9jKyHkYSFzPY7xiXLwSc