lib/release_tools/release_managers/schedule.rb (82 lines of code) (raw):
# frozen_string_literal: true
module ReleaseTools
module ReleaseManagers
# Obtaining of release managers for a given major/minor release.
class Schedule
include ::SemanticLogger::Loggable
# Raised when release managers for the specified version can't be found
VersionNotFoundError = Class.new(StandardError)
# The base interval for retrying operations that failed, in seconds.
#
# This is set higher than the default as obtaining the release managers
# schedule can time out, and it often takes a while before these requests
# stop timing out.
RETRY_INTERVAL = 5
# Releases SSOT - Contains releases and release manager information.
RELEASES_YAML = 'https://gitlab.com/gitlab-com/www-gitlab-com/-/raw/master/data/releases.yml'
APPSEC_GROUP_ID = 4_654_006
def initialize
@schedule_yaml = nil
end
# Returns the scheduled major.minor version for today.
#
# To be deprecated https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/19851
#
# @return [ReleaseTools::Version|NilClass]
def active_version
Version.new(ReleaseTools::GitlabReleasesGemClient.active_version)
end
# Returns an Array of users for the current milestone release managers
#
# @return [Array<Gitlab::ObjectifiedHash>]
def active_release_managers
authorized_release_managers(active_version)
end
# Returns an Array of users for the current milestone release managers
#
# @return [Array<Gitlab::ObjectifiedHash>]
def active_appsec_release_managers
# Appsec release managers are listed for the previous release
appsec_release_managers(Version.new(active_version.previous_minor))
end
# Returns the scheduled major.minor version for the given date.
#
# To be deprecated https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/19851
#
# @param [Date|Time] date
# @return [ReleaseTools::Version|NilClass]
def version_for_date(date)
Version.new(ReleaseTools::GitlabReleasesGemClient.version_for_date(date))
rescue StandardError
nil
end
# Returns the user IDs of the release managers for the current version.
# Used to assign to resources such as Issues.
#
# @param [ReleaseTools::Version] version
# @return [Array<Integer>]
def ids_for_version(version)
authorized_release_managers(version).collect(&:id)
end
# Returns the usernames of the release managers for the current version.
# Used to add/remove access to groups at various GitLab instances.
#
# @param [ReleaseTools::Version] version
# @return [Array<String>]
def usernames_for_version(version)
authorized_release_managers(version).collect(&:username)
end
# Returns an Array of users authorized for release manager tasks for current version.
#
# @param [ReleaseTools::Version] version
# @return [Array<Gitlab::ObjectifiedHash>]
def authorized_release_managers(version)
names = release_manager_names_from_yaml(version)
client = ReleaseManagers::Client.new
Definitions.new.find_by_name(names).map do |release_manager|
client.get_user(release_manager.production)
end
end
# Returns a Hash mapping release manager names with all their attributes.
#
# @return [Hash<String, Gitlab::ObjectifiedHash>]
def group_members
members =
begin
ReleaseManagers::Client.new.members
rescue StandardError
[]
end
members.each_with_object({}) do |user, hash|
hash[user.name] = user
end
end
# @return [Array<Hash>]
def schedule_yaml
@schedule_yaml ||=
begin
YAML.safe_load(download_schedule) || []
rescue StandardError
[]
end
end
private
def appsec_release_managers(version)
names = release_manager_names_from_yaml(version, appsec: true)
client = ReleaseTools::GitlabClient.client
appsec_members = Retriable.with_context(:api) do
client.group_members(APPSEC_GROUP_ID)
end
appsec_members.select! { |member| names.include?(member.name) }
end
def release_manager_names_from_yaml(version, appsec: false)
not_found = -> { raise VersionNotFoundError }
minor = version.to_minor
names = schedule_yaml
.find(not_found) { |row| row['version'] == minor }
return names['appsec'] if appsec
names['manager_americas'] | names['manager_apac_emea']
end
def download_schedule
Retriable.retriable(base_interval: RETRY_INTERVAL) do
HTTP.get(RELEASES_YAML).to_s
end
end
end
end
end