зеркало из https://github.com/mozilla/treeherder.git
Bug 1574651 - add tc_root_url to each repository (#5405)
* Bug 1574651 - add tc_root_url to each repository * Fix issues introduced since initial creation of this feature * Fix unit tests * Fix retriggers in Compare Chooser of Perfherder
This commit is contained in:
Родитель
6ca78bd25c
Коммит
7f72192565
|
@ -66,6 +66,7 @@
|
|||
"redux-thunk": "2.3.0",
|
||||
"taskcluster-client-web": "8.1.1",
|
||||
"taskcluster-lib-scopes": "10.0.2",
|
||||
"taskcluster-lib-urls": "12.0.0",
|
||||
"webpack": "4.39.3",
|
||||
"webpack-cli": "3.3.8",
|
||||
"victory": "33.0.5"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"active_status": "active",
|
||||
"performance_alerts_enabled": false,
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net",
|
||||
"is_try_repo": false,
|
||||
"pushLogUrl": "https://hg.mozilla.org/mozilla-central/pushloghtml",
|
||||
"revisionHrefPrefix": "https://hg.mozilla.org/mozilla-central/rev/"
|
||||
|
@ -33,6 +34,7 @@
|
|||
"active_status": "active",
|
||||
"performance_alerts_enabled": false,
|
||||
"expire_performance_data": true,
|
||||
"tc_root_url": "https://taskcluster.net",
|
||||
"is_try_repo": true,
|
||||
"pushLogUrl": "https://hg.mozilla.org/try/pushloghtml",
|
||||
"revisionHrefPrefix": "https://hg.mozilla.org/try/rev/"
|
||||
|
@ -52,6 +54,7 @@
|
|||
"active_status": "active",
|
||||
"performance_alerts_enabled": true,
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net",
|
||||
"is_try_repo": false,
|
||||
"pushLogUrl": "https://hg.mozilla.org/integration/autoland/pushloghtml",
|
||||
"revisionHrefPrefix": "https://hg.mozilla.org/integration/autoland/rev/"
|
||||
|
|
|
@ -5,6 +5,7 @@ import { decisionTaskIdCache } from '../../../ui/models/push';
|
|||
import { getApiUrl } from '../../../ui/helpers/url';
|
||||
import paginatedJobListFixtureOne from '../mock/job_list/pagination/page_1';
|
||||
import paginatedJobListFixtureTwo from '../mock/job_list/pagination/page_2';
|
||||
import repositories from '../mock/repositories';
|
||||
import { getProjectUrl } from '../../../ui/helpers/location';
|
||||
|
||||
describe('JobModel', () => {
|
||||
|
@ -57,6 +58,7 @@ describe('JobModel', () => {
|
|||
const testJobs = [
|
||||
{ id: 123, push_id: 526443, job_type_name: 'foo', task_id: 'TASKID' },
|
||||
];
|
||||
const currentRepo = repositories[2];
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock.mock(
|
||||
|
@ -89,7 +91,7 @@ describe('JobModel', () => {
|
|||
test('retrigger uses passed-in decisionTaskMap', async () => {
|
||||
await JobModel.retrigger(
|
||||
testJobs,
|
||||
'autoland',
|
||||
currentRepo,
|
||||
notify,
|
||||
1,
|
||||
decisionTaskMap,
|
||||
|
@ -101,7 +103,7 @@ describe('JobModel', () => {
|
|||
});
|
||||
|
||||
test('retrigger calls for decision task when not passed-in', async () => {
|
||||
await JobModel.retrigger(testJobs, 'autoland', notify, 1);
|
||||
await JobModel.retrigger(testJobs, currentRepo, notify, 1);
|
||||
|
||||
expect(fetchMock.called(decisionTaskMapUrl)).toBe(true);
|
||||
expect(fetchMock.called(tcTaskUrl)).toBe(false);
|
||||
|
@ -109,7 +111,7 @@ describe('JobModel', () => {
|
|||
});
|
||||
|
||||
test('cancel uses passed-in decisionTask', async () => {
|
||||
await JobModel.cancel(testJobs, 'autoland', () => {}, decisionTaskMap);
|
||||
await JobModel.cancel(testJobs, currentRepo, () => {}, decisionTaskMap);
|
||||
|
||||
expect(fetchMock.called(decisionTaskMapUrl)).toBe(false);
|
||||
expect(fetchMock.called(tcTaskUrl)).toBe(true);
|
||||
|
@ -117,7 +119,7 @@ describe('JobModel', () => {
|
|||
});
|
||||
|
||||
test('cancel calls for decision task when not passed-in', async () => {
|
||||
await JobModel.cancel(testJobs, 'autoland', () => {});
|
||||
await JobModel.cancel(testJobs, currentRepo, () => {});
|
||||
|
||||
expect(fetchMock.called(decisionTaskMapUrl)).toBe(true);
|
||||
expect(fetchMock.called(tcTaskUrl)).toBe(true);
|
||||
|
@ -127,7 +129,7 @@ describe('JobModel', () => {
|
|||
test('cancelAll uses passed-in decisionTask', async () => {
|
||||
const decisionTask = { id: 'LVTawdmFR2-uJiWWS2NxSw', run: '0' };
|
||||
|
||||
await JobModel.cancelAll(526443, 'autoland', () => {}, decisionTask);
|
||||
await JobModel.cancelAll(526443, currentRepo, () => {}, decisionTask);
|
||||
|
||||
expect(fetchMock.called(decisionTaskMapUrl)).toBe(false);
|
||||
expect(fetchMock.called(tcTaskUrl)).toBe(false);
|
||||
|
@ -135,7 +137,7 @@ describe('JobModel', () => {
|
|||
});
|
||||
|
||||
test('cancelAll calls for decision task when not passed-in', async () => {
|
||||
await JobModel.cancelAll(526443, 'autoland', () => {});
|
||||
await JobModel.cancelAll(526443, currentRepo, () => {});
|
||||
|
||||
expect(fetchMock.called(decisionTaskMapUrl)).toBe(true);
|
||||
expect(fetchMock.called(tcTaskUrl)).toBe(false);
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
waitForElementToBeRemoved,
|
||||
} from '@testing-library/react';
|
||||
|
||||
import projects from '../mock/repositories';
|
||||
import CompareTableControls from '../../../ui/perfherder/compare/CompareTableControls';
|
||||
import { compareTableText, filterText } from '../../../ui/perfherder/constants';
|
||||
import CompareTable from '../../../ui/perfherder/compare/CompareTable';
|
||||
|
@ -103,6 +104,7 @@ const compareTableControlsNode = (onPermalinkClick, userLoggedIn = false) => {
|
|||
notify={() => {}}
|
||||
isBaseAggregate={false}
|
||||
onPermalinkClick={handlePermalinkClick}
|
||||
projects={projects}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -126,6 +128,7 @@ const compareTable = (
|
|||
getJob={(repoName, jobId) => {
|
||||
return { id: jobId };
|
||||
}}
|
||||
projects={projects}
|
||||
/>,
|
||||
);
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
"codebase": "gecko",
|
||||
"repository_group": 1,
|
||||
"description": "",
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -25,7 +26,8 @@
|
|||
"repository_group": 1,
|
||||
"description": "",
|
||||
"performance_alerts_enabled": true,
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -38,7 +40,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 1,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -52,7 +55,8 @@
|
|||
"codebase": "gecko",
|
||||
"repository_group": 1,
|
||||
"description": "",
|
||||
"is_try_repo": true
|
||||
"is_try_repo": true,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -67,7 +71,8 @@
|
|||
"repository_group": 2,
|
||||
"description": "",
|
||||
"performance_alerts_enabled": true,
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -82,7 +87,8 @@
|
|||
"repository_group": 2,
|
||||
"description": "",
|
||||
"performance_alerts_enabled": true,
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -97,7 +103,8 @@
|
|||
"repository_group": 2,
|
||||
"description": "",
|
||||
"performance_alerts_enabled": true,
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -110,7 +117,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -123,7 +131,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -136,7 +145,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -149,7 +159,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -162,7 +173,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "jetpack",
|
||||
"repository_group": 1,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -175,7 +187,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -190,7 +203,8 @@
|
|||
"repository_group": 1,
|
||||
"description": "",
|
||||
"performance_alerts_enabled": false,
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -203,7 +217,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -216,7 +231,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -229,7 +245,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -242,7 +259,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -255,7 +273,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -268,7 +287,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -281,7 +301,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -294,7 +315,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -307,7 +329,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -320,7 +343,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -333,7 +357,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -346,7 +371,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -359,7 +385,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -372,7 +399,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -385,7 +413,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -398,7 +427,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -411,7 +441,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -424,7 +455,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -437,7 +469,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "comm",
|
||||
"repository_group": 8,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -451,7 +484,8 @@
|
|||
"codebase": "comm",
|
||||
"repository_group": 8,
|
||||
"description": "",
|
||||
"is_try_repo": true
|
||||
"is_try_repo": true,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -464,7 +498,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "comm",
|
||||
"repository_group": 8,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -477,7 +512,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "comm",
|
||||
"repository_group": 8,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -490,7 +526,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "comm",
|
||||
"repository_group": 8,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -503,7 +540,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 6,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -516,7 +554,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "",
|
||||
"repository_group": 1,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -529,7 +568,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -543,7 +583,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gaia",
|
||||
"repository_group": 1,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -556,7 +597,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -569,7 +611,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "taskcluster",
|
||||
"repository_group": 4,
|
||||
"description": "taskcluster integration test dumping ground."
|
||||
"description": "taskcluster integration test dumping ground.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -583,7 +626,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gaia",
|
||||
"repository_group": 4,
|
||||
"description": "Gaia master branch"
|
||||
"description": "Gaia master branch",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -596,7 +640,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gaia",
|
||||
"repository_group": 4,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -609,7 +654,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 4,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -622,7 +668,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gaia",
|
||||
"repository_group": 1,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -635,7 +682,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -648,7 +696,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 5,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -661,7 +710,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -674,7 +724,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -687,7 +738,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 1,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -700,7 +752,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -713,7 +766,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -726,7 +780,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "comm",
|
||||
"repository_group": 8,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -739,7 +794,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -752,7 +808,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -766,7 +823,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "bugzilla",
|
||||
"repository_group": 4,
|
||||
"description": "A suite of tests to check the quality of the Bugzilla codebase."
|
||||
"description": "A suite of tests to check the quality of the Bugzilla codebase.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -780,7 +838,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "bugzilla",
|
||||
"repository_group": 4,
|
||||
"description": "A suite of tests to check the quality of the BMO codebase."
|
||||
"description": "A suite of tests to check the quality of the BMO codebase.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -793,7 +852,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -806,7 +866,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "comm",
|
||||
"repository_group": 8,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -820,7 +881,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "bugzilla",
|
||||
"repository_group": 4,
|
||||
"description": "A suite of tests to check the quality of the Bugzilla 5.0 codebase."
|
||||
"description": "A suite of tests to check the quality of the Bugzilla 5.0 codebase.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -834,7 +896,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "bugzilla",
|
||||
"repository_group": 4,
|
||||
"description": "A suite of tests to check the quality of the Bugzilla 4.4 codebase."
|
||||
"description": "A suite of tests to check the quality of the Bugzilla 4.4 codebase.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -848,7 +911,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "bugzilla",
|
||||
"repository_group": 4,
|
||||
"description": "A suite of tests to check the quality of the Bugzilla 4.2 codebase."
|
||||
"description": "A suite of tests to check the quality of the Bugzilla 4.2 codebase.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -862,7 +926,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "bugzilla",
|
||||
"repository_group": 4,
|
||||
"description": "A suite of tests to check the quality of the BMO codebase."
|
||||
"description": "A suite of tests to check the quality of the BMO codebase.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -875,7 +940,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -888,7 +954,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -902,7 +969,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "bugzilla",
|
||||
"repository_group": 4,
|
||||
"description": "A suite of tests to check the quality of the BMO codebase."
|
||||
"description": "A suite of tests to check the quality of the BMO codebase.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -915,7 +983,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -928,7 +997,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -941,7 +1011,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "comm",
|
||||
"repository_group": 8,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -956,7 +1027,8 @@
|
|||
"codebase": "servo",
|
||||
"repository_group": 10,
|
||||
"description": "The Servo Parallel Browser Engine − master",
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -969,7 +1041,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "version-control-tools",
|
||||
"repository_group": 7,
|
||||
"description": "Version control infrastructure and tooling."
|
||||
"description": "Version control infrastructure and tooling.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -984,7 +1057,8 @@
|
|||
"repository_group": 1,
|
||||
"description": "The destination for automatically landed Firefox commits.",
|
||||
"performance_alerts_enabled": true,
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -998,7 +1072,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "autopush",
|
||||
"repository_group": 7,
|
||||
"description": "Mozilla Push server and Push Endpoint."
|
||||
"description": "Mozilla Push server and Push Endpoint.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1011,7 +1086,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "nss",
|
||||
"repository_group": 7,
|
||||
"description": "Network Security Services."
|
||||
"description": "Network Security Services.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1025,7 +1101,8 @@
|
|||
"codebase": "nss",
|
||||
"repository_group": 7,
|
||||
"description": "Network Security Services.",
|
||||
"is_try_repo": true
|
||||
"is_try_repo": true,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1039,7 +1116,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "example-addon-repo",
|
||||
"repository_group": 7,
|
||||
"description": "Example add-on repository for templates and best practices."
|
||||
"description": "Example add-on repository for templates and best practices.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1052,7 +1130,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 1,
|
||||
"description": "Testing Servo integration with Gecko"
|
||||
"description": "Testing Servo integration with Gecko",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1066,7 +1145,8 @@
|
|||
"codebase": "gecko",
|
||||
"repository_group": 1,
|
||||
"description": "Try repo for Servo integration",
|
||||
"is_try_repo": true
|
||||
"is_try_repo": true,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1079,7 +1159,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1092,7 +1173,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "comm",
|
||||
"repository_group": 8,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1106,7 +1188,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "servo",
|
||||
"repository_group": 7,
|
||||
"description": "GPU renderer for Servo"
|
||||
"description": "GPU renderer for Servo",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1120,7 +1203,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "addon-tests",
|
||||
"repository_group": 5,
|
||||
"description": "Tests for Add-ons"
|
||||
"description": "Tests for Add-ons",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1134,7 +1218,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "fxapom",
|
||||
"repository_group": 5,
|
||||
"description": "Firefox Account Page Object Model"
|
||||
"description": "Firefox Account Page Object Model",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1148,7 +1233,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "go-bouncer",
|
||||
"repository_group": 5,
|
||||
"description": "Go version of the redirector portion of bouncer"
|
||||
"description": "Go version of the redirector portion of bouncer",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1162,7 +1248,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "mozillians-tests",
|
||||
"repository_group": 5,
|
||||
"description": "Tests for Mozillians"
|
||||
"description": "Tests for Mozillians",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1176,7 +1263,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "snippets-service",
|
||||
"repository_group": 5,
|
||||
"description": "Snippets Service"
|
||||
"description": "Snippets Service",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1190,7 +1278,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "socorro",
|
||||
"repository_group": 5,
|
||||
"description": "Server for collecting, processing, and displaying crash reports from clients using the Breakpad libraries"
|
||||
"description": "Server for collecting, processing, and displaying crash reports from clients using the Breakpad libraries",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1204,7 +1293,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "stubattribution-tests",
|
||||
"repository_group": 5,
|
||||
"description": "Tests for the stub attribution service"
|
||||
"description": "Tests for the stub attribution service",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1218,7 +1308,8 @@
|
|||
"active_status": "onhold",
|
||||
"codebase": "treeherder",
|
||||
"repository_group": 5,
|
||||
"description": "A system for managing CI data for Mozilla projects"
|
||||
"description": "A system for managing CI data for Mozilla projects",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1231,7 +1322,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1244,7 +1336,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "comm",
|
||||
"repository_group": 8,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1257,7 +1350,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "ci-admin",
|
||||
"repository_group": 9,
|
||||
"description": "Administrative scripts for Firefox CI"
|
||||
"description": "Administrative scripts for Firefox CI",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1270,7 +1364,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "ci-admin",
|
||||
"repository_group": 9,
|
||||
"description": "Administrative configuration for Firefox CI"
|
||||
"description": "Administrative configuration for Firefox CI",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1285,7 +1380,8 @@
|
|||
"codebase": "servo",
|
||||
"repository_group": 10,
|
||||
"description": "The Servo Parallel Browser Engine − try (multiple branches)",
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1300,7 +1396,8 @@
|
|||
"codebase": "servo",
|
||||
"repository_group": 10,
|
||||
"description": "The Servo Parallel Browser Engine − auto: testing PRs after review and before merging to master.",
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1315,7 +1412,8 @@
|
|||
"codebase": "servo",
|
||||
"repository_group": 10,
|
||||
"description": "The Servo Parallel Browser Engine − try, Taskcluster only",
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1330,7 +1428,8 @@
|
|||
"codebase": "servo",
|
||||
"repository_group": 10,
|
||||
"description": "The Servo Parallel Browser Engine − pull requests",
|
||||
"expire_performance_data": false
|
||||
"expire_performance_data": false,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1343,7 +1442,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "taskgraph",
|
||||
"repository_group": 9,
|
||||
"description": "Tools for defining graphs fo taskclutser tasks"
|
||||
"description": "Tools for defining graphs fo taskclutser tasks",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1357,7 +1457,8 @@
|
|||
"codebase": "taskgraph",
|
||||
"repository_group": 9,
|
||||
"description": "Tools for defining graphs fo taskclutser tasks",
|
||||
"is_try_repo": true
|
||||
"is_try_repo": true,
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1370,7 +1471,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "ci-admin",
|
||||
"repository_group": 9,
|
||||
"description": "Administrative scripts for Firefox CI"
|
||||
"description": "Administrative scripts for Firefox CI",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1383,7 +1485,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "ci-admin",
|
||||
"repository_group": 9,
|
||||
"description": "Administrative configuration for Firefox CI"
|
||||
"description": "Administrative configuration for Firefox CI",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1397,7 +1500,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "reference-browser",
|
||||
"repository_group": 11,
|
||||
"description": "A full-featured browser reference implementation using Mozilla Android Components"
|
||||
"description": "A full-featured browser reference implementation using Mozilla Android Components",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1411,7 +1515,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "fenix",
|
||||
"repository_group": 11,
|
||||
"description": "Fenix is not your parent's Android browser"
|
||||
"description": "Fenix is not your parent's Android browser",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1424,7 +1529,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "gecko",
|
||||
"repository_group": 2,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1437,7 +1543,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "comm",
|
||||
"repository_group": 8,
|
||||
"description": ""
|
||||
"description": "",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -1451,7 +1558,8 @@
|
|||
"active_status": "active",
|
||||
"codebase": "android-components",
|
||||
"repository_group": 11,
|
||||
"description": "A collection of Android libraries to build browsers or browser-like applications."
|
||||
"description": "A collection of Android libraries to build browsers or browser-like applications.",
|
||||
"tc_root_url": "https://taskcluster.net"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 2.2.4 on 2019-08-28 17:39
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('model', '0014_add_job_log_status_skipped_size'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='repository',
|
||||
name='tc_root_url',
|
||||
field=models.CharField(db_index=True, default='https://taskcluster.net', max_length=255),
|
||||
# only apply this default when migrating; after this users must supply their
|
||||
# own rootUrl (and by the time you're reading this, `taskcluster.net` is likely
|
||||
# no longer operating)
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -108,6 +108,7 @@ class Repository(models.Model):
|
|||
performance_alerts_enabled = models.BooleanField(default=False)
|
||||
expire_performance_data = models.BooleanField(default=True)
|
||||
is_try_repo = models.BooleanField(default=False)
|
||||
tc_root_url = models.CharField(max_length=255, null=False, db_index=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'repository'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { OIDCCredentialAgent, Queue } from 'taskcluster-client-web';
|
||||
|
||||
import { tcRootUrl, getUserSessionUrl } from './url';
|
||||
import { loginRootUrl, getUserSessionUrl } from './url';
|
||||
|
||||
const taskcluster = (() => {
|
||||
let credentialAgent = null;
|
||||
|
@ -19,7 +19,7 @@ const taskcluster = (() => {
|
|||
accessToken: JSON.parse(userSession).accessToken,
|
||||
oidcProvider,
|
||||
url: getUserSessionUrl(oidcProvider),
|
||||
rootUrl: tcRootUrl,
|
||||
rootUrl: loginRootUrl,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ const taskcluster = (() => {
|
|||
getQueue: () =>
|
||||
new Queue({
|
||||
credentialAgent: tcAgent(),
|
||||
rootUrl: tcRootUrl,
|
||||
rootUrl: loginRootUrl,
|
||||
}),
|
||||
updateAgent: () => {
|
||||
const userSession = localStorage.getItem('userSession');
|
||||
|
|
|
@ -12,7 +12,8 @@ export const hgBaseUrl = 'https://hg.mozilla.org/';
|
|||
|
||||
export const dxrBaseUrl = 'https://dxr.mozilla.org/';
|
||||
|
||||
export const tcRootUrl = 'https://taskcluster.net';
|
||||
// the rootUrl of the TC deployment for which user login gets credentials
|
||||
export const loginRootUrl = 'https://taskcluster.net';
|
||||
|
||||
export const bugsEndpoint = 'failures/';
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import jsonSchemaDefaults from 'json-schema-defaults';
|
|||
// https://github.com/nodeca/js-yaml/pull/462
|
||||
import jsyaml from 'js-yaml/dist/js-yaml';
|
||||
import { slugid } from 'taskcluster-client-web';
|
||||
import tcLibUrls from 'taskcluster-lib-urls';
|
||||
import {
|
||||
Button,
|
||||
Label,
|
||||
|
@ -45,10 +46,10 @@ class CustomJobActions extends React.PureComponent {
|
|||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const { pushId, job, notify, decisionTaskMap } = this.props;
|
||||
const { pushId, job, notify, decisionTaskMap, currentRepo } = this.props;
|
||||
const { id: decisionTaskId } = decisionTaskMap[pushId];
|
||||
|
||||
TaskclusterModel.load(decisionTaskId, job).then(results => {
|
||||
TaskclusterModel.load(decisionTaskId, job, currentRepo).then(results => {
|
||||
const {
|
||||
originalTask,
|
||||
originalTaskId,
|
||||
|
@ -123,7 +124,7 @@ class CustomJobActions extends React.PureComponent {
|
|||
selectedActionOption,
|
||||
staticActionVariables,
|
||||
} = this.state;
|
||||
const { notify } = this.props;
|
||||
const { notify, currentRepo } = this.props;
|
||||
const action = selectedActionOption.value;
|
||||
|
||||
let input = null;
|
||||
|
@ -151,11 +152,12 @@ class CustomJobActions extends React.PureComponent {
|
|||
task: originalTask,
|
||||
input,
|
||||
staticActionVariables,
|
||||
currentRepo,
|
||||
}).then(
|
||||
taskId => {
|
||||
this.setState({ triggering: false });
|
||||
let message = 'Custom action request sent successfully:';
|
||||
let url = `https://tools.taskcluster.net/tasks/${taskId}`;
|
||||
let url = tcLibUrls.ui(currentRepo.tc_root_url, `/tasks/${taskId}`);
|
||||
|
||||
// For the time being, we are redirecting specific actions to
|
||||
// specific urls that are different than usual. At this time, we are
|
||||
|
@ -166,7 +168,7 @@ class CustomJobActions extends React.PureComponent {
|
|||
'generic-worker-windows-loaner',
|
||||
];
|
||||
if (loaners.includes(action.name)) {
|
||||
message = 'Visit Taskcluster Tools site to access loaner:';
|
||||
message = 'Visit Taskcluster site to access loaner:';
|
||||
url = `${url}/connect`;
|
||||
}
|
||||
notify(message, 'success', { linkText: 'Open in Taskcluster', url });
|
||||
|
@ -306,6 +308,7 @@ CustomJobActions.propTypes = {
|
|||
toggle: PropTypes.func.isRequired,
|
||||
decisionTaskMap: PropTypes.object.isRequired,
|
||||
job: PropTypes.object,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
CustomJobActions.defaultProps = {
|
||||
|
|
|
@ -97,7 +97,7 @@ class DetailsPanel extends React.Component {
|
|||
};
|
||||
|
||||
loadBugSuggestions = () => {
|
||||
const { repoName, selectedJob } = this.props;
|
||||
const { currentRepo, selectedJob } = this.props;
|
||||
|
||||
if (!selectedJob) {
|
||||
return;
|
||||
|
@ -131,7 +131,7 @@ class DetailsPanel extends React.Component {
|
|||
result: step.result,
|
||||
logViewerUrl: getLogViewerUrl(
|
||||
selectedJob.id,
|
||||
repoName,
|
||||
currentRepo.name,
|
||||
step.finished_line_number,
|
||||
),
|
||||
}));
|
||||
|
@ -160,7 +160,7 @@ class DetailsPanel extends React.Component {
|
|||
};
|
||||
|
||||
selectJob = () => {
|
||||
const { repoName, selectedJob } = this.props;
|
||||
const { currentRepo, selectedJob } = this.props;
|
||||
const push = this.findPush(selectedJob.push_id);
|
||||
|
||||
this.setState(
|
||||
|
@ -178,7 +178,7 @@ class DetailsPanel extends React.Component {
|
|||
'logs' in selectedJob
|
||||
? Promise.resolve(selectedJob)
|
||||
: JobModel.get(
|
||||
repoName,
|
||||
currentRepo.name,
|
||||
selectedJob.id,
|
||||
this.selectJobController.signal,
|
||||
);
|
||||
|
@ -193,9 +193,12 @@ class DetailsPanel extends React.Component {
|
|||
this.selectJobController.signal,
|
||||
);
|
||||
|
||||
const phSeriesPromise = PerfSeriesModel.getSeriesData(repoName, {
|
||||
job_id: selectedJob.id,
|
||||
});
|
||||
const phSeriesPromise = PerfSeriesModel.getSeriesData(
|
||||
currentRepo.name,
|
||||
{
|
||||
job_id: selectedJob.id,
|
||||
},
|
||||
);
|
||||
|
||||
Promise.all([
|
||||
jobPromise,
|
||||
|
@ -235,7 +238,10 @@ class DetailsPanel extends React.Component {
|
|||
logParseStatus = jobLogUrls[0].parse_status;
|
||||
}
|
||||
|
||||
const logViewerUrl = getLogViewerUrl(selectedJob.id, repoName);
|
||||
const logViewerUrl = getLogViewerUrl(
|
||||
selectedJob.id,
|
||||
currentRepo.name,
|
||||
);
|
||||
const logViewerFullUrl = `${window.location.origin}/${logViewerUrl}`;
|
||||
const reftestUrl = jobLogUrls.length
|
||||
? getReftestUrl(jobLogUrls[0].url)
|
||||
|
@ -252,7 +258,7 @@ class DetailsPanel extends React.Component {
|
|||
];
|
||||
const seriesListList = await Promise.all(
|
||||
chunk(signatureIds, 20).map(signatureIdChunk =>
|
||||
PerfSeriesModel.getSeriesList(repoName, {
|
||||
PerfSeriesModel.getSeriesList(currentRepo.name, {
|
||||
id: signatureIdChunk,
|
||||
}),
|
||||
),
|
||||
|
@ -270,12 +276,12 @@ class DetailsPanel extends React.Component {
|
|||
.filter(d => !d.series.parentSignature)
|
||||
.map(d => ({
|
||||
url: `/perf.html#/graphs?series=${[
|
||||
repoName,
|
||||
currentRepo.name,
|
||||
d.signature_id,
|
||||
1,
|
||||
d.series.frameworkId,
|
||||
]}&selected=${[
|
||||
repoName,
|
||||
currentRepo.name,
|
||||
d.signature_id,
|
||||
selectedJob.push_id,
|
||||
d.id,
|
||||
|
@ -314,7 +320,6 @@ class DetailsPanel extends React.Component {
|
|||
|
||||
render() {
|
||||
const {
|
||||
repoName,
|
||||
user,
|
||||
currentRepo,
|
||||
resizedHeight,
|
||||
|
@ -350,7 +355,6 @@ class DetailsPanel extends React.Component {
|
|||
className={selectedJobFull ? 'details-panel-slide' : 'hidden'}
|
||||
>
|
||||
<PinBoard
|
||||
repoName={repoName}
|
||||
currentRepo={currentRepo}
|
||||
isLoggedIn={user.isLoggedIn || false}
|
||||
classificationTypes={classificationTypes}
|
||||
|
@ -360,7 +364,6 @@ class DetailsPanel extends React.Component {
|
|||
<div id="details-panel-content">
|
||||
<SummaryPanel
|
||||
selectedJobFull={selectedJobFull}
|
||||
repoName={repoName}
|
||||
currentRepo={currentRepo}
|
||||
classificationMap={classificationMap}
|
||||
jobLogUrls={jobLogUrls}
|
||||
|
@ -379,7 +382,7 @@ class DetailsPanel extends React.Component {
|
|||
selectedJobFull={selectedJobFull}
|
||||
jobDetails={jobDetails}
|
||||
perfJobDetail={perfJobDetail}
|
||||
repoName={repoName}
|
||||
repoName={currentRepo.name}
|
||||
jobRevision={jobRevision}
|
||||
suggestions={suggestions}
|
||||
errors={errors}
|
||||
|
@ -404,7 +407,6 @@ class DetailsPanel extends React.Component {
|
|||
}
|
||||
|
||||
DetailsPanel.propTypes = {
|
||||
repoName: PropTypes.string.isRequired,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
resizedHeight: PropTypes.number.isRequired,
|
||||
|
|
|
@ -198,14 +198,14 @@ class PinBoard extends React.Component {
|
|||
};
|
||||
|
||||
cancelAllPinnedJobs = () => {
|
||||
const { notify, repoName, pinnedJobs, decisionTaskMap } = this.props;
|
||||
const { notify, currentRepo, pinnedJobs, decisionTaskMap } = this.props;
|
||||
|
||||
if (
|
||||
window.confirm('This will cancel all the selected jobs. Are you sure?')
|
||||
) {
|
||||
JobModel.cancel(
|
||||
Object.values(pinnedJobs),
|
||||
repoName,
|
||||
currentRepo,
|
||||
notify,
|
||||
decisionTaskMap,
|
||||
);
|
||||
|
@ -354,10 +354,10 @@ class PinBoard extends React.Component {
|
|||
};
|
||||
|
||||
retriggerAllPinnedJobs = async () => {
|
||||
const { pinnedJobs, notify, repoName, decisionTaskMap } = this.props;
|
||||
const { pinnedJobs, notify, currentRepo, decisionTaskMap } = this.props;
|
||||
const jobs = Object.values(pinnedJobs);
|
||||
|
||||
JobModel.retrigger(jobs, repoName, notify, 1, decisionTaskMap);
|
||||
JobModel.retrigger(jobs, currentRepo, notify, 1, decisionTaskMap);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -650,7 +650,6 @@ PinBoard.propTypes = {
|
|||
setClassificationComment: PropTypes.func.isRequired,
|
||||
setSelectedJob: PropTypes.func.isRequired,
|
||||
notify: PropTypes.func.isRequired,
|
||||
repoName: PropTypes.string.isRequired,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
failureClassificationId: PropTypes.number.isRequired,
|
||||
failureClassificationComment: PropTypes.string.isRequired,
|
||||
|
|
|
@ -77,53 +77,62 @@ class ActionBar extends React.PureComponent {
|
|||
};
|
||||
|
||||
createGeckoProfile = async () => {
|
||||
const { user, selectedJobFull, notify, decisionTaskMap } = this.props;
|
||||
const {
|
||||
user,
|
||||
selectedJobFull,
|
||||
notify,
|
||||
decisionTaskMap,
|
||||
currentRepo,
|
||||
} = this.props;
|
||||
if (!user.isLoggedIn) {
|
||||
return notify('Must be logged in to create a gecko profile', 'danger');
|
||||
}
|
||||
|
||||
const decisionTaskId = decisionTaskMap[selectedJobFull.push_id];
|
||||
TaskclusterModel.load(decisionTaskId, selectedJobFull).then(results => {
|
||||
try {
|
||||
const geckoprofile = getAction(results.actions, 'geckoprofile');
|
||||
TaskclusterModel.load(decisionTaskId, selectedJobFull, currentRepo).then(
|
||||
results => {
|
||||
try {
|
||||
const geckoprofile = getAction(results.actions, 'geckoprofile');
|
||||
|
||||
if (
|
||||
geckoprofile === undefined ||
|
||||
!Object.prototype.hasOwnProperty.call(geckoprofile, 'kind')
|
||||
) {
|
||||
return notify(
|
||||
'Job was scheduled without taskcluster support for GeckoProfiles',
|
||||
);
|
||||
}
|
||||
|
||||
TaskclusterModel.submit({
|
||||
action: geckoprofile,
|
||||
decisionTaskId,
|
||||
taskId: results.originalTaskId,
|
||||
task: results.originalTask,
|
||||
input: {},
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
}).then(
|
||||
() => {
|
||||
notify(
|
||||
'Request sent to collect gecko profile job via actions.json',
|
||||
'success',
|
||||
if (
|
||||
geckoprofile === undefined ||
|
||||
!Object.prototype.hasOwnProperty.call(geckoprofile, 'kind')
|
||||
) {
|
||||
return notify(
|
||||
'Job was scheduled without taskcluster support for GeckoProfiles',
|
||||
);
|
||||
},
|
||||
e => {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
// notification box.
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TaskclusterModel.submit({
|
||||
action: geckoprofile,
|
||||
decisionTaskId,
|
||||
taskId: results.originalTaskId,
|
||||
task: results.originalTask,
|
||||
input: {},
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
currentRepo,
|
||||
}).then(
|
||||
() => {
|
||||
notify(
|
||||
'Request sent to collect gecko profile job via actions.json',
|
||||
'success',
|
||||
);
|
||||
},
|
||||
e => {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
// notification box.
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
retriggerJob = async jobs => {
|
||||
const { user, repoName, notify, decisionTaskMap } = this.props;
|
||||
const { user, notify, decisionTaskMap, currentRepo } = this.props;
|
||||
|
||||
if (!user.isLoggedIn) {
|
||||
return notify('Must be logged in to retrigger a job', 'danger');
|
||||
|
@ -141,11 +150,17 @@ class ActionBar extends React.PureComponent {
|
|||
});
|
||||
});
|
||||
|
||||
JobModel.retrigger(jobs, repoName, notify, 1, decisionTaskMap);
|
||||
JobModel.retrigger(jobs, currentRepo, notify, 1, decisionTaskMap);
|
||||
};
|
||||
|
||||
backfillJob = async () => {
|
||||
const { user, selectedJobFull, notify, decisionTaskMap } = this.props;
|
||||
const {
|
||||
user,
|
||||
selectedJobFull,
|
||||
notify,
|
||||
decisionTaskMap,
|
||||
currentRepo,
|
||||
} = this.props;
|
||||
|
||||
if (!this.canBackfill()) {
|
||||
return;
|
||||
|
@ -165,34 +180,46 @@ class ActionBar extends React.PureComponent {
|
|||
|
||||
const { id: decisionTaskId } = decisionTaskMap[selectedJobFull.push_id];
|
||||
|
||||
TaskclusterModel.load(decisionTaskId, selectedJobFull).then(results => {
|
||||
try {
|
||||
const backfilltask = getAction(results.actions, 'backfill');
|
||||
TaskclusterModel.load(decisionTaskId, selectedJobFull, currentRepo).then(
|
||||
results => {
|
||||
try {
|
||||
const backfilltask = getAction(results.actions, 'backfill');
|
||||
|
||||
return TaskclusterModel.submit({
|
||||
action: backfilltask,
|
||||
decisionTaskId,
|
||||
taskId: results.originalTaskId,
|
||||
input: {},
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
}).then(
|
||||
() => {
|
||||
notify('Request sent to backfill job via actions.json', 'success');
|
||||
},
|
||||
e => {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
// notification box.
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
}
|
||||
});
|
||||
return TaskclusterModel.submit({
|
||||
action: backfilltask,
|
||||
decisionTaskId,
|
||||
taskId: results.originalTaskId,
|
||||
input: {},
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
currentRepo,
|
||||
}).then(
|
||||
() => {
|
||||
notify(
|
||||
'Request sent to backfill job via actions.json',
|
||||
'success',
|
||||
);
|
||||
},
|
||||
e => {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
// notification box.
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
isolateJob = async () => {
|
||||
const { user, selectedJobFull, notify, decisionTaskMap } = this.props;
|
||||
const {
|
||||
user,
|
||||
selectedJobFull,
|
||||
notify,
|
||||
decisionTaskMap,
|
||||
currentRepo,
|
||||
} = this.props;
|
||||
const { id: decisionTaskId } = decisionTaskMap[selectedJobFull.push_id];
|
||||
|
||||
if (!isTestIsolatable(selectedJobFull)) {
|
||||
|
@ -217,63 +244,66 @@ class ActionBar extends React.PureComponent {
|
|||
return;
|
||||
}
|
||||
|
||||
TaskclusterModel.load(decisionTaskId, selectedJobFull).then(results => {
|
||||
try {
|
||||
const isolationtask = getAction(
|
||||
results.actions,
|
||||
'isolate-test-failures',
|
||||
);
|
||||
|
||||
if (!isolationtask) {
|
||||
notify(
|
||||
'Request to isolate job via actions.json failed could not find action.',
|
||||
'danger',
|
||||
{ sticky: true },
|
||||
TaskclusterModel.load(decisionTaskId, selectedJobFull, currentRepo).then(
|
||||
results => {
|
||||
try {
|
||||
const isolationtask = getAction(
|
||||
results.actions,
|
||||
'isolate-test-failures',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let times = 1;
|
||||
let response = null;
|
||||
do {
|
||||
response = window.prompt(
|
||||
'Enter number of times (1..100) to run isolation jobs: ',
|
||||
times,
|
||||
);
|
||||
if (response == null) {
|
||||
break;
|
||||
}
|
||||
times = parseInt(response, 10);
|
||||
} while (Number.isNaN(times) || times < 1 || times > 100);
|
||||
|
||||
if (response === null) {
|
||||
notify('Request to isolate job via actions.json aborted.');
|
||||
return;
|
||||
}
|
||||
|
||||
return TaskclusterModel.submit({
|
||||
action: isolationtask,
|
||||
decisionTaskId,
|
||||
taskId: results.originalTaskId,
|
||||
input: { times },
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
}).then(
|
||||
() => {
|
||||
if (!isolationtask) {
|
||||
notify(
|
||||
'Request sent to isolate-test-failures job via actions.json',
|
||||
'success',
|
||||
'Request to isolate job via actions.json failed could not find action.',
|
||||
'danger',
|
||||
{ sticky: true },
|
||||
);
|
||||
},
|
||||
e => {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
// notification box.
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let times = 1;
|
||||
let response = null;
|
||||
do {
|
||||
response = window.prompt(
|
||||
'Enter number of times (1..100) to run isolation jobs: ',
|
||||
times,
|
||||
);
|
||||
if (response == null) {
|
||||
break;
|
||||
}
|
||||
times = parseInt(response, 10);
|
||||
} while (Number.isNaN(times) || times < 1 || times > 100);
|
||||
|
||||
if (response === null) {
|
||||
notify('Request to isolate job via actions.json aborted.');
|
||||
return;
|
||||
}
|
||||
|
||||
return TaskclusterModel.submit({
|
||||
action: isolationtask,
|
||||
decisionTaskId,
|
||||
taskId: results.originalTaskId,
|
||||
input: { times },
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
currentRepo,
|
||||
}).then(
|
||||
() => {
|
||||
notify(
|
||||
'Request sent to isolate-test-failures job via actions.json',
|
||||
'success',
|
||||
);
|
||||
},
|
||||
e => {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
// notification box.
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
// Can we backfill? At the moment, this only ensures we're not in a 'try' repo.
|
||||
|
@ -308,7 +338,13 @@ class ActionBar extends React.PureComponent {
|
|||
};
|
||||
|
||||
createInteractiveTask = async () => {
|
||||
const { user, selectedJobFull, notify, decisionTaskMap } = this.props;
|
||||
const {
|
||||
user,
|
||||
selectedJobFull,
|
||||
notify,
|
||||
decisionTaskMap,
|
||||
currentRepo,
|
||||
} = this.props;
|
||||
|
||||
if (!user.isLoggedIn) {
|
||||
return notify(
|
||||
|
@ -321,6 +357,7 @@ class ActionBar extends React.PureComponent {
|
|||
const results = await TaskclusterModel.load(
|
||||
decisionTaskId,
|
||||
selectedJobFull,
|
||||
currentRepo,
|
||||
);
|
||||
|
||||
try {
|
||||
|
@ -334,6 +371,7 @@ class ActionBar extends React.PureComponent {
|
|||
notify: user.email,
|
||||
},
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
currentRepo,
|
||||
});
|
||||
|
||||
notify(
|
||||
|
@ -349,14 +387,14 @@ class ActionBar extends React.PureComponent {
|
|||
};
|
||||
|
||||
cancelJobs = jobs => {
|
||||
const { user, repoName, notify, decisionTaskMap } = this.props;
|
||||
const { user, notify, decisionTaskMap, currentRepo } = this.props;
|
||||
|
||||
if (!user.isLoggedIn) {
|
||||
return notify('Must be logged in to cancel a job', 'danger');
|
||||
}
|
||||
JobModel.cancel(
|
||||
jobs.filter(({ state }) => state === 'pending' || state === 'running'),
|
||||
repoName,
|
||||
currentRepo,
|
||||
notify,
|
||||
decisionTaskMap,
|
||||
);
|
||||
|
@ -380,6 +418,7 @@ class ActionBar extends React.PureComponent {
|
|||
jobLogUrls,
|
||||
user,
|
||||
pinJob,
|
||||
currentRepo,
|
||||
} = this.props;
|
||||
const { customJobActionsShowing } = this.state;
|
||||
|
||||
|
@ -538,6 +577,7 @@ class ActionBar extends React.PureComponent {
|
|||
<CustomJobActions
|
||||
job={selectedJobFull}
|
||||
pushId={selectedJobFull.push_id}
|
||||
currentRepo={currentRepo}
|
||||
isLoggedIn={user.isLoggedIn}
|
||||
toggle={this.toggleCustomJobActions}
|
||||
/>
|
||||
|
@ -551,11 +591,11 @@ ActionBar.propTypes = {
|
|||
pinJob: PropTypes.func.isRequired,
|
||||
decisionTaskMap: PropTypes.object.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
repoName: PropTypes.string.isRequired,
|
||||
selectedJobFull: PropTypes.object.isRequired,
|
||||
logParseStatus: PropTypes.string.isRequired,
|
||||
notify: PropTypes.func.isRequired,
|
||||
jobLogUrls: PropTypes.array,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
isTryRepo: PropTypes.bool,
|
||||
logViewerUrl: PropTypes.string,
|
||||
logViewerFullUrl: PropTypes.string,
|
||||
|
|
|
@ -12,7 +12,6 @@ import StatusPanel from './StatusPanel';
|
|||
class SummaryPanel extends React.PureComponent {
|
||||
render() {
|
||||
const {
|
||||
repoName,
|
||||
selectedJobFull,
|
||||
latestClassification,
|
||||
bugs,
|
||||
|
@ -39,8 +38,8 @@ class SummaryPanel extends React.PureComponent {
|
|||
<div id="summary-panel" role="region" aria-label="Summary">
|
||||
<ActionBar
|
||||
selectedJobFull={selectedJobFull}
|
||||
repoName={repoName}
|
||||
logParseStatus={logParseStatus}
|
||||
currentRepo={currentRepo}
|
||||
isTryRepo={currentRepo.is_try_repo}
|
||||
logViewerUrl={logViewerUrl}
|
||||
logViewerFullUrl={logViewerFullUrl}
|
||||
|
@ -81,7 +80,6 @@ class SummaryPanel extends React.PureComponent {
|
|||
}
|
||||
|
||||
SummaryPanel.propTypes = {
|
||||
repoName: PropTypes.string.isRequired,
|
||||
bugs: PropTypes.array.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
|
|
|
@ -28,16 +28,6 @@ export default function InfraMenu() {
|
|||
CI Duty
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
className="dropdown-item"
|
||||
href="https://tools.taskcluster.net/diagnostics"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Taskcluster Diagnostics
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
className="dropdown-item"
|
||||
|
|
|
@ -140,6 +140,7 @@ class FuzzyJobFinder extends React.Component {
|
|||
PushModel.triggerNewJobs(
|
||||
this.state.selectedList,
|
||||
this.props.decisionTaskId,
|
||||
this.props.currentRepo,
|
||||
)
|
||||
.then(result => {
|
||||
notify(result, 'success');
|
||||
|
@ -315,6 +316,7 @@ FuzzyJobFinder.propTypes = {
|
|||
decisionTaskId: PropTypes.string,
|
||||
jobList: PropTypes.array,
|
||||
filteredJobList: PropTypes.array,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
FuzzyJobFinder.defaultProps = {
|
||||
|
|
|
@ -102,9 +102,9 @@ class Push extends React.PureComponent {
|
|||
}
|
||||
|
||||
setSingleRevisionWindowTitle() {
|
||||
const { allUnclassifiedFailureCount, repoName, push } = this.props;
|
||||
const { allUnclassifiedFailureCount, currentRepo, push } = this.props;
|
||||
const percentComplete = getPercentComplete(this.state.jobCounts);
|
||||
const title = `[${allUnclassifiedFailureCount}] ${repoName}`;
|
||||
const title = `[${allUnclassifiedFailureCount}] ${currentRepo.name}`;
|
||||
|
||||
document.title = `${percentComplete}% - ${title}: ${getRevisionTitle(
|
||||
push.revisions,
|
||||
|
@ -264,7 +264,7 @@ class Push extends React.PureComponent {
|
|||
showUpdateNotifications = prevState => {
|
||||
const { watched, jobCounts } = this.state;
|
||||
const {
|
||||
repoName,
|
||||
currentRepo,
|
||||
notificationSupported,
|
||||
push: { revision, id: pushId },
|
||||
notify,
|
||||
|
@ -297,7 +297,7 @@ class Push extends React.PureComponent {
|
|||
|
||||
if (message) {
|
||||
const notification = new Notification(message, {
|
||||
body: `${repoName} rev ${revision.substring(0, 12)}`,
|
||||
body: `${currentRepo.name} rev ${revision.substring(0, 12)}`,
|
||||
tag: pushId,
|
||||
});
|
||||
|
||||
|
@ -316,10 +316,10 @@ class Push extends React.PureComponent {
|
|||
};
|
||||
|
||||
showRunnableJobs = async () => {
|
||||
const { push, repoName, notify, decisionTaskMap } = this.props;
|
||||
const { push, notify, decisionTaskMap, currentRepo } = this.props;
|
||||
|
||||
try {
|
||||
const jobList = await RunnableJobModel.getList(repoName, {
|
||||
const jobList = await RunnableJobModel.getList(currentRepo.name, {
|
||||
decisionTask: decisionTaskMap[push.id],
|
||||
push_id: push.id,
|
||||
});
|
||||
|
@ -352,7 +352,7 @@ class Push extends React.PureComponent {
|
|||
};
|
||||
|
||||
showFuzzyJobs = async () => {
|
||||
const { push, repoName, notify, decisionTaskMap } = this.props;
|
||||
const { push, currentRepo, notify, decisionTaskMap } = this.props;
|
||||
const createRegExp = (str, opts) =>
|
||||
new RegExp(str.raw[0].replace(/\s/gm, ''), opts || '');
|
||||
const excludedJobNames = createRegExp`
|
||||
|
@ -366,7 +366,7 @@ class Push extends React.PureComponent {
|
|||
|
||||
try {
|
||||
notify('Fetching runnable jobs... This could take a while...');
|
||||
let fuzzyJobList = await RunnableJobModel.getList(repoName, {
|
||||
let fuzzyJobList = await RunnableJobModel.getList(currentRepo.name, {
|
||||
decisionTask: decisionTaskMap[push.id],
|
||||
});
|
||||
fuzzyJobList = [
|
||||
|
@ -429,7 +429,6 @@ class Push extends React.PureComponent {
|
|||
const {
|
||||
push,
|
||||
isLoggedIn,
|
||||
repoName,
|
||||
currentRepo,
|
||||
duplicateJobsVisible,
|
||||
filterModel,
|
||||
|
@ -477,6 +476,7 @@ class Push extends React.PureComponent {
|
|||
className="fuzzy-modal"
|
||||
pushId={id}
|
||||
decisionTaskId={decisionTaskId}
|
||||
currentRepo={currentRepo}
|
||||
/>
|
||||
<PushHeader
|
||||
push={push}
|
||||
|
@ -487,7 +487,7 @@ class Push extends React.PureComponent {
|
|||
jobCounts={jobCounts}
|
||||
watchState={watched}
|
||||
isLoggedIn={isLoggedIn}
|
||||
repoName={repoName}
|
||||
currentRepo={currentRepo}
|
||||
filterModel={filterModel}
|
||||
runnableVisible={runnableVisible}
|
||||
showRunnableJobs={this.showRunnableJobs}
|
||||
|
@ -509,7 +509,7 @@ class Push extends React.PureComponent {
|
|||
<PushJobs
|
||||
push={push}
|
||||
platforms={platforms}
|
||||
repoName={repoName}
|
||||
repoName={currentRepo.name}
|
||||
filterModel={filterModel}
|
||||
pushGroupState={pushGroupState}
|
||||
toggleSelectedRunnableJob={this.toggleSelectedRunnableJob}
|
||||
|
@ -539,7 +539,6 @@ Push.propTypes = {
|
|||
push: PropTypes.object.isRequired,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
filterModel: PropTypes.object.isRequired,
|
||||
repoName: PropTypes.string.isRequired,
|
||||
isLoggedIn: PropTypes.bool.isRequired,
|
||||
notificationSupported: PropTypes.bool.isRequired,
|
||||
getAllShownJobs: PropTypes.func.isRequired,
|
||||
|
|
|
@ -53,7 +53,7 @@ class PushActionMenu extends React.PureComponent {
|
|||
};
|
||||
|
||||
triggerMissingJobs = () => {
|
||||
const { notify, revision, pushId } = this.props;
|
||||
const { notify, revision, pushId, currentRepo } = this.props;
|
||||
|
||||
if (
|
||||
!window.confirm(
|
||||
|
@ -63,13 +63,13 @@ class PushActionMenu extends React.PureComponent {
|
|||
return;
|
||||
}
|
||||
|
||||
PushModel.triggerMissingJobs(pushId, notify).catch(e => {
|
||||
PushModel.triggerMissingJobs(pushId, notify, currentRepo).catch(e => {
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
});
|
||||
};
|
||||
|
||||
triggerAllTalosJobs = () => {
|
||||
const { notify, revision, pushId } = this.props;
|
||||
const { notify, revision, pushId, currentRepo } = this.props;
|
||||
|
||||
if (
|
||||
!window.confirm(
|
||||
|
@ -90,7 +90,7 @@ class PushActionMenu extends React.PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
PushModel.triggerAllTalosJobs(times, pushId, notify)
|
||||
PushModel.triggerAllTalosJobs(times, pushId, notify, currentRepo)
|
||||
.then(msg => {
|
||||
notify(msg, 'success');
|
||||
})
|
||||
|
@ -108,13 +108,13 @@ class PushActionMenu extends React.PureComponent {
|
|||
render() {
|
||||
const {
|
||||
isLoggedIn,
|
||||
repoName,
|
||||
revision,
|
||||
runnableVisible,
|
||||
hideRunnableJobs,
|
||||
showRunnableJobs,
|
||||
showFuzzyJobs,
|
||||
pushId,
|
||||
currentRepo,
|
||||
} = this.props;
|
||||
const {
|
||||
topOfRangeUrl,
|
||||
|
@ -174,7 +174,7 @@ class PushActionMenu extends React.PureComponent {
|
|||
Add new jobs (Search)
|
||||
</li>
|
||||
)}
|
||||
{triggerMissingRepos.includes(repoName) && (
|
||||
{triggerMissingRepos.includes(currentRepo.name) && (
|
||||
<li
|
||||
title={
|
||||
isLoggedIn
|
||||
|
@ -205,7 +205,7 @@ class PushActionMenu extends React.PureComponent {
|
|||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="dropdown-item"
|
||||
href={`https://bugherder.mozilla.org/?cset=${revision}&tree=${repoName}`}
|
||||
href={`https://bugherder.mozilla.org/?cset=${revision}&tree=${currentRepo.name}`}
|
||||
title="Use Bugherder to mark the bugs in this push"
|
||||
>
|
||||
Mark with Bugherder
|
||||
|
@ -238,7 +238,7 @@ class PushActionMenu extends React.PureComponent {
|
|||
<li>
|
||||
<a
|
||||
className="dropdown-item"
|
||||
href={getPushHealthUrl({ repo: repoName, revision })}
|
||||
href={getPushHealthUrl({ repo: currentRepo.name, revision })}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
|
@ -251,6 +251,7 @@ class PushActionMenu extends React.PureComponent {
|
|||
job={null}
|
||||
pushId={pushId}
|
||||
isLoggedIn={isLoggedIn}
|
||||
currentRepo={currentRepo}
|
||||
toggle={this.toggleCustomJobActions}
|
||||
/>
|
||||
)}
|
||||
|
@ -263,7 +264,7 @@ PushActionMenu.propTypes = {
|
|||
runnableVisible: PropTypes.bool.isRequired,
|
||||
isLoggedIn: PropTypes.bool.isRequired,
|
||||
revision: PropTypes.string.isRequired,
|
||||
repoName: PropTypes.string.isRequired,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
pushId: PropTypes.number.isRequired,
|
||||
hideRunnableJobs: PropTypes.func.isRequired,
|
||||
showRunnableJobs: PropTypes.func.isRequired,
|
||||
|
|
|
@ -143,6 +143,7 @@ class PushHeader extends React.Component {
|
|||
hideRunnableJobs,
|
||||
notify,
|
||||
decisionTaskMap,
|
||||
currentRepo,
|
||||
} = this.props;
|
||||
|
||||
if (
|
||||
|
@ -155,7 +156,11 @@ class PushHeader extends React.Component {
|
|||
if (isLoggedIn) {
|
||||
const { id: decisionTaskId } = decisionTaskMap[pushId];
|
||||
|
||||
PushModel.triggerNewJobs(selectedRunnableJobs, decisionTaskId)
|
||||
PushModel.triggerNewJobs(
|
||||
selectedRunnableJobs,
|
||||
decisionTaskId,
|
||||
currentRepo,
|
||||
)
|
||||
.then(result => {
|
||||
notify(result, 'success');
|
||||
hideRunnableJobs(pushId);
|
||||
|
@ -177,15 +182,20 @@ class PushHeader extends React.Component {
|
|||
) {
|
||||
const {
|
||||
notify,
|
||||
repoName,
|
||||
push,
|
||||
isLoggedIn,
|
||||
decisionTaskMap,
|
||||
currentRepo,
|
||||
} = this.props;
|
||||
|
||||
if (!isLoggedIn) return;
|
||||
|
||||
JobModel.cancelAll(push.id, repoName, notify, decisionTaskMap[push.id]);
|
||||
JobModel.cancelAll(
|
||||
push.id,
|
||||
currentRepo,
|
||||
notify,
|
||||
decisionTaskMap[push.id],
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -234,7 +244,6 @@ class PushHeader extends React.Component {
|
|||
|
||||
render() {
|
||||
const {
|
||||
repoName,
|
||||
isLoggedIn,
|
||||
pushId,
|
||||
jobCounts,
|
||||
|
@ -250,6 +259,7 @@ class PushHeader extends React.Component {
|
|||
selectedRunnableJobs,
|
||||
collapsed,
|
||||
pushHealthVisibility,
|
||||
currentRepo,
|
||||
} = this.props;
|
||||
const cancelJobsTitle = isLoggedIn
|
||||
? 'Cancel all jobs'
|
||||
|
@ -259,7 +269,7 @@ class PushHeader extends React.Component {
|
|||
const authorPushFilterUrl = getJobsUrl({ ...linkParams, author });
|
||||
const showPushHealthStatus =
|
||||
pushHealthVisibility === 'All' ||
|
||||
repoName === pushHealthVisibility.toLowerCase();
|
||||
currentRepo.name === pushHealthVisibility.toLowerCase();
|
||||
const watchStateLabel = {
|
||||
none: 'Watch',
|
||||
push: 'Notifying (per-push)',
|
||||
|
@ -293,7 +303,7 @@ class PushHeader extends React.Component {
|
|||
</span>
|
||||
{showPushHealthStatus && (
|
||||
<PushHealthStatus
|
||||
repoName={repoName}
|
||||
repoName={currentRepo.name}
|
||||
pushId={pushId}
|
||||
revision={revision}
|
||||
jobCounts={jobCounts}
|
||||
|
@ -324,7 +334,7 @@ class PushHeader extends React.Component {
|
|||
)}
|
||||
<a
|
||||
className="btn btn-sm btn-push test-view-btn"
|
||||
href={`/testview.html?repo=${repoName}&revision=${revision}`}
|
||||
href={`/testview.html?repo=${currentRepo.name}&revision=${revision}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="View details on failed test results for this push"
|
||||
|
@ -372,7 +382,7 @@ class PushHeader extends React.Component {
|
|||
isLoggedIn={isLoggedIn}
|
||||
runnableVisible={runnableVisible}
|
||||
revision={revision}
|
||||
repoName={repoName}
|
||||
currentRepo={currentRepo}
|
||||
pushId={pushId}
|
||||
showRunnableJobs={showRunnableJobs}
|
||||
hideRunnableJobs={hideRunnableJobs}
|
||||
|
@ -391,7 +401,6 @@ PushHeader.propTypes = {
|
|||
pushTimestamp: PropTypes.number.isRequired,
|
||||
author: PropTypes.string.isRequired,
|
||||
revision: PropTypes.string.isRequired,
|
||||
repoName: PropTypes.string.isRequired,
|
||||
filterModel: PropTypes.object.isRequired,
|
||||
runnableVisible: PropTypes.bool.isRequired,
|
||||
showRunnableJobs: PropTypes.func.isRequired,
|
||||
|
@ -411,6 +420,7 @@ PushHeader.propTypes = {
|
|||
pushHealthVisibility: PropTypes.string.isRequired,
|
||||
decisionTaskMap: PropTypes.object.isRequired,
|
||||
watchState: PropTypes.string,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
PushHeader.defaultProps = {
|
||||
|
|
|
@ -153,7 +153,6 @@ class PushList extends React.Component {
|
|||
push={push}
|
||||
isLoggedIn={isLoggedIn || false}
|
||||
currentRepo={currentRepo}
|
||||
repoName={repoName}
|
||||
filterModel={filterModel}
|
||||
notificationSupported={notificationSupported}
|
||||
duplicateJobsVisible={duplicateJobsVisible}
|
||||
|
|
104
ui/models/job.js
104
ui/models/job.js
|
@ -85,13 +85,12 @@ export default class JobModel {
|
|||
|
||||
static async retrigger(
|
||||
jobs,
|
||||
repoName,
|
||||
currentRepo,
|
||||
notify,
|
||||
times = 1,
|
||||
decisionTaskIdMap = null,
|
||||
) {
|
||||
const jobTerm = jobs.length > 1 ? 'jobs' : 'job';
|
||||
|
||||
try {
|
||||
notify(`Attempting to retrigger/add ${jobTerm} via actions.json`, 'info');
|
||||
|
||||
|
@ -105,49 +104,52 @@ export default class JobModel {
|
|||
for (const [key, value] of Object.entries(uniquePerPushJobs)) {
|
||||
const decisionTaskId = taskIdMap[key].id;
|
||||
|
||||
TaskclusterModel.load(decisionTaskId).then(async results => {
|
||||
const actionTaskId = slugid();
|
||||
const taskLabels = value.map(job => job.job_type_name);
|
||||
TaskclusterModel.load(decisionTaskId, null, currentRepo).then(
|
||||
async results => {
|
||||
const actionTaskId = slugid();
|
||||
const taskLabels = value.map(job => job.job_type_name);
|
||||
|
||||
let retriggerAction = results.actions.find(
|
||||
action => action.name === 'retrigger-multiple',
|
||||
);
|
||||
let actionInput = {
|
||||
requests: [{ tasks: taskLabels, times }],
|
||||
};
|
||||
if (!retriggerAction) {
|
||||
// The `retrigger-multiple` action as introduced in Bug 1521032, to all the action
|
||||
// to control whether new task are created, or existing ones re-run. We fall back
|
||||
// to `add-new-jobs` to support pushing old revision to try, where the duplicating
|
||||
// the release tasks impacted is unlikely to cause problems.
|
||||
retriggerAction = getAction(results.actions, 'add-new-jobs');
|
||||
actionInput = {
|
||||
tasks: taskLabels,
|
||||
let retriggerAction = results.actions.find(
|
||||
action => action.name === 'retrigger-multiple',
|
||||
);
|
||||
let actionInput = {
|
||||
requests: [{ tasks: taskLabels, times }],
|
||||
};
|
||||
}
|
||||
if (!retriggerAction) {
|
||||
// The `retrigger-multiple` action as introduced in Bug 1521032, to all the action
|
||||
// to control whether new task are created, or existing ones re-run. We fall back
|
||||
// to `add-new-jobs` to support pushing old revision to try, where the duplicating
|
||||
// the release tasks impacted is unlikely to cause problems.
|
||||
retriggerAction = getAction(results.actions, 'add-new-jobs');
|
||||
actionInput = {
|
||||
tasks: taskLabels,
|
||||
};
|
||||
}
|
||||
|
||||
await TaskclusterModel.submit({
|
||||
action: retriggerAction,
|
||||
actionTaskId,
|
||||
decisionTaskId,
|
||||
taskId: null,
|
||||
task: null,
|
||||
input: actionInput,
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
})
|
||||
.then(() =>
|
||||
notify(
|
||||
`Request sent to retrigger/add new jobs via actions.json (${actionTaskId})`,
|
||||
),
|
||||
)
|
||||
.catch(error => {
|
||||
notify(
|
||||
`Retrigger failed with Decision task: ${decisionTaskId}: ${error}`,
|
||||
'danger',
|
||||
{ sticky: true },
|
||||
);
|
||||
});
|
||||
});
|
||||
await TaskclusterModel.submit({
|
||||
action: retriggerAction,
|
||||
actionTaskId,
|
||||
decisionTaskId,
|
||||
taskId: null,
|
||||
task: null,
|
||||
input: actionInput,
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
currentRepo,
|
||||
})
|
||||
.then(() =>
|
||||
notify(
|
||||
`Request sent to retrigger/add new jobs via actions.json (${actionTaskId})`,
|
||||
),
|
||||
)
|
||||
.catch(error => {
|
||||
notify(
|
||||
`Retrigger failed with Decision task: ${decisionTaskId}: ${error}`,
|
||||
'danger',
|
||||
{ sticky: true },
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
notify(
|
||||
|
@ -158,11 +160,15 @@ export default class JobModel {
|
|||
}
|
||||
}
|
||||
|
||||
static async cancelAll(pushId, repoName, notify, decisionTask) {
|
||||
static async cancelAll(pushId, currentRepo, notify, decisionTask) {
|
||||
const { id: decisionTaskId } =
|
||||
decisionTask || (await PushModel.getDecisionTaskId(pushId, notify));
|
||||
|
||||
const results = await TaskclusterModel.load(decisionTaskId);
|
||||
const results = await TaskclusterModel.load(
|
||||
decisionTaskId,
|
||||
null,
|
||||
currentRepo,
|
||||
);
|
||||
|
||||
try {
|
||||
const cancelAllTask = getAction(results.actions, 'cancel-all');
|
||||
|
@ -172,6 +178,7 @@ export default class JobModel {
|
|||
decisionTaskId,
|
||||
input: {},
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
currentRepo,
|
||||
});
|
||||
} catch (e) {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
|
@ -182,7 +189,7 @@ export default class JobModel {
|
|||
notify('Request sent to cancel all jobs via action.json', 'success');
|
||||
}
|
||||
|
||||
static async cancel(jobs, repoName, notify, decisionTaskIdMap) {
|
||||
static async cancel(jobs, currentRepo, notify, decisionTaskIdMap) {
|
||||
const jobTerm = jobs.length > 1 ? 'jobs' : 'job';
|
||||
const taskIdMap =
|
||||
decisionTaskIdMap ||
|
||||
|
@ -201,7 +208,11 @@ export default class JobModel {
|
|||
// eslint-disable-next-line no-unused-vars
|
||||
for (const job of jobs) {
|
||||
const decisionTaskId = taskIdMap[job.push_id].id;
|
||||
const results = await TaskclusterModel.load(decisionTaskId, job);
|
||||
const results = await TaskclusterModel.load(
|
||||
decisionTaskId,
|
||||
job,
|
||||
currentRepo,
|
||||
);
|
||||
|
||||
try {
|
||||
const cancelTask = getAction(results.actions, 'cancel');
|
||||
|
@ -212,6 +223,7 @@ export default class JobModel {
|
|||
taskId: results.originalTaskId,
|
||||
input: {},
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
currentRepo,
|
||||
});
|
||||
} catch (e) {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
|
|
|
@ -65,89 +65,104 @@ export default class PushModel {
|
|||
return fetch(getProjectUrl(`${pushEndpoint}${pk}/`, repoName));
|
||||
}
|
||||
|
||||
static async triggerMissingJobs(pushId, notify, decisionTask) {
|
||||
static async triggerMissingJobs(pushId, notify, decisionTask, currentRepo) {
|
||||
const decisionTaskId =
|
||||
decisionTask || (await PushModel.getDecisionTaskId(pushId, notify)).id;
|
||||
|
||||
return TaskclusterModel.load(decisionTaskId).then(results => {
|
||||
const actionTaskId = slugid();
|
||||
return TaskclusterModel.load(decisionTaskId, null, currentRepo).then(
|
||||
results => {
|
||||
const actionTaskId = slugid();
|
||||
|
||||
try {
|
||||
const missingTestsTask = getAction(
|
||||
results.actions,
|
||||
'run-missing-tests',
|
||||
);
|
||||
try {
|
||||
const missingTestsTask = getAction(
|
||||
results.actions,
|
||||
'run-missing-tests',
|
||||
);
|
||||
|
||||
return TaskclusterModel.submit({
|
||||
action: missingTestsTask,
|
||||
actionTaskId,
|
||||
decisionTaskId,
|
||||
taskId: null,
|
||||
task: null,
|
||||
input: {},
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
}).then(
|
||||
notify(
|
||||
`Request sent to trigger missing jobs (${actionTaskId})`,
|
||||
'success',
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
// notification box.
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
}
|
||||
});
|
||||
return TaskclusterModel.submit({
|
||||
action: missingTestsTask,
|
||||
actionTaskId,
|
||||
decisionTaskId,
|
||||
taskId: null,
|
||||
task: null,
|
||||
input: {},
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
currentRepo,
|
||||
}).then(
|
||||
notify(
|
||||
`Request sent to trigger missing jobs (${actionTaskId})`,
|
||||
'success',
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
// notification box.
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static async triggerAllTalosJobs(times, pushId, notify, decisionTask) {
|
||||
static async triggerAllTalosJobs(
|
||||
times,
|
||||
pushId,
|
||||
notify,
|
||||
decisionTask,
|
||||
currentRepo,
|
||||
) {
|
||||
const decisionTaskId =
|
||||
decisionTask || (await PushModel.getDecisionTaskId(pushId, notify)).id;
|
||||
|
||||
return TaskclusterModel.load(decisionTaskId).then(results => {
|
||||
const actionTaskId = slugid();
|
||||
return TaskclusterModel.load(decisionTaskId, null, currentRepo).then(
|
||||
results => {
|
||||
const actionTaskId = slugid();
|
||||
|
||||
try {
|
||||
const allTalosTask = getAction(results.actions, 'run-all-talos');
|
||||
try {
|
||||
const allTalosTask = getAction(results.actions, 'run-all-talos');
|
||||
|
||||
return TaskclusterModel.submit({
|
||||
action: allTalosTask,
|
||||
actionTaskId,
|
||||
decisionTaskId,
|
||||
taskId: null,
|
||||
task: null,
|
||||
input: { times },
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
currentRepo,
|
||||
}).then(
|
||||
() =>
|
||||
`Request sent to trigger all talos jobs ${times} time(s) via actions.json (${actionTaskId})`,
|
||||
);
|
||||
} catch (e) {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
// notification box.
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static triggerNewJobs(jobs, decisionTaskId, currentRepo) {
|
||||
return TaskclusterModel.load(decisionTaskId, null, currentRepo).then(
|
||||
results => {
|
||||
const actionTaskId = slugid();
|
||||
const addNewJobsTask = getAction(results.actions, 'add-new-jobs');
|
||||
|
||||
return TaskclusterModel.submit({
|
||||
action: allTalosTask,
|
||||
action: addNewJobsTask,
|
||||
actionTaskId,
|
||||
decisionTaskId,
|
||||
taskId: null,
|
||||
task: null,
|
||||
input: { times },
|
||||
input: { tasks: jobs },
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
currentRepo,
|
||||
}).then(
|
||||
() =>
|
||||
`Request sent to trigger all talos jobs ${times} time(s) via actions.json (${actionTaskId})`,
|
||||
`Request sent to trigger new jobs via actions.json (${actionTaskId})`,
|
||||
);
|
||||
} catch (e) {
|
||||
// The full message is too large to fit in a Treeherder
|
||||
// notification box.
|
||||
notify(formatTaskclusterError(e), 'danger', { sticky: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static triggerNewJobs(jobs, decisionTaskId) {
|
||||
return TaskclusterModel.load(decisionTaskId).then(results => {
|
||||
const actionTaskId = slugid();
|
||||
const addNewJobsTask = getAction(results.actions, 'add-new-jobs');
|
||||
|
||||
return TaskclusterModel.submit({
|
||||
action: addNewJobsTask,
|
||||
actionTaskId,
|
||||
decisionTaskId,
|
||||
taskId: null,
|
||||
task: null,
|
||||
input: { tasks: jobs },
|
||||
staticActionVariables: results.staticActionVariables,
|
||||
}).then(
|
||||
() =>
|
||||
`Request sent to trigger new jobs via actions.json (${actionTaskId})`,
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static getHealth(repoName, revision) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import defaults from 'lodash/defaults';
|
||||
import jsone from 'json-e';
|
||||
import { Auth, Hooks } from 'taskcluster-client-web';
|
||||
import { Auth, Hooks, Queue } from 'taskcluster-client-web';
|
||||
import { satisfiesExpression } from 'taskcluster-lib-scopes';
|
||||
|
||||
import taskcluster from '../helpers/taskcluster';
|
||||
import { tcRootUrl } from '../helpers/url';
|
||||
import { loginRootUrl } from '../helpers/url';
|
||||
|
||||
export default class TaskclusterModel {
|
||||
static taskInContext(tagSetList, taskTags) {
|
||||
|
@ -23,7 +23,16 @@ export default class TaskclusterModel {
|
|||
task,
|
||||
input,
|
||||
staticActionVariables,
|
||||
currentRepo,
|
||||
}) {
|
||||
if (currentRepo.tc_root_url !== loginRootUrl) {
|
||||
// This limit could be lifted by allowing users to login to multiple TC deployments at once, using
|
||||
// https://github.com/taskcluster/taskcluster-rfcs/blob/master/rfcs/0147-third-party-login.md
|
||||
throw Error(
|
||||
`Actions are not supported for this repository, as it does not use TC deployment ${loginRootUrl}`,
|
||||
);
|
||||
}
|
||||
|
||||
const context = defaults(
|
||||
{},
|
||||
{
|
||||
|
@ -50,10 +59,10 @@ export default class TaskclusterModel {
|
|||
if (action.kind === 'hook') {
|
||||
const hookPayload = jsone(action.hookPayload, context);
|
||||
const { hookId, hookGroupId } = action;
|
||||
const auth = new Auth({ rootUrl: tcRootUrl });
|
||||
const auth = new Auth({ rootUrl: currentRepo.tc_root_url });
|
||||
const hooks = new Hooks({
|
||||
credentialAgent: taskcluster.getAgent(),
|
||||
rootUrl: tcRootUrl,
|
||||
rootUrl: currentRepo.tc_root_url,
|
||||
});
|
||||
const decisionTask = await queue.task(decisionTaskId);
|
||||
const expansion = await auth.expandScopes({
|
||||
|
@ -73,11 +82,19 @@ export default class TaskclusterModel {
|
|||
}
|
||||
}
|
||||
|
||||
static async load(decisionTaskID, job) {
|
||||
static async load(decisionTaskID, job, currentRepo) {
|
||||
if (!decisionTaskID) {
|
||||
throw Error("No decision task, can't find taskcluster actions");
|
||||
}
|
||||
|
||||
if (currentRepo.tc_root_url !== loginRootUrl) {
|
||||
// This limit could be lifted by allowing users to login to multiple TC deployments at once, using
|
||||
// https://github.com/taskcluster/taskcluster-rfcs/blob/master/rfcs/0147-third-party-login.md
|
||||
throw Error(
|
||||
`Actions are not supported for this repository, as it does not use TC deployment ${loginRootUrl}`,
|
||||
);
|
||||
}
|
||||
|
||||
const queue = taskcluster.getQueue();
|
||||
const actionsUrl = queue.buildUrl(
|
||||
queue.getLatestArtifact,
|
||||
|
@ -90,9 +107,8 @@ export default class TaskclusterModel {
|
|||
let originalTaskPromise = Promise.resolve(null);
|
||||
if (job) {
|
||||
originalTaskId = job.task_id;
|
||||
originalTaskPromise = fetch(
|
||||
`https://queue.taskcluster.net/v1/task/${originalTaskId}`,
|
||||
).then(async response => response.json());
|
||||
const queue = new Queue({ rootUrl: currentRepo.tc_root_url });
|
||||
originalTaskPromise = queue.task(originalTaskId);
|
||||
}
|
||||
|
||||
return Promise.all([fetch(actionsUrl), originalTaskPromise]).then(
|
||||
|
@ -109,7 +125,7 @@ export default class TaskclusterModel {
|
|||
|
||||
// The filter in the value of the actions key is an implementation
|
||||
// of the specification for action context in
|
||||
// https://docs.taskcluster.net/manual/using/actions/spec#action-context
|
||||
// https://docs.taskcluster.net/docs/manual/design/conventions/actions/spec
|
||||
// It decides if the specific action is applicable for this task.
|
||||
return {
|
||||
originalTask,
|
||||
|
|
|
@ -217,6 +217,7 @@ class CompareSubtestsView extends React.PureComponent {
|
|||
}
|
||||
|
||||
CompareSubtestsView.propTypes = {
|
||||
projects: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
||||
validated: PropTypes.shape({
|
||||
originalResultSet: PropTypes.shape({}),
|
||||
newResultSet: PropTypes.shape({}),
|
||||
|
|
|
@ -15,6 +15,7 @@ import { compareTableText } from '../constants';
|
|||
import ProgressBar from '../ProgressBar';
|
||||
import { hashFunction } from '../../helpers/utils';
|
||||
import JobModel from '../../models/job';
|
||||
import RepositoryModel from '../../models/repository';
|
||||
|
||||
import TableAverage from './TableAverage';
|
||||
|
||||
|
@ -50,22 +51,24 @@ export default class CompareTable extends React.PureComponent {
|
|||
|
||||
retriggerJobs = async (results, times) => {
|
||||
// retrigger base revision jobs
|
||||
const { projects } = this.props;
|
||||
|
||||
this.retriggerByRevision(
|
||||
results.originalRetriggerableJobId,
|
||||
results.originalRepoName,
|
||||
RepositoryModel.getRepo(results.originalRepoName, projects),
|
||||
true,
|
||||
times,
|
||||
);
|
||||
// retrigger new revision jobs
|
||||
this.retriggerByRevision(
|
||||
results.newRetriggerableJobId,
|
||||
results.newRepoName,
|
||||
RepositoryModel.getRepo(results.newRepoName, projects),
|
||||
false,
|
||||
times,
|
||||
);
|
||||
};
|
||||
|
||||
retriggerByRevision = async (jobId, repoName, isBaseline, times) => {
|
||||
retriggerByRevision = async (jobId, currentRepo, isBaseline, times) => {
|
||||
const { isBaseAggregate, notify, retriggerJob, getJob } = this.props;
|
||||
|
||||
// do not retrigger if the base is aggregate (there is a selected time range)
|
||||
|
@ -74,8 +77,8 @@ export default class CompareTable extends React.PureComponent {
|
|||
}
|
||||
|
||||
if (jobId) {
|
||||
const job = await getJob(repoName, jobId);
|
||||
retriggerJob([job], repoName, notify, times);
|
||||
const job = await getJob(currentRepo.name, jobId);
|
||||
retriggerJob([job], currentRepo, notify, times);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@ export default class CompareTableControls extends React.Component {
|
|||
notify,
|
||||
hasSubtests,
|
||||
onPermalinkClick,
|
||||
projects,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
|
@ -175,6 +176,7 @@ export default class CompareTableControls extends React.Component {
|
|||
isBaseAggregate={isBaseAggregate}
|
||||
notify={notify}
|
||||
hasSubtests={hasSubtests}
|
||||
projects={projects}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
|
@ -191,6 +193,7 @@ CompareTableControls.propTypes = {
|
|||
user: PropTypes.shape({}).isRequired,
|
||||
isBaseAggregate: PropTypes.bool.isRequired,
|
||||
notify: PropTypes.func.isRequired,
|
||||
projects: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
||||
hasSubtests: PropTypes.bool,
|
||||
validated: PropTypes.shape({
|
||||
showOnlyImportant: PropTypes.string,
|
||||
|
|
|
@ -196,6 +196,7 @@ export default class CompareTableView extends React.Component {
|
|||
hasSubtests,
|
||||
onPermalinkClick,
|
||||
frameworks,
|
||||
projects,
|
||||
} = this.props;
|
||||
const {
|
||||
compareResults,
|
||||
|
@ -312,6 +313,7 @@ export default class CompareTableView extends React.Component {
|
|||
compareResults={compareResults}
|
||||
isBaseAggregate={!originalRevision}
|
||||
notify={this.notifyFailure}
|
||||
projects={projects}
|
||||
showTestsWithNoise={
|
||||
testsWithNoise.length > 0 && (
|
||||
<Row>
|
||||
|
@ -352,6 +354,7 @@ CompareTableView.propTypes = {
|
|||
filterByFramework: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.bool]),
|
||||
getDisplayResults: PropTypes.func.isRequired,
|
||||
getQueryParams: PropTypes.func.isRequired,
|
||||
projects: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
||||
hasSubtests: PropTypes.bool,
|
||||
onPermalinkClick: PropTypes.func,
|
||||
hashFragment: PropTypes.string,
|
||||
|
|
|
@ -244,6 +244,7 @@ class CompareView extends React.PureComponent {
|
|||
}
|
||||
|
||||
CompareView.propTypes = {
|
||||
projects: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
||||
validated: PropTypes.shape({
|
||||
originalResultSet: PropTypes.shape({}),
|
||||
newResultSet: PropTypes.shape({}),
|
||||
|
|
|
@ -3,6 +3,9 @@ import PropTypes from 'prop-types';
|
|||
import { hot } from 'react-hot-loader/root';
|
||||
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
||||
|
||||
import RepositoryModel from '../models/repository';
|
||||
import { getRepo } from '../helpers/location';
|
||||
|
||||
import NotFound from './NotFound';
|
||||
import Health from './Health';
|
||||
|
||||
|
@ -12,28 +15,53 @@ function hasProps(search) {
|
|||
return params.get('repo') && params.get('revision');
|
||||
}
|
||||
|
||||
const App = () => (
|
||||
<BrowserRouter>
|
||||
<div>
|
||||
<div>
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path="/pushhealth.html"
|
||||
render={props =>
|
||||
hasProps(props.location.search) ? (
|
||||
<Health {...props} />
|
||||
) : (
|
||||
<NotFound {...props} />
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Route name="notfound" component={NotFound} />
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
);
|
||||
class App extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
currentRepo: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const repoName = getRepo();
|
||||
|
||||
if (repoName) {
|
||||
RepositoryModel.getList().then(repos => {
|
||||
const newRepo = repos.find(repo => repo.name === repoName);
|
||||
|
||||
this.setState({ currentRepo: newRepo });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { currentRepo } = this.state;
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<div>
|
||||
<div>
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path="/pushhealth.html"
|
||||
render={props =>
|
||||
hasProps(props.location.search) ? (
|
||||
<Health currentRepo={currentRepo} {...props} />
|
||||
) : (
|
||||
<NotFound {...props} />
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Route name="notfound" component={NotFound} />
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
App.propTypes = {
|
||||
location: PropTypes.object,
|
||||
|
|
|
@ -42,7 +42,7 @@ class ClassificationGroup extends React.PureComponent {
|
|||
};
|
||||
|
||||
retriggerAll = times => {
|
||||
const { group, notify } = this.props;
|
||||
const { group, notify, currentRepo } = this.props;
|
||||
// Reduce down to the unique jobs
|
||||
const jobs = group.reduce(
|
||||
(acc, test) => ({
|
||||
|
@ -53,7 +53,7 @@ class ClassificationGroup extends React.PureComponent {
|
|||
);
|
||||
const uniqueJobs = Object.values(jobs);
|
||||
|
||||
JobModel.retrigger(uniqueJobs, null, notify, times);
|
||||
JobModel.retrigger(uniqueJobs, null, notify, currentRepo, times);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -68,6 +68,7 @@ class ClassificationGroup extends React.PureComponent {
|
|||
user,
|
||||
hasRetriggerAll,
|
||||
notify,
|
||||
currentRepo,
|
||||
} = this.props;
|
||||
const expandIcon = detailsShowing ? faMinusSquare : faPlusSquare;
|
||||
|
||||
|
@ -123,6 +124,7 @@ class ClassificationGroup extends React.PureComponent {
|
|||
key={failure.key}
|
||||
failure={failure}
|
||||
repo={repo}
|
||||
currentRepo={currentRepo}
|
||||
revision={revision}
|
||||
user={user}
|
||||
notify={notify}
|
||||
|
@ -139,6 +141,7 @@ ClassificationGroup.propTypes = {
|
|||
group: PropTypes.array.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
repo: PropTypes.string.isRequired,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
revision: PropTypes.string.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
notify: PropTypes.func.isRequired,
|
||||
|
|
|
@ -92,6 +92,7 @@ export default class Health extends React.PureComponent {
|
|||
failureMessage,
|
||||
notifications,
|
||||
} = this.state;
|
||||
const { currentRepo } = this.props;
|
||||
const overallResult = healthData
|
||||
? resultColorMap[healthData.result]
|
||||
: 'none';
|
||||
|
@ -129,6 +130,7 @@ export default class Health extends React.PureComponent {
|
|||
details={metric.details}
|
||||
failures={metric.failures}
|
||||
repo={repo}
|
||||
currentRepo={currentRepo}
|
||||
revision={revision}
|
||||
user={user}
|
||||
notify={this.notify}
|
||||
|
@ -149,4 +151,5 @@ export default class Health extends React.PureComponent {
|
|||
|
||||
Health.propTypes = {
|
||||
location: PropTypes.object.isRequired,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
};
|
||||
|
|
|
@ -36,6 +36,7 @@ export default class Metric extends React.PureComponent {
|
|||
revision,
|
||||
user,
|
||||
notify,
|
||||
currentRepo,
|
||||
} = this.props;
|
||||
const resultColor = resultColorMap[result];
|
||||
const expandIcon = detailsShowing ? faMinusSquare : faPlusSquare;
|
||||
|
@ -67,6 +68,7 @@ export default class Metric extends React.PureComponent {
|
|||
<TestFailures
|
||||
failures={failures}
|
||||
repo={repo}
|
||||
currentRepo={currentRepo}
|
||||
revision={revision}
|
||||
user={user}
|
||||
notify={notify}
|
||||
|
@ -90,6 +92,7 @@ export default class Metric extends React.PureComponent {
|
|||
|
||||
Metric.propTypes = {
|
||||
repo: PropTypes.string.isRequired,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
revision: PropTypes.string.isRequired,
|
||||
result: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
|
|
|
@ -28,7 +28,7 @@ class TestFailure extends React.PureComponent {
|
|||
};
|
||||
|
||||
retriggerJob = async job => {
|
||||
const { user, repo, notify } = this.props;
|
||||
const { user, notify, currentRepo } = this.props;
|
||||
|
||||
if (!user.isLoggedIn) {
|
||||
notify('Must be logged in to retrigger a job', 'danger', {
|
||||
|
@ -36,7 +36,7 @@ class TestFailure extends React.PureComponent {
|
|||
});
|
||||
return;
|
||||
}
|
||||
JobModel.retrigger([job], repo, notify);
|
||||
JobModel.retrigger([job], currentRepo, notify);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -180,6 +180,7 @@ TestFailure.propTypes = {
|
|||
key: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
repo: PropTypes.string.isRequired,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
revision: PropTypes.string.isRequired,
|
||||
notify: PropTypes.func.isRequired,
|
||||
|
|
|
@ -5,7 +5,7 @@ import ClassificationGroup from './ClassificationGroup';
|
|||
|
||||
export default class TestFailures extends React.PureComponent {
|
||||
render() {
|
||||
const { failures, repo, revision, user, notify } = this.props;
|
||||
const { failures, repo, revision, user, notify, currentRepo } = this.props;
|
||||
const { needInvestigation, intermittent } = failures;
|
||||
const needInvestigationLength = Object.keys(needInvestigation).length;
|
||||
|
||||
|
@ -15,6 +15,7 @@ export default class TestFailures extends React.PureComponent {
|
|||
group={needInvestigation}
|
||||
name="Need Investigation"
|
||||
repo={repo}
|
||||
currentRepo={currentRepo}
|
||||
revision={revision}
|
||||
className="mb-5"
|
||||
headerColor={needInvestigationLength ? 'danger' : 'secondary'}
|
||||
|
@ -26,6 +27,7 @@ export default class TestFailures extends React.PureComponent {
|
|||
group={intermittent}
|
||||
name="Known Intermittent"
|
||||
repo={repo}
|
||||
currentRepo={currentRepo}
|
||||
revision={revision}
|
||||
className="mb-5"
|
||||
headerColor="secondary"
|
||||
|
@ -42,6 +44,7 @@ TestFailures.propTypes = {
|
|||
failures: PropTypes.object.isRequired,
|
||||
user: PropTypes.object.isRequired,
|
||||
repo: PropTypes.string.isRequired,
|
||||
currentRepo: PropTypes.object.isRequired,
|
||||
revision: PropTypes.string.isRequired,
|
||||
notify: PropTypes.func.isRequired,
|
||||
};
|
||||
|
|
|
@ -9006,6 +9006,11 @@ taskcluster-lib-scopes@10.0.2:
|
|||
resolved "https://registry.yarnpkg.com/taskcluster-lib-scopes/-/taskcluster-lib-scopes-10.0.2.tgz#ec7df9c13ba187dfb9836623fe53e9290fa6770b"
|
||||
integrity sha512-imeywPQva/St/uykCxTq7QrP0Hlte3mSpV917kvdVqunrsHs0k3E90kdi9KdGyDRzncVeKbCjTZjyaDf7VndVg==
|
||||
|
||||
taskcluster-lib-urls@12.0.0:
|
||||
version "12.0.0"
|
||||
resolved "https://registry.yarnpkg.com/taskcluster-lib-urls/-/taskcluster-lib-urls-12.0.0.tgz#f56190eec9e9597d37a42ad0e7f461e8e0e6732b"
|
||||
integrity sha512-OrEFE0m3p/+mGsmIwjttLhSKg3io6MpJLhYtPNjVSZA9Ix8Y5tprN3vM6a3MjWt5asPF6AKZsfT43cgpGwJB0g==
|
||||
|
||||
taskcluster-lib-urls@^10.0.0:
|
||||
version "10.1.1"
|
||||
resolved "https://registry.yarnpkg.com/taskcluster-lib-urls/-/taskcluster-lib-urls-10.1.1.tgz#67d5b9449b947e5234eafdd15c46267dde29bf74"
|
||||
|
|
Загрузка…
Ссылка в новой задаче