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:
@@ -292,6 +292,28 @@ def mark_finalize(record):
|
|||||||
return new_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):
|
def person_day_filter(result, record, param_id, context):
|
||||||
day = utils.timestamp_to_day(record.date)
|
day = utils.timestamp_to_day(record.date)
|
||||||
# fact that record-days are grouped by days in some order is used
|
# 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),
|
'resolved-bugs': (incremental_filter, None),
|
||||||
'members': (incremental_filter, None),
|
'members': (incremental_filter, None),
|
||||||
'person-day': (person_day_filter, None),
|
'person-day': (person_day_filter, None),
|
||||||
'ci': (None, None),
|
'ci': (ci_filter, ci_finalize),
|
||||||
'patches': (None, None),
|
'patches': (None, None),
|
||||||
}
|
}
|
||||||
if metric not in metric_to_filters_map:
|
if metric not in metric_to_filters_map:
|
||||||
|
@@ -152,8 +152,8 @@ def contribution(module, days):
|
|||||||
@decorators.templated()
|
@decorators.templated()
|
||||||
@decorators.exception_handler()
|
@decorators.exception_handler()
|
||||||
def external_ci(module, days):
|
def external_ci(module, days):
|
||||||
if int(days) > 30:
|
if int(days) > 100:
|
||||||
days = 30
|
days = 100
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'module': module,
|
'module': module,
|
||||||
|
@@ -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>
|
<div class="header">{%html author_link %} ({%html company_link %})</div>
|
||||||
{%/if%}
|
{%/if%}
|
||||||
<div class="header">${date_str} in {%html module_link%}
|
<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 branch != "master" %}(${branch}){%/if%}
|
||||||
{%/if%}
|
{%/if%}
|
||||||
</div>
|
</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
|
<div class="header">CI vote in merged change request
|
||||||
<a href="https://review.openstack.org/#/c/${review_number}" target="_blank">${review_number}</a>
|
<a href="https://review.openstack.org/#/c/${review_number}" target="_blank">${review_number}</a>
|
||||||
</div>
|
</div>
|
||||||
<div>Parsed result: {%if value == true %}<span style="color: green">Success</span>{%else%}<span style="color: red">Failure</span>{%/if%}</div>
|
<div>{%if value == true %}<span style="color: green">Success</span>{%else%}<span style="color: red">Failure</span>{%/if%}</div>
|
||||||
<div>Message: ${message}</div>
|
<div class="message">${message}</div>
|
||||||
<div>Change Id: <a href="https://review.openstack.org/#/c/${review_number}" target="_blank">${review_id}</a></div>
|
<div>Change Id: <a href="https://review.openstack.org/#/c/${review_number}" target="_blank">${review_id}</a></div>
|
||||||
{%elif record_type == "member" %}
|
{%elif record_type == "member" %}
|
||||||
<div class="header"><a href="${member_uri}" target="_blank">Registered</a> in OpenStack Foundation</div>
|
<div class="header"><a href="${member_uri}" target="_blank">Registered</a> in OpenStack Foundation</div>
|
||||||
|
@@ -16,14 +16,15 @@
|
|||||||
{% set show_user_profile = (user_id) %}
|
{% set show_user_profile = (user_id) %}
|
||||||
{% set show_module_details = (module) %}
|
{% set show_module_details = (module) %}
|
||||||
{% set show_review_ratio = (metric in ['marks']) %}
|
{% set show_review_ratio = (metric in ['marks']) %}
|
||||||
|
{% set show_ci = (metric in ['ci']) %}
|
||||||
|
|
||||||
{% macro show_report_links(module=None, company=None, user_id=None) -%}
|
{% macro show_report_links(module=None, company=None, user_id=None) -%}
|
||||||
{% if module %}
|
{% 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/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 }}/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>
|
<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 %}
|
{% if module_inst.has_drivers %}
|
||||||
<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>
|
<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 %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if company %}
|
{% if company %}
|
||||||
@@ -46,6 +47,9 @@
|
|||||||
{% if show_review_ratio %}
|
{% if show_review_ratio %}
|
||||||
renderTableAndChart("/api/1.0/stats/engineers", "engineer_container", "engineer_table", "engineer_chart", "user_id",
|
renderTableAndChart("/api/1.0/stats/engineers", "engineer_container", "engineer_table", "engineer_chart", "user_id",
|
||||||
["index", "link", "mark_ratio", "metric"]);
|
["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 %}
|
{% else %}
|
||||||
renderTableAndChart("/api/1.0/stats/engineers", "engineer_container", "engineer_table", "engineer_chart", "user_id");
|
renderTableAndChart("/api/1.0/stats/engineers", "engineer_container", "engineer_table", "engineer_chart", "user_id");
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -95,11 +99,14 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>#</th>
|
<th>#</th>
|
||||||
<th>Contributor</th>
|
<th>{% if show_ci %}Driver{% else %}Contributor{% endif %}</th>
|
||||||
{% if show_review_ratio %}
|
{% if show_review_ratio %}
|
||||||
<th>-2|-1|+1|+2|A (+ ratio)</th>
|
<th>-2|-1|+1|+2|A (+ ratio)</th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<th>{{ metric_label }}</th>
|
<th>{{ metric_label }}</th>
|
||||||
|
{% if show_ci %}
|
||||||
|
<th>Success</th>
|
||||||
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@@ -25,8 +25,7 @@ External CI status for {{ module }} for the last {{ days }} days
|
|||||||
});
|
});
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
var table_column_names = ["name", "merge_run_count", "merge_success_rate", "merge_date_str", "merge_result",
|
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_id = "summary_stats_table";
|
var table_id = "summary_stats_table";
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@@ -49,55 +48,41 @@ External CI status for {{ module }} for the last {{ days }} days
|
|||||||
for (i = 0; i < activity.length; i++) {
|
for (i = 0; i < activity.length; i++) {
|
||||||
var ai = activity[i];
|
var ai = activity[i];
|
||||||
|
|
||||||
if (ai.branch != "master") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ci_id = ai.user_id;
|
var ci_id = ai.user_id;
|
||||||
|
|
||||||
var ci = ci_map[ci_id];
|
var ci = ci_map[ci_id];
|
||||||
if (!ci) {
|
if (!ci) {
|
||||||
ci = {total_run_count: 0, total_success: 0, merge_run_count: 0, merge_success: 0,
|
ci = {merge_run_count: 0, merge_success: 0,
|
||||||
merge_date: 0, total_date: 0, merge_result: "N/A",
|
merge_date: 0, merge_result: "N/A",
|
||||||
merge_date_str: "N/A", "total_date_str": "N/A"};
|
merge_date_str: "N/A", "total_date_str": "N/A"};
|
||||||
}
|
}
|
||||||
ci.id = ai.user_id;
|
ci.id = ai.user_id;
|
||||||
ci.name = "<a href=\"https://review.openstack.org/#/q/reviewer:" + ai.user_id +
|
ci.name = "<a href=\"/?metric=ci&user_id=" + ai.user_id +
|
||||||
"+project:openstack/{{ module }},n,z\" target=\"_blank\">" + ai.user_id + "</a>";
|
"&module={{ module }}\">" + ai.driver_name + "</a>";
|
||||||
ci_id_to_name[ci_id] = ci.name;
|
ci_id_to_name[ci_id] = ci.name;
|
||||||
|
|
||||||
ci.total_run_count ++;
|
var review_id = ai.review_number;
|
||||||
if (ai.ci_result) {
|
if (!review_ids_set[review_id]) {
|
||||||
ci.total_success ++;
|
review_ids_set[review_id] = review_id;
|
||||||
}
|
review_ids.push({review_id: review_id, date_str: ai.date_str});
|
||||||
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\">✔</span>":
|
|
||||||
"<span style=\"color: red\">✖</span>";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ai.date > ci.total_date) {
|
if (!res_map[ci_id]) {
|
||||||
ci.total_date = ai.date;
|
res_map[ci_id] = {};
|
||||||
ci.total_date_str = ai.date_str;
|
|
||||||
}
|
}
|
||||||
|
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\">✔</span>":
|
||||||
|
"<span style=\"color: red\">✖</span>";
|
||||||
|
}
|
||||||
|
|
||||||
ci_map[ci_id] = ci;
|
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];
|
var c = ci_map[ci_id];
|
||||||
|
|
||||||
if (c.merge_run_count > 0) {
|
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 {
|
} else {
|
||||||
c.merge_success_rate = "-";
|
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);
|
tableData.push(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,8 +111,8 @@ External CI status for {{ module }} for the last {{ days }} days
|
|||||||
"aaData": tableData,
|
"aaData": tableData,
|
||||||
"aoColumns": tableColumns,
|
"aoColumns": tableColumns,
|
||||||
"aoColumnDefs": [
|
"aoColumnDefs": [
|
||||||
{ "sClass": "center", "aTargets": [1, 2, 3, 4, 5, 6, 7] },
|
{ "sClass": "center", "aTargets": [1, 2, 3, 4] },
|
||||||
{ "sType": "ratio", "aTargets": [2, 6]}
|
{ "sType": "ratio", "aTargets": [2]}
|
||||||
]
|
]
|
||||||
}).show();
|
}).show();
|
||||||
$("#" + table_id + "_loading").hide();
|
$("#" + table_id + "_loading").hide();
|
||||||
@@ -144,7 +124,7 @@ External CI status for {{ module }} for the last {{ days }} days
|
|||||||
table.append(table_head);
|
table.append(table_head);
|
||||||
var table_head_row = $("<tr></tr>");
|
var table_head_row = $("<tr></tr>");
|
||||||
table_head.append(table_head_row);
|
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>");
|
var table_second_head_row = $("<tr></tr>");
|
||||||
table_head.append(table_second_head_row);
|
table_head.append(table_second_head_row);
|
||||||
var table_body = $("<tbody></tbody>");
|
var table_body = $("<tbody></tbody>");
|
||||||
@@ -165,7 +145,8 @@ External CI status for {{ module }} for the last {{ days }} days
|
|||||||
}
|
}
|
||||||
prev_date = date;
|
prev_date = date;
|
||||||
count++;
|
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) {
|
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 review_id = review_ids[i].review_id;
|
||||||
|
|
||||||
var color = "#cfcfcf";
|
var color = "#cfcfcf";
|
||||||
|
var title = "N/A";
|
||||||
|
|
||||||
if (res_map[ci_id]) {
|
if (res_map[ci_id]) {
|
||||||
var res = res_map[ci_id][review_id];
|
var res = res_map[ci_id][review_id];
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
color = "#40bf00";
|
color = "#40bf00";
|
||||||
|
title = "SUCCESS";
|
||||||
} else if (res == false) {
|
} else if (res == false) {
|
||||||
color = "#bf4000";
|
color = "#bf4000";
|
||||||
|
title = "FAILURE";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const url = "https://review.openstack.org/#/c/" + review_id;
|
const url = "https://review.openstack.org/#/c/" + review_id;
|
||||||
var cell = $("<td></td>");
|
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) {
|
cell.click(function(evt) {
|
||||||
window.open($(this).prop("title"));
|
window.open($(this).prop("url"));
|
||||||
});
|
});
|
||||||
table_row.append(cell);
|
table_row.append(cell);
|
||||||
}
|
}
|
||||||
@@ -228,31 +213,24 @@ External CI status for {{ module }} for the last {{ days }} days
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% 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
|
<h2>Drivers summary</h2>
|
||||||
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>
|
|
||||||
|
|
||||||
<table id="summary_stats_table" style="display: none;">
|
<table id="summary_stats_table" style="display: none;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th rowspan="2">CI</th>
|
<th>Driver</th>
|
||||||
<th colspan="4" title="Stats for the last patch set in the merged change request">Merged patch sets</th>
|
<th>CI votes</th>
|
||||||
<th colspan="3">All patch sets</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Total runs</th>
|
|
||||||
<th>Success, %</th>
|
<th>Success, %</th>
|
||||||
<th>Last run</th>
|
<th>Latest run</th>
|
||||||
<th>Last result</th>
|
<th>Latest result</th>
|
||||||
<th>Total runs</th>
|
|
||||||
<th>Success, %</th>
|
|
||||||
<th>Last run</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<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>
|
<div id="summary_stats_table_loading" class="select2-loading" style="width: 7em;">Loading...</div>
|
||||||
|
|
||||||
<h2>Status for merged changed requests</h2>
|
<h2>Status per change 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>
|
|
||||||
|
|
||||||
<div id="table_status_container"></div>
|
<div id="table_status_container"></div>
|
||||||
<div id="table_status_container_loading" class="select2-loading" style="width: 7em;">Loading...</div>
|
<div id="table_status_container_loading" class="select2-loading" style="width: 7em;">Loading...</div>
|
||||||
|
@@ -587,6 +587,8 @@ def timeline(records, **kwargs):
|
|||||||
|
|
||||||
if ('commits' in metric) or ('loc' in metric):
|
if ('commits' in metric) or ('loc' in metric):
|
||||||
handler = lambda record: record.loc
|
handler = lambda record: record.loc
|
||||||
|
elif 'ci' in metric:
|
||||||
|
handler = lambda record: 0 if record.value else 1
|
||||||
else:
|
else:
|
||||||
handler = lambda record: 0
|
handler = lambda record: 0
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user