diff --git a/Gemfile b/Gemfile index f179d6798..95c92d6d5 100644 --- a/Gemfile +++ b/Gemfile @@ -95,10 +95,6 @@ gem "omniauth-saml", "~> 2.1" gem "aasm" gem "after_commit_everywhere", "~> 1.0" -# Feature flags -gem "flipper" -gem "flipper-active_record" - # AI gem "ruby-openai" gem "langfuse-ruby", "~> 0.1.4", require: "langfuse" diff --git a/Gemfile.lock b/Gemfile.lock index 31e96df40..90cd42ced 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -219,11 +219,6 @@ GEM ffi (1.17.2-x86_64-darwin) ffi (1.17.2-x86_64-linux-gnu) ffi (1.17.2-x86_64-linux-musl) - flipper (1.3.6) - concurrent-ruby (< 2) - flipper-active_record (1.3.6) - activerecord (>= 4.2, < 9) - flipper (~> 1.3.6) foreman (0.88.1) fugit (1.11.1) et-orbi (~> 1, >= 1.2.11) @@ -803,8 +798,6 @@ DEPENDENCIES faraday faraday-multipart faraday-retry - flipper - flipper-active_record foreman hotwire-livereload hotwire_combobox diff --git a/app/services/provider_loader.rb b/app/services/provider_loader.rb index e2bf35365..e50b527e0 100644 --- a/app/services/provider_loader.rb +++ b/app/services/provider_loader.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Service class to load SSO provider configurations from either YAML or database -# based on the :db_sso_providers feature flag. +# based on the AUTH_PROVIDERS_SOURCE environment setting. # # Usage: # providers = ProviderLoader.load_providers @@ -38,17 +38,7 @@ class ProviderLoader def use_database_providers? return false if Rails.env.test? - begin - # Check if feature exists, create if not (defaults to disabled) - unless Flipper.exist?(:db_sso_providers) - Flipper.add(:db_sso_providers) - end - Flipper.enabled?(:db_sso_providers) - rescue ActiveRecord::NoDatabaseError, ActiveRecord::StatementInvalid, StandardError => e - # Database not ready or other error, fall back to YAML - Rails.logger.warn("[ProviderLoader] Could not check feature flag (#{e.class}), falling back to YAML providers") - false - end + FeatureFlags.db_sso_providers? end def load_from_database diff --git a/app/views/admin/sso_providers/index.html.erb b/app/views/admin/sso_providers/index.html.erb index 006dc2647..8709fbdb1 100644 --- a/app/views/admin/sso_providers/index.html.erb +++ b/app/views/admin/sso_providers/index.html.erb @@ -3,7 +3,7 @@

Manage single sign-on authentication providers for your instance. - <% unless Flipper.enabled?(:db_sso_providers) %> + <% unless FeatureFlags.db_sso_providers? %> Changes require a server restart to take effect. <% end %>

@@ -107,7 +107,7 @@

Database-backed providers

Load providers from database instead of YAML config

- <% if Flipper.enabled?(:db_sso_providers) %> + <% if FeatureFlags.db_sso_providers? %> Enabled diff --git a/app/views/invitations/new.html.erb b/app/views/invitations/new.html.erb index 7becb7650..a45c680b2 100644 --- a/app/views/invitations/new.html.erb +++ b/app/views/invitations/new.html.erb @@ -10,7 +10,7 @@ <%= form.select :role, options_for_select([ - (Flipper.enabled?(:intro_ui) ? [t(".role_guest"), "guest"] : nil), + (FeatureFlags.intro_ui? ? [t(".role_guest"), "guest"] : nil), [t(".role_member"), "member"], [t(".role_admin"), "admin"] ].compact), diff --git a/config/initializers/flipper.rb b/config/initializers/flipper.rb deleted file mode 100644 index 8c16b2e01..000000000 --- a/config/initializers/flipper.rb +++ /dev/null @@ -1,53 +0,0 @@ -# frozen_string_literal: true - -require "flipper" -require "flipper/adapters/active_record" -require "flipper/adapters/memory" - -# Configure Flipper with ActiveRecord adapter for database-backed feature flags -# Falls back to memory adapter if tables don't exist yet (during migrations) -Flipper.configure do |config| - config.adapter do - begin - Flipper::Adapters::ActiveRecord.new - rescue ActiveRecord::NoDatabaseError, ActiveRecord::StatementInvalid, NameError - # Tables don't exist yet, use memory adapter as fallback - Flipper::Adapters::Memory.new - end - end -end - -# Initialize feature flags IMMEDIATELY (not in after_initialize) -# This must happen before OmniAuth initializer runs -unless Rails.env.test? - begin - # Feature flag to control SSO provider source (YAML vs DB) - # ENV: AUTH_PROVIDERS_SOURCE=db|yaml - # Default: "db" for self-hosted, "yaml" for managed - auth_source = ENV.fetch("AUTH_PROVIDERS_SOURCE") do - Rails.configuration.app_mode.self_hosted? ? "db" : "yaml" - end.downcase - default_ui_layout = ENV.fetch("DEFAULT_UI_LAYOUT", "").downcase - - # Ensure feature exists before enabling/disabling - Flipper.add(:db_sso_providers) unless Flipper.exist?(:db_sso_providers) - if default_ui_layout.in?(%w[intro]) - Flipper.add(:intro_ui, tags: [ :intro_ui ]) unless Flipper.exist?(:intro_ui) - end - - if auth_source == "db" - Flipper.enable(:db_sso_providers) - else - Flipper.disable(:db_sso_providers) - end - - if default_ui_layout.in?(%w[intro]) - default_ui_layout == "intro" ? Flipper.enable(:intro_ui) : Flipper.disable(:intro_ui) - end - rescue ActiveRecord::NoDatabaseError, ActiveRecord::StatementInvalid - # Database not ready yet (e.g., during initial setup or migrations) - # This is expected during db:create or initial setup - rescue StandardError => e - Rails.logger.warn("[Flipper] Error initializing feature flags: #{e.message}") - end -end diff --git a/db/migrate/20260210120000_remove_flipper_tables.rb b/db/migrate/20260210120000_remove_flipper_tables.rb new file mode 100644 index 000000000..c9e64a869 --- /dev/null +++ b/db/migrate/20260210120000_remove_flipper_tables.rb @@ -0,0 +1,22 @@ +class RemoveFlipperTables < ActiveRecord::Migration[7.2] + def up + drop_table :flipper_gates, if_exists: true + drop_table :flipper_features, if_exists: true + end + + def down + create_table :flipper_features do |t| + t.string :key, null: false + t.timestamps null: false + end + add_index :flipper_features, :key, unique: true + + create_table :flipper_gates do |t| + t.string :feature_key, null: false + t.string :key, null: false + t.text :value + t.timestamps null: false + end + add_index :flipper_gates, [ :feature_key, :key, :value ], unique: true, length: { value: 255 } + end +end diff --git a/db/schema.rb b/db/schema.rb index 257ca09f1..dd8b82423 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2026_02_08_110000) do +ActiveRecord::Schema[7.2].define(version: 2026_02_10_120000) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -522,22 +522,6 @@ ActiveRecord::Schema[7.2].define(version: 2026_02_08_110000) do t.index ["merchant_id"], name: "index_family_merchant_associations_on_merchant_id" end - create_table "flipper_features", force: :cascade do |t| - t.string "key", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["key"], name: "index_flipper_features_on_key", unique: true - end - - create_table "flipper_gates", force: :cascade do |t| - t.string "feature_key", null: false - t.string "key", null: false - t.text "value" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["feature_key", "key", "value"], name: "index_flipper_gates_on_feature_key_and_key_and_value", unique: true - end - create_table "holdings", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "account_id", null: false t.uuid "security_id", null: false diff --git a/lib/feature_flags.rb b/lib/feature_flags.rb new file mode 100644 index 000000000..e20472e81 --- /dev/null +++ b/lib/feature_flags.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module FeatureFlags + class << self + def db_sso_providers? + auth_source = ENV.fetch("AUTH_PROVIDERS_SOURCE") do + Rails.configuration.app_mode.self_hosted? ? "db" : "yaml" + end + + auth_source.to_s.downcase == "db" + end + + def intro_ui? + Rails.configuration.x.ui.default_layout.to_s.in?(%w[intro dashboard]) + end + end +end diff --git a/test/controllers/invitations_controller_test.rb b/test/controllers/invitations_controller_test.rb index 7035eee5c..90a8e7102 100644 --- a/test/controllers/invitations_controller_test.rb +++ b/test/controllers/invitations_controller_test.rb @@ -9,7 +9,6 @@ class InvitationsControllerTest < ActionDispatch::IntegrationTest test "should get new" do get new_invitation_url assert_response :success - assert_select "option[value=?]", "guest", count: 0 unless Flipper.enabled?(:intro_ui) assert_select "option[value=?]", "member" assert_select "option[value=?]", "admin" end