Extensions Are Dead, Long Live Extensions!
SolidusConf 2019
alessandro.codes

github.com/aldesantis
medium.com/@aldesantis

Why extensions?
Indicator of health 🏥
Reduced overhead 💰
Ease of onboarding 🚀
The questions we get most often about Solidus are about the size, governance model and overall health of its extension ecosystem.
50+ extensions
180K+ lines of code
Where are we today?
6 core team members
40 hours in the week
😕
What we'll cover
Maintaining extensions 🛠
Extending extensions 🙆♂️
Governing extensions 👑
Advertising extensions 📣
🛠
Maintaining extensions
Stale issues and PRs

Broken builds


Outdated docs
No changelogs
Inconsistent coding style
Insufficient tests
Outdated dependencies
Just the tip of the iceberg...
What can we do?
Designated maintainers

Implement new features
Triage issues and PRs
Improve tests
Upgrade dependencies
Maintain documentation
Maintainers will...
Gather feedback
Automate all the things!
Our goal is to minimize the human work required for maintaining extensions.
🤖
Readme template

Changelog generation
$ github_changelog_generator solidusio/solidus_auth_devise

PR reminders



Automatic upgrades
A few more tricks
One spec_helper to rule them all
ENV["RAILS_ENV"] ||= "test"
require File.expand_path("dummy/config/environment.rb", __dir__)
require "solidus_support/extension/feature_helper"
Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each { |f| require f }
$ rake

Centralized CI
version: 2.1
orbs:
ext: solidusio/extensions@volatile
jobs:
run-specs-with-postgres:
executor: ext/postgres
steps:
- ext/run-tests
run-specs-with-mysql:
executor: ext/mysql
steps:
- ext/run-tests
workflows:
"Run specs on supported Solidus versions":
jobs:
- run-specs-with-postgres
- run-specs-with-mysql
"Weekly run specs against master":
triggers:
- schedule:
cron: "0 0 * * 4"
jobs:
- run-specs-with-postgres
- run-specs-with-mysql


$ gem install solidus_cmd
$ solidus extension my_extension

🙆♂️
Extending
extensions
module Spree
class FeedProduct
attr_reader :product
def initialize(product)
@product = product
end
def id
product.id
end
def title
product.name
end
# ...
end
end

class_eval
Spree::FeedProduct.class_eval do
def description
product.description
end
end
super ❌
Hard to debug
Very brittle
prepend
module AcmeStore
module Spree
module FeedProduct
module AddDescription
def description
product.description
end
::Spree::FeedProduct.prepend self
end
end
end
end
super ✅
Module#ancestors
Still brittle
POROs
# app/models/acme_store/feed_product.rb
module AcmeStore
class FeedProduct < Spree::FeedProduct
def description
product.description
end
end
end
# config/intitializers/solidus_product_feed.rb
SolidusProductFeed.configure do |config|
config.feed_product_class = 'AcmeStore::FeedProduct'
end
super ✅
Clearly documented
Stable contract
One more thing...
The Event Bus
# Somewhere in an extension:
Spree::Event.fire(
'subscription.renewed',
subscription: @subscription
)
# Somewhere in my app:
Spree::Event.subscribe 'subscription.renewed' do |event|
subscription = event.payload[:subscription]
SubscriptionsMailer.thank_you_email(subscription).deliver_now
end
Support for multiple adapters
Flexible subscribers
Extension-friendly
👑
Governing extensions
Unclear governance
solidus_virtual_gift_card
solidus_multi_domain
solidus_asset_variant_options
solidus_signifyd
solidus_avatax
solidusio
solidus_reviews
solidus_stripe
solidus_cmd
solidus_reports
solidus_graphql_api
solidusio-contrib
solidusio
solidusio-contrib
Critical functionality/integrations
Maintained by the core team
Proposed by the core team
Additional functionality
Maintained by the community
Proposed by the community
Unclear governance
We don't need...
Legacy code
Trivial customizations
Business-specific features

📣
Advertising extensions
Presentation matters








Too many channels

a single point of discovery,
quality metrics, and
a dashboard for maintainers.
We want to streamline the experience of looking for Solidus extensions by creating a unified experience that will provide:
(Coming in 2020!)
☠️
Extensions are dead.
We need to radically rethink how we use extensions and where we direct our maintenance efforts.
🙌
Long live extensions!
With the right mindset, we can create an extensions ecosystem that will save our users time and money.
🙏
We need you!
Volunteer as an extension maintainer
Contribute on GitHub
Improve our automation tools
Support us on OpenCollective
With your help, we can build the future of Solidus, a future that will continue to be
free,
open
and extensible.
