-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #485 from jjaquish/jjaquish/importance-by-componen…
…t-widget Initial draft commit for importance widget component
- Loading branch information
Showing
7 changed files
with
301 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
from ibutsu_server.constants import BARCHART_MAX_BUILDS | ||
from ibutsu_server.constants import JJV_RUN_LIMIT | ||
from ibutsu_server.db.models import Result | ||
from ibutsu_server.db.models import Run | ||
from ibutsu_server.filters import string_to_column | ||
from ibutsu_server.widgets.jenkins_job_view import get_jenkins_job_view | ||
|
||
|
||
def get_importance_component( | ||
env="prod", group_field="component", job_name="", builds=5, components="", project=None | ||
): | ||
# taken from get_jenkins_line_chart in jenkins_job_analysis.py | ||
run_limit = int((JJV_RUN_LIMIT / BARCHART_MAX_BUILDS) * builds) | ||
jobs = get_jenkins_job_view( | ||
filter_=f"job_name={job_name}", page_size=builds, project=project, run_limit=run_limit | ||
).get("jobs") | ||
|
||
# A list of job build numbers to filter our runs by | ||
job_ids = [] | ||
for job in jobs: | ||
job_ids.append(job["build_number"]) | ||
|
||
# query for RUN ids | ||
# metadata has to have a string to column to work | ||
# because it is a sqlalchemy property otherwise (AFAIK) | ||
bnumdat = string_to_column("metadata.jenkins.build_number", Run) | ||
run_data = ( | ||
Run.query.filter(bnumdat.in_(job_ids), Run.component.in_(components.split(","))) | ||
.add_columns(Run.id, bnumdat.label("build_number")) | ||
.all() | ||
) | ||
|
||
# get a list of the job IDs | ||
run_info = {} | ||
for run in run_data: | ||
run_info[run.id] = run.build_number | ||
|
||
mdat = string_to_column("metadata.importance", Result) | ||
result_data = ( | ||
Result.query.filter( | ||
Result.run_id.in_(run_info.keys()), Result.component.in_(components.split(",")) | ||
) | ||
.add_columns( | ||
Result.run_id, Result.component, Result.id, Result.result, mdat.label("importance") | ||
) | ||
.all() | ||
) | ||
|
||
""" | ||
This starts a (probably) over complicated bit of data maniplation | ||
to get sdatdict in a proper state to be broken down into | ||
sdatret, which is the format we need for the widget. | ||
""" | ||
sdatdict = {} | ||
bnums = set() | ||
importances = ["critical", "high", "medium", "low"] | ||
for datum in result_data: | ||
# getting the components from the results | ||
if datum.component not in sdatdict.keys(): | ||
sdatdict[datum.component] = {} | ||
|
||
# getting the build numbers from the results | ||
if run_info[datum.run_id] not in sdatdict[datum.component].keys(): | ||
bnums.add(run_info[datum.run_id]) | ||
sdatdict[datum.component][run_info[datum.run_id]] = {} | ||
|
||
# Adding all importances from our constant | ||
if datum.importance not in sdatdict[datum.component][run_info[datum.run_id]].keys(): | ||
sdatdict[datum.component][run_info[datum.run_id]][datum.importance] = [] | ||
# adding the result value | ||
sdatdict[datum.component][run_info[datum.run_id]][datum.importance].append( | ||
{"result": datum.result, "result_id": datum.id} | ||
) | ||
|
||
# This adds the extra importance values that didn't appear in the results | ||
for component in sdatdict.keys(): | ||
for bnum in sdatdict[component].keys(): | ||
for importance in importances: | ||
if importance not in sdatdict[component][bnum].keys(): | ||
sdatdict[component][bnum][importance] = [] | ||
|
||
# this is to change result values into numbers | ||
# TODO: This doesn't handle xpassed, xfailed, skipped, etc. so figure that out | ||
for component in sdatdict.keys(): | ||
for bnum in sdatdict[component].keys(): | ||
for importance in sdatdict[component][bnum].keys(): | ||
total = 0 | ||
passed = 0 | ||
res_list = [] | ||
for item in sdatdict[component][bnum][importance]: | ||
total += 1 | ||
res_list.append(item["result_id"]) | ||
if item["result"] == "passed": | ||
passed += 1 | ||
|
||
if total != 0: | ||
sdatdict[component][bnum][importance] = { | ||
"percentage": round(passed / total, 2), | ||
"result_list": res_list, | ||
} | ||
else: | ||
sdatdict[component][bnum][importance] = { | ||
"percentage": 0, | ||
"result_list": res_list, | ||
} | ||
|
||
for bnum in bnums: | ||
if bnum not in sdatdict[component].keys(): | ||
sdatdict[component][bnum] = {} | ||
for importance in importances: | ||
sdatdict[component][bnum][importance] = {"percentage": "NA", "result_list": []} | ||
|
||
# Need this broken down more for the table | ||
table_data = [] | ||
for key in sdatdict.keys(): | ||
table_data.append( | ||
{ | ||
"component": key, | ||
"bnums": sorted(list(bnums)), | ||
"importances": importances, | ||
"data": sdatdict[key], | ||
} | ||
) | ||
|
||
# return data, for sanity | ||
data = {"table_data": table_data} | ||
return data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
import { | ||
Card, | ||
CardBody, | ||
Text | ||
} from '@patternfly/react-core'; | ||
|
||
import { | ||
Table, | ||
Thead, | ||
Th, | ||
Tbody, | ||
Tr, | ||
Td | ||
} from '@patternfly/react-table'; | ||
|
||
import { Link } from 'react-router-dom'; | ||
|
||
import { HttpClient } from '../services/http'; | ||
import { Settings } from '../settings'; | ||
import { WidgetHeader } from '../components/widget-components'; | ||
|
||
export class ImportanceComponentWidget extends React.Component { | ||
static propTypes = { | ||
title: PropTypes.string, | ||
params: PropTypes.object, | ||
onDeleteClick: PropTypes.func, | ||
onEditClick: PropTypes.func | ||
} | ||
|
||
constructor(props) { | ||
super(props); | ||
this.title = props.title || 'Importance Component Widget'; | ||
this.params = props.params || {}; | ||
this.state = { | ||
data: { | ||
table_data: [] | ||
}, | ||
isLoading: true, | ||
}; | ||
} | ||
|
||
getData = () => { | ||
this.setState({isLoading: true}) | ||
HttpClient.get([Settings.serverUrl, 'widget', 'importance-component'], this.params) | ||
.then(response => { | ||
response = HttpClient.handleResponse(response, 'response'); | ||
if (!response.ok) { | ||
throw Error(response.statusText); | ||
} | ||
return response.json(); | ||
}) | ||
.then(data => this.setState({data: data, isLoading: false})) | ||
.catch(error => { | ||
this.setState({dataError: true}); | ||
console.log(error); | ||
}); | ||
} | ||
|
||
componentDidMount() { | ||
this.getData(); | ||
} | ||
|
||
componentDidUpdate(prevProps) { | ||
if (prevProps.params !== this.props.params) { | ||
this.params = this.props.params; | ||
this.getData(); | ||
} | ||
} | ||
|
||
render() { | ||
return ( | ||
<Card> | ||
<WidgetHeader title={this.title} getDataFunc={this.getData} onEditClick={this.props.onEditClick} onDeleteClick={this.props.onDeleteClick}/> | ||
{(!this.state.dataError && this.state.isLoading) && | ||
<CardBody> | ||
<Text component="h2">Loading ...</Text> | ||
</CardBody> | ||
} | ||
{(!this.state.dataError && !this.state.isLoading) && | ||
<CardBody> | ||
{this.state.data.table_data.map((tdat) => ( | ||
<> | ||
<Text key={tdat.component} component="h2">{tdat.component}</Text> | ||
<Table aria-label="importance-component-table" variant="compact"> | ||
<Thead> | ||
<Tr> | ||
{["-", ...tdat.bnums].map((buildnum) => ( | ||
<Th key={buildnum}>{buildnum}</Th> | ||
))} | ||
</Tr> | ||
</Thead> | ||
<Tbody> | ||
{tdat.importances.map((importance) => ( | ||
<Tr key={importance}> | ||
<Text component="h2">{importance}</Text> | ||
{tdat.bnums.map((buildnum) => ( | ||
<Td key={buildnum}><Link to={`/results?id[in]=${tdat.data[buildnum][importance]["result_list"].join(";")}`}>{tdat.data[buildnum][importance]["percentage"]}</Link></Td> | ||
))} | ||
</Tr> | ||
))} | ||
</Tbody> | ||
</Table> | ||
</> | ||
))} | ||
</CardBody> | ||
} | ||
</Card> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters