@elisra-devops/docgen-data-provider 1.130.0 → 1.132.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/modules/GitDataProvider.js +77 -30
- package/bin/modules/GitDataProvider.js.map +1 -1
- package/bin/modules/JfrogDataProvider.js +11 -1
- package/bin/modules/JfrogDataProvider.js.map +1 -1
- package/bin/modules/TicketsDataProvider.d.ts +16 -0
- package/bin/modules/TicketsDataProvider.js +34 -1
- package/bin/modules/TicketsDataProvider.js.map +1 -1
- package/bin/tests/modules/JfrogDataProvider.test.js +1 -1
- package/bin/tests/modules/JfrogDataProvider.test.js.map +1 -1
- package/bin/tests/modules/gitDataProvider.test.js +22 -24
- package/bin/tests/modules/gitDataProvider.test.js.map +1 -1
- package/package.json +1 -1
- package/src/modules/GitDataProvider.ts +79 -39
- package/src/modules/JfrogDataProvider.ts +12 -1
- package/src/modules/TicketsDataProvider.ts +32 -1
- package/src/tests/modules/JfrogDataProvider.test.ts +1 -1
- package/src/tests/modules/gitDataProvider.test.ts +27 -25
|
@@ -14,8 +14,11 @@ export default class JfrogDataProvider {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
async getServiceConnectionUrlByConnectionId(teamProject: string, connectionId: string) {
|
|
17
|
-
let url = `${this.orgUrl}${teamProject}/_apis/serviceendpoint/endpoints/${connectionId}?api-version=
|
|
17
|
+
let url = `${this.orgUrl}${teamProject}/_apis/serviceendpoint/endpoints/${connectionId}?api-version=7.1`;
|
|
18
18
|
const serviceConnectionResponse = await TFSServices.getItemContent(url, this.tfsToken);
|
|
19
|
+
if (!serviceConnectionResponse?.url) {
|
|
20
|
+
throw new Error(`Service connection ${connectionId} returned no URL — identity may lack service-endpoint read permission`);
|
|
21
|
+
}
|
|
19
22
|
logger.debug(`service connection url ${JSON.stringify(serviceConnectionResponse.url)}`);
|
|
20
23
|
return serviceConnectionResponse.url;
|
|
21
24
|
}
|
|
@@ -23,6 +26,11 @@ export default class JfrogDataProvider {
|
|
|
23
26
|
async getCiDataFromJfrog(jfrogUrl: string, buildName: string, buildVersion: string): Promise<string> {
|
|
24
27
|
let jfrogHeader: any = {};
|
|
25
28
|
try {
|
|
29
|
+
if (!jfrogUrl) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`JFrog service connection URL is unresolved for build "${buildName}" — the caller identity may lack service-endpoint read permission`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
26
34
|
if (this.jfrogToken !== '') {
|
|
27
35
|
jfrogHeader['Authorization'] = `Bearer ${this.jfrogToken}`;
|
|
28
36
|
}
|
|
@@ -42,6 +50,9 @@ export default class JfrogDataProvider {
|
|
|
42
50
|
this.jfrogToken !== ''
|
|
43
51
|
? await TFSServices.getJfrogRequest(getCiRequestUrl, jfrogHeader)
|
|
44
52
|
: await TFSServices.getJfrogRequest(getCiRequestUrl);
|
|
53
|
+
if (!getCiResponse?.buildInfo?.url) {
|
|
54
|
+
throw new Error(`JFrog response for build "${buildName}${buildVersion}" is missing buildInfo.url`);
|
|
55
|
+
}
|
|
45
56
|
logger.debug(`CI Url from JFROG: ${getCiResponse.buildInfo.url}`);
|
|
46
57
|
return getCiResponse.buildInfo.url;
|
|
47
58
|
} catch (err: any) {
|
|
@@ -514,6 +514,37 @@ export default class TicketsDataProvider {
|
|
|
514
514
|
}
|
|
515
515
|
}
|
|
516
516
|
|
|
517
|
+
/**
|
|
518
|
+
* Returns the project's work item type names and the complete set of valid state names.
|
|
519
|
+
* Used to validate SVD work-item filter options before generation so callers receive
|
|
520
|
+
* a descriptive error instead of a silent zero-result document.
|
|
521
|
+
*
|
|
522
|
+
* Types come from GET _apis/wit/workitemtypes (value[].name).
|
|
523
|
+
* States are extracted from the transitions map keys on the same response — each key
|
|
524
|
+
* is a state name — avoiding N extra per-type state calls.
|
|
525
|
+
*
|
|
526
|
+
* @param project - The project name.
|
|
527
|
+
* @returns An object with `types` (work item type names) and `states` (all state names across types).
|
|
528
|
+
*/
|
|
529
|
+
async GetWorkItemTypeStates(project: string): Promise<{ types: string[]; states: string[] }> {
|
|
530
|
+
try {
|
|
531
|
+
const url = `${this.orgUrl}${project}/_apis/wit/workitemtypes`;
|
|
532
|
+
const { value: workItemTypes } = await TFSServices.getItemContent(url, this.token);
|
|
533
|
+
const types: string[] = (workItemTypes ?? []).map((t: any) => t?.name).filter(Boolean);
|
|
534
|
+
// transitions is a map whose keys are state names (e.g. { "Active": [...], "Closed": [...] })
|
|
535
|
+
const stateSet = new Set<string>();
|
|
536
|
+
for (const t of workItemTypes ?? []) {
|
|
537
|
+
for (const stateName of Object.keys(t?.transitions ?? {})) {
|
|
538
|
+
if (stateName) stateSet.add(stateName);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return { types, states: Array.from(stateSet) };
|
|
542
|
+
} catch (err: any) {
|
|
543
|
+
logger.error(`Error fetching work item type states: ${err.message}`);
|
|
544
|
+
throw err;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
517
548
|
/**
|
|
518
549
|
* fetches linked queries
|
|
519
550
|
* @param queries fetched queries
|
|
@@ -2334,7 +2365,7 @@ export default class TicketsDataProvider {
|
|
|
2334
2365
|
const postBatch = (currentIds: any[]) =>
|
|
2335
2366
|
this.withHistoricalApiVersionFallback('populate-workitems-batch', (apiVersion) =>
|
|
2336
2367
|
TFSServices.getItemContent(this.appendApiVersion(baseUrl, apiVersion), this.token, 'post', {
|
|
2337
|
-
$expand: '
|
|
2368
|
+
$expand: 'All',
|
|
2338
2369
|
ids: currentIds,
|
|
2339
2370
|
}),
|
|
2340
2371
|
).then(({ result }) => result);
|
|
@@ -33,7 +33,7 @@ describe('JfrogDataProvider', () => {
|
|
|
33
33
|
|
|
34
34
|
// Assert
|
|
35
35
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
36
|
-
`${mockOrgUrl}${mockTeamProject}/_apis/serviceendpoint/endpoints/${mockConnectionId}?api-version=
|
|
36
|
+
`${mockOrgUrl}${mockTeamProject}/_apis/serviceendpoint/endpoints/${mockConnectionId}?api-version=7.1`,
|
|
37
37
|
mockTfsToken
|
|
38
38
|
);
|
|
39
39
|
expect(logger.debug).toHaveBeenCalledWith(`service connection url "${mockResponse.url}"`);
|
|
@@ -1129,8 +1129,8 @@ describe('GitDataProvider - GetItemsInCommitRange', () => {
|
|
|
1129
1129
|
const mockPRsResponse = { count: 0, value: [] };
|
|
1130
1130
|
|
|
1131
1131
|
(TFSServices.getItemContent as jest.Mock)
|
|
1132
|
-
.mockResolvedValueOnce(mockPopulatedWI)
|
|
1133
|
-
.mockResolvedValueOnce(mockPRsResponse);
|
|
1132
|
+
.mockResolvedValueOnce({ value: [mockPopulatedWI] }) // batch POST for work items
|
|
1133
|
+
.mockResolvedValueOnce(mockPRsResponse); // GetPullRequestsLinkedItemsInCommitRange (default: includePullRequestWorkItems=true)
|
|
1134
1134
|
|
|
1135
1135
|
// Act
|
|
1136
1136
|
const result = await gitDataProvider.GetItemsInCommitRange(projectId, repoId, commitRange, null, false);
|
|
@@ -1248,7 +1248,7 @@ describe('GitDataProvider - getItemsForPipelineRange', () => {
|
|
|
1248
1248
|
|
|
1249
1249
|
(TFSServices.getItemContent as jest.Mock)
|
|
1250
1250
|
.mockResolvedValueOnce(mockRepoData)
|
|
1251
|
-
.mockResolvedValueOnce(mockPopulatedWI);
|
|
1251
|
+
.mockResolvedValueOnce({ value: [mockPopulatedWI] }); // batch POST for work items
|
|
1252
1252
|
|
|
1253
1253
|
// Act
|
|
1254
1254
|
const result = await gitDataProvider.getItemsForPipelineRange(
|
|
@@ -1320,8 +1320,7 @@ describe('GitDataProvider - getItemsForPipelineRange', () => {
|
|
|
1320
1320
|
|
|
1321
1321
|
(TFSServices.getItemContent as jest.Mock)
|
|
1322
1322
|
.mockResolvedValueOnce(mockRepoData)
|
|
1323
|
-
.mockResolvedValueOnce(mockPopulatedWI)
|
|
1324
|
-
.mockResolvedValueOnce(mockPopulatedWI);
|
|
1323
|
+
.mockResolvedValueOnce({ value: [mockPopulatedWI] }); // single batch POST (WI id=1 deduped)
|
|
1325
1324
|
|
|
1326
1325
|
// Act
|
|
1327
1326
|
const result = await gitDataProvider.getItemsForPipelineRange(
|
|
@@ -1361,8 +1360,8 @@ describe('GitDataProvider - getItemsForPipelineRange', () => {
|
|
|
1361
1360
|
const mockPopulatedWI = { id: 42, fields: { 'System.Title': 'Cross-project WI' } };
|
|
1362
1361
|
|
|
1363
1362
|
(TFSServices.getItemContent as jest.Mock)
|
|
1364
|
-
.mockResolvedValueOnce(mockRepoDataNoCrossLink)
|
|
1365
|
-
.mockResolvedValueOnce(mockPopulatedWI);
|
|
1363
|
+
.mockResolvedValueOnce(mockRepoDataNoCrossLink) // repo metadata call
|
|
1364
|
+
.mockResolvedValueOnce({ value: [mockPopulatedWI] }); // batch POST for work items
|
|
1366
1365
|
|
|
1367
1366
|
const result = await gitDataProvider.getItemsForPipelineRange(
|
|
1368
1367
|
pipelineTeamProject,
|
|
@@ -1373,10 +1372,12 @@ describe('GitDataProvider - getItemsForPipelineRange', () => {
|
|
|
1373
1372
|
|
|
1374
1373
|
expect(result.commitChangesArray).toHaveLength(1);
|
|
1375
1374
|
expect(result.commitChangesArray[0].workItem.id).toBe(42);
|
|
1376
|
-
//
|
|
1375
|
+
// batch POST URL contains the repo's projectId (cross-project-id)
|
|
1377
1376
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
1378
1377
|
expect.stringContaining('cross-project-id'),
|
|
1379
|
-
expect.any(String)
|
|
1378
|
+
expect.any(String),
|
|
1379
|
+
'post',
|
|
1380
|
+
expect.objectContaining({ ids: expect.any(Array) })
|
|
1380
1381
|
);
|
|
1381
1382
|
});
|
|
1382
1383
|
|
|
@@ -1401,7 +1402,7 @@ describe('GitDataProvider - getItemsForPipelineRange', () => {
|
|
|
1401
1402
|
|
|
1402
1403
|
(TFSServices.getItemContent as jest.Mock)
|
|
1403
1404
|
.mockResolvedValueOnce(mockRepoDataEmpty)
|
|
1404
|
-
.mockResolvedValueOnce(mockPopulatedWI);
|
|
1405
|
+
.mockResolvedValueOnce({ value: [mockPopulatedWI] }); // batch POST for work items
|
|
1405
1406
|
|
|
1406
1407
|
const result = await gitDataProvider.getItemsForPipelineRange(
|
|
1407
1408
|
pipelineTeamProject,
|
|
@@ -1412,10 +1413,12 @@ describe('GitDataProvider - getItemsForPipelineRange', () => {
|
|
|
1412
1413
|
|
|
1413
1414
|
expect(result.commitChangesArray).toHaveLength(1);
|
|
1414
1415
|
expect(result.commitChangesArray[0].workItem.id).toBe(99);
|
|
1415
|
-
//
|
|
1416
|
+
// batch POST URL contains the fallback teamProject
|
|
1416
1417
|
expect(TFSServices.getItemContent).toHaveBeenCalledWith(
|
|
1417
1418
|
expect.stringContaining(pipelineTeamProject),
|
|
1418
|
-
expect.any(String)
|
|
1419
|
+
expect.any(String),
|
|
1420
|
+
'post',
|
|
1421
|
+
expect.objectContaining({ ids: expect.any(Array) })
|
|
1419
1422
|
);
|
|
1420
1423
|
expect(logger.warn).toHaveBeenCalledWith(
|
|
1421
1424
|
expect.stringContaining(`falling back to pipeline teamProject=${pipelineTeamProject}`)
|
|
@@ -1774,9 +1777,9 @@ describe('GitDataProvider - createLinkedRelatedItemsForSVD (via GetItemsInCommit
|
|
|
1774
1777
|
const mockPRsResponse = { count: 0, value: [] };
|
|
1775
1778
|
|
|
1776
1779
|
(TFSServices.getItemContent as jest.Mock)
|
|
1777
|
-
.mockResolvedValueOnce(mockPopulatedWI)
|
|
1778
|
-
.mockResolvedValueOnce(mockRelatedWI)
|
|
1779
|
-
.mockResolvedValueOnce(mockPRsResponse);
|
|
1780
|
+
.mockResolvedValueOnce({ value: [mockPopulatedWI] }) // batch POST for work items
|
|
1781
|
+
.mockResolvedValueOnce(mockRelatedWI) // GetWorkItemByUrl (linked relation)
|
|
1782
|
+
.mockResolvedValueOnce(mockPRsResponse); // GetPullRequestsLinkedItemsInCommitRange
|
|
1780
1783
|
|
|
1781
1784
|
// Act
|
|
1782
1785
|
const result = await gitDataProvider.GetItemsInCommitRange(
|
|
@@ -1826,8 +1829,8 @@ describe('GitDataProvider - createLinkedRelatedItemsForSVD (via GetItemsInCommit
|
|
|
1826
1829
|
const mockPRsResponse = { count: 0, value: [] };
|
|
1827
1830
|
|
|
1828
1831
|
(TFSServices.getItemContent as jest.Mock)
|
|
1829
|
-
.mockResolvedValueOnce(mockPopulatedWI)
|
|
1830
|
-
.mockResolvedValueOnce(mockPRsResponse);
|
|
1832
|
+
.mockResolvedValueOnce({ value: [mockPopulatedWI] }) // batch POST for work items
|
|
1833
|
+
.mockResolvedValueOnce(mockPRsResponse); // GetPullRequestsLinkedItemsInCommitRange
|
|
1831
1834
|
|
|
1832
1835
|
// Act
|
|
1833
1836
|
const result = await gitDataProvider.GetItemsInCommitRange(
|
|
@@ -1877,8 +1880,8 @@ describe('GitDataProvider - createLinkedRelatedItemsForSVD (via GetItemsInCommit
|
|
|
1877
1880
|
const mockPRsResponse = { count: 0, value: [] };
|
|
1878
1881
|
|
|
1879
1882
|
(TFSServices.getItemContent as jest.Mock)
|
|
1880
|
-
.mockResolvedValueOnce(mockPopulatedWI)
|
|
1881
|
-
.mockResolvedValueOnce(mockPRsResponse);
|
|
1883
|
+
.mockResolvedValueOnce({ value: [mockPopulatedWI] }) // batch POST for work items
|
|
1884
|
+
.mockResolvedValueOnce(mockPRsResponse); // GetPullRequestsLinkedItemsInCommitRange
|
|
1882
1885
|
|
|
1883
1886
|
// Act
|
|
1884
1887
|
const result = await gitDataProvider.GetItemsInCommitRange(
|
|
@@ -1936,9 +1939,9 @@ describe('GitDataProvider - createLinkedRelatedItemsForSVD (via GetItemsInCommit
|
|
|
1936
1939
|
const mockPRsResponse = { count: 0, value: [] };
|
|
1937
1940
|
|
|
1938
1941
|
(TFSServices.getItemContent as jest.Mock)
|
|
1939
|
-
.mockResolvedValueOnce(mockPopulatedWI)
|
|
1940
|
-
.mockResolvedValueOnce(mockRelatedWI)
|
|
1941
|
-
.mockResolvedValueOnce(mockPRsResponse);
|
|
1942
|
+
.mockResolvedValueOnce({ value: [mockPopulatedWI] }) // batch POST for work items
|
|
1943
|
+
.mockResolvedValueOnce(mockRelatedWI) // GetWorkItemByUrl (linked relation)
|
|
1944
|
+
.mockResolvedValueOnce(mockPRsResponse); // GetPullRequestsLinkedItemsInCommitRange
|
|
1942
1945
|
|
|
1943
1946
|
// Act
|
|
1944
1947
|
const result = await gitDataProvider.GetItemsInCommitRange(
|
|
@@ -2105,9 +2108,8 @@ describe('GitDataProvider - duplicate work item removal', () => {
|
|
|
2105
2108
|
const mockPRsResponse = { count: 0, value: [] };
|
|
2106
2109
|
|
|
2107
2110
|
(TFSServices.getItemContent as jest.Mock)
|
|
2108
|
-
.mockResolvedValueOnce(mockPopulatedWI)
|
|
2109
|
-
.mockResolvedValueOnce(
|
|
2110
|
-
.mockResolvedValueOnce(mockPRsResponse);
|
|
2111
|
+
.mockResolvedValueOnce({ value: [mockPopulatedWI] }) // batch POST (WI id=1 deduped from 2 commits)
|
|
2112
|
+
.mockResolvedValueOnce(mockPRsResponse); // GetPullRequestsLinkedItemsInCommitRange
|
|
2111
2113
|
|
|
2112
2114
|
// Act
|
|
2113
2115
|
const result = await gitDataProvider.GetItemsInCommitRange(projectId, repoId, commitRange, null, false);
|