Commit 37993d95 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'remove-feature_flags_environment_scope-feature-flag' into 'master'

Remove feature_flags_environment_scope feature flag

Closes #9763

See merge request gitlab-org/gitlab-ee!9588
parents 370fe13a cdc4c62c
import initEditFeatureFlags from 'ee/feature_flags/edit';
if (gon.features && gon.features.featureFlagsEnvironmentScope) {
document.addEventListener('DOMContentLoaded', initEditFeatureFlags);
}
document.addEventListener('DOMContentLoaded', initEditFeatureFlags);
import initNewFeatureFlags from 'ee/feature_flags/new';
if (gon.features && gon.features.featureFlagsEnvironmentScope) {
document.addEventListener('DOMContentLoaded', initNewFeatureFlags);
}
document.addEventListener('DOMContentLoaded', initNewFeatureFlags);
......@@ -3,7 +3,6 @@
class Projects::FeatureFlagsController < Projects::ApplicationController
respond_to :html
before_action :push_feature_flag_to_frontend!
before_action :authorize_read_feature_flag!
before_action :authorize_create_feature_flag!, only: [:new, :create]
before_action :authorize_update_feature_flag!, only: [:edit, :update]
......@@ -138,8 +137,4 @@ class Projects::FeatureFlagsController < Projects::ApplicationController
render json: { message: feature_flag.errors.full_messages },
status: :bad_request
end
def push_feature_flag_to_frontend!
push_frontend_feature_flag(:feature_flags_environment_scope, project)
end
end
......@@ -36,10 +36,6 @@ class FeatureFlagsFinder
end
def for_list(items)
if Feature.enabled?(:feature_flags_environment_scope, project)
items.for_list
else
items
end
items.for_list
end
end
......@@ -36,19 +36,11 @@ module Operations
scope :ordered, -> { order(:name) }
scope :enabled, -> do
if Feature.enabled?(:feature_flags_environment_scope)
where('EXISTS (?)', join_enabled_scopes)
else
where(active: true)
end
where('EXISTS (?)', join_enabled_scopes)
end
scope :disabled, -> do
if Feature.enabled?(:feature_flags_environment_scope)
where('NOT EXISTS (?)', join_enabled_scopes)
else
where(active: false)
end
where('NOT EXISTS (?)', join_enabled_scopes)
end
scope :for_environment, -> (environment) do
......
- if @feature_flag.errors.any?
= render 'errors'
%fieldset
.row
.form-group.col-md-4
= f.label :name, class: 'label-bold', for: 'feature_flag_name' do
= s_('FeatureFlags|Name')
= f.text_field :name, class: "form-control", id: "feature_flag_name"
.row
.form-group.col-md-4
= f.label :description, class: 'label-bold', for: 'feature_flag_description' do
= s_('FeatureFlags|Description')
= f.text_area :description, class: "form-control", id: "feature_flag_description", rows: 4
.row
.form-group.col-md-1
= f.label :active, class: 'label-bold' do
= s_('FeatureFlags|Status')
.form-check
= f.check_box :active, id: 'feature_flag_status', class: 'form-check-input'
= f.label :active, for: 'feature_flag_status', class: 'form-check-label' do
= s_('FeatureFlags|Active')
.form-actions
- if @feature_flag.persisted?
= f.submit s_('FeatureFlags|Save changes'), class: "btn btn-success"
- else
= f.submit s_('FeatureFlags|Create feature flag'), class: "btn btn-success"
.float-right
= link_to _('Cancel'), project_feature_flags_path(@project), class: 'btn btn-cancel'
......@@ -2,12 +2,4 @@
- breadcrumb_title @feature_flag.name
- page_title s_('FeatureFlags|Edit Feature Flag')
- if Feature.enabled?(:feature_flags_environment_scope, @project)
#js-edit-feature-flag{ data: { endpoint: project_feature_flag_path(@project, @feature_flag), feature_flags_path: project_feature_flags_path(@project), environments_endpoint: search_project_environments_path(@project, format: :json)} }
- else
%h3.page-title
= s_('FeatureFlags|Edit %{feature_flag_name}') % { feature_flag_name: @feature_flag.name }
%hr.clearfix
%div
= form_for [@project, @feature_flag], url: project_feature_flag_path(@project, @feature_flag), html: { class: 'fieldset-form' } do |f|
= render 'form', { f: f }
#js-edit-feature-flag{ data: { endpoint: project_feature_flag_path(@project, @feature_flag), feature_flags_path: project_feature_flags_path(@project), environments_endpoint: search_project_environments_path(@project, format: :json)} }
......@@ -3,12 +3,4 @@
- breadcrumb_title s_('FeatureFlags|New')
- page_title s_('FeatureFlags|New Feature Flag')
- if Feature.enabled?(:feature_flags_environment_scope, @project)
#js-new-feature-flag{ data: { endpoint: project_feature_flags_path(@project, format: :json), feature_flags_path: project_feature_flags_path(@project), environments_endpoint: search_project_environments_path(@project, format: :json) } }
- else
%h3.page-title
= s_('FeatureFlags|New Feature Flag')
%hr.clearfix
%div
= form_for [@project, @feature_flag], url: project_feature_flags_path(@project), html: { class: 'fieldset-form' } do |f|
= render 'form', { f: f }
#js-new-feature-flag{ data: { endpoint: project_feature_flags_path(@project, format: :json), feature_flags_path: project_feature_flags_path(@project), environments_endpoint: search_project_environments_path(@project, format: :json) } }
......@@ -70,14 +70,10 @@ module API
end
def feature_flags
if Feature.enabled?(:feature_flags_environment_scope, project)
return [] unless unleash_app_name.present?
return [] unless unleash_app_name.present?
project.operations_feature_flags.for_environment(unleash_app_name)
.ordered
else
project.operations_feature_flags.ordered
end
project.operations_feature_flags.for_environment(unleash_app_name)
.ordered
end
end
end
......
require 'spec_helper'
describe 'Feature Flags', :js do
using RSpec::Parameterized::TableSyntax
invalid_input_table = proc do
'with space' | '' | 'Name can contain only'
'<script>' | '' | 'Name can contain only'
'x' * 100 | '' | 'Name is too long'
'some-name' | 'y' * 1001 | 'Description is too long'
end
let(:user) {create(:user)}
let(:project) {create(:project, namespace: user.namespace)}
before do
stub_licensed_features(feature_flags: true)
stub_feature_flags(feature_flags_environment_scope: false)
sign_in(user)
end
it 'shows empty state' do
visit(project_feature_flags_path(project))
expect_empty_state
end
context 'when creating a new feature flag' do
context 'and input is valid' do
where(:name, :description, :status) do
'my-active-flag' | 'a new flag' | true
'my-inactive-flag' | '' | false
end
with_them do
it 'adds the feature flag to the table' do
add_feature_flag(name, description, status)
expect_feature_flag(name, description, status)
expect(page).to have_selector '.flash-container', text: 'successfully created'
end
end
end
context 'and input is invalid' do
where(:name, :description, :error_message, &invalid_input_table)
with_them do
it 'displays an error message' do
add_feature_flag(name, description, false)
expect(page).to have_selector '.alert-danger', text: error_message
end
end
end
end
context 'when editing a feature flag' do
before do
add_feature_flag('feature-flag-to-edit', 'with some description', false)
end
shared_examples_for 'correct edit behavior' do
context 'and input is valid' do
it 'updates the feature flag' do
name = 'new-name'
description = 'new description'
edit_feature_flag('feature-flag-to-edit', name, description, true)
expect_feature_flag(name, description, true)
expect(page).to have_selector '.flash-container', text: 'successfully updated'
end
end
context 'and input is invalid' do
where(:name, :description, :error_message, &invalid_input_table)
with_them do
it 'displays an error message' do
edit_feature_flag('feature-flag-to-edit', name, description, false)
expect(page).to have_selector '.alert-danger', text: error_message
end
end
end
end
it_behaves_like 'correct edit behavior'
end
context 'when deleting a feature flag' do
before do
add_feature_flag('feature-flag-to-delete', 'with some description', false)
end
shared_examples_for 'correct delete behavior' do
context 'and no feature flags are left' do
it 'shows empty state' do
visit(project_feature_flags_path(project))
delete_feature_flag('feature-flag-to-delete')
expect_empty_state
end
end
context 'and there is a feature flag left' do
before do
add_feature_flag('another-feature-flag', '', true)
end
it 'shows feature flag table without deleted feature flag' do
visit(project_feature_flags_path(project))
delete_feature_flag('feature-flag-to-delete')
expect_feature_flag('another-feature-flag', '', true)
end
end
it 'does not delete if modal is cancelled' do
visit(project_feature_flags_path(project))
delete_feature_flag('feature-flag-to-delete', false)
expect_feature_flag('feature-flag-to-delete', 'with some description', false)
end
end
it_behaves_like 'correct delete behavior'
end
context 'when user sees empty index page' do
before do
visit(project_feature_flags_path(project))
end
shared_examples_for 'correct empty index behavior' do
it 'shows empty state' do
expect(page).to have_content('Get started with Feature Flags')
expect(page).to have_link('New Feature Flag')
expect(page).to have_button('Configure')
end
end
it_behaves_like 'correct empty index behavior'
end
context 'when user sees index page' do
let!(:feature_flag_enabled) { create(:operations_feature_flag, project: project, active: true) }
let!(:feature_flag_disabled) { create(:operations_feature_flag, project: project, active: false) }
before do
visit(project_feature_flags_path(project))
end
context 'when user sees all tab' do
it 'shows all feature flags' do
expect(page).to have_content(feature_flag_enabled.name)
expect(page).to have_content(feature_flag_disabled.name)
expect(page).to have_link('New Feature Flag')
expect(page).to have_button('Configure')
end
end
context 'when user sees enabled tab' do
it 'shows only active feature flags' do
find('.js-featureflags-tab-enabled').click
expect(page).to have_content(feature_flag_enabled.name)
expect(page).not_to have_content(feature_flag_disabled.name)
end
end
context 'when user sees disabled tab' do
it 'shows only inactive feature flags' do
find('.js-featureflags-tab-disabled').click
expect(page).not_to have_content(feature_flag_enabled.name)
expect(page).to have_content(feature_flag_disabled.name)
end
end
end
private
def add_feature_flag(name, description, status)
visit(new_project_feature_flag_path(project))
fill_in 'Name', with: name
fill_in 'Description', with: description
if status
check('Active')
else
uncheck('Active')
end
click_button 'Create feature flag'
end
def delete_feature_flag(name, confirm = true)
delete_button = find('.gl-responsive-table-row', text: name).find('.js-feature-flag-delete-button')
delete_button.click
within '.modal' do
if confirm
click_button 'Delete'
else
click_button 'Cancel'
end
end
end
def edit_feature_flag(old_name, new_name, new_description, new_status)
visit(project_feature_flags_path(project))
edit_button = find('.gl-responsive-table-row', text: old_name).find('.js-feature-flag-edit-button')
edit_button.click
fill_in 'Name', with: new_name
fill_in 'Description', with: new_description
if new_status
check('Active')
else
uncheck('Active')
end
click_button 'Save changes'
end
def expect_empty_state
expect(page).to have_selector('.js-feature-flags-empty-state')
expect(page).to have_selector('.btn-success', text: 'New Feature Flag')
expect(page).to have_selector('.btn-primary.btn-inverted', text: 'Configure')
end
def expect_feature_flag(name, description, status)
expect(current_path).to eq project_feature_flags_path(project)
expect(page).to have_selector '.table-section .badge', text: status ? 'Active' : 'Inactive'
expect(page).to have_selector '.table-section', text: name
expect(page).to have_selector '.table-section', text: description
end
end
......@@ -95,10 +95,6 @@ describe Operations::FeatureFlag do
describe '.for_environment' do
subject { described_class.for_environment(environment_name) }
before do
stub_feature_flags(feature_flags_environment_scope: true)
end
context 'when feature flag is off on production' do
before do
feature_flag = create(:operations_feature_flag, active: true)
......@@ -166,10 +162,6 @@ describe Operations::FeatureFlag do
describe '.for_list' do
subject { described_class.for_list }
before do
stub_feature_flags(feature_flags_environment_scope: true)
end
context 'when all scopes are active' do
let!(:feature_flag) { create(:operations_feature_flag, active: true) }
let!(:scope) { create_scope(feature_flag, 'production', true) }
......
......@@ -98,18 +98,6 @@ describe API::Unleash do
subject
end
context 'when the feature is disabled on the project' do
before do
stub_feature_flags(feature_flags_environment_scope: { enabled: false, thing: project })
end
it 'does not call for_environment method' do
expect(Operations::FeatureFlag).not_to receive(:for_environment)
subject
end
end
context 'when app name is staging' do
let(:headers) { base_headers.merge({ "UNLEASH-APPNAME" => "staging" }) }
......@@ -169,10 +157,6 @@ describe API::Unleash do
let!(:enable_feature_flag) { create(:operations_feature_flag, project: project, name: 'feature1', active: true) }
let!(:disabled_feature_flag) { create(:operations_feature_flag, project: project, name: 'feature2', active: false) }
before do
stub_feature_flags(feature_flags_environment_scope: false)
end
it 'responds with a list' do
subject
......
......@@ -4056,9 +4056,6 @@ msgstr ""
msgid "FeatureFlags|Description"
msgstr ""
msgid "FeatureFlags|Edit %{feature_flag_name}"
msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
......@@ -4116,9 +4113,6 @@ msgstr ""
msgid "FeatureFlags|New Feature Flag"
msgstr ""
msgid "FeatureFlags|Save changes"
msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment