Reworked tests/build status representation

Added links for downloading bootcd/livecd
Added a hack for distinguishing GCC/GCC8 builds
This commit is contained in:
Victor Perevertkin 2020-02-16 21:11:17 +03:00
parent 8d35e26504
commit 30e4e23ac6
No known key found for this signature in database
GPG Key ID: C750B7222E9C7830
18 changed files with 398 additions and 153 deletions

View File

@ -1,46 +1,50 @@
import React from 'react';
import { connect } from 'react-redux';
function Build({ builderName, ...build }) {
let completedDate = new Date(build.complete_at * 1000);
let startedDate = new Date(build.started_at * 1000);
import { JOB_STATUS } from '../redux/constants'
import { statusElement } from './utils'
function bootcdUrl(suffix) {
return `https://iso.reactos.org/bootcd/reactos-bootcd-${suffix}.7z`
}
function livecdUrl(suffix) {
return `https://iso.reactos.org/livecd/reactos-livecd-${suffix}.7z`
}
function Build({buildId, builderId, number, builderName, status, statusText, isoSuffix}) {
return (
<React.Fragment>
<div className='col-sm-2'>
<div className="row" key={buildId}>
<div className='col-sm-1'>
{statusElement(status, statusText)}
</div>
<div className='col-sm-5'>
<a
target='_blank'
rel='noreferrer noopener'
href={`https://build.reactos.org/#builders/${
build.builderid
}/builds/${build.number}`}
href={`https://build.reactos.org/#builders/${builderId}/builds/${number}`}
>
{builderName}
</a>
</div>
<div className='col-sm-3'>
{build.state_string}
{build.state_string === 'build successful' ? (
<i className='fa fa-check' />
) : (
<i />
)}
</div>
<div className='col-sm-3'>Started: {startedDate.toLocaleString()}</div>
<div className='col-sm-4'>
Completed: {build.complete_at ? completedDate.toLocaleString() : <p />}
</div>
<div className='col-sm-6'>
{status === JOB_STATUS.SUCCESS &&
<React.Fragment>
<a href={bootcdUrl(isoSuffix)}><i className="fa fa-download" />{" bootcd"}</a>
{" "}
<a href={livecdUrl(isoSuffix)}><i className="fa fa-download" />{" livecd"}</a>
</React.Fragment>
}
</div>
</div>
);
}
function renderBuild(props) {
return <Build key={props.buildid} {...props} />;
}
function BuildDetails({ builds }) {
return (
<React.Fragment>
{builds.length > 0 ? (
<div className='row'>{builds.map(renderBuild)}</div>
builds.map(Build)
) : (
<p>
<strong>No data Exists</strong>
@ -54,7 +58,7 @@ const mapStateToProps = ({ builders }, ownProps) => {
return {
builds: ownProps.builds.map(build => ({
...build,
builderName: builders[build.builderid] && builders[build.builderid].name
builderName: builders[build.builderId] && builders[build.builderId].name
}))
};
};

View File

@ -1,7 +1,7 @@
import React from 'react';
import { connect } from 'react-redux';
import { useParams } from 'react-router-dom';
import { loadCommits, loadBuildSets } from '../redux/actions';
import { loadCommits, loadBuilds } from '../redux/actions';
import Branches from './Branches';
import './styles/Commit.css';
import CommitsCard from './CommitsCard';
@ -10,24 +10,26 @@ import Loading from './Loading';
class Commits extends React.PureComponent {
componentDidMount() {
this.props.loadCommits(this.props.branch);
this.props.loadBuildSets();
this.props.loadBuilds();
}
componentDidUpdate(prevProps) {
if (this.props.branch !== prevProps.branch) {
this.props.loadCommits(this.props.branch)
this.props.loadBuildSets()
this.props.loadBuilds()
}
}
renderCommits = commit => {
const tests = this.props.tests[commit.sha]
return (
<CommitsCard
key={commit.sha}
{...commit}
builds={this.props.build[commit.sha]}
tests={this.props.testData[commit.sha]}
previousTests={extractCommitsParentTestsCount(this.props.testData, commit)}
builds={this.props.builds[commit.sha]}
tests={tests ? Object.values(tests) : []}
previousTests={extractCommitsParentTestsCount(this.props.tests, commit)}
/>
);
};
@ -109,16 +111,16 @@ const mapStateToProps = ({
builders,
error,
page,
build,
testData
builds,
tests
}) => ({
isLoading,
commits,
builders,
error,
page,
build,
testData
builds,
tests
});
/**
@ -137,7 +139,7 @@ function extractCommitsParentTestsCount(testData, commit) {
let result = {};
for (let test of tests) {
for (let test of Object.values(tests)) {
result[test.source] = test.count
}
@ -145,7 +147,7 @@ function extractCommitsParentTestsCount(testData, commit) {
}
const mapDispatchToProps = dispatch => ({
loadBuildSets: () => dispatch(loadBuildSets()),
loadBuilds: () => dispatch(loadBuilds()),
loadCommits: (branch, next) => dispatch(loadCommits(branch, next))
});

View File

@ -2,6 +2,8 @@ import React from 'react';
import { UncontrolledCollapse, CardBody, Card, CardHeader } from 'reactstrap';
import BuildDetails from './BuildDetails';
import TestDetails from './TestDetails';
import { JOB_STATUS } from '../redux/constants'
import { statusElement } from './utils'
function firstLineTrimmed(str) {
const newStr = str.split('\n', 1)[0]
@ -13,6 +15,21 @@ function firstLineTrimmed(str) {
}
}
function getTotalStatus(jobs) {
if (!jobs.length) return null
let ret = JOB_STATUS.SUCCESS
for (let job of jobs) {
if (job.status === JOB_STATUS.ONGOING)
return JOB_STATUS.ONGOING
else if (job.status === JOB_STATUS.FAILURE)
ret = JOB_STATUS.FAILURE
}
return ret
}
function CommitsCard({sha, ...props}) {
let tog = 'toggler' + sha;
let committerDate = new Date(props.commit.committer.date);
@ -23,11 +40,22 @@ function CommitsCard({sha, ...props}) {
<Card className="mb-1">
<CardHeader className='new' type='button' id={tog}>
<div className='row'>
<div className='col-sm-2'><a href={`https://github.com/reactos/reactos/commit/${sha}`}>{sha.substring(0, 7)}</a></div>
<div className='col-sm-8'>
{firstLineTrimmed(props.commit.message)}
<div className='col-sm-9'>
<a className="text-monospace" href={`https://github.com/reactos/reactos/commit/${sha}`}>{sha.substring(0, 7)}</a>
{" "}{firstLineTrimmed(props.commit.message)}
</div>
<div className='col-sm-2'>{props.author.login}</div>
<div className="col-sm-1">
{props.builds &&
props.builds.length > 0
? statusElement(getTotalStatus(props.builds), "Build status")
: <span title="Loading results"><i className="fa fa-refresh fa-spin" /></span> }
{" "}
{props.tests &&
props.tests.length > 0
? statusElement(getTotalStatus(props.tests), "Test status")
: <span title="Loading results"><i className="fa fa-refresh fa-spin" /></span> }
</div>
</div>
</CardHeader>
<UncontrolledCollapse toggler={tog}>
@ -57,17 +85,12 @@ function CommitsCard({sha, ...props}) {
>
{props.commit.author.name}
</a>
{` <${props.commit.author.email}>`}
</div>
<div className='col-sm'>
<strong>Author Date: </strong>
{authorDate.toLocaleString()}
</div>
<div className='col-sm'>
<strong>Author Email: </strong>
<a href={`mailto:${props.commit.author.email}`} target='_top'>
{props.commit.author.email}
</a>
</div>
</div>
<div className='row'>
<div className='col-sm'>
@ -79,19 +102,16 @@ function CommitsCard({sha, ...props}) {
>
{props.commit.committer.name}
</a>
{` <${props.commit.committer.email}>`}
</div>
<div className='col-sm'>
<strong>Committer Date: </strong>
{committerDate.toLocaleString()}
</div>
<div className='col-sm'>
<strong>Committer Email: </strong>
<a href={`mailto:${props.commit.committer.email}`} target='_top'>
{props.commit.committer.email}
</a>
</div>
</div>
<hr />
<div className="row">
<div className="col-md-5">
<h5>Build Details:</h5>
{props.builds ? (
<BuildDetails builds={props.builds} />
@ -100,7 +120,8 @@ function CommitsCard({sha, ...props}) {
<strong>Loading Builds...</strong>
</div>
)}
<hr />
</div>
<div className="col-md-7">
<h5>Test Details:</h5>
{props.tests ? (
<TestDetails tests={props.tests} previousTests={props.previousTests} />
@ -109,6 +130,8 @@ function CommitsCard({sha, ...props}) {
<strong>No data Exists</strong>
</div>
)}
</div>
</div>
</CardBody>
</UncontrolledCollapse>
</Card>

View File

@ -18,12 +18,14 @@ class Pulls extends React.PureComponent {
}
renderPulls = pull => {
const tests = this.props.tests[pull.merge_commit_sha]
return (
<PullsCard
key={pull.id}
{...pull}
builds={this.props.build[pull.number]}
tests={this.props.testData[pull.merge_commit_sha]}
builds={this.props.builds[pull.number]}
tests={tests ? Object.values(tests) : []}
/>
);
};
@ -112,16 +114,16 @@ const mapStateToProps = ({
page,
isLoading,
error,
build,
testData
builds,
tests
}) => ({
pulls,
builders,
page,
isLoading,
error,
build,
testData
builds,
tests
});
const mapDispatchToProps = dispatch => ({

View File

@ -1,4 +1,7 @@
import React from 'react';
import { connect } from 'react-redux'
import { statusElement } from './utils'
function renderCountChange(test, previousTestCount) {
if (!previousTestCount) {
@ -13,38 +16,63 @@ function renderCountChange(test, previousTestCount) {
}
}
const trStyle = {fontSize: "0.85rem"}
function renderTest(test, previousTests) {
return (
<React.Fragment key={test.id}>
<div className='col-sm-2'>Test id: {test.id}</div>
<div className='col-sm-4'>
<tr key={test.buildBotId} style={trStyle}>
<td>
{statusElement(test.status, test.statusText)}
</td>
<td>
{test.testerName}
{/* Hack: to be removed when we will properly populate build properties */}
{test.parentBuild && test.parentBuild.builderid === 10 ? " (GCC8)" : " (GCC)"}
</td>
<td>
{test.testManData
? <span title="Tests count: failures/total">{`${test.testManData.failures}/${test.testManData.count}`}</span>
: ""}
</td>
<td>
<a
target='_blank'
rel='noreferrer noopener'
href={`https://reactos.org/testman/compare.php?ids=${test.id}`}
href={`https://build.reactos.org/#builders/${test.builderId}/builds/${test.number}`}
>
{test.source}
{`bbot: ${test.number}`}
</a>
</div>
<div className='col-sm-3'>
{" "}
{test.testManData && <a
target='_blank'
rel='noreferrer noopener'
href={`https://reactos.org/testman/compare.php?ids=${test.testManData.id}`}
>
{`tm: ${test.testManData.id}`}
</a>}
</td>
</tr>
);
}
/*
Count: {test.count}
{/* previousTests[test.source] returns undefined when PR State === closed */}
{ previousTests[test.source] returns undefined when PR State === closed }
{previousTests
? renderCountChange(test, previousTests[test.source])
: null}
</div>
<div className='col-sm-3'>Failures: {test.failures}</div>
</React.Fragment>
);
}
<div className='col-sm-3'>Failures: {test.failures}</div>
*/
function TestDetails(props) {
return (
<React.Fragment>
{props.tests.length > 0 ? (
<div className='row'>
<table className="table table-sm table-striped">
<tbody>
{props.tests.map(test => renderTest(test, props.previousTests))}
</div>
</tbody>
</table>
) : (
<p>
<strong>No data Exists</strong>
@ -54,4 +82,13 @@ function TestDetails(props) {
);
}
export default TestDetails;
function mapStateToProps({ builders }, ownProps) {
return {
tests: ownProps.tests.map(t => ({
...t,
testerName: builders[t.builderId] && builders[t.builderId].name
}))
}
}
export default connect(mapStateToProps)(TestDetails);

View File

@ -0,0 +1,16 @@
import React from 'react'
import { JOB_STATUS } from '../redux/constants'
export function statusElement(status, statusText) {
switch(status) {
case JOB_STATUS.SUCCESS:
return <span className="text-success" title={statusText}><i className="fa fa-check" /></span>
case JOB_STATUS.ONGOING:
return <span className="text-warning" title={statusText}><i className="fa fa-hourglass" /></span>
case JOB_STATUS.FAILURE:
return <span className="text-danger" title={statusText}><i className="fa fa-times" /></span>
default:
return null
}
}

View File

@ -3,6 +3,7 @@ import {
BRANCHES,
PULLS,
BUILD_DATA,
TEST_DATA,
BUILDERS,
TESTMAN_DATA
} from '../constants';
@ -23,25 +24,46 @@ export const setCommitsError = error => ({
error
});
export const loadBuildSets = () => ({
// builds
export const loadBuilds = () => ({
type: BUILD_DATA.LOAD
});
export const setBuilds = build => ({
export const setBuilds = builds => ({
type: BUILD_DATA.LOAD_SUCCESS,
build
builds
});
export const setBuildSetsError = error => ({
export const setBuildsError = error => ({
type: BUILD_DATA.LOAD_FAIL,
error
});
// tests
export const loadTests = () => ({
type: TEST_DATA.LOAD
});
export const setTests = tests => ({
type: TEST_DATA.LOAD_SUCCESS,
tests
});
export const setTestsError = error => ({
type: TEST_DATA.LOAD_FAIL,
error
});
// testman data
export const loadTestman = () => ({
type: TESTMAN_DATA.LOAD
});
export const setTestman = tests => ({
export const setTestman = testmanTests => ({
type: TESTMAN_DATA.LOAD_SUCCESS,
tests
testmanTests
});
export const setTestmanError = error => ({

View File

@ -4,6 +4,17 @@ export const PULL_STATE = {
ALL: 'all',
}
export const JOB_STATUS = {
SUCCESS: 0,
FAILURE: 1,
ONGOING: 2
}
export const BUILDER_TYPE = {
BUILDER: 0,
TESTER: 1
}
export const COMMITS = {
LOAD: 'COMMITS_LOAD',
LOAD_SUCCESS: 'COMMITS_LOAD_SUCCESS',
@ -28,6 +39,12 @@ export const BUILD_DATA = {
LOAD_FAIL: 'BUILD_DATA_LOAD_FAIL'
};
export const TEST_DATA = {
LOAD: 'TEST_DATA_LOAD',
LOAD_SUCCESS: 'TEST_DATA_LOAD_SUCCESS',
LOAD_FAIL: 'TEST_DATA_LOAD_FAIL'
}
export const TESTMAN_DATA = {
LOAD: 'TESTMAN_DATA_LOAD',
LOAD_SUCCESS: 'TESTMAN_DATA_LOAD_SUCCESS',

View File

@ -1,10 +0,0 @@
//handling builds endpoint
import { BUILD_DATA } from '../constants';
const buildStatusReducer = (state = {}, action) => {
if (action.type === BUILD_DATA.LOAD_SUCCESS) {
return { ...action.build };
}
return state;
};
export default buildStatusReducer;

View File

@ -1,10 +1,32 @@
import { BUILDERS } from '../constants';
import { BUILDERS, BUILDER_TYPE } from '../constants';
/*
Builder object, derived from buildbot
{
"builders": [
{
"builderid": 1,
"description": null,
"masterids": [1],
"name": "Build MSVC_x86",
"tags": []
},
<...>
]
}
*/
const builderReducer = (state = {}, action) => {
if (action.type === BUILDERS.LOAD_SUCCESS) {
const builders = {};
for (const builder of action.builders) {
builders[builder.builderid] = builder;
builders[builder.builderid] = {
builderid: builder.builderid,
type: builder.name.startsWith("Build") ? BUILDER_TYPE.BUILDER : BUILDER_TYPE.TESTER,
name: builder.name.substring(builder.name.indexOf(" ")).trim(),
full_name: builder.name
}
}
return builders;
}

View File

@ -0,0 +1,35 @@
import { BUILD_DATA, JOB_STATUS } from '../constants';
export default function buildsReducer(state = {}, action) {
if (action.type === BUILD_DATA.LOAD_SUCCESS) {
const buildsBySha = {}
for (let [sha, builds] of Object.entries(action.builds)) {
buildsBySha[sha] = builds.map(b => {
let isoSuffix, status
if (b.properties && b.properties.suffix && b.properties.suffix[0]) {
isoSuffix = b.properties.suffix[0]
}
if (!b.complete) status = JOB_STATUS.ONGOING
else if (b.state_string.includes("success")) status = JOB_STATUS.SUCCESS
else status = JOB_STATUS.FAILURE
return {
builderId: b.builderid,
buildId: b.buildid,
number: b.number,
statusText: b.state_string,
status,
isoSuffix
}
})
}
return buildsBySha
}
return state
}

View File

@ -7,8 +7,8 @@ import branchReducer from './branchReducer';
import builderReducer from './builderReducer';
import pullsReducer from './pullsReducer';
import pageReducer from './pageReducer';
import buildStatusReducer from './buildStatusReducer';
import testmanReducer from './testmanReducer';
import builds from './builds';
import tests from './tests'
const rootReducer = combineReducers({
isLoading: loadingReducer,
@ -18,8 +18,8 @@ const rootReducer = combineReducers({
builders: builderReducer,
pulls: pullsReducer,
page: pageReducer,
build: buildStatusReducer,
testData: testmanReducer
builds,
tests
});
export default rootReducer;

View File

@ -1,20 +0,0 @@
import { TESTMAN_DATA } from '../constants';
const testmanReducer = (state = {}, action) => {
if (action.type === TESTMAN_DATA.LOAD_SUCCESS) {
let cleanedTestmanData = {};
for (const [sha, tests] of Object.entries(action.tests)) {
cleanedTestmanData[sha] = tests.map(t => {
let reducedKeyVal = {};
for (const [k, v] of Object.entries(t)) {
reducedKeyVal[k] = v._text;
}
return reducedKeyVal;
})
}
return cleanedTestmanData;
}
return state;
};
export default testmanReducer;

View File

@ -0,0 +1,53 @@
import { TEST_DATA, TESTMAN_DATA, JOB_STATUS } from '../constants';
export default function testsReducer(state = {}, action) {
if (action.type === TEST_DATA.LOAD_SUCCESS) {
const newState = {}
for (let [sha, tests] of Object.entries(action.tests)) {
const testsOfSha = {}
for (let test of tests) {
let status
if (!test.complete) status = JOB_STATUS.ONGOING
else if (test.state_string.includes("success")) status = JOB_STATUS.SUCCESS
else status = JOB_STATUS.FAILURE
testsOfSha[test.buildid] = {
builderId: test.builderid,
buildBotId: test.buildid,
number: test.number,
statusText: test.state_string,
status,
testManData: null,
parentBuild: test.parentBuild
}
}
newState[sha] = testsOfSha
}
return newState
}
else if (action.type === TESTMAN_DATA.LOAD_SUCCESS) {
const newState = {...state}
for (let [sha, tests] of Object.entries(action.testmanTests)) {
for (let t of tests) {
if (newState[sha] && newState[sha][t.buildBotId]) {
newState[sha][t.buildBotId].testManData = {
id: parseInt(t.id._text),
platform: t.platform._text,
count: parseInt(t.count._text),
failures: parseInt(t.failures._text)
}
}
}
}
return newState
}
return state
}

View File

@ -1,7 +1,7 @@
import { takeEvery, call, put, select } from 'redux-saga/effects';
import { COMMITS } from '../constants';
import { COMMITS, BUILDER_TYPE } from '../constants';
import { fetchBuildSets, fetchBuildReq, fetchBuilds } from '../api';
import { setBuildSetsError, setBuilds } from '../actions';
import { setBuildsError, setBuilds, setTests } from '../actions';
/* These functions are used to build an HTTP query string for
* filtering data on BuildBot side.
@ -23,7 +23,8 @@ function convertIsoToUnixTime(isoF, isoL) {
}
function getBuildQString(builds) {
return builds
// besides buildRequestId filtering, we need to get a suffix property from a build
return "property=suffix&" + builds
.map(build => 'buildrequestid__contains=' + build.buildrequestid)
.join('&');
}
@ -51,12 +52,14 @@ function getBuildReqQString(commits, buildData) {
function* handleBuildsLoad() {
try {
const commits = yield select(state => state.commits);
const builders = yield select(state => state.builders)
const buildSetsRaw = yield call(
fetchBuildSets,
convertIsoToUnixTime(commits[0], commits[9])
);
if (buildSetsRaw.length === 0) {
yield put(setBuildSetsError('Nothing returned'));
yield put(setBuildsError('Nothing returned'));
return;
}
@ -66,23 +69,38 @@ function* handleBuildsLoad() {
);
const buildsRaw = yield call(fetchBuilds, getBuildQString(buildReqsRaw));
// populate builds with buildSetId
for (let b of buildsRaw) {
b.bsid = buildReqsRaw.find(br => br.buildrequestid === b.buildrequestid).buildsetid
}
const buildsBySha = {};
const testsBySha = {}
for (let { sha } of commits) {
const buildSetIds = buildSetsRaw
.filter(bs => bs.sourcestamps[0].revision === sha)
.map(bs => bs.bsid);
const buildReqIds = buildReqsRaw
.filter(br => buildSetIds.includes(br.buildsetid))
.map(br => br.buildrequestid);
const builds = buildsRaw.filter(b =>
buildReqIds.includes(b.buildrequestid)
);
buildsBySha[sha] = builds;
// here we separate "test" builds from "build" builds
// because they are processed by different reducers
buildsBySha[sha] = buildsRaw.filter(b =>
builders[b.builderid].type === BUILDER_TYPE.BUILDER && buildSetIds.includes(b.bsid));
testsBySha[sha] = buildsRaw.filter(b =>
builders[b.builderid].type === BUILDER_TYPE.TESTER && buildSetIds.includes(b.bsid));
// populate the parent build data
for (let t of testsBySha[sha]) {
const parentBuildId = buildSetsRaw.find(bs => bs.bsid === t.bsid).parent_buildid
t.parentBuild = buildsBySha[sha].find(b => b.buildid === parentBuildId)
}
}
yield put(setBuilds(buildsBySha));
yield put(setTests(testsBySha));
} catch (error) {
yield put(setBuildSetsError(error.toString()));
yield put(setBuildsError(error.toString()));
}
}

View File

@ -1,16 +1,40 @@
import { takeEvery, call, select, put } from 'redux-saga/effects';
import { COMMITS } from '../constants';
import { TEST_DATA } from '../constants';
import { fetchTests } from '../api';
import { setTestman, setTestmanError } from '../actions';
function* handleTestmanLoad() {
try {
const commits = yield select(state => state.commits);
const builders = yield select(state => state.builders)
const tests = yield select(state => state.tests)
let shas = [];
if (commits.length > 0) {
shas = [commits[0].sha, ...commits.map(commit => commit.parents[0].sha)];
}
const testResults = yield call(fetchTests, shas[shas.length - 1], shas[0], 1);
// connecting testman entry with buildbot build by testerName + buildNumber
for (let t of testResults) {
const buildNumber = parseInt(t.comment._text.match(/Build\s(\d+)/i)[1])
const testerName = t.source._text.match(/Build\s.*\son\s(Test.*)/i)[1]
const builder = Object.values(builders).find(b => b.full_name === testerName)
const builderId = builder.builderid
for (let shaTests of Object.values(tests)) {
for (let test of Object.values(shaTests)) {
if (test.number === buildNumber && test.builderId === builderId)
{
t.buildBotId = test.buildBotId
t.testerName = builder.name
break
}
}
if (t.buildBotId) break
}
}
const testBySha = {};
for (let sha of shas) {
testBySha[sha] = testResults.filter(test =>
@ -24,5 +48,5 @@ function* handleTestmanLoad() {
}
export default function* watchTestmanLoad() {
yield takeEvery(COMMITS.LOAD_SUCCESS, handleTestmanLoad);
yield takeEvery(TEST_DATA.LOAD_SUCCESS, handleTestmanLoad);
}

View File

@ -1,7 +1,7 @@
import { takeEvery, call, put, select } from 'redux-saga/effects';
import { PULLS } from '../constants';
import { fetchBuildSets, fetchBuildReq, fetchBuilds } from '../api';
import { setBuildSetsError, setBuilds } from '../actions';
import { setBuildsError, setBuilds } from '../actions';
function convertIsoToUnixTime(isoF, isoL) {
let unixF = Date.parse(isoF.created_at) / 1000 + 30000;
@ -38,7 +38,7 @@ function* handlePullsBuildLoad() {
convertIsoToUnixTime(pulls[0], pulls[9])
);
if (buildSetsRaw.length === 0) {
yield put(setBuildSetsError('Nothing returned'));
yield put(setBuildsError('Nothing returned'));
return;
}
@ -69,7 +69,7 @@ function* handlePullsBuildLoad() {
}
yield put(setBuilds(buildsByPR));
} catch (error) {
yield put(setBuildSetsError(error.toString()));
yield put(setBuildsError(error.toString()));
}
}

View File

@ -7,7 +7,7 @@ const rp = require('request-promise');
function buildSetReq(str) {
//https://build.reactos.org/api/v2/buildsets?field=bsid&field=sourcestamps&order=-bsid&offset=0&limit=200
const buildSets = {
uri: `https://build.reactos.org/api/v2/buildsets?field=bsid&field=sourcestamps&field=submitted_at&order=-bsid${str}`,
uri: `https://build.reactos.org/api/v2/buildsets?field=parent_buildid&field=bsid&field=sourcestamps&field=submitted_at&order=-bsid${str}`,
headers: {
'User-Agent': 'Request-Promise'
},
@ -76,7 +76,7 @@ function builds(str) {
router.get('/builds', (req, res) => {
let f = req.query.buildrequestid__contains;
let queryStr = f.join('&buildrequestid__contains=');
queryStr = 'buildrequestid__contains=' + queryStr;
queryStr = 'property=suffix&buildrequestid__contains=' + queryStr;
rp(builds(queryStr))
.then(body => {
res.json(body);