148 lines
3.7 KiB
Ruby
148 lines
3.7 KiB
Ruby
require 'redis'
|
|
require 'rollout'
|
|
require 'active_support/deprecation'
|
|
require 'active_support/core_ext/module'
|
|
|
|
module Travis
|
|
# Travis::Features contains methods to handle feature flags.
|
|
module Features
|
|
class << self
|
|
methods = (Rollout.public_instance_methods(false) - [:active?, "active?"]) << {:to => :rollout}
|
|
delegate(*methods)
|
|
end
|
|
|
|
def redis
|
|
Travis.redis
|
|
end
|
|
|
|
def rollout
|
|
@rollout ||= ::Rollout.new(redis)
|
|
end
|
|
|
|
# Returns whether a given feature is enabled either globally or for a given
|
|
# repository.
|
|
#
|
|
# By default, this will return false.
|
|
def active?(feature, repository)
|
|
feature_active?(feature) or
|
|
(rollout.active?(feature, repository.owner) or
|
|
repository_active?(feature, repository))
|
|
end
|
|
|
|
def activate_repository(feature, repository)
|
|
redis.sadd(repository_key(feature), repository_id(repository))
|
|
end
|
|
|
|
def deactivate_repository(feature, repository)
|
|
redis.srem(repository_key(feature), repository_id(repository))
|
|
end
|
|
|
|
# Return whether a given feature is enabled for a repository.
|
|
#
|
|
# By default, this will return false.
|
|
def repository_active?(feature, repository)
|
|
redis.sismember(repository_key(feature), repository_id(repository))
|
|
end
|
|
|
|
# Return whether a given feature is enabled for a user.
|
|
#
|
|
# By default, this will return false.
|
|
def user_active?(feature, user)
|
|
rollout.active?(feature, user)
|
|
end
|
|
|
|
def activate_all(feature)
|
|
redis.del(disabled_key(feature))
|
|
end
|
|
|
|
# Return whether a feature is enabled globally.
|
|
#
|
|
# By default, this will return false.
|
|
def feature_active?(feature)
|
|
enabled_for_all?(feature) and !feature_inactive?(feature)
|
|
end
|
|
|
|
# Return whether a feature has been disabled.
|
|
#
|
|
# This is similar to feature_deactivated?, but with the opposite default.
|
|
#
|
|
# By default this will return true (ie. disabled).
|
|
def feature_inactive?(feature)
|
|
redis.get(disabled_key(feature)) != "1"
|
|
end
|
|
|
|
# Return whether a feature has been disabled.
|
|
#
|
|
# This is similar to feature_inactive?, but with the opposite default.
|
|
#
|
|
# By default this will return false (ie not disabled).
|
|
def feature_deactivated?(feature)
|
|
redis.get(disabled_key(feature)) == '0'
|
|
end
|
|
|
|
def deactivate_all(feature)
|
|
redis.set(disabled_key(feature), 0)
|
|
end
|
|
|
|
# Return whether a feature has been enabled globally.
|
|
#
|
|
# By default this will return false.
|
|
def enabled_for_all?(feature)
|
|
redis.get(enabled_for_all_key(feature)) == '1'
|
|
end
|
|
|
|
def enable_for_all(feature)
|
|
redis.set(enabled_for_all_key(feature), 1)
|
|
end
|
|
|
|
def disable_for_all(feature)
|
|
redis.set(enabled_for_all_key(feature), 0)
|
|
end
|
|
|
|
def activate_owner(feature, owner)
|
|
redis.sadd(owner_key(feature, owner), owner.id)
|
|
end
|
|
|
|
def deactivate_owner(feature, owner)
|
|
redis.srem(owner_key(feature, owner), owner.id)
|
|
end
|
|
|
|
# Return whether a feature has been enabled for a user.
|
|
#
|
|
# By default, this return false.
|
|
def owner_active?(feature, owner)
|
|
return false unless owner
|
|
redis.sismember(owner_key(feature, owner), owner.id)
|
|
end
|
|
|
|
extend self
|
|
|
|
private
|
|
|
|
def key(name)
|
|
"feature:#{name}"
|
|
end
|
|
|
|
def owner_key(feature, owner)
|
|
suffix = owner.class.table_name if owner
|
|
"#{key(feature)}:#{suffix}"
|
|
end
|
|
|
|
def repository_key(feature)
|
|
"#{key(feature)}:repositories"
|
|
end
|
|
|
|
def disabled_key(feature)
|
|
"#{key(feature)}:disabled"
|
|
end
|
|
|
|
def enabled_for_all_key(feature)
|
|
"#{key(feature)}:disabled"
|
|
end
|
|
|
|
def repository_id(repository)
|
|
repository.respond_to?(:id) ? repository.id : repository.to_i
|
|
end
|
|
end
|
|
end
|