Commit c2737699 authored by Andrejs Cunskis's avatar Andrejs Cunskis

Merge branch 'acunskis-close-old-reliable-report' into 'master'

Automatically close previous reliable test reports

See merge request gitlab-org/gitlab!85090
parents e9f85a9f 9f7de974
......@@ -20,9 +20,7 @@ module QA
verify_ssl: false
}
RestClient::Request.execute(
default_args.merge(args)
)
RestClient::Request.execute(default_args.merge(args))
rescue RestClient::ExceptionWithResponse => e
return_response_or_raise(e)
end
......@@ -56,13 +54,16 @@ module QA
end
end
def put(url, payload = nil)
def put(url, payload = nil, args = {})
with_retry_on_too_many_requests do
RestClient::Request.execute(
default_args = {
method: :put,
url: url,
payload: payload,
verify_ssl: false)
verify_ssl: false
}
RestClient::Request.execute(default_args.merge(args))
rescue RestClient::ExceptionWithResponse => e
return_response_or_raise(e)
end
......
......@@ -11,6 +11,8 @@ module QA
include Support::InfluxdbTools
include Support::API
RELIABLE_REPORT_LABEL = "reliable test report"
# Project for report creation: https://gitlab.com/gitlab-org/gitlab
PROJECT_ID = 278964
......@@ -28,7 +30,11 @@ module QA
reporter = new(range)
reporter.print_report
reporter.report_in_issue_and_slack if report_in_issue_and_slack == "true"
if report_in_issue_and_slack == "true"
reporter.report_in_issue_and_slack
reporter.close_previous_reports
end
rescue StandardError => e
reporter&.notify_failure(e)
raise(e)
......@@ -51,16 +57,15 @@ module QA
# @return [void]
def report_in_issue_and_slack
puts "Creating report".colorize(:green)
response = post(
"#{gitlab_api_url}/projects/#{PROJECT_ID}/issues",
{
title: "Reliable e2e test report",
description: report_issue_body,
labels: "Quality,test,type::maintenance,reliable test report,automation:ml"
},
headers: { "PRIVATE-TOKEN" => gitlab_access_token }
issue = api_update(
:post,
"projects/#{PROJECT_ID}/issues",
title: "Reliable e2e test report",
description: report_issue_body,
labels: "#{RELIABLE_REPORT_LABEL},Quality,test,type::maintenance,automation:ml"
)
web_url = parse_body(response)[:web_url]
@report_iid = issue[:iid]
web_url = issue[:web_url]
puts "Created report issue: #{web_url}"
puts "Sending slack notification".colorize(:green)
......@@ -76,6 +81,25 @@ module QA
puts "Done!"
end
# Close previous reliable test reports
#
# @return [void]
def close_previous_reports
puts "Closing previous reports".colorize(:green)
issues = api_get("projects/#{PROJECT_ID}/issues?labels=#{RELIABLE_REPORT_LABEL}&state=opened")
issues
.reject { |issue| issue[:iid] == report_iid }
.each do |issue|
issue_iid = issue[:iid]
issue_endpoint = "projects/#{PROJECT_ID}/issues/#{issue_iid}"
puts "Closing previous report '#{issue[:web_url]}'"
api_update(:put, issue_endpoint, state_event: "close")
api_update(:post, "#{issue_endpoint}/notes", body: "Closed issue in favor of ##{report_iid}")
end
end
# Notify failure
#
# @param [StandardError] error
......@@ -89,7 +113,39 @@ module QA
private
attr_reader :range, :slack_channel
attr_reader :range, :slack_channel, :report_iid
# Slack notifier
#
# @return [Slack::Notifier]
def notifier
@notifier ||= Slack::Notifier.new(
slack_webhook_url,
channel: slack_channel,
username: "Reliable Spec Report"
)
end
# Gitlab access token
#
# @return [String]
def gitlab_access_token
@gitlab_access_token ||= ENV["GITLAB_ACCESS_TOKEN"] || raise("Missing GITLAB_ACCESS_TOKEN env variable")
end
# Gitlab api url
#
# @return [String]
def gitlab_api_url
@gitlab_api_url ||= ENV["CI_API_V4_URL"] || raise("Missing CI_API_V4_URL env variable")
end
# Slack webhook url
#
# @return [String]
def slack_webhook_url
@slack_webhook_url ||= ENV["SLACK_WEBHOOK"] || raise("Missing SLACK_WEBHOOK env variable")
end
# Markdown formatted report issue body
#
......@@ -324,36 +380,30 @@ module QA
QUERY
end
# Slack notifier
# Api get request
#
# @return [Slack::Notifier]
def notifier
@notifier ||= Slack::Notifier.new(
slack_webhook_url,
channel: slack_channel,
username: "Reliable Spec Report"
)
# @param [String] path
# @param [Hash] payload
# @return [Hash, Array]
def api_get(path)
response = get("#{gitlab_api_url}/#{path}", { headers: { "PRIVATE-TOKEN" => gitlab_access_token } })
parse_body(response)
end
# Gitlab access token
# Api update request
#
# @return [String]
def gitlab_access_token
@gitlab_access_token ||= ENV["GITLAB_ACCESS_TOKEN"] || raise("Missing GITLAB_ACCESS_TOKEN env variable")
end
# Gitlab api url
#
# @return [String]
def gitlab_api_url
@gitlab_api_url ||= ENV["CI_API_V4_URL"] || raise("Missing CI_API_V4_URL env variable")
end
# Slack webhook url
#
# @return [String]
def slack_webhook_url
@slack_webhook_url ||= ENV["SLACK_WEBHOOK"] || raise("Missing SLACK_WEBHOOK env variable")
# @param [Symbol] verb :post or :put
# @param [String] path
# @param [Hash] payload
# @return [Hash, Array]
def api_update(verb, path, **payload)
response = send(
verb,
"#{gitlab_api_url}/#{path}",
payload,
{ headers: { "PRIVATE-TOKEN" => gitlab_access_token } }
)
parse_body(response)
end
end
end
......
......@@ -5,7 +5,6 @@ describe QA::Tools::ReliableReport do
subject(:run) { described_class.run(range: range, report_in_issue_and_slack: create_issue) }
let(:gitlab_response) { instance_double("RestClient::Response", code: 200, body: { web_url: issue_url }.to_json) }
let(:slack_notifier) { instance_double("Slack::Notifier", post: nil) }
let(:influx_client) { instance_double("InfluxDB2::Client", create_query_api: query_api) }
let(:query_api) { instance_double("InfluxDB2::QueryApi") }
......@@ -118,7 +117,7 @@ describe QA::Tools::ReliableReport do
stub_env("CI_API_V4_URL", "gitlab_api_url")
stub_env("GITLAB_ACCESS_TOKEN", "gitlab_token")
allow(RestClient::Request).to receive(:execute).and_return(gitlab_response)
allow(RestClient::Request).to receive(:execute)
allow(Slack::Notifier).to receive(:new).and_return(slack_notifier)
allow(InfluxDB2::Client).to receive(:new).and_return(influx_client)
......@@ -139,6 +138,37 @@ describe QA::Tools::ReliableReport do
context "with report creation" do
let(:create_issue) { "true" }
let(:iid) { 2 }
let(:old_iid) { 1 }
let(:issue_endpoint) { "gitlab_api_url/projects/278964/issues" }
let(:common_api_args) do
{
verify_ssl: false,
headers: { "PRIVATE-TOKEN" => "gitlab_token" }
}
end
let(:create_issue_response) do
instance_double(
"RestClient::Response",
code: 200,
body: { web_url: issue_url, iid: iid }.to_json
)
end
let(:open_issues_response) do
instance_double(
"RestClient::Response",
code: 200,
body: [{ web_url: issue_url, iid: iid }, { web_url: issue_url, iid: old_iid }].to_json
)
end
let(:success_response) do
instance_double("RestClient::Response", code: 200, body: {}.to_json)
end
let(:issue_body) do
<<~TXT.strip
[[_TOC_]]
......@@ -157,19 +187,48 @@ describe QA::Tools::ReliableReport do
TXT
end
it "creates report issue", :aggregate_failures do
before do
allow(RestClient::Request).to receive(:execute).exactly(4).times.and_return(
create_issue_response,
open_issues_response,
success_response,
success_response
)
end
it "creates report issue" do
expect { run }.to output.to_stdout
expect(RestClient::Request).to have_received(:execute).with(
method: :post,
url: "gitlab_api_url/projects/278964/issues",
verify_ssl: false,
headers: { "PRIVATE-TOKEN" => "gitlab_token" },
url: issue_endpoint,
payload: {
title: "Reliable e2e test report",
description: issue_body,
labels: "Quality,test,type::maintenance,reliable test report,automation:ml"
}
labels: "reliable test report,Quality,test,type::maintenance,automation:ml"
},
**common_api_args
)
expect(RestClient::Request).to have_received(:execute).with(
method: :get,
url: "#{issue_endpoint}?labels=reliable test report&state=opened",
**common_api_args
)
expect(RestClient::Request).to have_received(:execute).with(
method: :put,
url: "#{issue_endpoint}/#{old_iid}",
payload: {
state_event: "close"
},
**common_api_args
)
expect(RestClient::Request).to have_received(:execute).with(
method: :post,
url: "#{issue_endpoint}/#{old_iid}/notes",
payload: {
body: "Closed issue in favor of ##{iid}"
},
**common_api_args
)
expect(slack_notifier).to have_received(:post).with(
icon_emoji: ":tanuki-protect:",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment