зеркало из https://github.com/mozilla/treeherder.git
Add error handling to Perfherder createAlert (#5407)
Replace create functions use of fetch with getData and update use in createAlert, Bugfiler and JobModelClassification model; cleanup graphsContainer
This commit is contained in:
Родитель
2f96be8b2a
Коммит
6f5129ab6e
|
@ -40,7 +40,7 @@ export const getData = async function getData(url, options = {}) {
|
|||
|
||||
// TODO: The credentials param can be removed in July once Firefox 62 ships and it is the default.
|
||||
export const create = function postJson(uri, data) {
|
||||
return fetch(uri, {
|
||||
return getData(uri, {
|
||||
method: 'POST',
|
||||
headers: generateHeaders(),
|
||||
body: JSON.stringify(data),
|
||||
|
|
|
@ -471,22 +471,16 @@ export class BugFilerClass extends React.Component {
|
|||
comment_tags: 'treeherder',
|
||||
};
|
||||
|
||||
const bugResp = await create(
|
||||
const { data, failureStatus } = await create(
|
||||
getApiUrl('/bugzilla/create_bug/'),
|
||||
payload,
|
||||
);
|
||||
// const bugResp = await create('http://httpstat.us/404', payload);
|
||||
const data = await bugResp.json();
|
||||
if (bugResp.ok) {
|
||||
|
||||
if (!failureStatus) {
|
||||
successCallback(data);
|
||||
toggle();
|
||||
} else {
|
||||
this.submitFailure(
|
||||
'Treeherder Bug Filer API',
|
||||
bugResp.status,
|
||||
bugResp.statusText,
|
||||
data,
|
||||
);
|
||||
this.submitFailure('Treeherder Bug Filer API', failureStatus, data);
|
||||
}
|
||||
} else {
|
||||
this.submitFailure(
|
||||
|
|
|
@ -114,7 +114,7 @@ class PinBoard extends React.Component {
|
|||
});
|
||||
};
|
||||
|
||||
saveClassification = job => {
|
||||
saveClassification = async job => {
|
||||
const { recalculateUnclassifiedCounts, notify } = this.props;
|
||||
const classification = this.createNewClassification();
|
||||
|
||||
|
@ -125,21 +125,19 @@ class PinBoard extends React.Component {
|
|||
recalculateUnclassifiedCounts();
|
||||
|
||||
classification.job_id = job.id;
|
||||
return classification
|
||||
.create()
|
||||
.then(() => {
|
||||
notify(`Classification saved for ${job.title}`, 'success');
|
||||
// update the job to show that it's now classified
|
||||
const jobInstance = findJobInstance(job.id);
|
||||
const { data, failureStatus } = await classification.create();
|
||||
if (!failureStatus) {
|
||||
notify(`Classification saved for ${job.title}`, 'success');
|
||||
// update the job to show that it's now classified
|
||||
const jobInstance = findJobInstance(job.id);
|
||||
|
||||
if (jobInstance) {
|
||||
jobInstance.refilter();
|
||||
}
|
||||
})
|
||||
.catch(response => {
|
||||
const message = `Error saving classification for ${job.platform} ${job.job_type_name}`;
|
||||
notify(formatModelError(response, message), 'danger');
|
||||
});
|
||||
if (jobInstance) {
|
||||
jobInstance.refilter();
|
||||
}
|
||||
} else {
|
||||
const message = `Error saving classification for ${job.platform} ${job.job_type_name}: ${data}`;
|
||||
notify(message, 'danger');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,14 @@ import { create } from '../../helpers/http';
|
|||
import RepositoryModel from '../../models/repository';
|
||||
import { displayNumber, getStatus } from '../helpers';
|
||||
|
||||
const GraphTooltip = ({ dataPoint, testData, user, updateData, projects }) => {
|
||||
const GraphTooltip = ({
|
||||
dataPoint,
|
||||
testData,
|
||||
user,
|
||||
updateData,
|
||||
projects,
|
||||
updateStateParams,
|
||||
}) => {
|
||||
// we either have partial information provided by the selected
|
||||
// query parameter or the full dataPoint object provided from the
|
||||
// graph library
|
||||
|
@ -79,29 +86,46 @@ const GraphTooltip = ({ dataPoint, testData, user, updateData, projects }) => {
|
|||
group_state: 'expanded',
|
||||
});
|
||||
|
||||
// TODO refactor create to use getData wrapper
|
||||
const createAlert = () =>
|
||||
create(getApiUrl(endpoints.alertSummary), {
|
||||
const createAlert = async () => {
|
||||
let data;
|
||||
let failureStatus;
|
||||
|
||||
({ data, failureStatus } = await create(getApiUrl(endpoints.alertSummary), {
|
||||
repository_id: testDetails.projectId,
|
||||
framework_id: testDetails.framework_id,
|
||||
push_id: dataPointDetails.pushId,
|
||||
prev_push_id: prevPushId,
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
const newAlertSummaryId = response.alert_summary_id;
|
||||
return create(getApiUrl('/performance/alert/'), {
|
||||
summary_id: newAlertSummaryId,
|
||||
signature_id: testDetails.signature_id,
|
||||
}).then(() =>
|
||||
updateData(
|
||||
testDetails.signature_id,
|
||||
testDetails.projectId,
|
||||
newAlertSummaryId,
|
||||
flotIndex,
|
||||
),
|
||||
);
|
||||
}));
|
||||
|
||||
if (failureStatus) {
|
||||
return updateStateParams({
|
||||
errorMessages: [
|
||||
`Failed to create an alert summary for push ${dataPointDetails.push_id}: ${data}`,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
const newAlertSummaryId = data.alert_summary_id;
|
||||
({ data, failureStatus } = await create(getApiUrl(endpoints.alert), {
|
||||
summary_id: newAlertSummaryId,
|
||||
signature_id: testDetails.signature_id,
|
||||
}));
|
||||
|
||||
if (failureStatus) {
|
||||
updateStateParams({
|
||||
errorMessages: [
|
||||
`Failed to create an alert for alert summary ${newAlertSummaryId}: ${data}`,
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
updateData(
|
||||
testDetails.signature_id,
|
||||
testDetails.projectId,
|
||||
newAlertSummaryId,
|
||||
flotIndex,
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="body">
|
||||
|
|
|
@ -289,11 +289,7 @@ class GraphsContainer extends React.Component {
|
|||
/>
|
||||
</span>
|
||||
{dataPoint && showTooltip && (
|
||||
<GraphTooltip
|
||||
dataPoint={dataPoint}
|
||||
testData={testData}
|
||||
{...this.props}
|
||||
/>
|
||||
<GraphTooltip dataPoint={dataPoint} {...this.props} />
|
||||
)}
|
||||
<div className="tip" />
|
||||
</div>
|
||||
|
@ -452,7 +448,6 @@ GraphsContainer.propTypes = {
|
|||
PropTypes.string,
|
||||
PropTypes.arrayOf(PropTypes.string),
|
||||
]),
|
||||
user: PropTypes.shape({}).isRequired,
|
||||
timeRange: PropTypes.shape({}).isRequired,
|
||||
};
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ import ErrorMessages from '../../shared/ErrorMessages';
|
|||
import ErrorBoundary from '../../shared/ErrorBoundary';
|
||||
import LoadingSpinner from '../../shared/LoadingSpinner';
|
||||
|
||||
import GraphsContainer from './GraphsContainer';
|
||||
import LegendCard from './LegendCard';
|
||||
import GraphsViewControls from './GraphsViewControls';
|
||||
|
||||
|
@ -351,7 +350,7 @@ class GraphsView extends React.Component {
|
|||
visibilityChanged,
|
||||
} = this.state;
|
||||
|
||||
const { projects, frameworks } = this.props;
|
||||
const { projects, frameworks, user } = this.props;
|
||||
return (
|
||||
<ErrorBoundary
|
||||
errorClasses={errorMessageClass}
|
||||
|
@ -399,36 +398,22 @@ class GraphsView extends React.Component {
|
|||
<GraphsViewControls
|
||||
timeRange={timeRange}
|
||||
frameworks={frameworks}
|
||||
user={user}
|
||||
projects={projects}
|
||||
options={options}
|
||||
getTestData={this.getTestData}
|
||||
testData={testData}
|
||||
showModal={showModal}
|
||||
toggle={() => this.setState({ showModal: !showModal })}
|
||||
graphs={
|
||||
testData.length > 0 && (
|
||||
<GraphsContainer
|
||||
timeRange={timeRange}
|
||||
highlightAlerts={highlightAlerts}
|
||||
highlightedRevisions={highlightedRevisions}
|
||||
zoom={zoom}
|
||||
selectedDataPoint={selectedDataPoint}
|
||||
testData={testData}
|
||||
updateStateParams={state =>
|
||||
this.setState(state, this.changeParams)
|
||||
}
|
||||
user={this.props.user}
|
||||
updateData={this.updateData}
|
||||
projects={projects}
|
||||
visibilityChanged={visibilityChanged}
|
||||
/>
|
||||
)
|
||||
}
|
||||
highlightAlerts={highlightAlerts}
|
||||
highlightedRevisions={highlightedRevisions}
|
||||
zoom={zoom}
|
||||
selectedDataPoint={selectedDataPoint}
|
||||
updateStateParams={state =>
|
||||
this.setState(state, this.changeParams)
|
||||
}
|
||||
highlightAlerts={highlightAlerts}
|
||||
highlightedRevisions={highlightedRevisions}
|
||||
visibilityChanged={visibilityChanged}
|
||||
updateData={this.updateData}
|
||||
toggle={() => this.setState({ showModal: !showModal })}
|
||||
updateTimeRange={timeRange =>
|
||||
this.setState(
|
||||
{
|
||||
|
@ -464,7 +449,6 @@ GraphsView.propTypes = {
|
|||
PropTypes.arrayOf(PropTypes.string),
|
||||
]),
|
||||
}),
|
||||
user: PropTypes.shape({}).isRequired,
|
||||
};
|
||||
|
||||
GraphsView.defaultProps = {
|
||||
|
|
|
@ -14,6 +14,7 @@ import { phTimeRanges } from '../constants';
|
|||
import DropdownMenuItems from '../../shared/DropdownMenuItems';
|
||||
|
||||
import TestDataModal from './TestDataModal';
|
||||
import GraphsContainer from './GraphsContainer';
|
||||
|
||||
export default class GraphsViewControls extends React.Component {
|
||||
changeHighlightedRevision = (index, newValue) => {
|
||||
|
@ -28,7 +29,6 @@ export default class GraphsViewControls extends React.Component {
|
|||
render() {
|
||||
const {
|
||||
timeRange,
|
||||
graphs,
|
||||
updateStateParams,
|
||||
highlightAlerts,
|
||||
highlightedRevisions,
|
||||
|
@ -36,6 +36,7 @@ export default class GraphsViewControls extends React.Component {
|
|||
hasNoData,
|
||||
toggle,
|
||||
showModal,
|
||||
testData,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
|
@ -75,7 +76,8 @@ export default class GraphsViewControls extends React.Component {
|
|||
</Row>
|
||||
) : (
|
||||
<React.Fragment>
|
||||
{graphs}
|
||||
{testData.length > 0 && <GraphsContainer {...this.props} />}
|
||||
|
||||
<Row className="justify-content-start pt-2">
|
||||
{highlightedRevisions.length > 0 &&
|
||||
highlightedRevisions.map((revision, index) => (
|
||||
|
@ -117,7 +119,6 @@ export default class GraphsViewControls extends React.Component {
|
|||
|
||||
GraphsViewControls.propTypes = {
|
||||
updateStateParams: PropTypes.func.isRequired,
|
||||
graphs: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.bool]).isRequired,
|
||||
timeRange: PropTypes.shape({}).isRequired,
|
||||
highlightAlerts: PropTypes.bool.isRequired,
|
||||
highlightedRevisions: PropTypes.oneOfType([
|
||||
|
|
Загрузка…
Ссылка в новой задаче