diff --git a/Gemfile b/Gemfile index 43e9002f9..63f834d22 100644 --- a/Gemfile +++ b/Gemfile @@ -44,6 +44,9 @@ gem "fastly", "~> 2.5" # Client library for the Fastly acceleration system gem "feedjira", "~> 3.1" # A feed fetching and parsing library gem "field_test", "~> 0.3" # A/B testing gem "figaro", "~> 1.2" # Simple, Heroku-friendly Rails app configuration using ENV and a single YAML file +gem "flipper", "~> 0.17.2" # Feature flipping / flags for Ruby +gem "flipper-active_record", "~> 0.17.2" # Store Flipper flags in ActiveRecord +gem "flipper-ui", "~> 0.17.2" gem "fog-aws", "~> 3.6" # 'fog' gem to support Amazon Web Services gem "front_matter_parser", "~> 0.2" # Parse a front matter from syntactically correct strings or files gem "gemoji", "~> 4.0.0.rc2" # Character information and metadata for standard and custom emoji diff --git a/Gemfile.lock b/Gemfile.lock index bc9b73872..363e66e47 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -323,6 +323,15 @@ GEM thor (>= 0.14.0, < 2) fix-db-schema-conflicts (3.0.3) rubocop (>= 0.38.0) + flipper (0.17.2) + flipper-active_record (0.17.2) + activerecord (>= 4.2, < 7) + flipper (~> 0.17.2) + flipper-ui (0.17.2) + erubi (>= 1.0.0, < 2.0.0) + flipper (~> 0.17.2) + rack (>= 1.4, < 3) + rack-protection (>= 1.5.3, < 2.1.0) fog-aws (3.6.4) fog-core (~> 2.1) fog-json (~> 1.1) @@ -891,6 +900,9 @@ DEPENDENCIES field_test (~> 0.3) figaro (~> 1.2) fix-db-schema-conflicts (~> 3.0) + flipper (~> 0.17.2) + flipper-active_record (~> 0.17.2) + flipper-ui (~> 0.17.2) fog-aws (~> 3.6) front_matter_parser (~> 0.2) gemoji (~> 4.0.0.rc2) diff --git a/app/helpers/feature_flag.rb b/app/helpers/feature_flag.rb new file mode 100644 index 000000000..6e7d9d559 --- /dev/null +++ b/app/helpers/feature_flag.rb @@ -0,0 +1,7 @@ +module FeatureFlag + extend self # rubocop:disable Style/ModuleFunction + + def enabled?(feature_name, *args) + Flipper[feature_name].enabled?(*args) + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 0c427ba9f..7cb0d7417 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -462,6 +462,10 @@ class User < ApplicationRecord RateLimitChecker.new(self) end + def flipper_id + "User:#{id}" + end + private def estimate_default_language diff --git a/config/initializers/flipper.rb b/config/initializers/flipper.rb new file mode 100644 index 000000000..1a1a5e565 --- /dev/null +++ b/config/initializers/flipper.rb @@ -0,0 +1,15 @@ +Flipper.configure do |config| + config.default do + # pick an adapter, this uses memory, any will do + adapter = Flipper::Adapters::ActiveRecord.new + + # pass adapter to handy DSL instance + Flipper.new(adapter) + end +end + +Flipper::UI.configure do |config| + # Provide guidance on format for user ids + config.actors.title = "Actor (ex: User:123)" + config.actors.description = "ex: User:123" +end diff --git a/config/routes.rb b/config/routes.rb index 44bbbe369..a08142413 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -42,6 +42,7 @@ Rails.application.routes.draw do authenticate :user, ->(user) { user.has_role?(:tech_admin) } do mount Blazer::Engine, at: "blazer" + mount Flipper::UI.app(Flipper), at: "feature_flags" end resources :articles, only: %i[index show update] diff --git a/db/migrate/20200519220213_create_flipper_tables.rb b/db/migrate/20200519220213_create_flipper_tables.rb new file mode 100644 index 000000000..ca4390c5c --- /dev/null +++ b/db/migrate/20200519220213_create_flipper_tables.rb @@ -0,0 +1,22 @@ +class CreateFlipperTables < ActiveRecord::Migration[5.2] + def self.up + 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.string :value + t.timestamps null: false + end + add_index :flipper_gates, [:feature_key, :key, :value], unique: true + end + + def self.down + drop_table :flipper_gates + drop_table :flipper_features + end +end diff --git a/db/schema.rb b/db/schema.rb index c8e8dc9fb..6cf6d9598 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -506,6 +506,22 @@ ActiveRecord::Schema.define(version: 2020_05_25_125611) do t.index ["participant_type", "participant_id", "experiment"], name: "index_field_test_memberships_on_participant", unique: true end + create_table "flipper_features", force: :cascade do |t| + t.datetime "created_at", null: false + t.string "key", 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.datetime "created_at", null: false + t.string "feature_key", null: false + t.string "key", null: false + t.datetime "updated_at", null: false + t.string "value" + t.index ["feature_key", "key", "value"], name: "index_flipper_gates_on_feature_key_and_key_and_value", unique: true + end + create_table "follows", id: :serial, force: :cascade do |t| t.boolean "blocked", default: false, null: false t.datetime "created_at"