Commit 16d324a7 authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch 'remove-feature_flags_new_version' into 'master'

Remove feature_flags_new_version feature flag

See merge request gitlab-org/gitlab!48442
parents 6c2a3c24 9e9078b2
...@@ -4,7 +4,7 @@ import { mapState, mapActions } from 'vuex'; ...@@ -4,7 +4,7 @@ import { mapState, mapActions } from 'vuex';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { sprintf, s__ } from '~/locale'; import { sprintf, s__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { LEGACY_FLAG, NEW_FLAG_ALERT } from '../constants'; import { LEGACY_FLAG } from '../constants';
import FeatureFlagForm from './form.vue'; import FeatureFlagForm from './form.vue';
export default { export default {
...@@ -36,7 +36,6 @@ export default { ...@@ -36,7 +36,6 @@ export default {
legacyReadOnlyFlagAlert: s__( legacyReadOnlyFlagAlert: s__(
'FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag.', 'FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag.',
), ),
newFlagAlert: NEW_FLAG_ALERT,
}, },
computed: { computed: {
...mapState([ ...mapState([
...@@ -58,7 +57,7 @@ export default { ...@@ -58,7 +57,7 @@ export default {
: sprintf(s__('Edit %{name}'), { name: this.name }); : sprintf(s__('Edit %{name}'), { name: this.name });
}, },
deprecated() { deprecated() {
return this.hasNewVersionFlags && this.version === LEGACY_FLAG; return this.version === LEGACY_FLAG;
}, },
deprecatedAndEditable() { deprecatedAndEditable() {
return this.deprecated && !this.hasLegacyReadOnlyFlags; return this.deprecated && !this.hasLegacyReadOnlyFlags;
...@@ -66,18 +65,12 @@ export default { ...@@ -66,18 +65,12 @@ export default {
deprecatedAndReadOnly() { deprecatedAndReadOnly() {
return this.deprecated && this.hasLegacyReadOnlyFlags; return this.deprecated && this.hasLegacyReadOnlyFlags;
}, },
hasNewVersionFlags() {
return this.glFeatures.featureFlagsNewVersion;
},
hasLegacyReadOnlyFlags() { hasLegacyReadOnlyFlags() {
return ( return (
this.glFeatures.featureFlagsLegacyReadOnly && this.glFeatures.featureFlagsLegacyReadOnly &&
!this.glFeatures.featureFlagsLegacyReadOnlyOverride !this.glFeatures.featureFlagsLegacyReadOnlyOverride
); );
}, },
shouldShowNewFlagAlert() {
return !this.hasNewVersionFlags && this.userShouldSeeNewFlagAlert;
},
}, },
created() { created() {
return this.fetchFeatureFlag(); return this.fetchFeatureFlag();
...@@ -95,14 +88,6 @@ export default { ...@@ -95,14 +88,6 @@ export default {
</script> </script>
<template> <template>
<div> <div>
<gl-alert
v-if="shouldShowNewFlagAlert"
variant="warning"
class="gl-my-5"
@dismiss="dismissNewVersionFlagAlert"
>
{{ $options.translations.newFlagAlert }}
</gl-alert>
<gl-loading-icon v-if="isLoading" size="xl" class="gl-mt-7" /> <gl-loading-icon v-if="isLoading" size="xl" class="gl-mt-7" />
<template v-else-if="!isLoading && !hasError"> <template v-else-if="!isLoading && !hasError">
......
...@@ -38,9 +38,6 @@ export default { ...@@ -38,9 +38,6 @@ export default {
permissions() { permissions() {
return this.glFeatures.featureFlagPermissions; return this.glFeatures.featureFlagPermissions;
}, },
isNewVersionFlagsEnabled() {
return this.glFeatures.featureFlagsNewVersion;
},
isLegacyReadOnlyFlagsEnabled() { isLegacyReadOnlyFlagsEnabled() {
return ( return (
this.glFeatures.featureFlagsLegacyReadOnly && this.glFeatures.featureFlagsLegacyReadOnly &&
...@@ -68,7 +65,7 @@ export default { ...@@ -68,7 +65,7 @@ export default {
}, },
methods: { methods: {
isLegacyFlag(flag) { isLegacyFlag(flag) {
return !this.isNewVersionFlagsEnabled || flag.version !== NEW_VERSION_FLAG; return flag.version !== NEW_VERSION_FLAG;
}, },
statusToggleDisabled(flag) { statusToggleDisabled(flag) {
return this.isLegacyReadOnlyFlagsEnabled && flag.version === LEGACY_FLAG; return this.isLegacyReadOnlyFlagsEnabled && flag.version === LEGACY_FLAG;
......
...@@ -137,14 +137,13 @@ export default { ...@@ -137,14 +137,13 @@ export default {
return this.glFeatures.featureFlagPermissions; return this.glFeatures.featureFlagPermissions;
}, },
supportsStrategies() { supportsStrategies() {
return this.glFeatures.featureFlagsNewVersion && this.version === NEW_VERSION_FLAG; return this.version === NEW_VERSION_FLAG;
}, },
showRelatedIssues() { showRelatedIssues() {
return this.featureFlagIssuesEndpoint.length > 0; return this.featureFlagIssuesEndpoint.length > 0;
}, },
readOnly() { readOnly() {
return ( return (
this.glFeatures.featureFlagsNewVersion &&
this.glFeatures.featureFlagsLegacyReadOnly && this.glFeatures.featureFlagsLegacyReadOnly &&
!this.glFeatures.featureFlagsLegacyReadOnlyOverride && !this.glFeatures.featureFlagsLegacyReadOnlyOverride &&
this.version === LEGACY_FLAG this.version === LEGACY_FLAG
......
<script> <script>
import { mapState, mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import { GlAlert } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import FeatureFlagForm from './form.vue'; import FeatureFlagForm from './form.vue';
import { import { NEW_VERSION_FLAG, ROLLOUT_STRATEGY_ALL_USERS } from '../constants';
LEGACY_FLAG,
NEW_VERSION_FLAG,
NEW_FLAG_ALERT,
ROLLOUT_STRATEGY_ALL_USERS,
} from '../constants';
import { createNewEnvironmentScope } from '../store/helpers'; import { createNewEnvironmentScope } from '../store/helpers';
import featureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import featureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default { export default {
components: { components: {
GlAlert,
FeatureFlagForm, FeatureFlagForm,
}, },
mixins: [featureFlagsMixin()], mixins: [featureFlagsMixin()],
...@@ -33,9 +26,6 @@ export default { ...@@ -33,9 +26,6 @@ export default {
userShouldSeeNewFlagAlert: this.showUserCallout, userShouldSeeNewFlagAlert: this.showUserCallout,
}; };
}, },
translations: {
newFlagAlert: NEW_FLAG_ALERT,
},
computed: { computed: {
...mapState(['error', 'path']), ...mapState(['error', 'path']),
scopes() { scopes() {
...@@ -50,13 +40,7 @@ export default { ...@@ -50,13 +40,7 @@ export default {
]; ];
}, },
version() { version() {
return this.hasNewVersionFlags ? NEW_VERSION_FLAG : LEGACY_FLAG; return NEW_VERSION_FLAG;
},
hasNewVersionFlags() {
return this.glFeatures.featureFlagsNewVersion;
},
shouldShowNewFlagAlert() {
return !this.hasNewVersionFlags && this.userShouldSeeNewFlagAlert;
}, },
strategies() { strategies() {
return [{ name: ROLLOUT_STRATEGY_ALL_USERS, parameters: {}, scopes: [] }]; return [{ name: ROLLOUT_STRATEGY_ALL_USERS, parameters: {}, scopes: [] }];
...@@ -75,14 +59,6 @@ export default { ...@@ -75,14 +59,6 @@ export default {
</script> </script>
<template> <template>
<div> <div>
<gl-alert
v-if="shouldShowNewFlagAlert"
variant="warning"
class="gl-my-5"
@dismiss="dismissNewVersionFlagAlert"
>
{{ $options.translations.newFlagAlert }}
</gl-alert>
<h3 class="page-title">{{ s__('FeatureFlags|New feature flag') }}</h3> <h3 class="page-title">{{ s__('FeatureFlags|New feature flag') }}</h3>
<div v-if="error.length" class="alert alert-danger"> <div v-if="error.length" class="alert alert-danger">
......
...@@ -21,10 +21,6 @@ export const fetchUserIdParams = property(['parameters', 'userIds']); ...@@ -21,10 +21,6 @@ export const fetchUserIdParams = property(['parameters', 'userIds']);
export const NEW_VERSION_FLAG = 'new_version_flag'; export const NEW_VERSION_FLAG = 'new_version_flag';
export const LEGACY_FLAG = 'legacy_flag'; export const LEGACY_FLAG = 'legacy_flag';
export const NEW_FLAG_ALERT = s__(
'FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow.',
);
export const FEATURE_FLAG_SCOPE = 'featureFlags'; export const FEATURE_FLAG_SCOPE = 'featureFlags';
export const USER_LIST_SCOPE = 'userLists'; export const USER_LIST_SCOPE = 'userLists';
......
...@@ -14,7 +14,6 @@ class Projects::FeatureFlagsController < Projects::ApplicationController ...@@ -14,7 +14,6 @@ class Projects::FeatureFlagsController < Projects::ApplicationController
before_action do before_action do
push_frontend_feature_flag(:feature_flag_permissions) push_frontend_feature_flag(:feature_flag_permissions)
push_frontend_feature_flag(:feature_flags_new_version, project, default_enabled: true)
push_frontend_feature_flag(:feature_flags_legacy_read_only, project, default_enabled: true) push_frontend_feature_flag(:feature_flags_legacy_read_only, project, default_enabled: true)
push_frontend_feature_flag(:feature_flags_legacy_read_only_override, project) push_frontend_feature_flag(:feature_flags_legacy_read_only_override, project)
end end
...@@ -101,15 +100,7 @@ class Projects::FeatureFlagsController < Projects::ApplicationController ...@@ -101,15 +100,7 @@ class Projects::FeatureFlagsController < Projects::ApplicationController
protected protected
def feature_flag def feature_flag
@feature_flag ||= @noteable = if new_version_feature_flags_enabled? @feature_flag ||= @noteable = project.operations_feature_flags.find_by_iid!(params[:iid])
project.operations_feature_flags.find_by_iid!(params[:iid])
else
project.operations_feature_flags.legacy_flag.find_by_iid!(params[:iid])
end
end
def new_version_feature_flags_enabled?
::Feature.enabled?(:feature_flags_new_version, project, default_enabled: true)
end end
def ensure_legacy_flags_writable! def ensure_legacy_flags_writable!
......
...@@ -24,11 +24,7 @@ class FeatureFlagsFinder ...@@ -24,11 +24,7 @@ class FeatureFlagsFinder
private private
def feature_flags def feature_flags
if Feature.enabled?(:feature_flags_new_version, project, default_enabled: true) project.operations_feature_flags
project.operations_feature_flags
else
project.operations_feature_flags.legacy_flag
end
end end
def by_scope(items) def by_scope(items)
......
...@@ -5,7 +5,6 @@ module FeatureFlags ...@@ -5,7 +5,6 @@ module FeatureFlags
def execute def execute
return error('Access Denied', 403) unless can_create? return error('Access Denied', 403) unless can_create?
return error('Version is invalid', :bad_request) unless valid_version? return error('Version is invalid', :bad_request) unless valid_version?
return error('New version feature flags are not enabled for this project', :bad_request) unless flag_version_enabled?
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
feature_flag = project.operations_feature_flags.new(params) feature_flag = project.operations_feature_flags.new(params)
...@@ -40,13 +39,5 @@ module FeatureFlags ...@@ -40,13 +39,5 @@ module FeatureFlags
def valid_version? def valid_version?
!params.key?(:version) || Operations::FeatureFlag.versions.key?(params[:version]) !params.key?(:version) || Operations::FeatureFlag.versions.key?(params[:version])
end end
def flag_version_enabled?
params[:version] != 'new_version_flag' || new_version_feature_flags_enabled?
end
def new_version_feature_flags_enabled?
::Feature.enabled?(:feature_flags_new_version, project, default_enabled: true)
end
end end
end end
---
name: feature_flags_new_version
introduced_by_url:
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258831
milestone: '13.7'
type: development
group: group::progressive delivery
default_enabled: true
...@@ -10,10 +10,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w ...@@ -10,10 +10,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4. > - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.5. > - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.5.
NOTE: **Note:**
This API is behind a [feature flag](../operations/feature_flags.md#enable-or-disable-feature-flag-strategies).
If this flag is not enabled in your environment, you can use the [legacy feature flags API](feature_flags_legacy.md).
API for accessing resources of [GitLab Feature Flags](../operations/feature_flags.md). API for accessing resources of [GitLab Feature Flags](../operations/feature_flags.md).
Users with Developer or higher [permissions](../user/permissions.md) can access Feature Flag API. Users with Developer or higher [permissions](../user/permissions.md) can access Feature Flag API.
......
...@@ -77,7 +77,6 @@ is 200. On GitLab.com, the maximum number is determined by [GitLab.com tier](htt ...@@ -77,7 +77,6 @@ is 200. On GitLab.com, the maximum number is determined by [GitLab.com tier](htt
> - It became [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/214684) in GitLab 13.2. > - It became [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/214684) in GitLab 13.2.
> - It's recommended for production use. > - It's recommended for production use.
> - It's enabled on GitLab.com. > - It's enabled on GitLab.com.
> - For GitLab self-managed instances, a GitLab administrator can choose to [disable it](#enable-or-disable-feature-flag-strategies). **(CORE ONLY)**
You can apply a feature flag strategy across multiple environments, without defining You can apply a feature flag strategy across multiple environments, without defining
the strategy multiple times. the strategy multiple times.
...@@ -222,25 +221,6 @@ To remove users from a user list: ...@@ -222,25 +221,6 @@ To remove users from a user list:
1. Click on the **{pencil}** (edit) button next to the list you want to change. 1. Click on the **{pencil}** (edit) button next to the list you want to change.
1. Click on the **{remove}** (remove) button next to the ID you want to remove. 1. Click on the **{remove}** (remove) button next to the ID you want to remove.
### Enable or disable feature flag strategies
This feature is under development, but is ready for production use. It's
deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md)
can disable it for your instance.
To disable it:
```ruby
Feature.disable(:feature_flags_new_version)
```
To enable it:
```ruby
Feature.enable(:feature_flags_new_version)
```
## Rollout strategy (legacy) ## Rollout strategy (legacy)
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8240) in GitLab 12.2. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8240) in GitLab 12.2.
......
...@@ -14,24 +14,18 @@ RSpec.describe 'User creates feature flag', :js do ...@@ -14,24 +14,18 @@ RSpec.describe 'User creates feature flag', :js do
sign_in(user) sign_in(user)
end end
context 'with new version flags disabled' do context 'when creates without changing scopes' do
before do before do
stub_feature_flags(feature_flags_new_version: false) visit(new_project_feature_flag_path(project))
set_feature_flag_info('ci_live_trace', 'For live trace')
click_button 'Create feature flag'
expect(page).to have_current_path(project_feature_flags_path(project))
end end
context 'when creates without changing scopes' do it 'records audit event' do
before do visit(project_audit_events_path(project))
visit(new_project_feature_flag_path(project))
set_feature_flag_info('ci_live_trace', 'For live trace')
click_button 'Create feature flag'
expect(page).to have_current_path(project_feature_flags_path(project))
end
it 'records audit event' do expect(page).to have_text("Created feature flag ci_live_trace with description \"For live trace\".")
visit(project_audit_events_path(project))
expect(page).to have_text("Created feature flag ci_live_trace with description \"For live trace\".")
end
end end
end end
......
...@@ -6,11 +6,11 @@ module API ...@@ -6,11 +6,11 @@ module API
expose :name expose :name
expose :description expose :description
expose :active expose :active
expose :version, if: :feature_flags_new_version_enabled expose :version
expose :created_at expose :created_at
expose :updated_at expose :updated_at
expose :scopes, using: FeatureFlag::LegacyScope expose :scopes, using: FeatureFlag::LegacyScope
expose :strategies, using: FeatureFlag::Strategy, if: :feature_flags_new_version_enabled expose :strategies, using: FeatureFlag::Strategy
end end
end end
end end
...@@ -62,8 +62,6 @@ module API ...@@ -62,8 +62,6 @@ module API
attrs = declared_params(include_missing: false) attrs = declared_params(include_missing: false)
ensure_post_version_2_flags_enabled! if attrs[:version] == 'new_version_flag'
rename_key(attrs, :scopes, :scopes_attributes) rename_key(attrs, :scopes, :scopes_attributes)
rename_key(attrs, :strategies, :strategies_attributes) rename_key(attrs, :strategies, :strategies_attributes)
update_value(attrs, :strategies_attributes) do |strategies| update_value(attrs, :strategies_attributes) do |strategies|
...@@ -143,7 +141,7 @@ module API ...@@ -143,7 +141,7 @@ module API
end end
desc 'Update a feature flag' do desc 'Update a feature flag' do
detail 'This feature will be introduced in GitLab 13.1 if feature_flags_new_version feature flag is removed' detail 'This feature was introduced in GitLab 13.2'
success ::API::Entities::FeatureFlag success ::API::Entities::FeatureFlag
end end
params do params do
...@@ -163,7 +161,6 @@ module API ...@@ -163,7 +161,6 @@ module API
end end
end end
put do put do
not_found! unless feature_flags_new_version_enabled?
authorize_update_feature_flag! authorize_update_feature_flag!
render_api_error!('PUT operations are not supported for legacy feature flags', :unprocessable_entity) if feature_flag.legacy_flag? render_api_error!('PUT operations are not supported for legacy feature flags', :unprocessable_entity) if feature_flag.legacy_flag?
...@@ -228,32 +225,17 @@ module API ...@@ -228,32 +225,17 @@ module API
def present_entity(result) def present_entity(result)
present result, present result,
with: ::API::Entities::FeatureFlag, with: ::API::Entities::FeatureFlag
feature_flags_new_version_enabled: feature_flags_new_version_enabled?
end
def ensure_post_version_2_flags_enabled!
unless feature_flags_new_version_enabled?
render_api_error!('Version 2 flags are not enabled for this project', :unprocessable_entity)
end
end end
def feature_flag def feature_flag
@feature_flag ||= if feature_flags_new_version_enabled? @feature_flag ||= user_project.operations_feature_flags.find_by_name!(params[:feature_flag_name])
user_project.operations_feature_flags.find_by_name!(params[:feature_flag_name])
else
user_project.operations_feature_flags.legacy_flag.find_by_name!(params[:feature_flag_name])
end
end end
def new_version_flag_present? def new_version_flag_present?
user_project.operations_feature_flags.new_version_flag.find_by_name(params[:name]).present? user_project.operations_feature_flags.new_version_flag.find_by_name(params[:name]).present?
end end
def feature_flags_new_version_enabled?
Feature.enabled?(:feature_flags_new_version, user_project, default_enabled: true)
end
def rename_key(hash, old_key, new_key) def rename_key(hash, old_key, new_key)
hash[new_key] = hash.delete(old_key) if hash.key?(old_key) hash[new_key] = hash.delete(old_key) if hash.key?(old_key)
hash hash
......
...@@ -11759,9 +11759,6 @@ msgstr "" ...@@ -11759,9 +11759,6 @@ msgstr ""
msgid "FeatureFlags|Feature Flags" msgid "FeatureFlags|Feature Flags"
msgstr "" msgstr ""
msgid "FeatureFlags|Feature Flags will look different in the next milestone. No action is needed, but you may notice the functionality was changed to improve the workflow."
msgstr ""
msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?" msgid "FeatureFlags|Feature flag %{name} will be removed. Are you sure?"
msgstr "" msgstr ""
......
...@@ -217,15 +217,6 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -217,15 +217,6 @@ RSpec.describe Projects::FeatureFlagsController do
expect(json_response['feature_flags'].count).to eq(3) expect(json_response['feature_flags'].count).to eq(3)
end end
it 'returns only version 1 flags when new version flags are disabled' do
stub_feature_flags(feature_flags_new_version: false)
subject
expected = [feature_flag_active.name, feature_flag_inactive.name].sort
expect(json_response['feature_flags'].map { |f| f['name'] }.sort).to eq(expected)
end
end end
end end
...@@ -283,24 +274,6 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -283,24 +274,6 @@ RSpec.describe Projects::FeatureFlagsController do
expect(json_response['name']).to eq(other_feature_flag.name) expect(json_response['name']).to eq(other_feature_flag.name)
end end
it 'routes based on iid when new version flags are disabled' do
stub_feature_flags(feature_flags_new_version: false)
other_project = create(:project)
other_project.add_developer(user)
other_feature_flag = create(:operations_feature_flag, project: other_project,
name: 'other_flag')
params = {
namespace_id: other_project.namespace,
project_id: other_project,
iid: other_feature_flag.iid
}
get(:show, params: params, format: :json)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['name']).to eq(other_feature_flag.name)
end
context 'when feature flag is not found' do context 'when feature flag is not found' do
let!(:feature_flag) { } let!(:feature_flag) { }
...@@ -386,14 +359,6 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -386,14 +359,6 @@ RSpec.describe Projects::FeatureFlagsController do
expect(json_response['version']).to eq('new_version_flag') expect(json_response['version']).to eq('new_version_flag')
end end
it 'returns a 404 when new version flags are disabled' do
stub_feature_flags(feature_flags_new_version: false)
subject
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns strategies ordered by id' do it 'returns strategies ordered by id' do
first_strategy = create(:operations_strategy, feature_flag: new_version_feature_flag) first_strategy = create(:operations_strategy, feature_flag: new_version_feature_flag)
second_strategy = create(:operations_strategy, feature_flag: new_version_feature_flag) second_strategy = create(:operations_strategy, feature_flag: new_version_feature_flag)
...@@ -791,54 +756,6 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -791,54 +756,6 @@ RSpec.describe Projects::FeatureFlagsController do
expect(Operations::FeatureFlag.count).to eq(0) expect(Operations::FeatureFlag.count).to eq(0)
end end
end end
context 'when version 2 flags are disabled' do
context 'and attempting to create a version 2 flag' do
let(:params) do
{
namespace_id: project.namespace,
project_id: project,
operations_feature_flag: {
name: 'my_feature_flag',
active: true,
version: 'new_version_flag'
}
}
end
it 'returns a 400' do
stub_feature_flags(feature_flags_new_version: false)
subject
expect(response).to have_gitlab_http_status(:bad_request)
expect(Operations::FeatureFlag.count).to eq(0)
end
end
context 'and attempting to create a version 1 flag' do
let(:params) do
{
namespace_id: project.namespace,
project_id: project,
operations_feature_flag: {
name: 'my_feature_flag',
active: true
}
}
end
it 'creates the flag' do
stub_feature_flags(feature_flags_new_version: false)
subject
expect(response).to have_gitlab_http_status(:ok)
expect(Operations::FeatureFlag.count).to eq(1)
expect(json_response['version']).to eq('legacy_flag')
end
end
end
end end
describe 'DELETE destroy.json' do describe 'DELETE destroy.json' do
...@@ -913,15 +830,6 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -913,15 +830,6 @@ RSpec.describe Projects::FeatureFlagsController do
it 'deletes the flag' do it 'deletes the flag' do
expect { subject }.to change { Operations::FeatureFlag.count }.by(-1) expect { subject }.to change { Operations::FeatureFlag.count }.by(-1)
end end
context 'when new version flags are disabled' do
it 'returns a 404' do
stub_feature_flags(feature_flags_new_version: false)
expect { subject }.not_to change { Operations::FeatureFlag.count }
expect(response).to have_gitlab_http_status(:not_found)
end
end
end end
end end
...@@ -1576,15 +1484,6 @@ RSpec.describe Projects::FeatureFlagsController do ...@@ -1576,15 +1484,6 @@ RSpec.describe Projects::FeatureFlagsController do
expect(json_response['strategies'].first['scopes']).to eq([]) expect(json_response['strategies'].first['scopes']).to eq([])
end end
it 'does not update the flag if version 2 flags are disabled' do
stub_feature_flags(feature_flags_new_version: false)
put_request(new_version_flag, { name: 'some-other-name' })
expect(response).to have_gitlab_http_status(:not_found)
expect(new_version_flag.reload.name).to eq('new-feature')
end
it 'updates the flag when legacy feature flags are set to be read only' do it 'updates the flag when legacy feature flags are set to be read only' do
stub_feature_flags(feature_flags_legacy_read_only: true) stub_feature_flags(feature_flags_legacy_read_only: true)
......
...@@ -67,118 +67,6 @@ RSpec.describe 'User creates feature flag', :js do ...@@ -67,118 +67,6 @@ RSpec.describe 'User creates feature flag', :js do
end end
end end
context 'with new version flags disabled' do
before do
stub_feature_flags(feature_flags_new_version: false)
end
context 'when creates without changing scopes' do
before do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('ci_live_trace', 'For live trace')
click_button 'Create feature flag'
expect(page).to have_current_path(project_feature_flags_path(project))
end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
end
end
end
end
context 'when creates with disabling the default scope' do
before do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('ci_live_trace', 'For live trace')
within_scope_row(1) do
within_status { find('.project-feature-toggle').click }
end
click_button 'Create feature flag'
end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('ci_live_trace')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(1)')).to have_content('*')
end
end
end
end
context 'when creates with an additional scope' do
before do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('mr_train', '')
within_scope_row(2) do
within_environment_spec do
find('.js-env-search > input').set("review/*")
find('.js-create-button').click
end
end
within_scope_row(2) do
within_status { find('.project-feature-toggle').click }
end
click_button 'Create feature flag'
end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(2)')).to have_content('review/*')
end
end
end
end
context 'when searches an environment name for scope creation' do
let!(:environment) { create(:environment, name: 'production', project: project) }
before do
visit(new_project_feature_flag_path(project))
set_feature_flag_info('mr_train', '')
within_scope_row(2) do
within_environment_spec do
find('.js-env-search > input').set('prod')
click_button 'production'
end
end
click_button 'Create feature flag'
end
it 'shows the created feature flag' do
within_feature_flag_row(1) do
expect(page.find('.feature-flag-name')).to have_content('mr_train')
expect_status_toggle_button_to_be_checked
within_feature_flag_scopes do
expect(page.find('[data-qa-selector="feature-flag-scope-info-badge"]:nth-child(1)')).to have_content('*')
expect(page.find('[data-qa-selector="feature-flag-scope-muted-badge"]:nth-child(2)')).to have_content('production')
end
end
end
end
end
private private
def set_feature_flag_info(name, description) def set_feature_flag_info(name, description)
......
...@@ -80,15 +80,5 @@ RSpec.describe FeatureFlagsFinder do ...@@ -80,15 +80,5 @@ RSpec.describe FeatureFlagsFinder do
is_expected.to eq([feature_flag_1, feature_flag_2, feature_flag_3]) is_expected.to eq([feature_flag_1, feature_flag_2, feature_flag_3])
end end
end end
context 'when new version flags are disabled' do
let!(:feature_flag_3) { create(:operations_feature_flag, :new_version_flag, name: 'flag-c', project: project) }
it 'returns only legacy flags' do
stub_feature_flags(feature_flags_new_version: false)
is_expected.to eq([feature_flag_1, feature_flag_2])
end
end
end end
end end
...@@ -4,7 +4,7 @@ import MockAdapter from 'axios-mock-adapter'; ...@@ -4,7 +4,7 @@ import MockAdapter from 'axios-mock-adapter';
import { GlToggle, GlAlert } from '@gitlab/ui'; import { GlToggle, GlAlert } from '@gitlab/ui';
import { TEST_HOST } from 'spec/test_constants'; import { TEST_HOST } from 'spec/test_constants';
import { mockTracking } from 'helpers/tracking_helper'; import { mockTracking } from 'helpers/tracking_helper';
import { LEGACY_FLAG, NEW_VERSION_FLAG, NEW_FLAG_ALERT } from '~/feature_flags/constants'; import { LEGACY_FLAG, NEW_VERSION_FLAG } from '~/feature_flags/constants';
import Form from '~/feature_flags/components/form.vue'; import Form from '~/feature_flags/components/form.vue';
import createStore from '~/feature_flags/store/edit'; import createStore from '~/feature_flags/store/edit';
import EditFeatureFlag from '~/feature_flags/components/edit_feature_flag.vue'; import EditFeatureFlag from '~/feature_flags/components/edit_feature_flag.vue';
...@@ -37,9 +37,6 @@ describe('Edit feature flag form', () => { ...@@ -37,9 +37,6 @@ describe('Edit feature flag form', () => {
showUserCallout: true, showUserCallout: true,
userCalloutId, userCalloutId,
userCalloutsPath, userCalloutsPath,
glFeatures: {
featureFlagsNewVersion: true,
},
...opts, ...opts,
}, },
}); });
...@@ -151,33 +148,4 @@ describe('Edit feature flag form', () => { ...@@ -151,33 +148,4 @@ describe('Edit feature flag form', () => {
}); });
}); });
}); });
describe('without new version flags', () => {
beforeEach(() => factory({ glFeatures: { featureFlagsNewVersion: false } }));
it('should alert users that feature flags are changing soon', () => {
expect(findAlert().text()).toBe(NEW_FLAG_ALERT);
});
});
describe('dismissing new version alert', () => {
beforeEach(() => {
factory({ glFeatures: { featureFlagsNewVersion: false } });
mock.onPost(userCalloutsPath, { feature_name: userCalloutId }).reply(200);
findAlert().vm.$emit('dismiss');
return wrapper.vm.$nextTick();
});
afterEach(() => {
mock.restore();
});
it('should hide the alert', () => {
expect(findAlert().exists()).toBe(false);
});
it('should send the dismissal event', () => {
expect(mock.history.post.length).toBe(1);
});
});
}); });
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex'; import Vuex from 'vuex';
import MockAdapter from 'axios-mock-adapter';
import { GlAlert } from '@gitlab/ui'; import { GlAlert } from '@gitlab/ui';
import { TEST_HOST } from 'spec/test_constants'; import { TEST_HOST } from 'spec/test_constants';
import Form from '~/feature_flags/components/form.vue'; import Form from '~/feature_flags/components/form.vue';
import createStore from '~/feature_flags/store/new'; import createStore from '~/feature_flags/store/new';
import NewFeatureFlag from '~/feature_flags/components/new_feature_flag.vue'; import NewFeatureFlag from '~/feature_flags/components/new_feature_flag.vue';
import { import { ROLLOUT_STRATEGY_ALL_USERS, DEFAULT_PERCENT_ROLLOUT } from '~/feature_flags/constants';
ROLLOUT_STRATEGY_ALL_USERS,
DEFAULT_PERCENT_ROLLOUT,
NEW_FLAG_ALERT,
} from '~/feature_flags/constants';
import axios from '~/lib/utils/axios_utils';
import { allUsersStrategy } from '../mock_data'; import { allUsersStrategy } from '../mock_data';
const userCalloutId = 'feature_flags_new_version'; const userCalloutId = 'feature_flags_new_version';
...@@ -42,9 +36,6 @@ describe('New feature flag form', () => { ...@@ -42,9 +36,6 @@ describe('New feature flag form', () => {
userCalloutsPath, userCalloutsPath,
environmentsEndpoint: 'environments.json', environmentsEndpoint: 'environments.json',
projectId: '8', projectId: '8',
glFeatures: {
featureFlagsNewVersion: true,
},
...opts, ...opts,
}, },
}); });
...@@ -58,8 +49,6 @@ describe('New feature flag form', () => { ...@@ -58,8 +49,6 @@ describe('New feature flag form', () => {
wrapper.destroy(); wrapper.destroy();
}); });
const findAlert = () => wrapper.find(GlAlert);
describe('with error', () => { describe('with error', () => {
it('should render the error', () => { it('should render the error', () => {
store.dispatch('receiveCreateFeatureFlagError', { message: ['The name is required'] }); store.dispatch('receiveCreateFeatureFlagError', { message: ['The name is required'] });
...@@ -101,36 +90,4 @@ describe('New feature flag form', () => { ...@@ -101,36 +90,4 @@ describe('New feature flag form', () => {
expect(strategies).toEqual([allUsersStrategy]); expect(strategies).toEqual([allUsersStrategy]);
}); });
describe('without new version flags', () => {
beforeEach(() => factory({ glFeatures: { featureFlagsNewVersion: false } }));
it('should alert users that feature flags are changing soon', () => {
expect(findAlert().text()).toBe(NEW_FLAG_ALERT);
});
});
describe('dismissing new version alert', () => {
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onPost(userCalloutsPath, { feature_name: userCalloutId }).reply(200);
factory({ glFeatures: { featureFlagsNewVersion: false } });
findAlert().vm.$emit('dismiss');
return wrapper.vm.$nextTick();
});
afterEach(() => {
mock.restore();
});
it('should hide the alert', () => {
expect(findAlert().exists()).toBe(false);
});
it('should send the dismissal event', () => {
expect(mock.history.post.length).toBe(1);
});
});
}); });
...@@ -65,26 +65,6 @@ RSpec.describe API::FeatureFlags do ...@@ -65,26 +65,6 @@ RSpec.describe API::FeatureFlags do
expect(json_response.map { |f| f['version'] }).to eq(%w[legacy_flag legacy_flag]) expect(json_response.map { |f| f['version'] }).to eq(%w[legacy_flag legacy_flag])
end end
it 'does not return the legacy flag version when the feature flag is disabled' do
stub_feature_flags(feature_flags_new_version: false)
subject
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/feature_flags')
expect(json_response.select { |f| f.key?('version') }).to eq([])
end
it 'does not return strategies if the new flag is disabled' do
stub_feature_flags(feature_flags_new_version: false)
subject
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/feature_flags')
expect(json_response.select { |f| f.key?('strategies') }).to eq([])
end
it 'does not have N+1 problem' do it 'does not have N+1 problem' do
control_count = ActiveRecord::QueryRecorder.new { subject } control_count = ActiveRecord::QueryRecorder.new { subject }
...@@ -134,16 +114,6 @@ RSpec.describe API::FeatureFlags do ...@@ -134,16 +114,6 @@ RSpec.describe API::FeatureFlags do
}] }]
}]) }])
end end
it 'does not return a version 2 flag when the feature flag is disabled' do
stub_feature_flags(feature_flags_new_version: false)
subject
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/feature_flags')
expect(json_response).to eq([])
end
end end
context 'with version 1 and 2 feature flags' do context 'with version 1 and 2 feature flags' do
...@@ -159,20 +129,6 @@ RSpec.describe API::FeatureFlags do ...@@ -159,20 +129,6 @@ RSpec.describe API::FeatureFlags do
expect(response).to match_response_schema('public_api/v4/feature_flags') expect(response).to match_response_schema('public_api/v4/feature_flags')
expect(json_response.map { |f| f['name'] }).to eq(%w[legacy_flag new_version_flag]) expect(json_response.map { |f| f['name'] }).to eq(%w[legacy_flag new_version_flag])
end end
it 'returns only version 1 flags when the feature flag is disabled' do
stub_feature_flags(feature_flags_new_version: false)
create(:operations_feature_flag, project: project, name: 'legacy_flag')
feature_flag = create(:operations_feature_flag, :new_version_flag, project: project, name: 'new_version_flag')
strategy = create(:operations_strategy, feature_flag: feature_flag, name: 'default', parameters: {})
create(:operations_scope, strategy: strategy, environment_scope: 'production')
subject
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/feature_flags')
expect(json_response.map { |f| f['name'] }).to eq(['legacy_flag'])
end
end end
end end
...@@ -224,18 +180,6 @@ RSpec.describe API::FeatureFlags do ...@@ -224,18 +180,6 @@ RSpec.describe API::FeatureFlags do
}] }]
}) })
end end
it 'returns a 404 when the feature is disabled' do
stub_feature_flags(feature_flags_new_version: false)
feature_flag = create(:operations_feature_flag, :new_version_flag, project: project, name: 'feature1')
strategy = create(:operations_strategy, feature_flag: feature_flag, name: 'default', parameters: {})
create(:operations_scope, strategy: strategy, environment_scope: 'production')
get api("/projects/#{project.id}/feature_flags/feature1", user)
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response).to eq({ 'message' => '404 Not found' })
end
end end
end end
...@@ -290,16 +234,6 @@ RSpec.describe API::FeatureFlags do ...@@ -290,16 +234,6 @@ RSpec.describe API::FeatureFlags do
expect(json_response['version']).to eq('legacy_flag') expect(json_response['version']).to eq('legacy_flag')
end end
it 'does not return version when new version flags are disabled' do
stub_feature_flags(feature_flags_new_version: false)
subject
expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('public_api/v4/feature_flag')
expect(json_response.key?('version')).to eq(false)
end
context 'with active set to false in the params for a legacy flag' do context 'with active set to false in the params for a legacy flag' do
let(:params) do let(:params) do
{ {
...@@ -505,20 +439,6 @@ RSpec.describe API::FeatureFlags do ...@@ -505,20 +439,6 @@ RSpec.describe API::FeatureFlags do
environment_scope: 'staging' environment_scope: 'staging'
}]) }])
end end
it 'returns a 422 when the feature flag is disabled' do
stub_feature_flags(feature_flags_new_version: false)
params = {
name: 'new-feature',
version: 'new_version_flag'
}
post api("/projects/#{project.id}/feature_flags", user), params: params
expect(response).to have_gitlab_http_status(:unprocessable_entity)
expect(json_response).to eq({ 'message' => 'Version 2 flags are not enabled for this project' })
expect(project.operations_feature_flags.count).to eq(0)
end
end end
context 'when given invalid parameters' do context 'when given invalid parameters' do
...@@ -744,16 +664,6 @@ RSpec.describe API::FeatureFlags do ...@@ -744,16 +664,6 @@ RSpec.describe API::FeatureFlags do
name: 'feature1', description: 'old description') name: 'feature1', description: 'old description')
end end
it 'returns a 404 if the feature is disabled' do
stub_feature_flags(feature_flags_new_version: false)
params = { description: 'new description' }
put api("/projects/#{project.id}/feature_flags/feature1", user), params: params
expect(response).to have_gitlab_http_status(:not_found)
expect(feature_flag.reload.description).to eq('old description')
end
it 'returns a 422' do it 'returns a 422' do
params = { description: 'new description' } params = { description: 'new description' }
...@@ -771,16 +681,6 @@ RSpec.describe API::FeatureFlags do ...@@ -771,16 +681,6 @@ RSpec.describe API::FeatureFlags do
name: 'feature1', description: 'old description') name: 'feature1', description: 'old description')
end end
it 'returns a 404 if the feature is disabled' do
stub_feature_flags(feature_flags_new_version: false)
params = { description: 'new description' }
put api("/projects/#{project.id}/feature_flags/feature1", user), params: params
expect(response).to have_gitlab_http_status(:not_found)
expect(feature_flag.reload.description).to eq('old description')
end
it 'returns a 404 if the feature flag does not exist' do it 'returns a 404 if the feature flag does not exist' do
params = { description: 'new description' } params = { description: 'new description' }
...@@ -1100,15 +1000,6 @@ RSpec.describe API::FeatureFlags do ...@@ -1100,15 +1000,6 @@ RSpec.describe API::FeatureFlags do
expect(json_response['version']).to eq('legacy_flag') expect(json_response['version']).to eq('legacy_flag')
end end
it 'does not return version when new version flags are disabled' do
stub_feature_flags(feature_flags_new_version: false)
subject
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.key?('version')).to eq(false)
end
context 'with a version 2 feature flag' do context 'with a version 2 feature flag' do
let!(:feature_flag) { create(:operations_feature_flag, :new_version_flag, project: project) } let!(:feature_flag) { create(:operations_feature_flag, :new_version_flag, project: project) }
...@@ -1117,14 +1008,6 @@ RSpec.describe API::FeatureFlags do ...@@ -1117,14 +1008,6 @@ RSpec.describe API::FeatureFlags do
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
end end
it 'returns a 404 if the feature is disabled' do
stub_feature_flags(feature_flags_new_version: false)
expect { subject }.not_to change { Operations::FeatureFlag.count }
expect(response).to have_gitlab_http_status(:not_found)
end
end end
end end
end end
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