blob: ce035248baa5c86c7503d1bcba27f874efa37881 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
# frozen_string_literal: true
require "fog/google"
require "slack-notifier"
module QA
module Tools
class LongRunningSpecReporter
extend SingleForwardable
SLACK_CHANNEL = "#quality-reports"
PROJECT = "gitlab-qa-resources"
BUCKET = "knapsack-reports"
REPORT_NAME = "ee-instance-parallel.json"
RUNTIME_THRESHOLD = 300
def_delegator :new, :execute
# Find and report specs exceeding runtime threshold
#
# @return [void]
def execute
return puts("No long running specs detected, all good!") if long_running_specs.empty?
specs = long_running_specs.map { |k, v| "#{k}: #{(v / 60).round(2)} minutes" }.join("\n")
average = mean_runtime < 60 ? "#{mean_runtime.round(0)} seconds" : "#{(mean_runtime / 60).round(2)} minutes"
msg = <<~MSG
Following spec files are exceeding #{RUNTIME_THRESHOLD / 60} minute runtime threshold!
Current average spec runtime: #{average}.
MSG
puts("#{msg}\n#{specs}")
notifier.post(icon_emoji: ":time-out:", text: "#{msg}\n```#{specs}```")
end
private
# Average runtime of spec files
#
# @return [Number]
def mean_runtime
@mean_runtime ||= latest_report.values
.select { |v| v < RUNTIME_THRESHOLD }
.yield_self { |runtimes| runtimes.sum(0.0) / runtimes.length }
end
# Spec files exceeding runtime threshold
#
# @return [Hash]
def long_running_specs
@long_running_specs ||= latest_report.select { |k, v| v > RUNTIME_THRESHOLD }
end
# Latest knapsack report
#
# @return [Hash]
def latest_report
@latest_report ||= JSON.parse(client.get_object(BUCKET, REPORT_NAME)[:body])
end
# Slack notifier
#
# @return [Slack::Notifier]
def notifier
@notifier ||= Slack::Notifier.new(
slack_webhook_url,
channel: SLACK_CHANNEL,
username: "Spec Runtime Report"
)
end
# GCS client
#
# @return [Fog::Storage::GoogleJSON]
def client
@client ||= Fog::Storage::Google.new(
google_project: PROJECT,
**(File.exist?(gcs_json) ? { google_json_key_location: gcs_json } : { google_json_key_string: gcs_json })
)
end
# Slack webhook url
#
# @return [String]
def slack_webhook_url
@slack_webhook_url ||= ENV["SLACK_WEBHOOK"] || raise("Missing SLACK_WEBHOOK env variable")
end
# GCS credentials json
#
# @return [Hash]
def gcs_json
ENV["QA_KNAPSACK_REPORT_GCS_CREDENTIALS"] || raise("Missing QA_KNAPSACK_REPORT_GCS_CREDENTIALS env variable!")
end
end
end
end
|