lib/release_tools/metrics/release_metric_updater.rb (73 lines of code) (raw):
# frozen_string_literal: true
module ReleaseTools
module Metrics
class ReleaseMetricUpdater
include ::SemanticLogger::Loggable
class InvalidReleaseStatusError < StandardError
def initialize(status_code)
super("Invalid release status: #{status_code}")
end
end
MONTHLY_STATUSES = %i[open announced tagged_rc].freeze
PATCH_STATUSES = %i[open warning closed].freeze
def initialize
@prometheus = ReleaseTools::Prometheus::Query.new
end
def execute
return unless Feature.enabled?(:release_status_metric_update)
update_monthly_release_status
update_patch_release_status
end
private
def releases_client
@releases_client ||= ReleaseTools::GitlabReleasesGemClient
end
# releases_client.current version gets the current deployed version, sourced from versions.gitlab.com
# releases.client.active_version gets the next version to be deployed, sourced from releases.yml (https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/releases.yml)
# This would return true only on the release day, after the new version has been created on versions.gitlab.com
def release_day?
releases_client.current_version == releases_client.active_version
end
# Monthly active version
def monthly_active_version
version = if release_day?
# On the release day, after the release has been published,
# we need to get the version for tomorrow
# This will fail before
releases_client.version_for_date(Date.tomorrow)
else
releases_client.active_version
end
ReleaseTools::Version.new(version).to_minor
end
def next_patch_release_date
@next_patch_release_date ||= releases_client.next_patch_release_date
end
def patch_next_versions
# Finds the current minor version when the next patch release is scheduled
# Then finds the previous minor versions for backports
minor_version_for_patch_release = releases_client.current_minor_for_date(next_patch_release_date)
releases_client
.previous_minors(minor_version_for_patch_release)
.join(" ")
end
def monthly_release_status(version)
value = @prometheus.monthly_release_status(version)
validate_release_status(value, MONTHLY_STATUSES)
value
end
def patch_release_status(versions)
value = @prometheus.patch_release_status(versions)
validate_release_status(value, PATCH_STATUSES)
value
end
def validate_release_status(value, statuses)
raise InvalidReleaseStatusError, value unless value.is_a?(Integer) && value.positive? && value <= statuses.size
end
def update_monthly_release_status
monthly_status = monthly_release_status(monthly_active_version)
# Status on the MonthlyReleaseStatus metric
# 1 = open, 2 = announced, 3 = tagged_rc
# so we need to subtract 1 to match it to MONTHLY_STATUSES
status = MONTHLY_STATUSES[monthly_status - 1]
ReleaseTools::Metrics::MonthlyReleaseStatus
.new(status: status)
.execute
end
def update_patch_release_status
patch_status = patch_release_status(patch_next_versions)
# Status on the PatchReleaseStatus metric
# 1 = open, 2 = warning, 3 = closed
# so we need to subtract 1 to match it to PATCH_STATUSES
status = PATCH_STATUSES[patch_status - 1]
ReleaseTools::Metrics::PatchReleaseStatus
.new(status: status)
.execute
end
end
end
end