Rework CI status report

The new report shows summary stats for drivers and detailed status
per change request.

Change-Id: I7c7ba9eda15fcfd21fc83f623e961f7ec352ffe9
This commit is contained in:
Ilya Shakhat
2015-10-07 18:23:07 +03:00
parent 1b6a5fe764
commit a6ff499de3
6 changed files with 88 additions and 82 deletions

View File

@@ -292,6 +292,28 @@ def mark_finalize(record):
return new_record
def ci_filter(result, record, param_id, context):
result_by_param = result[getattr(record, param_id)]
result_by_param['metric'] += 1
key = 'success' if record.value else 'failure'
result_by_param[key] = result_by_param.get(key, 0) + 1
def ci_finalize(record):
new_record = record.copy()
metric = record.get('metric')
if metric:
new_record['success_ratio'] = '%.1f%%' % (
(record.get('success', 0) * 100.0) / metric)
else:
new_record['success_rate'] = helpers.INFINITY_HTML
return new_record
def person_day_filter(result, record, param_id, context):
day = utils.timestamp_to_day(record.date)
# fact that record-days are grouped by days in some order is used
@@ -338,7 +360,7 @@ def aggregate_filter():
'resolved-bugs': (incremental_filter, None),
'members': (incremental_filter, None),
'person-day': (person_day_filter, None),
'ci': (None, None),
'ci': (ci_filter, ci_finalize),
'patches': (None, None),
}
if metric not in metric_to_filters_map:

View File

@@ -152,8 +152,8 @@ def contribution(module, days):
@decorators.templated()
@decorators.exception_handler()
def external_ci(module, days):
if int(days) > 30:
days = 30
if int(days) > 100:
days = 100
return {
'module': module,

View File

@@ -80,7 +80,7 @@ show_record_type=True, show_user_gravatar=True, gravatar_size=32, show_all=True)
<div class="header">{%html author_link %} ({%html company_link %})</div>
{%/if%}
<div class="header">${date_str} in {%html module_link%}
{%if record_type == "mark" || record_type == "review" || record_type == "patch" %}
{%if record_type == "mark" || record_type == "review" || record_type == "patch" || record_type == "ci" %}
{%if branch != "master" %}(${branch}){%/if%}
{%/if%}
</div>
@@ -162,8 +162,8 @@ show_record_type=True, show_user_gravatar=True, gravatar_size=32, show_all=True)
<div class="header">CI vote in merged change request
<a href="https://review.openstack.org/#/c/${review_number}" target="_blank">${review_number}</a>
</div>
<div>Parsed result: {%if value == true %}<span style="color: green">Success</span>{%else%}<span style="color: red">Failure</span>{%/if%}</div>
<div>Message: ${message}</div>
<div>{%if value == true %}<span style="color: green">Success</span>{%else%}<span style="color: red">Failure</span>{%/if%}</div>
<div class="message">${message}</div>
<div>Change Id: <a href="https://review.openstack.org/#/c/${review_number}" target="_blank">${review_id}</a></div>
{%elif record_type == "member" %}
<div class="header"><a href="${member_uri}" target="_blank">Registered</a> in OpenStack Foundation</div>

View File

@@ -16,14 +16,15 @@
{% set show_user_profile = (user_id) %}
{% set show_module_details = (module) %}
{% set show_review_ratio = (metric in ['marks']) %}
{% set show_ci = (metric in ['ci']) %}
{% macro show_report_links(module=None, company=None, user_id=None) -%}
{% if module %}
<div><b><a href="/report/reviews/{{ module }}/open" target="_blank">Show open reviews for {{ module_inst.module_group_name }}</a></b></div>
<div><b><a href="/report/contribution/{{ module }}/30" target="_blank">Contribution for the last 30 days in {{ module_inst.module_group_name }}</a></b></div>
<div><b><a href="/report/contribution/{{ module }}/90" target="_blank">Contribution for the last 90 days in {{ module_inst.module_group_name }}</a></b></div>
{% if module_inst.ci %}
<div><b><a href="/report/ci/{{ module }}/7" target="_blank">External CI status for {{ module_inst.module_group_name }} for the last 7 days</a></b></div>
{% if module_inst.has_drivers %}
<div><b><a href="/report/ci/{{ module }}/7" target="_blank">Status of drivers testing in {{ module_inst.module_group_name }} during recent 7 days</a></b></div>
{% endif %}
{% endif %}
{% if company %}
@@ -46,6 +47,9 @@
{% if show_review_ratio %}
renderTableAndChart("/api/1.0/stats/engineers", "engineer_container", "engineer_table", "engineer_chart", "user_id",
["index", "link", "mark_ratio", "metric"]);
{% elif show_ci %}
renderTableAndChart("/api/1.0/stats/engineers", "engineer_container", "engineer_table", "engineer_chart", "user_id",
["index", "link", "metric", "success_ratio"]);
{% else %}
renderTableAndChart("/api/1.0/stats/engineers", "engineer_container", "engineer_table", "engineer_chart", "user_id");
{% endif %}
@@ -95,11 +99,14 @@
<thead>
<tr>
<th>#</th>
<th>Contributor</th>
<th>{% if show_ci %}Driver{% else %}Contributor{% endif %}</th>
{% if show_review_ratio %}
<th>-2|-1|+1|+2|A (+ ratio)</th>
{% endif %}
<th>{{ metric_label }}</th>
{% if show_ci %}
<th>Success</th>
{% endif %}
</tr>
</thead>
<tbody>

View File

@@ -25,8 +25,7 @@ External CI status for {{ module }} for the last {{ days }} days
});
$(document).ready(function () {
var table_column_names = ["name", "merge_run_count", "merge_success_rate", "merge_date_str", "merge_result",
"total_run_count", "total_success_rate", "total_date_str"];
var table_column_names = ["name", "merge_run_count", "merge_success_rate", "merge_date_str", "merge_result"];
var table_id = "summary_stats_table";
$.ajax({
@@ -49,55 +48,41 @@ External CI status for {{ module }} for the last {{ days }} days
for (i = 0; i < activity.length; i++) {
var ai = activity[i];
if (ai.branch != "master") {
continue;
}
var ci_id = ai.user_id;
var ci = ci_map[ci_id];
if (!ci) {
ci = {total_run_count: 0, total_success: 0, merge_run_count: 0, merge_success: 0,
merge_date: 0, total_date: 0, merge_result: "N/A",
ci = {merge_run_count: 0, merge_success: 0,
merge_date: 0, merge_result: "N/A",
merge_date_str: "N/A", "total_date_str": "N/A"};
}
ci.id = ai.user_id;
ci.name = "<a href=\"https://review.openstack.org/#/q/reviewer:" + ai.user_id +
"+project:openstack/{{ module }},n,z\" target=\"_blank\">" + ai.user_id + "</a>";
ci.name = "<a href=\"/?metric=ci&user_id=" + ai.user_id +
"&module={{ module }}\">" + ai.driver_name + "</a>";
ci_id_to_name[ci_id] = ci.name;
ci.total_run_count ++;
if (ai.ci_result) {
ci.total_success ++;
}
if (ai.is_merged) {
var review_id = ai.review_number;
if (!review_ids_set[review_id]) {
review_ids_set[review_id] = review_id;
review_ids.push({review_id: review_id, date_str: ai.date_str});
}
if (!res_map[ci_id]) {
res_map[ci_id] = {};
}
res_map[ci_id][review_id] = ai.ci_result;
ci.merge_run_count ++;
if (ai.ci_result) {
ci.merge_success ++;
}
if (ai.date > ci.merge_date) {
ci.merge_date = ai.date;
ci.merge_date_str = ai.date_str;
ci.merge_result = (ai.ci_result)? "<span style=\"color: green\">&#x2714;</span>":
"<span style=\"color: red\">&#x2716;</span>";
}
var review_id = ai.review_number;
if (!review_ids_set[review_id]) {
review_ids_set[review_id] = review_id;
review_ids.push({review_id: review_id, date_str: ai.date_str});
}
if (ai.date > ci.total_date) {
ci.total_date = ai.date;
ci.total_date_str = ai.date_str;
if (!res_map[ci_id]) {
res_map[ci_id] = {};
}
res_map[ci_id][review_id] = ai.value;
ci.merge_run_count ++;
if (ai.value) {
ci.merge_success ++;
}
if (ai.date > ci.merge_date) {
ci.merge_date = ai.date;
ci.merge_date_str = ai.date_str;
ci.merge_result = (ai.value)? "<span style=\"color: green\">&#x2714;</span>":
"<span style=\"color: red\">&#x2716;</span>";
}
ci_map[ci_id] = ci;
}
@@ -106,16 +91,11 @@ External CI status for {{ module }} for the last {{ days }} days
var c = ci_map[ci_id];
if (c.merge_run_count > 0) {
c.merge_success_rate = Math.round(c.merge_success / c.merge_run_count * 100) + "%";
c.merge_success_rate = Math.round(100 * c.merge_success / c.merge_run_count) + "%";
} else {
c.merge_success_rate = "-";
}
if (c.total_run_count > 0) {
c.total_success_rate = Math.round(c.total_success / c.total_run_count * 100) + "%";
} else {
c.total_success_rate = "-";
}
tableData.push(c);
}
@@ -131,8 +111,8 @@ External CI status for {{ module }} for the last {{ days }} days
"aaData": tableData,
"aoColumns": tableColumns,
"aoColumnDefs": [
{ "sClass": "center", "aTargets": [1, 2, 3, 4, 5, 6, 7] },
{ "sType": "ratio", "aTargets": [2, 6]}
{ "sClass": "center", "aTargets": [1, 2, 3, 4] },
{ "sType": "ratio", "aTargets": [2]}
]
}).show();
$("#" + table_id + "_loading").hide();
@@ -144,7 +124,7 @@ External CI status for {{ module }} for the last {{ days }} days
table.append(table_head);
var table_head_row = $("<tr></tr>");
table_head.append(table_head_row);
table_head_row.append($("<th rowspan='2'>CI</th>"));
table_head_row.append($("<th rowspan='2'>Driver</th>"));
var table_second_head_row = $("<tr></tr>");
table_head.append(table_second_head_row);
var table_body = $("<tbody></tbody>");
@@ -165,7 +145,8 @@ External CI status for {{ module }} for the last {{ days }} days
}
prev_date = date;
count++;
table_second_head_row.append($("<th title='" + review_ids[i].review_id + "'></th>"));
table_second_head_row.append($("<th title='Change request " + review_ids[i].review_id +
"'><span style='font-size: 60%;'>" + review_ids[i].review_id + "</span></th>"));
}
if (count > 0) {
@@ -180,19 +161,23 @@ External CI status for {{ module }} for the last {{ days }} days
var review_id = review_ids[i].review_id;
var color = "#cfcfcf";
var title = "N/A";
if (res_map[ci_id]) {
var res = res_map[ci_id][review_id];
if (res == true) {
color = "#40bf00";
title = "SUCCESS";
} else if (res == false) {
color = "#bf4000";
title = "FAILURE";
}
}
const url = "https://review.openstack.org/#/c/" + review_id;
var cell = $("<td></td>");
cell.css("background-color", color).css("cursor", "pointer").prop("title", url);
cell.css("background-color", color).css("cursor", "pointer").prop("url", url).prop("title", title + " - " + url);
cell.click(function(evt) {
window.open($(this).prop("title"));
window.open($(this).prop("url"));
});
table_row.append(cell);
}
@@ -228,31 +213,24 @@ External CI status for {{ module }} for the last {{ days }} days
{% endblock %}
{% block content %}
<h1>External CI status for {{ module }} for the last {{ days }} days</h1>
<h1>Status of drivers testing in {{ module|title }} during recent {{ days }} days</h1>
<h2>Summary</h2>
<p>List of drivers is taken from <a href="/report/driverlog" target="_blank">DriverLog</a>.
The status is based on job results from the latest patch in merged change requests (thus assuming that the job is executed on code close to the master).
Missing or misconfigured drivers can be updated by commit into DriverLog's
<a href="https://git.openstack.org/cgit/stackforge/driverlog/tree/etc/default_data.json" target="_blank">default_data.json</a>.
</p>
<p>Overall stats for external CIs. <i>Merged patch sets</i> - results of test execution on the last patch set in the
merged change request (assuming that it is almost the same as to run tests against master). <i>All patch sets</i> -
results of test execution on all patch sets.</p>
<p>List of CIs is taken from <a href="/report/driverlog">DriverLog</a> and can be updated by commit into its
<a href="https://git.openstack.org/cgit/stackforge/driverlog/tree/etc/default_data.json">default_data.json</a></p>
<h2>Drivers summary</h2>
<table id="summary_stats_table" style="display: none;">
<thead>
<tr>
<th rowspan="2">CI</th>
<th colspan="4" title="Stats for the last patch set in the merged change request">Merged patch sets</th>
<th colspan="3">All patch sets</th>
</tr>
<tr>
<th>Total runs</th>
<th>Driver</th>
<th>CI votes</th>
<th>Success, %</th>
<th>Last run</th>
<th>Last result</th>
<th>Total runs</th>
<th>Success, %</th>
<th>Last run</th>
<th>Latest run</th>
<th>Latest result</th>
</tr>
</thead>
<tbody>
@@ -261,10 +239,7 @@ External CI status for {{ module }} for the last {{ days }} days
<div id="summary_stats_table_loading" class="select2-loading" style="width: 7em;">Loading...</div>
<h2>Status for merged changed requests</h2>
<p>Status of CI test execution for every merged patch set grouped by days. Green cell - tests ran successfully,
red cell - tests failed, grey cell - tests results not found.</p>
<h2>Status per change requests</h2>
<div id="table_status_container"></div>
<div id="table_status_container_loading" class="select2-loading" style="width: 7em;">Loading...</div>

View File

@@ -587,6 +587,8 @@ def timeline(records, **kwargs):
if ('commits' in metric) or ('loc' in metric):
handler = lambda record: record.loc
elif 'ci' in metric:
handler = lambda record: 0 if record.value else 1
else:
handler = lambda record: 0