lib/release_tools/release_managers/definitions.rb (103 lines of code) (raw):
# frozen_string_literal: true
module ReleaseTools
module ReleaseManagers
# Represents all defined Release Managers
class Definitions
extend Forwardable
include Enumerable
INSTANCES = %i(production dev ops).freeze
attr_accessor :config_file
attr_reader :all
def_delegator :@all, :each
class << self
extend Forwardable
def_delegators :new, :allowed?, :sync!, :join, :leave
end
def initialize(config_file = nil)
@config_file = config_file ||
File.expand_path('../../../config/release_managers.yml', __dir__)
reload!
end
def allowed?(username)
raise ArgumentError, "unknown environment: #{Runtime.ci_server_url}" unless Runtime.valid_environment?
source_env = Runtime.current_environment
any? { |user| user.send(source_env).casecmp?(username) }
end
def reload!
begin
content = YAML.load_file(config_file)
raise ArgumentError, "#{config_file} contains no data" if content.blank?
rescue Errno::ENOENT
raise ArgumentError, "#{config_file} does not exist!"
end
@all = content.map { |name, hash| User.new(name, hash) }
end
def sync!
release_managers = active_release_managers
slack_client.sync_membership(release_managers.filter_map(&:slack))
dev_client.sync_membership(release_managers.collect(&:dev))
production_client.sync_membership(release_managers.collect(&:production))
ops_client.sync_membership(release_managers.collect(&:ops))
ReleaseManagers::SyncResult.new([slack_client, dev_client, production_client, ops_client])
end
def join(username)
user = find_user(username, instance: :ops)
raise ArgumentError, "Unknown user #{username}" unless user
slack_client.join(user.slack)
dev_client.join(user.dev)
production_client.join(user.production)
ops_client.join(user.ops)
ReleaseManagers::SyncResult.new([slack_client, dev_client, production_client, ops_client])
end
def leave(username)
user = find_user(username, instance: :ops)
raise ArgumentError, "Unknown user #{username}" unless user
slack_client.leave(user.slack)
dev_client.leave(user.dev)
production_client.leave(user.production)
ops_client.leave(user.ops)
ReleaseManagers::SyncResult.new([slack_client, dev_client, production_client, ops_client])
end
def find_user(username, instance: :production)
raise ArgumentError, "Unknown instance #{instance}" unless INSTANCES.include?(instance)
find do |user|
user.send(instance) == username
end
end
# Returns an Array of users matching the provided names
#
# @param [Array<String>] the names to find a user for
# @return [Array<ReleaseTools::ReleaseManagers::Definitions::User>]
def find_by_name(names)
find_all do |user|
names.include?(user.name)
end
end
private
def dev_client
@dev_client ||= ReleaseManagers::Client.new(:dev)
end
def production_client
@production_client ||= ReleaseManagers::Client.new(:production)
end
def ops_client
@ops_client ||= ReleaseManagers::Client.new(:ops)
end
def slack_client
@slack_client ||= ReleaseManagers::SlackClient.new
end
def active_release_managers
active = Schedule.new.active_release_managers.collect(&:username)
all.select { |user| active.include?(user.production) }
end
# Represents a single entry from the configuration file
class User
attr_reader :name
attr_reader :dev, :production, :ops, :slack
def initialize(name, hash)
if hash['gitlab.com'].nil?
raise ArgumentError, "No `gitlab.com` value for #{name}"
end
@name = name
@production = hash['gitlab.com']
@dev = hash['gitlab.org'] || production
@ops = hash['ops.gitlab.net'] || production
@slack = hash['slack']
end
end
end
end
end