2020-11-24 15:15:51 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Operations
|
|
|
|
class FeatureFlag < ApplicationRecord
|
2021-01-29 00:20:46 +05:30
|
|
|
include AfterCommitQueue
|
2020-11-24 15:15:51 +05:30
|
|
|
include AtomicInternalId
|
|
|
|
include IidRoutes
|
|
|
|
include Limitable
|
2021-03-11 19:13:27 +05:30
|
|
|
include Referable
|
2020-11-24 15:15:51 +05:30
|
|
|
|
|
|
|
self.table_name = 'operations_feature_flags'
|
|
|
|
self.limit_scope = :project
|
|
|
|
self.limit_name = 'project_feature_flags'
|
|
|
|
|
|
|
|
belongs_to :project
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
has_internal_id :iid, scope: :project
|
2020-11-24 15:15:51 +05:30
|
|
|
|
2023-01-13 00:05:48 +05:30
|
|
|
attribute :active, default: true
|
|
|
|
attribute :version, default: :new_version_flag
|
2020-11-24 15:15:51 +05:30
|
|
|
|
|
|
|
# strategies exists only for the second version
|
|
|
|
has_many :strategies, class_name: 'Operations::FeatureFlags::Strategy'
|
|
|
|
has_many :feature_flag_issues
|
|
|
|
has_many :issues, through: :feature_flag_issues
|
|
|
|
|
|
|
|
validates :project, presence: true
|
|
|
|
validates :name,
|
|
|
|
presence: true,
|
|
|
|
length: 2..63,
|
|
|
|
format: {
|
|
|
|
with: Gitlab::Regex.feature_flag_regex,
|
|
|
|
message: Gitlab::Regex.feature_flag_regex_message
|
|
|
|
}
|
|
|
|
validates :name, uniqueness: { scope: :project_id }
|
|
|
|
validates :description, allow_blank: true, length: 0..255
|
|
|
|
|
|
|
|
accepts_nested_attributes_for :strategies, allow_destroy: true
|
|
|
|
|
|
|
|
scope :ordered, -> { order(:name) }
|
|
|
|
|
|
|
|
scope :enabled, -> { where(active: true) }
|
|
|
|
scope :disabled, -> { where(active: false) }
|
|
|
|
|
2022-08-27 11:52:29 +05:30
|
|
|
scope :new_version_only, -> { where(version: :new_version_flag) }
|
2021-09-04 01:27:46 +05:30
|
|
|
|
2020-11-24 15:15:51 +05:30
|
|
|
enum version: {
|
|
|
|
new_version_flag: 2
|
|
|
|
}
|
|
|
|
|
|
|
|
class << self
|
|
|
|
def preload_relations
|
2021-11-18 22:05:49 +05:30
|
|
|
preload(strategies: :scopes)
|
2020-11-24 15:15:51 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def for_unleash_client(project, environment)
|
|
|
|
includes(strategies: [:scopes, :user_list])
|
|
|
|
.where(project: project)
|
|
|
|
.merge(Operations::FeatureFlags::Scope.on_environment(environment))
|
|
|
|
.reorder(:id)
|
|
|
|
.references(:operations_scopes)
|
|
|
|
end
|
2021-03-11 19:13:27 +05:30
|
|
|
|
|
|
|
def reference_prefix
|
|
|
|
'[feature_flag:'
|
|
|
|
end
|
|
|
|
|
|
|
|
def reference_pattern
|
|
|
|
@reference_pattern ||= %r{
|
|
|
|
#{Regexp.escape(reference_prefix)}(#{::Project.reference_pattern}\/)?(?<feature_flag>\d+)#{Regexp.escape(reference_postfix)}
|
|
|
|
}x
|
|
|
|
end
|
|
|
|
|
|
|
|
def link_reference_pattern
|
2021-09-30 23:02:18 +05:30
|
|
|
@link_reference_pattern ||= super("feature_flags", %r{(?<feature_flag>\d+)/edit})
|
2021-03-11 19:13:27 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def reference_postfix
|
|
|
|
']'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def to_reference(from = nil, full: false)
|
|
|
|
project
|
|
|
|
.to_reference_base(from, full: full)
|
|
|
|
.then { |reference_base| reference_base.present? ? "#{reference_base}/" : nil }
|
|
|
|
.then { |reference_base| "#{self.class.reference_prefix}#{reference_base}#{iid}#{self.class.reference_postfix}" }
|
2020-11-24 15:15:51 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def related_issues(current_user, preload:)
|
|
|
|
issues = ::Issue
|
|
|
|
.select('issues.*, operations_feature_flags_issues.id AS link_id')
|
|
|
|
.joins(:feature_flag_issues)
|
2021-06-08 01:23:25 +05:30
|
|
|
.where(operations_feature_flags_issues: { feature_flag_id: id })
|
2020-11-24 15:15:51 +05:30
|
|
|
.order('operations_feature_flags_issues.id ASC')
|
|
|
|
.includes(preload)
|
|
|
|
|
|
|
|
Ability.issues_readable_by_user(issues, current_user)
|
|
|
|
end
|
|
|
|
|
2021-01-29 00:20:46 +05:30
|
|
|
def hook_attrs
|
|
|
|
{
|
|
|
|
id: id,
|
|
|
|
name: name,
|
|
|
|
description: description,
|
|
|
|
active: active
|
|
|
|
}
|
|
|
|
end
|
2020-11-24 15:15:51 +05:30
|
|
|
end
|
|
|
|
end
|