@elisra-devops/docgen-data-provider 1.5.0 → 1.6.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/helpers/tfs.js +1 -1
- package/bin/helpers/tfs.js.map +1 -1
- package/bin/models/tfs-data.d.ts +43 -0
- package/bin/modules/GitDataProvider.d.ts +4 -1
- package/bin/modules/GitDataProvider.js +118 -23
- package/bin/modules/GitDataProvider.js.map +1 -1
- package/bin/modules/PipelinesDataProvider.d.ts +5 -0
- package/bin/modules/PipelinesDataProvider.js +90 -14
- package/bin/modules/PipelinesDataProvider.js.map +1 -1
- package/package.json +1 -1
- package/src/helpers/tfs.ts +1 -1
- package/src/models/tfs-data.ts +51 -0
- package/src/modules/GitDataProvider.ts +183 -220
- package/src/modules/PipelinesDataProvider.ts +123 -76
package/src/helpers/tfs.ts
CHANGED
|
@@ -62,7 +62,7 @@ export class TFSServices {
|
|
|
62
62
|
pat: string,
|
|
63
63
|
requestMethod: string = 'post',
|
|
64
64
|
data: any,
|
|
65
|
-
customHeaders: any = {}
|
|
65
|
+
customHeaders: any = { headers: { 'Content-Type': 'application/json' } }
|
|
66
66
|
): Promise<any> {
|
|
67
67
|
let config: any = {
|
|
68
68
|
headers: customHeaders,
|
package/src/models/tfs-data.ts
CHANGED
|
@@ -171,3 +171,54 @@ export class TestSteps {
|
|
|
171
171
|
expected: string;
|
|
172
172
|
isSharedStepTitle: boolean;
|
|
173
173
|
}
|
|
174
|
+
|
|
175
|
+
export interface GitVersionDescriptor {
|
|
176
|
+
version: string;
|
|
177
|
+
versionType: string;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export interface Pipeline {
|
|
181
|
+
id: number;
|
|
182
|
+
revision: number;
|
|
183
|
+
name: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface Repository {
|
|
187
|
+
id: string;
|
|
188
|
+
name: string;
|
|
189
|
+
url: string;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface ResourceRepository {
|
|
193
|
+
repoName: string;
|
|
194
|
+
repoSha1: string;
|
|
195
|
+
url: string;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export interface Link {
|
|
199
|
+
href: string;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export interface PipelineLinks {
|
|
203
|
+
self: Link;
|
|
204
|
+
web: Link;
|
|
205
|
+
'pipeline.web': Link;
|
|
206
|
+
pipeline: Link;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export interface PipelineResources {
|
|
210
|
+
repositories: any;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface PipelineRun {
|
|
214
|
+
_links: PipelineLinks;
|
|
215
|
+
pipeline: Pipeline;
|
|
216
|
+
state: string;
|
|
217
|
+
result: string;
|
|
218
|
+
createdDate: string;
|
|
219
|
+
finishedDate: string;
|
|
220
|
+
url: string;
|
|
221
|
+
resources: PipelineResources;
|
|
222
|
+
id: number;
|
|
223
|
+
name: string;
|
|
224
|
+
}
|
|
@@ -1,60 +1,45 @@
|
|
|
1
|
-
import { TFSServices } from
|
|
2
|
-
import TicketsDataProvider from
|
|
3
|
-
import logger from
|
|
1
|
+
import { TFSServices } from '../helpers/tfs';
|
|
2
|
+
import TicketsDataProvider from './TicketsDataProvider';
|
|
3
|
+
import logger from '../utils/logger';
|
|
4
|
+
import { GitVersionDescriptor } from '../models/tfs-data';
|
|
4
5
|
export default class GitDataProvider {
|
|
5
|
-
orgUrl: string =
|
|
6
|
-
token: string =
|
|
6
|
+
orgUrl: string = '';
|
|
7
|
+
token: string = '';
|
|
7
8
|
ticketsDataProvider: TicketsDataProvider;
|
|
8
9
|
|
|
9
10
|
constructor(orgUrl: string, token: string) {
|
|
10
11
|
this.orgUrl = orgUrl;
|
|
11
12
|
this.token = token;
|
|
12
|
-
this.ticketsDataProvider = new TicketsDataProvider(
|
|
13
|
-
this.orgUrl,
|
|
14
|
-
this.token,
|
|
15
|
-
);
|
|
13
|
+
this.ticketsDataProvider = new TicketsDataProvider(this.orgUrl, this.token);
|
|
16
14
|
}
|
|
17
|
-
async GetTeamProjectGitReposList(
|
|
18
|
-
teamProject: string
|
|
19
|
-
) {
|
|
15
|
+
async GetTeamProjectGitReposList(teamProject: string) {
|
|
20
16
|
logger.debug(`fetching repos list for team project - ${teamProject}`);
|
|
21
17
|
let url = `${this.orgUrl}/${teamProject}/_apis/git/repositories`;
|
|
22
|
-
return TFSServices.getItemContent(url, this.token,
|
|
18
|
+
return TFSServices.getItemContent(url, this.token, 'get');
|
|
23
19
|
} //GetGitRepoFromPrId
|
|
24
20
|
|
|
25
|
-
async GetGitRepoFromRepoId(
|
|
26
|
-
repoId: string
|
|
27
|
-
) {
|
|
21
|
+
async GetGitRepoFromRepoId(repoId: string) {
|
|
28
22
|
logger.debug(`fetching repo data by id - ${repoId}`);
|
|
29
23
|
let url = `${this.orgUrl}_apis/git/repositories/${repoId}`;
|
|
30
|
-
return TFSServices.getItemContent(url, this.token,
|
|
24
|
+
return TFSServices.getItemContent(url, this.token, 'get');
|
|
31
25
|
} //GetGitRepoFromPrId
|
|
32
26
|
|
|
33
|
-
async GetJsonFileFromGitRepo(
|
|
34
|
-
projectName: string,
|
|
35
|
-
repoName: string,
|
|
36
|
-
filePath: string
|
|
37
|
-
) {
|
|
27
|
+
async GetJsonFileFromGitRepo(projectName: string, repoName: string, filePath: string) {
|
|
38
28
|
let url = `${this.orgUrl}${projectName}/_apis/git/repositories/${repoName}/items?path=${filePath}&includeContent=true`;
|
|
39
|
-
let res = await TFSServices.getItemContent(url, this.token,
|
|
29
|
+
let res = await TFSServices.getItemContent(url, this.token, 'get');
|
|
40
30
|
let jsonObject = JSON.parse(res.content);
|
|
41
31
|
return jsonObject;
|
|
42
32
|
} //GetJsonFileFromGitRepo
|
|
43
33
|
|
|
44
|
-
async GetGitRepoFromPrId(
|
|
45
|
-
pullRequestId: number
|
|
46
|
-
) {
|
|
34
|
+
async GetGitRepoFromPrId(pullRequestId: number) {
|
|
47
35
|
let url = `${this.orgUrl}_apis/git/pullrequests/${pullRequestId}`;
|
|
48
|
-
let res = await TFSServices.getItemContent(url, this.token,
|
|
36
|
+
let res = await TFSServices.getItemContent(url, this.token, 'get');
|
|
49
37
|
return res;
|
|
50
38
|
} //GetGitRepoFromPrId
|
|
51
39
|
|
|
52
|
-
async GetPullRequestCommits(
|
|
53
|
-
repositoryId: string,
|
|
54
|
-
pullRequestId: number
|
|
55
|
-
) {
|
|
40
|
+
async GetPullRequestCommits(repositoryId: string, pullRequestId: number) {
|
|
56
41
|
let url = `${this.orgUrl}_apis/git/repositories/${repositoryId}/pullRequests/${pullRequestId}/commits`;
|
|
57
|
-
let res = await TFSServices.getItemContent(url, this.token,
|
|
42
|
+
let res = await TFSServices.getItemContent(url, this.token, 'get');
|
|
58
43
|
return res;
|
|
59
44
|
} //GetGitRepoFromPrId
|
|
60
45
|
|
|
@@ -68,14 +53,8 @@ export default class GitDataProvider {
|
|
|
68
53
|
//get all pr's in git repo
|
|
69
54
|
let url = `${this.orgUrl}${projectId}/_apis/git/repositories/${repositoryId}/pullrequests?status=completed&includeLinks=true&$top=2000}`;
|
|
70
55
|
logger.debug(`request url: ${url}`);
|
|
71
|
-
let pullRequestsArray = await TFSServices.getItemContent(
|
|
72
|
-
|
|
73
|
-
this.token,
|
|
74
|
-
"get"
|
|
75
|
-
);
|
|
76
|
-
logger.info(
|
|
77
|
-
`got ${pullRequestsArray.count} pullrequests for repo: ${repositoryId}`
|
|
78
|
-
);
|
|
56
|
+
let pullRequestsArray = await TFSServices.getItemContent(url, this.token, 'get');
|
|
57
|
+
logger.info(`got ${pullRequestsArray.count} pullrequests for repo: ${repositoryId}`);
|
|
79
58
|
//iterate commit list to filter relavant pullrequests
|
|
80
59
|
pullRequestsArray.value.forEach((pr: any) => {
|
|
81
60
|
commitRangeArray.value.forEach((commit: any) => {
|
|
@@ -95,20 +74,11 @@ export default class GitDataProvider {
|
|
|
95
74
|
if (pr._links.workItems.href) {
|
|
96
75
|
//get workitems linked to pr
|
|
97
76
|
let url: string = pr._links.workItems.href;
|
|
98
|
-
linkedItems = await TFSServices.getItemContent(
|
|
99
|
-
|
|
100
|
-
this.token,
|
|
101
|
-
"get"
|
|
102
|
-
);
|
|
103
|
-
logger.info(
|
|
104
|
-
`got ${linkedItems.count} items linked to pr ${pr.pullRequestId}`
|
|
105
|
-
);
|
|
77
|
+
linkedItems = await TFSServices.getItemContent(url, this.token, 'get');
|
|
78
|
+
logger.info(`got ${linkedItems.count} items linked to pr ${pr.pullRequestId}`);
|
|
106
79
|
await Promise.all(
|
|
107
80
|
linkedItems.value.map(async (item: any) => {
|
|
108
|
-
let populatedItem = await this.ticketsDataProvider.GetWorkItem(
|
|
109
|
-
projectId,
|
|
110
|
-
item.id
|
|
111
|
-
);
|
|
81
|
+
let populatedItem = await this.ticketsDataProvider.GetWorkItem(projectId, item.id);
|
|
112
82
|
let changeSet: any = {
|
|
113
83
|
workItem: populatedItem,
|
|
114
84
|
pullrequest: pr,
|
|
@@ -125,11 +95,7 @@ export default class GitDataProvider {
|
|
|
125
95
|
return ChangeSetsArray;
|
|
126
96
|
} //GetPullRequestsInCommitRange
|
|
127
97
|
|
|
128
|
-
async GetItemsInCommitRange(
|
|
129
|
-
projectId: string,
|
|
130
|
-
repositoryId: string,
|
|
131
|
-
commitRange:any
|
|
132
|
-
) {
|
|
98
|
+
async GetItemsInCommitRange(projectId: string, repositoryId: string, commitRange: any) {
|
|
133
99
|
//get all items linked to commits
|
|
134
100
|
let res: any = [];
|
|
135
101
|
let commitChangesArray: any = [];
|
|
@@ -137,33 +103,28 @@ export default class GitDataProvider {
|
|
|
137
103
|
for (const commit of commitRange.value) {
|
|
138
104
|
if (commit.workItems) {
|
|
139
105
|
for (const wi of commit.workItems) {
|
|
140
|
-
let populatedItem = await this.ticketsDataProvider.GetWorkItem(
|
|
141
|
-
projectId,
|
|
142
|
-
wi.id
|
|
143
|
-
);
|
|
106
|
+
let populatedItem = await this.ticketsDataProvider.GetWorkItem(projectId, wi.id);
|
|
144
107
|
let changeSet: any = { workItem: populatedItem, commit: commit };
|
|
145
108
|
commitChangesArray.push(changeSet);
|
|
146
109
|
}
|
|
147
110
|
}
|
|
148
111
|
}
|
|
149
112
|
//get all items and pr data from pr's in commit range - using the above function
|
|
150
|
-
let pullRequestsChangesArray =
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
);
|
|
113
|
+
let pullRequestsChangesArray = await this.GetPullRequestsLinkedItemsInCommitRange(
|
|
114
|
+
projectId,
|
|
115
|
+
repositoryId,
|
|
116
|
+
commitRange
|
|
117
|
+
);
|
|
156
118
|
//merge commit links with pr links
|
|
157
119
|
logger.info(`got ${pullRequestsChangesArray.length} items from pr's and`);
|
|
158
120
|
res = [...commitChangesArray, ...pullRequestsChangesArray];
|
|
159
|
-
let workItemIds
|
|
121
|
+
let workItemIds: any = [];
|
|
160
122
|
for (let index = 0; index < res.length; index++) {
|
|
161
|
-
if (workItemIds.includes(res[index].workItem.id)){
|
|
162
|
-
res.splice(index, 1);
|
|
123
|
+
if (workItemIds.includes(res[index].workItem.id)) {
|
|
124
|
+
res.splice(index, 1);
|
|
163
125
|
index--;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
workItemIds.push(res[index].workItem.id)
|
|
126
|
+
} else {
|
|
127
|
+
workItemIds.push(res[index].workItem.id);
|
|
167
128
|
}
|
|
168
129
|
}
|
|
169
130
|
return res;
|
|
@@ -175,29 +136,23 @@ export default class GitDataProvider {
|
|
|
175
136
|
commitRangeArray: any
|
|
176
137
|
) {
|
|
177
138
|
let pullRequestsFilteredArray: any[] = [];
|
|
178
|
-
|
|
139
|
+
|
|
179
140
|
// Extract the organization name from orgUrl
|
|
180
141
|
let orgName = this.orgUrl.split('/').filter(Boolean).pop();
|
|
181
|
-
|
|
142
|
+
|
|
182
143
|
// Get all PRs in the git repo
|
|
183
144
|
let url = `${this.orgUrl}${projectId}/_apis/git/repositories/${repositoryId}/pullrequests?status=completed&includeLinks=true&$top=2000}`;
|
|
184
145
|
logger.debug(`request url: ${url}`);
|
|
185
|
-
let pullRequestsArray = await TFSServices.getItemContent(
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
"get"
|
|
189
|
-
);
|
|
190
|
-
logger.info(
|
|
191
|
-
`got ${pullRequestsArray.count} pullrequests for repo: ${repositoryId}`
|
|
192
|
-
);
|
|
193
|
-
|
|
146
|
+
let pullRequestsArray = await TFSServices.getItemContent(url, this.token, 'get');
|
|
147
|
+
logger.info(`got ${pullRequestsArray.count} pullrequests for repo: ${repositoryId}`);
|
|
148
|
+
|
|
194
149
|
// Iterate commit list to filter relevant pull requests
|
|
195
150
|
pullRequestsArray.value.forEach((pr: any) => {
|
|
196
151
|
commitRangeArray.value.forEach((commit: any) => {
|
|
197
152
|
if (pr.lastMergeCommit.commitId == commit.commitId) {
|
|
198
153
|
// Construct the pull request URL
|
|
199
154
|
const prUrl = `https://dev.azure.com/${orgName}/${projectId}/_git/${repositoryId}/pullrequest/${pr.pullRequestId}`;
|
|
200
|
-
|
|
155
|
+
|
|
201
156
|
// Extract only the desired properties from the PR
|
|
202
157
|
const prFilteredData = {
|
|
203
158
|
pullRequestId: pr.pullRequestId,
|
|
@@ -206,7 +161,7 @@ export default class GitDataProvider {
|
|
|
206
161
|
closedDate: pr.closedDate,
|
|
207
162
|
title: pr.title,
|
|
208
163
|
description: pr.description,
|
|
209
|
-
url: prUrl
|
|
164
|
+
url: prUrl, // Use the constructed URL here
|
|
210
165
|
};
|
|
211
166
|
pullRequestsFilteredArray.push(prFilteredData);
|
|
212
167
|
}
|
|
@@ -215,46 +170,30 @@ export default class GitDataProvider {
|
|
|
215
170
|
logger.info(
|
|
216
171
|
`filtered in commit range ${pullRequestsFilteredArray.length} pullrequests for repo: ${repositoryId}`
|
|
217
172
|
);
|
|
218
|
-
|
|
173
|
+
|
|
219
174
|
return pullRequestsFilteredArray;
|
|
220
175
|
} // GetPullRequestsInCommitRangeWithoutLinkedItems
|
|
221
|
-
|
|
222
176
|
|
|
223
|
-
async GetCommitByCommitId(
|
|
224
|
-
projectId: string,
|
|
225
|
-
repositoryId: string,
|
|
226
|
-
commitSha: string
|
|
227
|
-
) {
|
|
177
|
+
async GetCommitByCommitId(projectId: string, repositoryId: string, commitSha: string) {
|
|
228
178
|
let url = `${this.orgUrl}${projectId}/_apis/git/repositories/${repositoryId}/commits/${commitSha}`;
|
|
229
|
-
return TFSServices.getItemContent(url, this.token,
|
|
179
|
+
return TFSServices.getItemContent(url, this.token, 'get');
|
|
230
180
|
}
|
|
231
181
|
|
|
232
|
-
async GetCommitForPipeline(
|
|
233
|
-
projectId: string,
|
|
234
|
-
buildId: number
|
|
235
|
-
) {
|
|
182
|
+
async GetCommitForPipeline(projectId: string, buildId: number) {
|
|
236
183
|
let url = `${this.orgUrl}${projectId}/_apis/build/builds/${buildId}`;
|
|
237
|
-
let res = await TFSServices.getItemContent(url, this.token,
|
|
184
|
+
let res = await TFSServices.getItemContent(url, this.token, 'get');
|
|
238
185
|
return res.sourceVersion;
|
|
239
186
|
} //GetCommitForPipeline
|
|
240
187
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
fromBuildId: number,
|
|
244
|
-
toBuildId: number
|
|
245
|
-
) {
|
|
188
|
+
//TODO: replace this....
|
|
189
|
+
async GetItemsForPipelinesRange(projectId: string, fromBuildId: number, toBuildId: number) {
|
|
246
190
|
let linkedItemsArray: any = [];
|
|
247
191
|
let url = `${this.orgUrl}${projectId}/_apis/build/workitems?fromBuildId=${fromBuildId}&toBuildId=${toBuildId}&$top=2000`;
|
|
248
|
-
let res = await TFSServices.getItemContent(url, this.token,
|
|
249
|
-
logger.info(
|
|
250
|
-
`recieved ${res.count} items in build range ${fromBuildId}-${toBuildId}`
|
|
251
|
-
);
|
|
192
|
+
let res = await TFSServices.getItemContent(url, this.token, 'get');
|
|
193
|
+
logger.info(`recieved ${res.count} items in build range ${fromBuildId}-${toBuildId}`);
|
|
252
194
|
await Promise.all(
|
|
253
195
|
res.value.map(async (wi: any) => {
|
|
254
|
-
let populatedItem = await this.ticketsDataProvider.GetWorkItem(
|
|
255
|
-
projectId,
|
|
256
|
-
wi.id
|
|
257
|
-
);
|
|
196
|
+
let populatedItem = await this.ticketsDataProvider.GetWorkItem(projectId, wi.id);
|
|
258
197
|
let changeSet: any = { workItem: populatedItem, build: toBuildId };
|
|
259
198
|
linkedItemsArray.push(changeSet);
|
|
260
199
|
})
|
|
@@ -262,6 +201,48 @@ export default class GitDataProvider {
|
|
|
262
201
|
return linkedItemsArray;
|
|
263
202
|
} //GetCommitForPipeline
|
|
264
203
|
|
|
204
|
+
async getItemsForPipelineRange(projectName: string, extendedCommits: any[], targetRepo: any) {
|
|
205
|
+
let commitChangesArray: any[] = [];
|
|
206
|
+
try {
|
|
207
|
+
if (extendedCommits?.length === 0) {
|
|
208
|
+
throw new Error('extended commits cannot be empty');
|
|
209
|
+
}
|
|
210
|
+
//First fetch the repo web url
|
|
211
|
+
if (targetRepo.url) {
|
|
212
|
+
const repoData = await TFSServices.getItemContent(targetRepo.url, this.token);
|
|
213
|
+
const repoWebUrl = repoData._links?.web.href;
|
|
214
|
+
if (repoWebUrl) {
|
|
215
|
+
targetRepo['url'] = repoWebUrl;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
//Then extend the commit information with the related WIs
|
|
219
|
+
for (const extendedCommit of extendedCommits) {
|
|
220
|
+
const { commit } = extendedCommit;
|
|
221
|
+
if (!commit.workItems) {
|
|
222
|
+
throw new Error(`commit ${commit.commitId} does not have work items`);
|
|
223
|
+
}
|
|
224
|
+
for (const wi of commit.workItems) {
|
|
225
|
+
const populatedWorkItem = await this.ticketsDataProvider.GetWorkItem(projectName, wi.id);
|
|
226
|
+
let changeSet: any = { workItem: populatedWorkItem, commit: commit, targetRepo };
|
|
227
|
+
commitChangesArray.push(changeSet);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
let workItemIds: any = [];
|
|
232
|
+
for (let index = 0; index < commitChangesArray.length; index++) {
|
|
233
|
+
if (workItemIds.includes(commitChangesArray[index].workItem.id)) {
|
|
234
|
+
commitChangesArray.splice(index, 1);
|
|
235
|
+
index--;
|
|
236
|
+
} else {
|
|
237
|
+
workItemIds.push(commitChangesArray[index].workItem.id);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
} catch (error: any) {
|
|
241
|
+
logger.error(error.message);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return commitChangesArray;
|
|
245
|
+
}
|
|
265
246
|
|
|
266
247
|
async GetCommitsInDateRange(
|
|
267
248
|
projectId: string,
|
|
@@ -270,116 +251,57 @@ export default class GitDataProvider {
|
|
|
270
251
|
toDate: string,
|
|
271
252
|
branchName?: string
|
|
272
253
|
) {
|
|
273
|
-
let url:string
|
|
254
|
+
let url: string;
|
|
274
255
|
if (typeof branchName !== 'undefined') {
|
|
275
256
|
url = `${this.orgUrl}${projectId}/_apis/git/repositories/${repositoryId}/commits?searchCriteria.fromDate=${fromDate}&searchCriteria.toDate=${toDate}&searchCriteria.includeWorkItems=true&searchCriteria.$top=2000&searchCriteria.itemVersion.version=${branchName}`;
|
|
276
|
-
}
|
|
277
|
-
else{
|
|
257
|
+
} else {
|
|
278
258
|
url = `${this.orgUrl}${projectId}/_apis/git/repositories/${repositoryId}/commits?searchCriteria.fromDate=${fromDate}&searchCriteria.toDate=${toDate}&searchCriteria.includeWorkItems=true&searchCriteria.$top=2000`;
|
|
279
259
|
}
|
|
280
|
-
return TFSServices.getItemContent(url, this.token,
|
|
260
|
+
return TFSServices.getItemContent(url, this.token, 'get');
|
|
281
261
|
} //GetCommitsInDateRange
|
|
282
262
|
|
|
283
|
-
async GetCommitsInCommitRange(
|
|
284
|
-
projectId: string,
|
|
285
|
-
repositoryId: string,
|
|
286
|
-
fromSha: string,
|
|
287
|
-
toSha: string
|
|
288
|
-
) {
|
|
263
|
+
async GetCommitsInCommitRange(projectId: string, repositoryId: string, fromSha: string, toSha: string) {
|
|
289
264
|
let url = `${this.orgUrl}${projectId}/_apis/git/repositories/${repositoryId}/commits?searchCriteria.fromCommitId=${fromSha}&searchCriteria.toCommitId=${toSha}&searchCriteria.includeWorkItems=true&searchCriteria.$top=2000`;
|
|
290
|
-
return TFSServices.getItemContent(url, this.token,
|
|
265
|
+
return TFSServices.getItemContent(url, this.token, 'get');
|
|
291
266
|
} //GetCommitsInCommitRange doesen't work!!!
|
|
292
|
-
|
|
293
|
-
async CreatePullRequestComment(
|
|
294
|
-
projectName: string,
|
|
295
|
-
repoID: string,
|
|
296
|
-
pullRequestID: number,
|
|
297
|
-
threads: any
|
|
298
|
-
) {
|
|
267
|
+
|
|
268
|
+
async CreatePullRequestComment(projectName: string, repoID: string, pullRequestID: number, threads: any) {
|
|
299
269
|
let url: string = `${this.orgUrl}${projectName}/_apis/git/repositories/${repoID}/pullRequests/${pullRequestID}/threads?api-version=5.0`;
|
|
300
|
-
let res: any = await TFSServices.getItemContent(
|
|
301
|
-
url,
|
|
302
|
-
this.token,
|
|
303
|
-
"post",
|
|
304
|
-
threads,
|
|
305
|
-
null
|
|
306
|
-
);
|
|
270
|
+
let res: any = await TFSServices.getItemContent(url, this.token, 'post', threads, null);
|
|
307
271
|
return res;
|
|
308
272
|
}
|
|
309
273
|
|
|
310
|
-
async GetPullRequestComments(
|
|
311
|
-
projectName: string,
|
|
312
|
-
repoID: string,
|
|
313
|
-
pullRequestID: number
|
|
314
|
-
) {
|
|
274
|
+
async GetPullRequestComments(projectName: string, repoID: string, pullRequestID: number) {
|
|
315
275
|
let url: string = `${this.orgUrl}${projectName}/_apis/git/repositories/${repoID}/pullRequests/${pullRequestID}/threads`;
|
|
316
|
-
return TFSServices.getItemContent(
|
|
317
|
-
url,
|
|
318
|
-
this.token,
|
|
319
|
-
"get",
|
|
320
|
-
null,
|
|
321
|
-
null
|
|
322
|
-
);
|
|
276
|
+
return TFSServices.getItemContent(url, this.token, 'get', null, null);
|
|
323
277
|
}
|
|
324
278
|
|
|
325
|
-
async GetCommitsForRepo(
|
|
326
|
-
|
|
327
|
-
repoID: string,
|
|
328
|
-
branchName?: string
|
|
329
|
-
){
|
|
330
|
-
let url: string
|
|
279
|
+
async GetCommitsForRepo(projectName: string, repoID: string, branchName?: string) {
|
|
280
|
+
let url: string;
|
|
331
281
|
if (typeof branchName !== 'undefined') {
|
|
332
|
-
url = `${this.orgUrl}${projectName}/_apis/git/repositories/${repoID}/commits?searchCriteria.$top=2000&searchCriteria.itemVersion.version=${branchName}
|
|
282
|
+
url = `${this.orgUrl}${projectName}/_apis/git/repositories/${repoID}/commits?searchCriteria.$top=2000&searchCriteria.itemVersion.version=${branchName}`;
|
|
283
|
+
} else {
|
|
284
|
+
url = `${this.orgUrl}${projectName}/_apis/git/repositories/${repoID}/commits?searchCriteria.$top=2000`;
|
|
333
285
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
let res:any = await TFSServices.getItemContent(
|
|
338
|
-
url,
|
|
339
|
-
this.token,
|
|
340
|
-
"get",
|
|
341
|
-
null,
|
|
342
|
-
null
|
|
343
|
-
);
|
|
344
|
-
return res;
|
|
286
|
+
let res: any = await TFSServices.getItemContent(url, this.token, 'get', null, null);
|
|
287
|
+
return res;
|
|
345
288
|
}
|
|
346
289
|
|
|
347
|
-
async GetPullRequestsForRepo(
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
let url: string =
|
|
352
|
-
`${this.orgUrl}${projectName}/_apis/git/repositories/${repoID}/pullrequests?status=completed&includeLinks=true&$top=2000}`;
|
|
353
|
-
|
|
354
|
-
let res:any = await TFSServices.getItemContent(
|
|
355
|
-
url,
|
|
356
|
-
this.token,
|
|
357
|
-
"get",
|
|
358
|
-
null,
|
|
359
|
-
null
|
|
360
|
-
);
|
|
290
|
+
async GetPullRequestsForRepo(projectName: string, repoID: string) {
|
|
291
|
+
let url: string = `${this.orgUrl}${projectName}/_apis/git/repositories/${repoID}/pullrequests?status=completed&includeLinks=true&$top=2000}`;
|
|
292
|
+
|
|
293
|
+
let res: any = await TFSServices.getItemContent(url, this.token, 'get', null, null);
|
|
361
294
|
return res;
|
|
362
295
|
}
|
|
363
296
|
|
|
364
|
-
|
|
365
|
-
async GetItemsInPullRequestRange(
|
|
366
|
-
projectId: string,
|
|
367
|
-
repositoryId: string,
|
|
368
|
-
pullRequestIDs: any,
|
|
369
|
-
) {
|
|
297
|
+
async GetItemsInPullRequestRange(projectId: string, repositoryId: string, pullRequestIDs: any) {
|
|
370
298
|
let pullRequestsFilteredArray: any = [];
|
|
371
299
|
let ChangeSetsArray: any = [];
|
|
372
300
|
//get all pr's in git repo
|
|
373
301
|
let url = `${this.orgUrl}${projectId}/_apis/git/repositories/${repositoryId}/pullrequests?status=completed&includeLinks=true&$top=2000}`;
|
|
374
302
|
logger.debug(`request url: ${url}`);
|
|
375
|
-
let pullRequestsArray = await TFSServices.getItemContent(
|
|
376
|
-
|
|
377
|
-
this.token,
|
|
378
|
-
"get"
|
|
379
|
-
);
|
|
380
|
-
logger.info(
|
|
381
|
-
`got ${pullRequestsArray.count} pullrequests for repo: ${repositoryId}`
|
|
382
|
-
);
|
|
303
|
+
let pullRequestsArray = await TFSServices.getItemContent(url, this.token, 'get');
|
|
304
|
+
logger.info(`got ${pullRequestsArray.count} pullrequests for repo: ${repositoryId}`);
|
|
383
305
|
//iterate commit list to filter relavant pullrequests
|
|
384
306
|
pullRequestsArray.value.forEach((pr: any) => {
|
|
385
307
|
pullRequestIDs.forEach((prId: any) => {
|
|
@@ -390,7 +312,7 @@ export default class GitDataProvider {
|
|
|
390
312
|
});
|
|
391
313
|
logger.info(
|
|
392
314
|
`filtered in prId range ${pullRequestsFilteredArray.length} pullrequests for repo: ${repositoryId}`
|
|
393
|
-
|
|
315
|
+
);
|
|
394
316
|
//extract linked items and append them to result
|
|
395
317
|
await Promise.all(
|
|
396
318
|
pullRequestsFilteredArray.map(async (pr: any) => {
|
|
@@ -399,20 +321,11 @@ export default class GitDataProvider {
|
|
|
399
321
|
if (pr._links.workItems.href) {
|
|
400
322
|
//get workitems linked to pr
|
|
401
323
|
let url: string = pr._links.workItems.href;
|
|
402
|
-
linkedItems = await TFSServices.getItemContent(
|
|
403
|
-
|
|
404
|
-
this.token,
|
|
405
|
-
"get"
|
|
406
|
-
);
|
|
407
|
-
logger.info(
|
|
408
|
-
`got ${linkedItems.count} items linked to pr ${pr.pullRequestId}`
|
|
409
|
-
);
|
|
324
|
+
linkedItems = await TFSServices.getItemContent(url, this.token, 'get');
|
|
325
|
+
logger.info(`got ${linkedItems.count} items linked to pr ${pr.pullRequestId}`);
|
|
410
326
|
await Promise.all(
|
|
411
327
|
linkedItems.value.map(async (item: any) => {
|
|
412
|
-
let populatedItem = await this.ticketsDataProvider.GetWorkItem(
|
|
413
|
-
projectId,
|
|
414
|
-
item.id
|
|
415
|
-
);
|
|
328
|
+
let populatedItem = await this.ticketsDataProvider.GetWorkItem(projectId, item.id);
|
|
416
329
|
let changeSet: any = {
|
|
417
330
|
workItem: populatedItem,
|
|
418
331
|
pullrequest: pr,
|
|
@@ -429,18 +342,68 @@ export default class GitDataProvider {
|
|
|
429
342
|
return ChangeSetsArray;
|
|
430
343
|
}
|
|
431
344
|
|
|
432
|
-
async GetRepoBranches(
|
|
345
|
+
async GetRepoBranches(projectName: string, repoID: string) {
|
|
346
|
+
let url: string = `${this.orgUrl}${projectName}/_apis/git/repositories/${repoID}/refs?searchCriteria.$top=1000&filter=heads`;
|
|
347
|
+
let res: any = await TFSServices.getItemContent(url, this.token, 'get', null, null);
|
|
348
|
+
return res;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async GetCommitBatch(
|
|
433
352
|
projectName: string,
|
|
434
|
-
repoID: string
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
353
|
+
repoID: string,
|
|
354
|
+
itemVersion: GitVersionDescriptor,
|
|
355
|
+
compareVersion: GitVersionDescriptor
|
|
356
|
+
) {
|
|
357
|
+
const allCommitsExtended: any[] = [];
|
|
358
|
+
let skipping = 0;
|
|
359
|
+
let chunkSize = 100;
|
|
360
|
+
let commitCounter = 0;
|
|
361
|
+
let logToConsoleAfterCommits = 500;
|
|
362
|
+
try {
|
|
363
|
+
let body = {
|
|
364
|
+
itemVersion,
|
|
365
|
+
compareVersion,
|
|
366
|
+
includeWorkItems: true,
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
let url = `${this.orgUrl}${projectName}/_apis/git/repositories/${repoID}/commitsBatch?api-version=5.0&$skip=${skipping}&$top=${chunkSize}`;
|
|
370
|
+
let commitsResponse = await TFSServices.postRequest(url, this.token, undefined, body);
|
|
371
|
+
let commits = commitsResponse.data;
|
|
372
|
+
while (commits.count > 0) {
|
|
373
|
+
for (const commit of commits.value) {
|
|
374
|
+
try {
|
|
375
|
+
if (commitCounter % logToConsoleAfterCommits === 0) {
|
|
376
|
+
logger.debug(`commit number ${commitCounter + 1}`);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (commit.workItems?.length > 0) {
|
|
380
|
+
let extendedCommit: any = {};
|
|
381
|
+
|
|
382
|
+
extendedCommit['commit'] = commit;
|
|
383
|
+
|
|
384
|
+
let committerName = commit.committer.name;
|
|
385
|
+
let commitDate = commit.committer.date.toString().slice(0, 10);
|
|
386
|
+
extendedCommit['committerName'] = committerName;
|
|
387
|
+
extendedCommit['commitDate'] = commitDate;
|
|
388
|
+
|
|
389
|
+
allCommitsExtended.push(extendedCommit);
|
|
390
|
+
}
|
|
391
|
+
} catch (err: any) {
|
|
392
|
+
const errMsg = `Cannot fetch commit batch: ${err.message}`;
|
|
393
|
+
throw new Error(errMsg);
|
|
394
|
+
} finally {
|
|
395
|
+
commitCounter++;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
skipping += chunkSize;
|
|
400
|
+
let url = `${this.orgUrl}${projectName}/_apis/git/repositories/${repoID}/commitsBatch?api-version=5.0&$skip=${skipping}&$top=${chunkSize}`;
|
|
401
|
+
commitsResponse = await TFSServices.postRequest(url, this.token, undefined, body);
|
|
402
|
+
commits = commitsResponse.data;
|
|
403
|
+
}
|
|
404
|
+
} catch (error: any) {
|
|
405
|
+
logger.error(error.message);
|
|
406
|
+
}
|
|
407
|
+
return allCommitsExtended;
|
|
445
408
|
}
|
|
446
409
|
}
|