@paklo/core 0.9.0 → 0.10.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/dist/azure/index.d.mts +997 -495
- package/dist/azure/index.mjs +877 -587
- package/dist/azure/index.mjs.map +1 -1
- package/dist/dependabot/index.d.mts +2 -2
- package/dist/dependabot/index.mjs +3 -3
- package/dist/{dependabot-rtPO9HdD.mjs → dependabot-DVf7lAEG.mjs} +80 -11
- package/dist/dependabot-DVf7lAEG.mjs.map +1 -0
- package/dist/github/index.mjs +1 -1
- package/dist/{index-Byxjhvfz.d.mts → index-CFWMNvXg.d.mts} +97 -37
- package/dist/{job-BxOZ-hqF.mjs → job-COuliaYg.mjs} +13 -16
- package/dist/{job-BxOZ-hqF.mjs.map → job-COuliaYg.mjs.map} +1 -1
- package/dist/{logger-5PEqZVLr.mjs → logger-3Qfh9NUj.mjs} +2 -2
- package/dist/logger-3Qfh9NUj.mjs.map +1 -0
- package/dist/logger.mjs +1 -1
- package/dist/usage.d.mts +1 -1
- package/dist/usage.mjs +1 -1
- package/package.json +4 -4
- package/dist/dependabot-rtPO9HdD.mjs.map +0 -1
- package/dist/logger-5PEqZVLr.mjs.map +0 -1
package/dist/azure/index.mjs
CHANGED
|
@@ -1,58 +1,581 @@
|
|
|
1
|
-
import { n as logger } from "../logger-
|
|
2
|
-
import {
|
|
1
|
+
import { n as logger } from "../logger-3Qfh9NUj.mjs";
|
|
2
|
+
import { T as CONFIG_FILE_PATHS_AZURE, _ as DependabotPersistedPrSchema, z as parseDependabotConfig } from "../job-COuliaYg.mjs";
|
|
3
|
+
import { n as getDependencyNames, o as normalizeBranchName, s as normalizeFilePath, t as areEqual } from "../dependabot-DVf7lAEG.mjs";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
import ky, { isHTTPError } from "ky";
|
|
5
6
|
import * as path from "node:path";
|
|
6
7
|
import { existsSync } from "node:fs";
|
|
7
8
|
import { readFile } from "node:fs/promises";
|
|
8
9
|
|
|
9
|
-
//#region src/azure/
|
|
10
|
+
//#region src/azure/client/constants.ts
|
|
11
|
+
const API_VERSION = "5.0";
|
|
12
|
+
const API_VERSION_PREVIEW = "5.0-preview";
|
|
13
|
+
/** Returned when no user is authenticated */
|
|
14
|
+
const ANONYMOUS_USER_ID = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa";
|
|
10
15
|
/**
|
|
11
16
|
* Pull request property names used to store metadata about the pull request.
|
|
12
17
|
* https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull-request-properties
|
|
13
18
|
*/
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
19
|
+
const PR_PROPERTY_MICROSOFT_GIT_SOURCE_REF_NAME = "Microsoft.Git.PullRequest.SourceRefName";
|
|
20
|
+
const PR_PROPERTY_DEPENDABOT_PACKAGE_MANAGER = "Dependabot.PackageManager";
|
|
21
|
+
const PR_PROPERTY_DEPENDABOT_DEPENDENCIES = "Dependabot.Dependencies";
|
|
22
|
+
const PR_DESCRIPTION_MAX_LENGTH = 4e3;
|
|
17
23
|
|
|
18
24
|
//#endregion
|
|
19
|
-
//#region src/azure/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
//#region src/azure/client/client-base.ts
|
|
26
|
+
var BaseAzureDevOpsClient = class {
|
|
27
|
+
constructor(client) {
|
|
28
|
+
this.client = client;
|
|
29
|
+
}
|
|
30
|
+
makeUrl(path$1, params, apiVersion = API_VERSION) {
|
|
31
|
+
if (typeof params === "string") {
|
|
32
|
+
apiVersion = params;
|
|
33
|
+
params = {};
|
|
34
|
+
}
|
|
35
|
+
return `${path$1}?${Object.entries({
|
|
36
|
+
"api-version": apiVersion,
|
|
37
|
+
...params
|
|
38
|
+
}).filter(([, value]) => value).map(([key, value]) => `${key}=${value}`).join("&")}`;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/azure/client/client-connection.ts
|
|
44
|
+
var ConnectionClient = class extends BaseAzureDevOpsClient {
|
|
45
|
+
/**
|
|
46
|
+
* Get the connection data for the current user.
|
|
47
|
+
*/
|
|
48
|
+
async get() {
|
|
49
|
+
return await this.client.get(this.makeUrl("_apis/connectiondata", API_VERSION_PREVIEW)).json();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/azure/client/client-git.ts
|
|
55
|
+
var GitClient = class extends BaseAzureDevOpsClient {
|
|
56
|
+
async getItem(projectIdOrName, repositoryIdOrName, path$1, includeContent = true, latestProcessedChange = true) {
|
|
57
|
+
try {
|
|
58
|
+
return await this.client.get(this.makeUrl(`${encodeURIComponent(projectIdOrName)}/_apis/git/repositories/${encodeURIComponent(repositoryIdOrName)}/items`, {
|
|
59
|
+
path: path$1,
|
|
60
|
+
includeContent,
|
|
61
|
+
latestProcessedChange
|
|
62
|
+
})).json();
|
|
63
|
+
} catch (e) {
|
|
64
|
+
if (isHTTPError(e) && e.response.status === 404) return;
|
|
65
|
+
throw e;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async getPush(projectIdOrName, repositoryIdOrName, pushId, includeCommits, includeRefUpdates) {
|
|
69
|
+
return await this.client.get(this.makeUrl(`${encodeURIComponent(projectIdOrName)}/_apis/git/repositories/${encodeURIComponent(repositoryIdOrName)}/pushes/${pushId}`, {
|
|
70
|
+
includeCommits,
|
|
71
|
+
includeRefUpdates
|
|
72
|
+
})).json();
|
|
73
|
+
}
|
|
74
|
+
async createPush(projectIdOrName, repositoryIdOrName, push) {
|
|
75
|
+
return await this.client.post(this.makeUrl(`${encodeURIComponent(projectIdOrName)}/_apis/git/repositories/${encodeURIComponent(repositoryIdOrName)}/pushes`), { json: push }).json();
|
|
76
|
+
}
|
|
77
|
+
async getDiffCommits(projectIdOrName, repositoryIdOrName, baseVersion, targetVersion) {
|
|
78
|
+
return await this.client.get(this.makeUrl(`${encodeURIComponent(projectIdOrName)}/_apis/git/repositories/${encodeURIComponent(repositoryIdOrName)}/diffs/commits`, {
|
|
79
|
+
baseVersion,
|
|
80
|
+
baseVersionType: "commit",
|
|
81
|
+
targetVersion,
|
|
82
|
+
targetVersionType: "commit"
|
|
83
|
+
})).json();
|
|
84
|
+
}
|
|
85
|
+
async updateRef(projectIdOrName, repositoryIdOrName, ref) {
|
|
86
|
+
return (await this.client.post(this.makeUrl(`${encodeURIComponent(projectIdOrName)}/_apis/git/repositories/${encodeURIComponent(repositoryIdOrName)}/refs`), { json: ref }).json()).value;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/azure/client/client-identity.ts
|
|
92
|
+
var IdentityClient = class extends BaseAzureDevOpsClient {
|
|
93
|
+
/**
|
|
94
|
+
* Get the identities that match the given user name, email, or group name.
|
|
95
|
+
* Requires scope "Identity (Read)" (vso.identity).
|
|
96
|
+
* @param filterValue username, email, or group name
|
|
97
|
+
* @returns
|
|
98
|
+
*/
|
|
99
|
+
async get(filterValue) {
|
|
100
|
+
return (await this.client.get(this.makeUrl("_apis/identities", {
|
|
101
|
+
searchFilter: "General",
|
|
102
|
+
filterValue,
|
|
103
|
+
queryMembership: "None"
|
|
104
|
+
})).json())?.value;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/azure/client/client-projects.ts
|
|
110
|
+
var ProjectsClient = class extends BaseAzureDevOpsClient {
|
|
111
|
+
async list() {
|
|
112
|
+
return (await this.client.get(this.makeUrl("_apis/projects")).json())?.value;
|
|
113
|
+
}
|
|
114
|
+
async get(idOrName) {
|
|
115
|
+
return await this.client.get(this.makeUrl(`_apis/projects/${encodeURIComponent(idOrName)}`)).json();
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
//#endregion
|
|
120
|
+
//#region src/azure/client/client-pull-requests.ts
|
|
121
|
+
var PullRequestsClient = class extends BaseAzureDevOpsClient {
|
|
122
|
+
/**
|
|
123
|
+
* List pull requests
|
|
124
|
+
* Requires scope "Code (Read)" (vso.code).
|
|
125
|
+
* @param projectIdOrName
|
|
126
|
+
* @param repositoryIdOrName
|
|
127
|
+
* @param creatorId ID of the user who created the pull requests
|
|
128
|
+
* @param status The status of the pull requests to filter by
|
|
129
|
+
*/
|
|
130
|
+
async list(projectIdOrName, repositoryIdOrName, creatorId, status) {
|
|
131
|
+
return (await this.client.get(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/pullrequests`, {
|
|
132
|
+
"searchCriteria.creatorId": creatorId,
|
|
133
|
+
"searchCriteria.status": status
|
|
134
|
+
})).json())?.value;
|
|
135
|
+
}
|
|
136
|
+
async get(projectIdOrName, repositoryIdOrName, pullRequestId) {
|
|
137
|
+
return await this.client.get(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/pullrequests/${pullRequestId}`)).json();
|
|
138
|
+
}
|
|
139
|
+
async create(projectIdOrName, repositoryIdOrName, pr) {
|
|
140
|
+
return await this.client.post(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/pullrequests`), { json: pr }).json();
|
|
141
|
+
}
|
|
142
|
+
async update(projectIdOrName, repositoryIdOrName, pullRequestId, pr) {
|
|
143
|
+
return await this.client.patch(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/pullrequests/${pullRequestId}`), { json: pr }).json();
|
|
144
|
+
}
|
|
145
|
+
async getProperties(projectIdOrName, repositoryIdOrName, pullRequestId) {
|
|
146
|
+
const response = await this.client.get(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/pullrequests/${pullRequestId}/properties`)).json();
|
|
147
|
+
return Object.entries(response?.value || {}).filter(([, val]) => val?.$value).map(([key, val]) => ({
|
|
148
|
+
name: key,
|
|
149
|
+
value: val.$value
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
async setProperties(projectIdOrName, repositoryIdOrName, pullRequestId, properties) {
|
|
153
|
+
return await this.client.patch(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/pullrequests/${pullRequestId}/properties`), {
|
|
154
|
+
headers: { "Content-Type": "application/json-patch+json" },
|
|
155
|
+
json: properties.map((property) => {
|
|
156
|
+
return {
|
|
157
|
+
op: "add",
|
|
158
|
+
path: `/${property.name}`,
|
|
159
|
+
value: property.value
|
|
160
|
+
};
|
|
161
|
+
})
|
|
162
|
+
}).json();
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Approve a pull request.
|
|
166
|
+
* Requires scope "Code (Write)" (vso.code_write).
|
|
167
|
+
*/
|
|
168
|
+
async approve(projectIdOrName, repositoryIdOrName, pullRequestId, userId) {
|
|
169
|
+
return await this.client.put(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/pullrequests/${pullRequestId}/reviewers/${userId}`, "7.1"), { json: {
|
|
170
|
+
vote: 10,
|
|
171
|
+
isReapprove: true
|
|
172
|
+
} }).json();
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Abandon a pull request.
|
|
176
|
+
* Requires scope "Code (Write)" (vso.code_write).
|
|
177
|
+
*/
|
|
178
|
+
async abandon(projectIdOrName, repositoryIdOrName, pullRequestId, userId) {
|
|
179
|
+
return await this.client.patch(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/pullrequests/${pullRequestId}`), { json: {
|
|
180
|
+
status: "abandoned",
|
|
181
|
+
closedBy: { id: userId }
|
|
182
|
+
} }).json();
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get commits of a pull request.
|
|
186
|
+
* Requires scope "Code (Read)" (vso.code_read).
|
|
187
|
+
*/
|
|
188
|
+
async getCommits(projectIdOrName, repositoryIdOrName, pullRequestId) {
|
|
189
|
+
return (await this.client.get(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/pullrequests/${pullRequestId}/commits`)).json())?.value;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Create a comment thread on a pull request.
|
|
193
|
+
* Requires scope "Code (Write)" (vso.code_write).
|
|
194
|
+
*/
|
|
195
|
+
async createCommentThread(projectIdOrName, repositoryIdOrName, pullRequestId, thread) {
|
|
196
|
+
return await this.client.post(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/pullrequests/${pullRequestId}/threads`), { json: thread }).json();
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region src/azure/client/client-repositories.ts
|
|
202
|
+
var RepositoriesClient = class extends BaseAzureDevOpsClient {
|
|
203
|
+
async list(projectIdOrName) {
|
|
204
|
+
return (await this.client.get(this.makeUrl(`${encodeURIComponent(projectIdOrName)}/_apis/git/repositories`)).json())?.value;
|
|
205
|
+
}
|
|
206
|
+
async get(projectIdOrName, repositoryIdOrName) {
|
|
207
|
+
try {
|
|
208
|
+
return await this.client.get(this.makeUrl(`${encodeURIComponent(projectIdOrName)}/_apis/git/repositories/${encodeURIComponent(repositoryIdOrName)}`)).json();
|
|
209
|
+
} catch (e) {
|
|
210
|
+
if (isHTTPError(e) && e.response.status === 404) return;
|
|
211
|
+
throw e;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get the list of refs (a.k.a branch names) for a repository.
|
|
216
|
+
* Requires scope "Code (Read)" (vso.code).
|
|
217
|
+
* @param projectIdOrName
|
|
218
|
+
* @param repositoryIdOrName
|
|
219
|
+
* @returns
|
|
220
|
+
*/
|
|
221
|
+
async getRefs(projectIdOrName, repositoryIdOrName) {
|
|
222
|
+
return (await this.client.get(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/refs`)).json())?.value;
|
|
223
|
+
}
|
|
224
|
+
async getBranchStats(projectIdOrName, repositoryIdOrName, branchName) {
|
|
225
|
+
return await this.client.get(this.makeUrl(`${projectIdOrName}/_apis/git/repositories/${repositoryIdOrName}/stats/branches`, { name: branchName })).json();
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
//#endregion
|
|
230
|
+
//#region src/azure/client/client-subscriptions.ts
|
|
231
|
+
var HookSubscriptionsClient = class extends BaseAzureDevOpsClient {
|
|
232
|
+
async query(query) {
|
|
233
|
+
return (await this.client.post(this.makeUrl("_apis/hooks/subscriptionsquery"), { json: query }).json())?.results;
|
|
234
|
+
}
|
|
235
|
+
async create(subscription) {
|
|
236
|
+
return await this.client.post(this.makeUrl("_apis/hooks/subscriptions"), { json: subscription }).json();
|
|
237
|
+
}
|
|
238
|
+
async replace(subscriptionId, subscription) {
|
|
239
|
+
return await this.client.put(this.makeUrl(`_apis/hooks/subscriptions/${subscriptionId}`), { json: subscription }).json();
|
|
240
|
+
}
|
|
241
|
+
async delete(subscriptionId) {
|
|
242
|
+
await this.client.delete(this.makeUrl(`_apis/hooks/subscriptions/${subscriptionId}`)).json();
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
//#endregion
|
|
247
|
+
//#region src/azure/client/client.ts
|
|
248
|
+
var AzureDevOpsClient = class AzureDevOpsClient {
|
|
249
|
+
organizationSlug;
|
|
250
|
+
organizationUrl;
|
|
251
|
+
connection;
|
|
252
|
+
identity;
|
|
253
|
+
projects;
|
|
254
|
+
repositories;
|
|
255
|
+
git;
|
|
256
|
+
pullRequests;
|
|
257
|
+
subscriptions;
|
|
258
|
+
constructor(url, accessToken, debug = false) {
|
|
259
|
+
this.organizationSlug = url.organisation;
|
|
260
|
+
const organizationUrl = url.value.toString().replace(/\/$/, "");
|
|
261
|
+
this.organizationUrl = organizationUrl;
|
|
262
|
+
const mainClientOptions = AzureDevOpsClient.createClientOptions(accessToken, debug, { prefixUrl: organizationUrl });
|
|
263
|
+
const mainClient = ky.create(mainClientOptions);
|
|
264
|
+
this.connection = new ConnectionClient(mainClient);
|
|
265
|
+
this.projects = new ProjectsClient(mainClient);
|
|
266
|
+
this.repositories = new RepositoriesClient(mainClient);
|
|
267
|
+
this.git = new GitClient(mainClient);
|
|
268
|
+
this.pullRequests = new PullRequestsClient(mainClient);
|
|
269
|
+
this.subscriptions = new HookSubscriptionsClient(mainClient);
|
|
270
|
+
const identityApiUrl = url["identity-api-url"].toString().replace(/\/$/, "");
|
|
271
|
+
this.identity = new IdentityClient(ky.create({
|
|
272
|
+
...mainClientOptions,
|
|
273
|
+
prefixUrl: identityApiUrl
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
static createClientOptions(accessToken, debug, options) {
|
|
277
|
+
return {
|
|
278
|
+
headers: {
|
|
279
|
+
Authorization: `Basic ${Buffer.from(`:${accessToken}`).toString("base64")}`,
|
|
280
|
+
Accept: "application/json"
|
|
281
|
+
},
|
|
282
|
+
hooks: {
|
|
283
|
+
beforeRequest: [async (request, options$1) => {
|
|
284
|
+
if (debug) logger.debug(`🌎 🠊 [${request.method}] ${request.url}`);
|
|
285
|
+
}],
|
|
286
|
+
afterResponse: [async (request, options$1, response) => {
|
|
287
|
+
if (debug) {
|
|
288
|
+
logger.debug(`🌎 🠈 [${response.status}] ${response.statusText}`);
|
|
289
|
+
if (request.body) logger.debug(`REQUEST: ${JSON.stringify(request.body)}`);
|
|
290
|
+
}
|
|
291
|
+
}],
|
|
292
|
+
beforeRetry: [async ({ request, options: options$1, error, retryCount }) => {
|
|
293
|
+
if (debug && isHTTPError(error)) logger.debug(`⏳ Retrying failed request with status code: ${error.response.status}`);
|
|
294
|
+
}]
|
|
295
|
+
},
|
|
296
|
+
retry: {
|
|
297
|
+
limit: 3,
|
|
298
|
+
delay: (attempt) => 3e3
|
|
299
|
+
},
|
|
300
|
+
...options
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
//#endregion
|
|
306
|
+
//#region src/azure/client/types.ts
|
|
307
|
+
const AzdoVersionControlChangeTypeSchema = z.enum([
|
|
308
|
+
"none",
|
|
309
|
+
"add",
|
|
310
|
+
"edit",
|
|
311
|
+
"encoding",
|
|
312
|
+
"rename",
|
|
313
|
+
"delete",
|
|
314
|
+
"undelete",
|
|
315
|
+
"branch",
|
|
316
|
+
"merge",
|
|
317
|
+
"lock",
|
|
318
|
+
"rollback",
|
|
319
|
+
"sourceRename",
|
|
320
|
+
"targetRename",
|
|
321
|
+
"property",
|
|
322
|
+
"all"
|
|
323
|
+
]);
|
|
324
|
+
const AZDO_PULL_REQUEST_MERGE_STRATEGIES = [
|
|
325
|
+
"noFastForward",
|
|
326
|
+
"squash",
|
|
327
|
+
"rebase",
|
|
328
|
+
"rebaseMerge"
|
|
329
|
+
];
|
|
330
|
+
const AzdoPullRequestMergeStrategySchema = z.enum(AZDO_PULL_REQUEST_MERGE_STRATEGIES);
|
|
331
|
+
const AzdoCommentThreadStatusSchema = z.enum([
|
|
332
|
+
"unknown",
|
|
333
|
+
"active",
|
|
334
|
+
"fixed",
|
|
335
|
+
"wontFix",
|
|
336
|
+
"closed",
|
|
337
|
+
"byDesign",
|
|
338
|
+
"pending"
|
|
339
|
+
]);
|
|
340
|
+
const AzdoCommentTypeSchema = z.enum([
|
|
341
|
+
"unknown",
|
|
342
|
+
"text",
|
|
343
|
+
"codeChange",
|
|
344
|
+
"system"
|
|
345
|
+
]);
|
|
346
|
+
const AzdoPullRequestAsyncStatusSchema = z.enum([
|
|
347
|
+
"notSet",
|
|
348
|
+
"queued",
|
|
349
|
+
"conflicts",
|
|
350
|
+
"succeeded",
|
|
351
|
+
"rejectedByPolicy",
|
|
352
|
+
"failure"
|
|
353
|
+
]);
|
|
354
|
+
const AzdoPullRequestStatusSchema = z.enum([
|
|
355
|
+
"notSet",
|
|
356
|
+
"active",
|
|
357
|
+
"abandoned",
|
|
358
|
+
"completed",
|
|
359
|
+
"all"
|
|
360
|
+
]);
|
|
361
|
+
const AzdoProjectSchema = z.object({
|
|
362
|
+
id: z.string(),
|
|
363
|
+
name: z.string(),
|
|
364
|
+
description: z.string().optional(),
|
|
365
|
+
url: z.string(),
|
|
366
|
+
state: z.enum([
|
|
367
|
+
"deleting",
|
|
368
|
+
"new",
|
|
369
|
+
"wellFormed",
|
|
370
|
+
"createPending",
|
|
371
|
+
"all",
|
|
372
|
+
"unchanged",
|
|
373
|
+
"deleted"
|
|
374
|
+
]),
|
|
375
|
+
_links: z.object({
|
|
376
|
+
self: z.object({ href: z.string() }),
|
|
377
|
+
collection: z.object({ href: z.string() }),
|
|
378
|
+
web: z.object({ href: z.string() })
|
|
379
|
+
}).optional()
|
|
380
|
+
});
|
|
381
|
+
const AzdoRepositorySchema = z.object({
|
|
382
|
+
id: z.string(),
|
|
383
|
+
name: z.string(),
|
|
384
|
+
defaultBranch: z.string().optional(),
|
|
385
|
+
project: AzdoProjectSchema,
|
|
386
|
+
isDisabled: z.boolean().optional(),
|
|
387
|
+
isFork: z.boolean().optional(),
|
|
388
|
+
url: z.string(),
|
|
389
|
+
remoteUrl: z.string(),
|
|
390
|
+
webUrl: z.string()
|
|
391
|
+
});
|
|
392
|
+
const AzdoIdentitySchema = z.object({
|
|
393
|
+
id: z.string(),
|
|
394
|
+
displayName: z.string(),
|
|
395
|
+
url: z.string()
|
|
396
|
+
});
|
|
397
|
+
const AzdoIdentityRefSchema = z.object({
|
|
398
|
+
id: z.string().optional(),
|
|
399
|
+
displayName: z.string().optional(),
|
|
400
|
+
uniqueName: z.string().optional(),
|
|
401
|
+
url: z.string().optional()
|
|
402
|
+
});
|
|
403
|
+
const AzdoConnectionDataSchema = z.object({
|
|
404
|
+
authenticatedUser: AzdoIdentitySchema,
|
|
405
|
+
authorizedUser: AzdoIdentitySchema
|
|
406
|
+
});
|
|
407
|
+
const AzdoGitUserDateSchema = z.object({
|
|
408
|
+
name: z.string(),
|
|
409
|
+
email: z.string(),
|
|
410
|
+
date: z.string().optional()
|
|
411
|
+
});
|
|
412
|
+
const AzdoGitRefSchema = z.object({
|
|
413
|
+
name: z.string(),
|
|
414
|
+
objectId: z.string(),
|
|
415
|
+
isLocked: z.boolean().optional()
|
|
416
|
+
});
|
|
417
|
+
const AzdoGitRefUpdateResultSchema = AzdoGitRefSchema.extend({
|
|
418
|
+
oldObjectId: z.string(),
|
|
419
|
+
newObjectId: z.string(),
|
|
420
|
+
success: z.boolean(),
|
|
421
|
+
customMessage: z.string().optional()
|
|
422
|
+
});
|
|
423
|
+
const AzdoGitChangeSchema = z.object({
|
|
424
|
+
changeType: AzdoVersionControlChangeTypeSchema,
|
|
425
|
+
item: z.object({ path: z.string() }).optional(),
|
|
426
|
+
newContent: z.object({
|
|
427
|
+
content: z.string(),
|
|
428
|
+
contentType: z.enum(["rawtext", "base64encoded"])
|
|
429
|
+
}).optional(),
|
|
430
|
+
originalPath: z.string().optional()
|
|
431
|
+
});
|
|
432
|
+
const AzdoGitCommitRefSchema = z.object({
|
|
433
|
+
commitId: z.string(),
|
|
434
|
+
author: AzdoGitUserDateSchema.optional(),
|
|
435
|
+
committer: AzdoGitUserDateSchema.optional(),
|
|
436
|
+
changes: AzdoGitChangeSchema.array().optional()
|
|
437
|
+
});
|
|
438
|
+
const AzdoGitPushSchema = z.object({
|
|
439
|
+
commits: AzdoGitCommitRefSchema.array(),
|
|
440
|
+
refUpdates: AzdoGitRefSchema.array()
|
|
441
|
+
});
|
|
442
|
+
const AzdoGitRefUpdateSchema = z.object({
|
|
443
|
+
name: z.string(),
|
|
444
|
+
oldObjectId: z.string(),
|
|
445
|
+
newObjectId: z.string().optional(),
|
|
446
|
+
isLocked: z.boolean().optional()
|
|
447
|
+
});
|
|
448
|
+
const AzdoGitPushCreateSchema = z.object({
|
|
449
|
+
refUpdates: AzdoGitRefUpdateSchema.array(),
|
|
450
|
+
commits: z.object({
|
|
451
|
+
comment: z.string(),
|
|
452
|
+
author: AzdoGitUserDateSchema.optional(),
|
|
453
|
+
changes: AzdoGitChangeSchema.array()
|
|
454
|
+
}).array()
|
|
455
|
+
});
|
|
456
|
+
const AzdoGitBranchStatsSchema = z.object({
|
|
457
|
+
aheadCount: z.number(),
|
|
458
|
+
behindCount: z.number()
|
|
459
|
+
});
|
|
460
|
+
const AzdoGitCommitDiffsSchema = z.object({
|
|
461
|
+
allChangesIncluded: z.boolean(),
|
|
462
|
+
baseCommit: z.string(),
|
|
463
|
+
changes: AzdoGitChangeSchema.array(),
|
|
464
|
+
targetCommit: z.string()
|
|
465
|
+
});
|
|
466
|
+
const AzdoRepositoryItemSchema = z.object({
|
|
467
|
+
latestProcessedChange: AzdoGitCommitRefSchema.optional(),
|
|
468
|
+
content: z.string().optional()
|
|
469
|
+
});
|
|
470
|
+
const AzdoIdentityRefWithVoteSchema = z.object({
|
|
471
|
+
id: z.string().optional(),
|
|
472
|
+
displayName: z.string().optional(),
|
|
473
|
+
vote: z.number().optional(),
|
|
474
|
+
hasDeclined: z.boolean().optional(),
|
|
475
|
+
isFlagged: z.boolean().optional(),
|
|
476
|
+
isRequired: z.boolean().optional()
|
|
477
|
+
});
|
|
478
|
+
const AzdoPullRequestSchema = z.object({
|
|
479
|
+
pullRequestId: z.number(),
|
|
480
|
+
status: AzdoPullRequestStatusSchema,
|
|
481
|
+
isDraft: z.boolean(),
|
|
482
|
+
sourceRefName: z.string(),
|
|
483
|
+
targetRefName: z.string(),
|
|
484
|
+
title: z.string(),
|
|
485
|
+
description: z.string().optional(),
|
|
486
|
+
lastMergeCommit: AzdoGitCommitRefSchema,
|
|
487
|
+
lastMergeSourceCommit: AzdoGitCommitRefSchema,
|
|
488
|
+
mergeStatus: AzdoPullRequestAsyncStatusSchema,
|
|
489
|
+
reviewers: AzdoIdentityRefWithVoteSchema.array().optional(),
|
|
490
|
+
workItemRefs: z.object({ id: z.string() }).array().optional(),
|
|
491
|
+
labels: z.object({ name: z.string() }).array().optional(),
|
|
492
|
+
autoCompleteSetBy: AzdoIdentityRefSchema.optional(),
|
|
493
|
+
completionOptions: z.object({
|
|
494
|
+
autoCompleteIgnoreConfigIds: z.number().array().optional(),
|
|
495
|
+
deleteSourceBranch: z.boolean().optional(),
|
|
496
|
+
mergeCommitMessage: z.string().optional(),
|
|
497
|
+
mergeStrategy: AzdoPullRequestMergeStrategySchema.optional(),
|
|
498
|
+
transitionWorkItems: z.boolean().optional()
|
|
499
|
+
}).optional(),
|
|
500
|
+
closedBy: AzdoIdentityRefSchema.optional()
|
|
501
|
+
});
|
|
502
|
+
const AzdoPropertiesSchema = z.record(z.string(), z.object({
|
|
503
|
+
$type: z.string(),
|
|
504
|
+
$value: z.string()
|
|
505
|
+
}));
|
|
506
|
+
const AzdoPullRequestCommentSchema = z.object({
|
|
507
|
+
id: z.number().optional(),
|
|
508
|
+
parentCommentId: z.number().optional(),
|
|
509
|
+
content: z.string(),
|
|
510
|
+
commentType: AzdoCommentTypeSchema,
|
|
511
|
+
publishedDate: z.string().optional(),
|
|
512
|
+
author: AzdoIdentityRefSchema
|
|
513
|
+
});
|
|
514
|
+
const AzdoPullRequestCommentThreadSchema = z.object({
|
|
515
|
+
id: z.number(),
|
|
516
|
+
comments: AzdoPullRequestCommentSchema.array(),
|
|
517
|
+
status: AzdoCommentThreadStatusSchema
|
|
518
|
+
});
|
|
519
|
+
const AzdoSubscriptionSchema = z.object({
|
|
520
|
+
id: z.string(),
|
|
521
|
+
status: z.enum([
|
|
522
|
+
"enabled",
|
|
523
|
+
"onProbation",
|
|
524
|
+
"disabledByUser",
|
|
525
|
+
"disabledBySystem",
|
|
526
|
+
"disabledByInactiveIdentity"
|
|
527
|
+
]),
|
|
528
|
+
publisherId: z.string(),
|
|
529
|
+
publisherInputs: z.record(z.string(), z.string()),
|
|
530
|
+
consumerId: z.string().optional(),
|
|
531
|
+
consumerActionId: z.string().optional(),
|
|
532
|
+
consumerInputs: z.record(z.string(), z.string()),
|
|
533
|
+
eventType: z.string(),
|
|
534
|
+
resourceVersion: z.string(),
|
|
535
|
+
eventDescription: z.string().optional(),
|
|
536
|
+
actionDescription: z.string().optional()
|
|
537
|
+
});
|
|
538
|
+
const AzdoSubscriptionsQueryResponseSchema = z.object({ results: AzdoSubscriptionSchema.array() });
|
|
539
|
+
const AzdoSubscriptionsQueryInputFilterSchema = z.object({ conditions: z.object({
|
|
540
|
+
caseSensitive: z.boolean().optional(),
|
|
541
|
+
inputId: z.string().optional(),
|
|
542
|
+
inputValue: z.string().optional(),
|
|
543
|
+
operator: z.enum(["equals", "notEquals"])
|
|
544
|
+
}).array().optional() });
|
|
545
|
+
const AzdoSubscriptionsQuerySchema = z.object({
|
|
546
|
+
consumerActionId: z.string().optional(),
|
|
547
|
+
consumerId: z.string().optional(),
|
|
548
|
+
consumerInputFilters: AzdoSubscriptionsQueryInputFilterSchema.array().optional(),
|
|
549
|
+
eventType: z.string().optional(),
|
|
550
|
+
publisherId: z.string().optional(),
|
|
551
|
+
publisherInputFilters: AzdoSubscriptionsQueryInputFilterSchema.array().optional(),
|
|
552
|
+
subscriberId: z.string().optional()
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
//#endregion
|
|
556
|
+
//#region src/azure/client/utils.ts
|
|
27
557
|
function buildPullRequestProperties(packageManager, dependencies) {
|
|
28
558
|
return [{
|
|
29
|
-
name:
|
|
559
|
+
name: PR_PROPERTY_DEPENDABOT_PACKAGE_MANAGER,
|
|
30
560
|
value: packageManager
|
|
31
561
|
}, {
|
|
32
|
-
name:
|
|
562
|
+
name: PR_PROPERTY_DEPENDABOT_DEPENDENCIES,
|
|
33
563
|
value: JSON.stringify(dependencies)
|
|
34
564
|
}];
|
|
35
565
|
}
|
|
36
566
|
function parsePullRequestProperties(pullRequests, packageManager) {
|
|
37
567
|
return Object.fromEntries(pullRequests.filter((pr) => {
|
|
38
|
-
return pr.properties?.find((p) => p.name ===
|
|
568
|
+
return pr.properties?.find((p) => p.name === PR_PROPERTY_DEPENDABOT_PACKAGE_MANAGER && (packageManager === null || p.value === packageManager));
|
|
39
569
|
}).map((pr) => {
|
|
40
|
-
return [pr.
|
|
570
|
+
return [pr.pullRequestId, DependabotPersistedPrSchema.parse(JSON.parse(pr.properties.find((p) => p.name === PR_PROPERTY_DEPENDABOT_DEPENDENCIES).value))];
|
|
41
571
|
}));
|
|
42
572
|
}
|
|
43
573
|
function getPullRequestForDependencyNames(existingPullRequests, packageManager, dependencyNames) {
|
|
44
574
|
return existingPullRequests.find((pr) => {
|
|
45
|
-
return pr.properties?.find((p) => p.name ===
|
|
575
|
+
return pr.properties?.find((p) => p.name === PR_PROPERTY_DEPENDABOT_PACKAGE_MANAGER && p.value === packageManager) && pr.properties?.find((p) => p.name === PR_PROPERTY_DEPENDABOT_DEPENDENCIES && areEqual(getDependencyNames(DependabotPersistedPrSchema.parse(JSON.parse(p.value))), dependencyNames));
|
|
46
576
|
});
|
|
47
577
|
}
|
|
48
|
-
function
|
|
49
|
-
return (Array.isArray(dependencies) ? dependencies : dependencies.dependencies).map((dep) => dep["dependency-name"]?.toString());
|
|
50
|
-
}
|
|
51
|
-
function areEqual(a, b) {
|
|
52
|
-
if (a.length !== b.length) return false;
|
|
53
|
-
return a.every((name) => b.includes(name));
|
|
54
|
-
}
|
|
55
|
-
function getPullRequestChangedFilesForOutputData(data) {
|
|
578
|
+
function getPullRequestChangedFiles(data) {
|
|
56
579
|
return data["updated-dependency-files"].filter((file) => file.type === "file").map((file) => {
|
|
57
580
|
let changeType = "none";
|
|
58
581
|
if (file.deleted === true || file.operation === "delete") changeType = "delete";
|
|
@@ -66,229 +589,91 @@ function getPullRequestChangedFilesForOutputData(data) {
|
|
|
66
589
|
};
|
|
67
590
|
});
|
|
68
591
|
}
|
|
69
|
-
function getPullRequestCloseReasonForOutputData(data) {
|
|
70
|
-
const leadDependencyName = data["dependency-names"][0];
|
|
71
|
-
let reason;
|
|
72
|
-
switch (data.reason) {
|
|
73
|
-
case "dependencies_changed":
|
|
74
|
-
reason = `Looks like the dependencies have changed`;
|
|
75
|
-
break;
|
|
76
|
-
case "dependency_group_empty":
|
|
77
|
-
reason = `Looks like the dependencies in this group are now empty`;
|
|
78
|
-
break;
|
|
79
|
-
case "dependency_removed":
|
|
80
|
-
reason = `Looks like ${leadDependencyName} is no longer a dependency`;
|
|
81
|
-
break;
|
|
82
|
-
case "up_to_date":
|
|
83
|
-
reason = `Looks like ${leadDependencyName} is up-to-date now`;
|
|
84
|
-
break;
|
|
85
|
-
case "update_no_longer_possible":
|
|
86
|
-
reason = `Looks like ${leadDependencyName} can no longer be updated`;
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
if (reason && reason.length > 0) reason += ", so this is no longer needed.";
|
|
90
|
-
return reason;
|
|
91
|
-
}
|
|
92
|
-
function getPullRequestDependenciesPropertyValueForOutputData(data) {
|
|
93
|
-
const dependencies = data.dependencies?.map((dep) => {
|
|
94
|
-
return {
|
|
95
|
-
"dependency-name": dep.name,
|
|
96
|
-
"dependency-version": dep.version,
|
|
97
|
-
directory: dep.directory
|
|
98
|
-
};
|
|
99
|
-
});
|
|
100
|
-
const dependencyGroupName = data["dependency-group"]?.name;
|
|
101
|
-
if (!dependencyGroupName) return dependencies;
|
|
102
|
-
return {
|
|
103
|
-
"dependency-group-name": dependencyGroupName,
|
|
104
|
-
dependencies
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
function getPullRequestDescription(packageManager, body, dependencies) {
|
|
108
|
-
let header = "";
|
|
109
|
-
const footer = "";
|
|
110
|
-
const description = (body || "").replace(new RegExp(decodeURIComponent("%EF%BF%BD%EF%BF%BD%EF%BF%BD"), "g"), "");
|
|
111
|
-
if (dependencies.length === 1) {
|
|
112
|
-
const compatibilityScoreBadges = dependencies.map((dep) => {
|
|
113
|
-
return ``;
|
|
114
|
-
});
|
|
115
|
-
header += `${compatibilityScoreBadges.join(" ")}\n\n`;
|
|
116
|
-
}
|
|
117
|
-
const maxDescriptionLengthAfterHeaderAndFooter = 4e3 - header.length - 0;
|
|
118
|
-
return `${header}${description.substring(0, maxDescriptionLengthAfterHeaderAndFooter)}${footer}`;
|
|
119
|
-
}
|
|
120
592
|
|
|
121
593
|
//#endregion
|
|
122
|
-
//#region src/azure/client.ts
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
/** Azure DevOps REST API client. */
|
|
126
|
-
var AzureDevOpsWebApiClient = class AzureDevOpsWebApiClient {
|
|
127
|
-
organisationApiUrl;
|
|
128
|
-
identityApiUrl;
|
|
129
|
-
accessToken;
|
|
130
|
-
debug;
|
|
131
|
-
client;
|
|
594
|
+
//#region src/azure/client/wrapper.ts
|
|
595
|
+
var AzureDevOpsClientWrapper = class {
|
|
596
|
+
inner;
|
|
132
597
|
authenticatedUserId;
|
|
133
|
-
resolvedUserIds;
|
|
134
|
-
|
|
135
|
-
|
|
598
|
+
resolvedUserIds = {};
|
|
599
|
+
/**
|
|
600
|
+
* Create a new Azure DevOps client wrapper.
|
|
601
|
+
* @param url The Azure DevOps organization URL
|
|
602
|
+
* @param accessToken The personal access token for authentication
|
|
603
|
+
* @param debug Enable debug logging for API requests (default: false)
|
|
604
|
+
*/
|
|
136
605
|
constructor(url, accessToken, debug = false) {
|
|
137
|
-
this.
|
|
138
|
-
this.identityApiUrl = url["identity-api-url"].toString().replace(/\/$/, "");
|
|
139
|
-
this.accessToken = accessToken;
|
|
140
|
-
this.debug = debug;
|
|
141
|
-
this.resolvedUserIds = {};
|
|
142
|
-
this.client = this.createClient();
|
|
606
|
+
this.inner = new AzureDevOpsClient(url, accessToken, debug);
|
|
143
607
|
}
|
|
144
608
|
/**
|
|
145
609
|
* Get the identity of the authenticated user.
|
|
146
|
-
*
|
|
610
|
+
* The result is cached after the first call to avoid repeated API requests.
|
|
147
611
|
*/
|
|
148
612
|
async getUserId() {
|
|
149
613
|
if (!this.authenticatedUserId) {
|
|
150
|
-
this.authenticatedUserId = (await this.
|
|
614
|
+
this.authenticatedUserId = (await this.inner.connection.get())?.authenticatedUser?.id;
|
|
151
615
|
if (!this.authenticatedUserId) throw new Error("Failed to get authenticated user ID");
|
|
152
616
|
}
|
|
153
617
|
return this.authenticatedUserId;
|
|
154
618
|
}
|
|
155
619
|
/**
|
|
156
620
|
* Get the identity id from a user name, email, or group name.
|
|
621
|
+
* Results are cached to avoid repeated API requests for the same identifier.
|
|
622
|
+
*
|
|
157
623
|
* Requires scope "Identity (Read)" (vso.identity).
|
|
158
|
-
* @param
|
|
159
|
-
* @returns
|
|
624
|
+
* @param identifier Username, email, or group name to resolve
|
|
625
|
+
* @returns The resolved identity ID, or undefined if not found or on error
|
|
160
626
|
*/
|
|
161
|
-
async resolveIdentityId(
|
|
162
|
-
if (this.resolvedUserIds[
|
|
627
|
+
async resolveIdentityId(identifier) {
|
|
628
|
+
if (this.resolvedUserIds[identifier]) return this.resolvedUserIds[identifier];
|
|
163
629
|
try {
|
|
164
|
-
const identities = await this.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
})).json();
|
|
169
|
-
if (!identities?.value || identities.value.length === 0) return;
|
|
170
|
-
this.resolvedUserIds[userNameEmailOrGroupName] = identities.value[0].id;
|
|
171
|
-
return this.resolvedUserIds[userNameEmailOrGroupName];
|
|
630
|
+
const identities = await this.inner.identity.get(identifier);
|
|
631
|
+
if (!identities || identities.length === 0) return;
|
|
632
|
+
this.resolvedUserIds[identifier] = identities[0].id;
|
|
633
|
+
return this.resolvedUserIds[identifier];
|
|
172
634
|
} catch (e) {
|
|
173
635
|
logger.error(`Failed to resolve user id: ${e}`);
|
|
174
636
|
logger.debug(e);
|
|
175
637
|
return;
|
|
176
638
|
}
|
|
177
639
|
}
|
|
178
|
-
async getProjects() {
|
|
179
|
-
try {
|
|
180
|
-
return await this.client.get(this.makeUrl(`${this.organisationApiUrl}/_apis/projects`)).json();
|
|
181
|
-
} catch (e) {
|
|
182
|
-
logger.error(`Failed to get projects: ${e}`);
|
|
183
|
-
logger.debug(e);
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
async getProject(idOrName) {
|
|
188
|
-
try {
|
|
189
|
-
return await this.client.get(this.makeUrl(`${this.organisationApiUrl}/_apis/projects/${encodeURIComponent(idOrName)}`)).json();
|
|
190
|
-
} catch (e) {
|
|
191
|
-
logger.error(`Failed to get project: ${e}`);
|
|
192
|
-
logger.debug(e);
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
async getRepositories(projectIdOrName) {
|
|
197
|
-
try {
|
|
198
|
-
return await this.client.get(this.makeUrl(`${this.organisationApiUrl}/${encodeURIComponent(projectIdOrName)}/_apis/git/repositories`)).json();
|
|
199
|
-
} catch (e) {
|
|
200
|
-
logger.error(`Failed to get repositories: ${e}`);
|
|
201
|
-
logger.debug(e);
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
async getRepository(projectIdOrName, repositoryIdOrName) {
|
|
206
|
-
try {
|
|
207
|
-
return await this.client.get(this.makeUrl(`${this.organisationApiUrl}/${encodeURIComponent(projectIdOrName)}/_apis/git/repositories/${encodeURIComponent(repositoryIdOrName)}`)).json();
|
|
208
|
-
} catch (e) {
|
|
209
|
-
if (isHTTPError(e) && e.response.status === 404) return;
|
|
210
|
-
else {
|
|
211
|
-
logger.error(`Failed to get repository: ${e}`);
|
|
212
|
-
logger.debug(e);
|
|
213
|
-
}
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
async getRepositoryItem(projectIdOrName, repositoryIdOrName, path$1, includeContent = true, latestProcessedChange = true) {
|
|
218
|
-
try {
|
|
219
|
-
return await this.client.get(this.makeUrl(`${this.organisationApiUrl}/${encodeURIComponent(projectIdOrName)}/_apis/git/repositories/${encodeURIComponent(repositoryIdOrName)}/items`, {
|
|
220
|
-
path: path$1,
|
|
221
|
-
includeContent,
|
|
222
|
-
latestProcessedChange
|
|
223
|
-
})).json();
|
|
224
|
-
} catch (e) {
|
|
225
|
-
if (isHTTPError(e) && e.response.status === 404) return;
|
|
226
|
-
else {
|
|
227
|
-
logger.error(`Failed to get repository item: ${e}`);
|
|
228
|
-
logger.debug(e);
|
|
229
|
-
}
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
640
|
/**
|
|
234
641
|
* Get the default branch for a repository.
|
|
642
|
+
*
|
|
235
643
|
* Requires scope "Code (Read)" (vso.code).
|
|
236
|
-
* @param project
|
|
237
|
-
* @
|
|
238
|
-
* @returns
|
|
644
|
+
* @param options Repository identification options (project and repository)
|
|
645
|
+
* @returns The normalized default branch name (e.g., "main"), or undefined if not found
|
|
239
646
|
*/
|
|
240
|
-
async getDefaultBranch(
|
|
241
|
-
|
|
242
|
-
const repo = await this.client.get(this.makeUrl(`${this.organisationApiUrl}/${project}/_apis/git/repositories/${repository}`)).json();
|
|
243
|
-
if (!repo) throw new Error(`Repository '${project}/${repository}' not found`);
|
|
244
|
-
return normalizeBranchName(repo.defaultBranch);
|
|
245
|
-
} catch (e) {
|
|
246
|
-
logger.error(`Failed to get default branch for '${project}/${repository}': ${e}`);
|
|
247
|
-
logger.debug(e);
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
647
|
+
async getDefaultBranch(options) {
|
|
648
|
+
return normalizeBranchName((await this.inner.repositories.get(options.project, options.repository))?.defaultBranch);
|
|
250
649
|
}
|
|
251
650
|
/**
|
|
252
651
|
* Get the list of branch names for a repository.
|
|
652
|
+
*
|
|
253
653
|
* Requires scope "Code (Read)" (vso.code).
|
|
254
|
-
* @param project
|
|
255
|
-
* @
|
|
256
|
-
* @returns
|
|
654
|
+
* @param options Repository identification options (project and repository)
|
|
655
|
+
* @returns Array of normalized branch names, or undefined if not found
|
|
257
656
|
*/
|
|
258
|
-
async getBranchNames(
|
|
259
|
-
|
|
260
|
-
const refs = await this.client.get(this.makeUrl(`${this.organisationApiUrl}/${project}/_apis/git/repositories/${repository}/refs`)).json();
|
|
261
|
-
if (!refs) throw new Error(`Repository '${project}/${repository}' not found`);
|
|
262
|
-
return refs.value?.map((r) => normalizeBranchName(r.name)) || [];
|
|
263
|
-
} catch (e) {
|
|
264
|
-
logger.error(`Failed to list branch names for '${project}/${repository}': ${e}`);
|
|
265
|
-
logger.debug(e);
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
657
|
+
async getBranchNames(options) {
|
|
658
|
+
return (await this.inner.repositories.getRefs(options.project, options.repository))?.map((r) => normalizeBranchName(r.name));
|
|
268
659
|
}
|
|
269
660
|
/**
|
|
270
|
-
* Get the properties for all active pull
|
|
661
|
+
* Get the properties for all active pull requests created by the specified user.
|
|
662
|
+
* This retrieves both the pull request IDs and their associated properties.
|
|
663
|
+
*
|
|
271
664
|
* Requires scope "Code (Read)" (vso.code).
|
|
272
|
-
* @param
|
|
273
|
-
* @
|
|
274
|
-
* @param creator
|
|
275
|
-
* @returns
|
|
665
|
+
* @param options Repository identification options including the creator user ID
|
|
666
|
+
* @returns Array of pull request IDs with their properties, empty array on error
|
|
276
667
|
*/
|
|
277
|
-
async getActivePullRequestProperties(project, repository,
|
|
668
|
+
async getActivePullRequestProperties({ project, repository, creatorId }) {
|
|
278
669
|
try {
|
|
279
|
-
const pullRequests = await this.
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if (!pullRequests?.value || pullRequests.value.length === 0) return [];
|
|
284
|
-
return await Promise.all(pullRequests.value.map(async (pr) => {
|
|
285
|
-
const properties = await this.client.get(this.makeUrl(`${this.organisationApiUrl}/${project}/_apis/git/repositories/${repository}/pullrequests/${pr.pullRequestId}/properties`)).json();
|
|
670
|
+
const pullRequests = await this.inner.pullRequests.list(project, repository, creatorId, "active");
|
|
671
|
+
if (!pullRequests || pullRequests.length === 0) return [];
|
|
672
|
+
return await Promise.all(pullRequests.map(async (pr) => {
|
|
673
|
+
const properties = await this.inner.pullRequests.getProperties(project, repository, pr.pullRequestId);
|
|
286
674
|
return {
|
|
287
|
-
|
|
288
|
-
properties
|
|
289
|
-
name: key,
|
|
290
|
-
value: val?.$value
|
|
291
|
-
}))
|
|
675
|
+
pullRequestId: pr.pullRequestId,
|
|
676
|
+
properties
|
|
292
677
|
};
|
|
293
678
|
}));
|
|
294
679
|
} catch (e) {
|
|
@@ -298,32 +683,39 @@ var AzureDevOpsWebApiClient = class AzureDevOpsWebApiClient {
|
|
|
298
683
|
}
|
|
299
684
|
}
|
|
300
685
|
/**
|
|
301
|
-
* Create a new pull request.
|
|
686
|
+
* Create a new pull request with the specified changes.
|
|
687
|
+
* This method performs the following operations:
|
|
688
|
+
* 1. Resolves assignee identities for assignees (if specified)
|
|
689
|
+
* 2. Creates a new branch and pushes changes
|
|
690
|
+
* 3. Creates the pull request with assignees (optional reviewers), labels, and work items
|
|
691
|
+
* 4. Sets pull request properties for dependency metadata
|
|
692
|
+
* 5. Configures auto-complete options (if specified)
|
|
693
|
+
*
|
|
302
694
|
* Requires scope "Code (Write)" (vso.code_write).
|
|
303
695
|
* Requires scope "Identity (Read)" (vso.identity), if assignees are specified.
|
|
304
|
-
* @param
|
|
305
|
-
* @returns
|
|
696
|
+
* @param options Pull request creation options including changes, assignees, and auto-complete settings
|
|
697
|
+
* @returns The created pull request ID, or null on error
|
|
306
698
|
*/
|
|
307
|
-
async createPullRequest(
|
|
308
|
-
logger.info(`Creating pull request '${
|
|
699
|
+
async createPullRequest(options) {
|
|
700
|
+
logger.info(`Creating pull request '${options.title}'...`);
|
|
309
701
|
try {
|
|
310
702
|
const userId = await this.getUserId();
|
|
311
703
|
const reviewers = [];
|
|
312
|
-
if (
|
|
313
|
-
const identityId = isGuid(assignee) ? assignee : await this.resolveIdentityId(assignee);
|
|
704
|
+
if (options.assignees && options.assignees.length > 0) for (const assignee of options.assignees) {
|
|
705
|
+
const identityId = this.isGuid(assignee) ? assignee : await this.resolveIdentityId(assignee);
|
|
314
706
|
if (identityId && !reviewers.some((r) => r.id === identityId)) reviewers.push({ id: identityId });
|
|
315
707
|
else logger.warn(`Unable to resolve assignee identity '${assignee}'`);
|
|
316
708
|
}
|
|
317
|
-
logger.info(` - Pushing ${
|
|
318
|
-
const push = await this.
|
|
709
|
+
logger.info(` - Pushing ${options.changes.length} file change(s) to branch '${options.source.branch}'...`);
|
|
710
|
+
const push = await this.inner.git.createPush(options.project, options.repository, {
|
|
319
711
|
refUpdates: [{
|
|
320
|
-
name: `refs/heads/${
|
|
321
|
-
oldObjectId:
|
|
712
|
+
name: `refs/heads/${options.source.branch}`,
|
|
713
|
+
oldObjectId: options.source.commit
|
|
322
714
|
}],
|
|
323
715
|
commits: [{
|
|
324
|
-
comment:
|
|
325
|
-
author:
|
|
326
|
-
changes:
|
|
716
|
+
comment: options.commitMessage,
|
|
717
|
+
author: options.author,
|
|
718
|
+
changes: options.changes.filter((change) => change.changeType !== "none").map(({ changeType, ...change }) => {
|
|
327
719
|
return {
|
|
328
720
|
changeType,
|
|
329
721
|
item: { path: normalizeFilePath(change.path) },
|
|
@@ -334,46 +726,37 @@ var AzureDevOpsWebApiClient = class AzureDevOpsWebApiClient {
|
|
|
334
726
|
};
|
|
335
727
|
})
|
|
336
728
|
}]
|
|
337
|
-
}
|
|
729
|
+
});
|
|
338
730
|
if (!push?.commits?.length) throw new Error("Failed to push changes to source branch, no commits were created");
|
|
339
731
|
logger.info(` - Pushed commit: ${push.commits.map((c) => c.commitId).join(", ")}.`);
|
|
340
|
-
logger.info(` - Creating pull request to merge '${
|
|
341
|
-
const pullRequest = await this.
|
|
342
|
-
sourceRefName: `refs/heads/${
|
|
343
|
-
targetRefName: `refs/heads/${
|
|
344
|
-
title:
|
|
345
|
-
description:
|
|
732
|
+
logger.info(` - Creating pull request to merge '${options.source.branch}' into '${options.target.branch}'...`);
|
|
733
|
+
const pullRequest = await this.inner.pullRequests.create(options.project, options.repository, {
|
|
734
|
+
sourceRefName: `refs/heads/${options.source.branch}`,
|
|
735
|
+
targetRefName: `refs/heads/${options.target.branch}`,
|
|
736
|
+
title: options.title,
|
|
737
|
+
description: options.description,
|
|
346
738
|
reviewers,
|
|
347
|
-
workItemRefs:
|
|
348
|
-
labels:
|
|
349
|
-
}
|
|
739
|
+
workItemRefs: options.workItems?.map((id) => ({ id })),
|
|
740
|
+
labels: options.labels?.map((label) => ({ name: label }))
|
|
741
|
+
});
|
|
350
742
|
if (!pullRequest?.pullRequestId) throw new Error("Failed to create pull request, no pull request id was returned");
|
|
351
743
|
logger.info(` - Created pull request: #${pullRequest.pullRequestId}.`);
|
|
352
|
-
if (
|
|
744
|
+
if (options.properties && options.properties.length > 0) {
|
|
353
745
|
logger.info(` - Adding dependency metadata to pull request properties...`);
|
|
354
|
-
if (!(await this.
|
|
355
|
-
json: pr.properties.map((property) => {
|
|
356
|
-
return {
|
|
357
|
-
op: "add",
|
|
358
|
-
path: `/${property.name}`,
|
|
359
|
-
value: property.value
|
|
360
|
-
};
|
|
361
|
-
}),
|
|
362
|
-
headers: { "Content-Type": "application/json-patch+json" }
|
|
363
|
-
}).json())?.count) throw new Error("Failed to add dependency metadata properties to pull request");
|
|
746
|
+
if (!(await this.inner.pullRequests.setProperties(options.project, options.repository, pullRequest.pullRequestId, options.properties))?.count) throw new Error("Failed to add dependency metadata properties to pull request");
|
|
364
747
|
}
|
|
365
|
-
if (
|
|
748
|
+
if (options.autoComplete) {
|
|
366
749
|
logger.info(` - Updating auto-complete options...`);
|
|
367
|
-
const updatedPullRequest = await this.
|
|
750
|
+
const updatedPullRequest = await this.inner.pullRequests.update(options.project, options.repository, pullRequest.pullRequestId, {
|
|
368
751
|
autoCompleteSetBy: { id: userId },
|
|
369
752
|
completionOptions: {
|
|
370
|
-
autoCompleteIgnoreConfigIds:
|
|
753
|
+
autoCompleteIgnoreConfigIds: options.autoComplete.ignorePolicyConfigIds,
|
|
371
754
|
deleteSourceBranch: true,
|
|
372
|
-
mergeCommitMessage: mergeCommitMessage(pullRequest.pullRequestId,
|
|
373
|
-
mergeStrategy:
|
|
755
|
+
mergeCommitMessage: this.mergeCommitMessage(pullRequest.pullRequestId, options.title, options.description),
|
|
756
|
+
mergeStrategy: options.autoComplete.mergeStrategy,
|
|
374
757
|
transitionWorkItems: false
|
|
375
758
|
}
|
|
376
|
-
}
|
|
759
|
+
});
|
|
377
760
|
if (!updatedPullRequest || updatedPullRequest.autoCompleteSetBy?.id !== userId) throw new Error("Failed to set auto-complete on pull request");
|
|
378
761
|
}
|
|
379
762
|
logger.info(` - Pull request was created successfully.`);
|
|
@@ -385,29 +768,29 @@ var AzureDevOpsWebApiClient = class AzureDevOpsWebApiClient {
|
|
|
385
768
|
}
|
|
386
769
|
}
|
|
387
770
|
/**
|
|
388
|
-
* Update
|
|
771
|
+
* Update an existing pull request with new changes.
|
|
772
|
+
* This method performs the following operations:
|
|
773
|
+
* 1. Validates the pull request hasn't been modified by another author
|
|
774
|
+
* 2. Checks if the source branch is behind the target branch
|
|
775
|
+
* 3. Rebases the target branch into the source branch if needed
|
|
776
|
+
* 4. Pushes the new changes to the source branch
|
|
777
|
+
*
|
|
389
778
|
* Requires scope "Code (Read & Write)" (vso.code, vso.code_write).
|
|
390
|
-
* @param
|
|
391
|
-
* @returns
|
|
779
|
+
* @param options Pull request update options including the commit and changes
|
|
780
|
+
* @returns True if successful, false on error
|
|
392
781
|
*/
|
|
393
|
-
async updatePullRequest(
|
|
394
|
-
logger.info(`Updating pull request #${
|
|
782
|
+
async updatePullRequest(options) {
|
|
783
|
+
logger.info(`Updating pull request #${options.pullRequestId}...`);
|
|
395
784
|
try {
|
|
396
|
-
const pullRequest = await this.
|
|
397
|
-
if (!pullRequest) throw new Error(`Pull request #${
|
|
398
|
-
if (
|
|
399
|
-
logger.info(` - Skipping update as pull request
|
|
785
|
+
const pullRequest = await this.inner.pullRequests.get(options.project, options.repository, options.pullRequestId);
|
|
786
|
+
if (!pullRequest) throw new Error(`Pull request #${options.pullRequestId} not found`);
|
|
787
|
+
if ((await this.inner.pullRequests.getCommits(options.project, options.repository, options.pullRequestId))?.some((c) => c.author?.email !== options.author.email)) {
|
|
788
|
+
logger.info(` - Skipping update as pull request has been modified by another user.`);
|
|
400
789
|
return true;
|
|
401
790
|
}
|
|
402
|
-
|
|
403
|
-
if ((await this.client.get(this.makeUrl(`${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/pullrequests/${pr.pullRequestId}/commits`)).json())?.value?.some((c) => c.author?.email !== pr.skipIfCommitsFromAuthorsOtherThan)) {
|
|
404
|
-
logger.info(` - Skipping update as pull request has been modified by another user.`);
|
|
405
|
-
return true;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
const stats = await this.client.get(this.makeUrl(`${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/stats/branches`, { name: normalizeBranchName(pullRequest.sourceRefName) })).json();
|
|
791
|
+
const stats = await this.inner.repositories.getBranchStats(options.project, options.repository, normalizeBranchName(pullRequest.sourceRefName));
|
|
409
792
|
if (stats?.behindCount === void 0) throw new Error(`Failed to get branch stats for '${pullRequest.sourceRefName}'`);
|
|
410
|
-
if (
|
|
793
|
+
if (stats.behindCount === 0) {
|
|
411
794
|
logger.info(` - Skipping update as source branch is not behind target branch.`);
|
|
412
795
|
return true;
|
|
413
796
|
}
|
|
@@ -415,22 +798,22 @@ var AzureDevOpsWebApiClient = class AzureDevOpsWebApiClient {
|
|
|
415
798
|
const targetBranchName = normalizeBranchName(pullRequest.targetRefName);
|
|
416
799
|
if (stats.behindCount > 0) {
|
|
417
800
|
logger.info(` - Rebasing '${targetBranchName}' into '${sourceBranchName}' (${stats.behindCount} commit(s) behind)...`);
|
|
418
|
-
if ((await this.
|
|
801
|
+
if ((await this.inner.git.updateRef(options.project, options.repository, [{
|
|
419
802
|
name: pullRequest.sourceRefName,
|
|
420
803
|
oldObjectId: pullRequest.lastMergeSourceCommit.commitId,
|
|
421
|
-
newObjectId:
|
|
422
|
-
}]
|
|
804
|
+
newObjectId: options.commit
|
|
805
|
+
}]))?.[0]?.success !== true) throw new Error("Failed to rebase the target branch into the source branch");
|
|
423
806
|
}
|
|
424
|
-
logger.info(` - Pushing ${
|
|
425
|
-
const push = await this.
|
|
807
|
+
logger.info(` - Pushing ${options.changes.length} file change(s) to branch '${pullRequest.sourceRefName}'...`);
|
|
808
|
+
const push = await this.inner.git.createPush(options.project, options.repository, {
|
|
426
809
|
refUpdates: [{
|
|
427
810
|
name: pullRequest.sourceRefName,
|
|
428
|
-
oldObjectId:
|
|
811
|
+
oldObjectId: options.commit
|
|
429
812
|
}],
|
|
430
813
|
commits: [{
|
|
431
814
|
comment: pullRequest.mergeStatus === "conflicts" ? "Resolve merge conflicts" : `Rebase '${sourceBranchName}' onto '${targetBranchName}'`,
|
|
432
|
-
author:
|
|
433
|
-
changes:
|
|
815
|
+
author: options.author,
|
|
816
|
+
changes: options.changes.filter((change) => change.changeType !== "none").map(({ changeType, ...change }) => {
|
|
434
817
|
return {
|
|
435
818
|
changeType,
|
|
436
819
|
item: { path: normalizeFilePath(change.path) },
|
|
@@ -441,7 +824,7 @@ var AzureDevOpsWebApiClient = class AzureDevOpsWebApiClient {
|
|
|
441
824
|
};
|
|
442
825
|
})
|
|
443
826
|
}]
|
|
444
|
-
}
|
|
827
|
+
});
|
|
445
828
|
if (!push?.commits?.length) throw new Error("Failed to push changes to source branch, no commits were created");
|
|
446
829
|
logger.info(` - Pushed commit: ${push.commits.map((c) => c.commitId).join(", ")}.`);
|
|
447
830
|
logger.info(` - Pull request was updated successfully.`);
|
|
@@ -453,20 +836,19 @@ var AzureDevOpsWebApiClient = class AzureDevOpsWebApiClient {
|
|
|
453
836
|
}
|
|
454
837
|
}
|
|
455
838
|
/**
|
|
456
|
-
* Approve a pull request.
|
|
839
|
+
* Approve a pull request as the authenticated user.
|
|
840
|
+
* Sets the reviewer vote to 10 (approved).
|
|
841
|
+
*
|
|
457
842
|
* Requires scope "Code (Write)" (vso.code_write).
|
|
458
|
-
* @param
|
|
459
|
-
* @returns
|
|
843
|
+
* @param options Pull request identification options
|
|
844
|
+
* @returns True if successful, false on error
|
|
460
845
|
*/
|
|
461
|
-
async approvePullRequest(
|
|
462
|
-
logger.info(`Approving pull request #${
|
|
846
|
+
async approvePullRequest(options) {
|
|
847
|
+
logger.info(`Approving pull request #${options.pullRequestId}...`);
|
|
463
848
|
try {
|
|
464
849
|
logger.info(` - Updating reviewer vote on pull request...`);
|
|
465
850
|
const userId = await this.getUserId();
|
|
466
|
-
if ((await this.
|
|
467
|
-
vote: 10,
|
|
468
|
-
isReapprove: true
|
|
469
|
-
} }).json())?.vote !== 10) throw new Error("Failed to approve pull request, vote was not recorded");
|
|
851
|
+
if ((await this.inner.pullRequests.approve(options.project, options.repository, options.pullRequestId, userId))?.vote !== 10) throw new Error("Failed to approve pull request, vote was not recorded");
|
|
470
852
|
logger.info(` - Pull request was approved successfully.`);
|
|
471
853
|
return true;
|
|
472
854
|
} catch (e) {
|
|
@@ -476,37 +858,39 @@ var AzureDevOpsWebApiClient = class AzureDevOpsWebApiClient {
|
|
|
476
858
|
}
|
|
477
859
|
}
|
|
478
860
|
/**
|
|
479
|
-
* Abandon a pull request.
|
|
861
|
+
* Abandon a pull request and optionally delete its source branch.
|
|
862
|
+
* This method performs the following operations:
|
|
863
|
+
* 1. Adds an optional comment explaining the abandonment reason
|
|
864
|
+
* 2. Sets the pull request status to abandoned
|
|
865
|
+
* 3. Deletes the source branch if requested
|
|
866
|
+
*
|
|
480
867
|
* Requires scope "Code (Write)" (vso.code_write).
|
|
481
|
-
* @param
|
|
482
|
-
* @returns
|
|
868
|
+
* @param options Pull request abandonment options including optional comment and branch deletion flag
|
|
869
|
+
* @returns True if successful, false on error
|
|
483
870
|
*/
|
|
484
|
-
async abandonPullRequest(
|
|
485
|
-
logger.info(`Abandoning pull request #${
|
|
871
|
+
async abandonPullRequest(options) {
|
|
872
|
+
logger.info(`Abandoning pull request #${options.pullRequestId}...`);
|
|
486
873
|
try {
|
|
487
874
|
const userId = await this.getUserId();
|
|
488
|
-
if (
|
|
875
|
+
if (options.comment) {
|
|
489
876
|
logger.info(` - Adding abandonment reason comment to pull request...`);
|
|
490
877
|
if (!await this.addCommentThread({
|
|
491
|
-
...
|
|
492
|
-
content:
|
|
878
|
+
...options,
|
|
879
|
+
content: options.comment,
|
|
493
880
|
userId
|
|
494
881
|
})) throw new Error("Failed to add comment to pull request, thread was not created");
|
|
495
882
|
}
|
|
496
883
|
logger.info(` - Abandoning pull request...`);
|
|
497
|
-
const abandonedPullRequest = await this.
|
|
498
|
-
status: "abandoned",
|
|
499
|
-
closedBy: { id: userId }
|
|
500
|
-
} }).json();
|
|
884
|
+
const abandonedPullRequest = await this.inner.pullRequests.abandon(options.project, options.repository, options.pullRequestId, userId);
|
|
501
885
|
if (abandonedPullRequest?.status !== "abandoned") throw new Error("Failed to abandon pull request, status was not updated");
|
|
502
|
-
if (
|
|
886
|
+
if (options.deleteSourceBranch) {
|
|
503
887
|
logger.info(` - Deleting source branch...`);
|
|
504
|
-
if ((await this.
|
|
888
|
+
if ((await this.inner.git.updateRef(options.project, options.repository, [{
|
|
505
889
|
name: abandonedPullRequest.sourceRefName,
|
|
506
890
|
oldObjectId: abandonedPullRequest.lastMergeSourceCommit.commitId,
|
|
507
891
|
newObjectId: "0000000000000000000000000000000000000000",
|
|
508
892
|
isLocked: false
|
|
509
|
-
}]
|
|
893
|
+
}]))?.[0]?.success !== true) throw new Error("Failed to delete the source branch");
|
|
510
894
|
}
|
|
511
895
|
logger.info(` - Pull request was abandoned successfully.`);
|
|
512
896
|
return true;
|
|
@@ -518,68 +902,149 @@ var AzureDevOpsWebApiClient = class AzureDevOpsWebApiClient {
|
|
|
518
902
|
}
|
|
519
903
|
/**
|
|
520
904
|
* Add a comment thread on a pull request.
|
|
905
|
+
* The comment thread is created with a closed status and system comment type.
|
|
906
|
+
*
|
|
521
907
|
* Requires scope "Code (Write)" (vso.code_write).
|
|
908
|
+
* @param options Comment creation options including content and optional user ID
|
|
909
|
+
* @returns The created thread ID, or undefined on error
|
|
522
910
|
*/
|
|
523
|
-
async addCommentThread(
|
|
524
|
-
const userId =
|
|
525
|
-
return (await this.
|
|
911
|
+
async addCommentThread(options) {
|
|
912
|
+
const userId = options.userId ?? await this.getUserId();
|
|
913
|
+
return (await this.inner.pullRequests.createCommentThread(options.project, options.repository, options.pullRequestId, {
|
|
526
914
|
status: "closed",
|
|
527
915
|
comments: [{
|
|
528
916
|
author: { id: userId },
|
|
529
|
-
content:
|
|
917
|
+
content: options.content,
|
|
530
918
|
commentType: "system"
|
|
531
919
|
}]
|
|
532
|
-
}
|
|
920
|
+
}))?.id;
|
|
533
921
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
922
|
+
/**
|
|
923
|
+
* Create or update webhook subscriptions for Azure DevOps events.
|
|
924
|
+
* This sets up subscriptions for various git events (push, pull request updates, repository changes, etc.)
|
|
925
|
+
* and ensures they are configured to send webhooks to the specified URL.
|
|
926
|
+
* Existing subscriptions matching the URL will be updated, otherwise new subscriptions are created.
|
|
927
|
+
*
|
|
928
|
+
* Requires scope "Service Hooks (Read & Write)" (vso.hooks_write).
|
|
929
|
+
* @returns Array of subscription IDs that were created or updated
|
|
930
|
+
*/
|
|
931
|
+
async createOrUpdateHookSubscriptions({ url, headers, project }) {
|
|
932
|
+
const subscriptionTypes = new Map([
|
|
933
|
+
["git.push", "1.0"],
|
|
934
|
+
["git.pullrequest.updated", "1.0"],
|
|
935
|
+
["git.pullrequest.merged", "1.0"],
|
|
936
|
+
["git.repo.created", "1.0-preview.1"],
|
|
937
|
+
["git.repo.deleted", "1.0-preview.1"],
|
|
938
|
+
["git.repo.renamed", "1.0-preview.1"],
|
|
939
|
+
["git.repo.statuschanged", "1.0-preview.1"],
|
|
940
|
+
["ms.vss-code.git-pullrequest-comment-event", "2.0"]
|
|
941
|
+
]);
|
|
942
|
+
const query = this.buildSubscriptionsQuery({
|
|
943
|
+
url,
|
|
944
|
+
project
|
|
945
|
+
});
|
|
946
|
+
const subscriptions = await this.inner.subscriptions.query(query);
|
|
947
|
+
const ids = [];
|
|
948
|
+
for (const [eventType, resourceVersion] of subscriptionTypes) {
|
|
949
|
+
const existing = subscriptions.find((sub) => {
|
|
950
|
+
return sub.eventType === eventType && sub.resourceVersion === resourceVersion;
|
|
951
|
+
});
|
|
952
|
+
let subscription;
|
|
953
|
+
if (existing) {
|
|
954
|
+
existing.status = "enabled";
|
|
955
|
+
existing.eventType = eventType;
|
|
956
|
+
existing.resourceVersion = resourceVersion;
|
|
957
|
+
existing.publisherInputs = this.makeTfsPublisherInputs({
|
|
958
|
+
eventType,
|
|
959
|
+
project
|
|
960
|
+
});
|
|
961
|
+
existing.consumerInputs = this.makeWebhookConsumerInputs({
|
|
962
|
+
url,
|
|
963
|
+
headers
|
|
964
|
+
});
|
|
965
|
+
subscription = await this.inner.subscriptions.replace(existing.id, existing);
|
|
966
|
+
} else subscription = await this.inner.subscriptions.create({
|
|
967
|
+
status: "enabled",
|
|
968
|
+
eventType,
|
|
969
|
+
resourceVersion,
|
|
970
|
+
publisherId: "tfs",
|
|
971
|
+
publisherInputs: this.makeTfsPublisherInputs({
|
|
972
|
+
eventType,
|
|
973
|
+
project
|
|
974
|
+
}),
|
|
975
|
+
consumerId: "webHooks",
|
|
976
|
+
consumerActionId: "httpRequest",
|
|
977
|
+
consumerInputs: this.makeWebhookConsumerInputs({
|
|
978
|
+
url,
|
|
979
|
+
headers
|
|
980
|
+
})
|
|
981
|
+
});
|
|
982
|
+
ids.push(subscription.id);
|
|
538
983
|
}
|
|
539
|
-
|
|
540
|
-
"api-version": apiVersion,
|
|
541
|
-
...params
|
|
542
|
-
}).map(([key, value]) => `${key}=${value}`).join("&")}`;
|
|
984
|
+
for (const sub of subscriptions) if (!ids.includes(sub.id)) await this.inner.subscriptions.delete(sub.id);
|
|
543
985
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
afterResponse: [async (request, options, response) => {
|
|
555
|
-
if (this.debug) {
|
|
556
|
-
logger.debug(`🌎 🠈 [${response.status}] ${response.statusText}`);
|
|
557
|
-
if (request.body) logger.debug(`REQUEST: ${JSON.stringify(request.body)}`);
|
|
558
|
-
}
|
|
559
|
-
}],
|
|
560
|
-
beforeRetry: [async ({ request, options, error, retryCount }) => {
|
|
561
|
-
if (this.debug && isHTTPError(error)) logger.debug(`⏳ Retrying failed request with status code: ${error.response.status}`);
|
|
562
|
-
}]
|
|
563
|
-
},
|
|
564
|
-
retry: {
|
|
565
|
-
limit: 3,
|
|
566
|
-
delay: (attempt) => 3e3
|
|
567
|
-
}
|
|
986
|
+
/**
|
|
987
|
+
* Remove all webhook subscriptions for a specific URL.
|
|
988
|
+
* This finds all subscriptions matching the provided URL and deletes them.
|
|
989
|
+
*
|
|
990
|
+
* Requires scope "Service Hooks (Read & Write)" (vso.hooks_write).
|
|
991
|
+
*/
|
|
992
|
+
async deleteHookSubscriptions({ url, project }) {
|
|
993
|
+
const query = this.buildSubscriptionsQuery({
|
|
994
|
+
url,
|
|
995
|
+
project
|
|
568
996
|
});
|
|
997
|
+
const subscriptions = await this.inner.subscriptions.query(query);
|
|
998
|
+
for (const sub of subscriptions) await this.inner.subscriptions.delete(sub.id);
|
|
999
|
+
}
|
|
1000
|
+
mergeCommitMessage(id, title, description) {
|
|
1001
|
+
return `Merged PR ${id}: ${title}\n\n${description}`.slice(0, 3500);
|
|
1002
|
+
}
|
|
1003
|
+
isGuid(guid) {
|
|
1004
|
+
return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(guid);
|
|
1005
|
+
}
|
|
1006
|
+
buildSubscriptionsQuery({ url, project }) {
|
|
1007
|
+
return {
|
|
1008
|
+
publisherId: "tfs",
|
|
1009
|
+
publisherInputFilters: [{ conditions: [{
|
|
1010
|
+
operator: "equals",
|
|
1011
|
+
inputId: "projectId",
|
|
1012
|
+
caseSensitive: false,
|
|
1013
|
+
inputValue: project
|
|
1014
|
+
}] }],
|
|
1015
|
+
consumerId: "webHooks",
|
|
1016
|
+
consumerActionId: "httpRequest",
|
|
1017
|
+
consumerInputFilters: [{ conditions: [{
|
|
1018
|
+
operator: "equals",
|
|
1019
|
+
inputId: "url",
|
|
1020
|
+
caseSensitive: false,
|
|
1021
|
+
inputValue: url
|
|
1022
|
+
}] }]
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
makeTfsPublisherInputs({ eventType, project }) {
|
|
1026
|
+
return {
|
|
1027
|
+
projectId: project,
|
|
1028
|
+
...eventType === "git.pullrequest.updated" && { notificationType: "StatusUpdateNotification" },
|
|
1029
|
+
...eventType === "git.pullrequest.merged" && { mergeResult: "Conflicts" }
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1032
|
+
makeWebhookConsumerInputs({ url, headers }) {
|
|
1033
|
+
return {
|
|
1034
|
+
url,
|
|
1035
|
+
acceptUntrustedCerts: "false",
|
|
1036
|
+
httpHeaders: Object.entries(headers).map(([key, value]) => `${key}:${value}`).join("\n"),
|
|
1037
|
+
messagesToSend: "none",
|
|
1038
|
+
detailedMessagesToSend: "none"
|
|
1039
|
+
};
|
|
569
1040
|
}
|
|
570
1041
|
};
|
|
571
|
-
function mergeCommitMessage(id, title, description) {
|
|
572
|
-
return `Merged PR ${id}: ${title}\n\n${description}`.slice(0, 3500);
|
|
573
|
-
}
|
|
574
|
-
function isGuid(guid) {
|
|
575
|
-
return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(guid);
|
|
576
|
-
}
|
|
577
1042
|
|
|
578
1043
|
//#endregion
|
|
579
1044
|
//#region src/azure/config.ts
|
|
580
1045
|
/**
|
|
581
1046
|
* Parse the dependabot config YAML file to specify update configuration.
|
|
582
|
-
* The file should be located at any of `
|
|
1047
|
+
* The file should be located at any of `CONFIG_FILE_PATHS_AZURE`.
|
|
583
1048
|
*
|
|
584
1049
|
* To view YAML file format, visit
|
|
585
1050
|
* https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#allow
|
|
@@ -591,7 +1056,7 @@ async function getDependabotConfig({ url, token, remote, rootDir = process.cwd()
|
|
|
591
1056
|
let configContents;
|
|
592
1057
|
if (remote) {
|
|
593
1058
|
logger.debug(`Attempting to fetch configuration file via REST API ...`);
|
|
594
|
-
for (const fp of
|
|
1059
|
+
for (const fp of CONFIG_FILE_PATHS_AZURE) {
|
|
595
1060
|
const requestUrl = `${url.value}${url.project}/_apis/git/repositories/${url.repository}/items?path=/${fp}`;
|
|
596
1061
|
logger.debug(`GET ${requestUrl}`);
|
|
597
1062
|
try {
|
|
@@ -622,7 +1087,7 @@ async function getDependabotConfig({ url, token, remote, rootDir = process.cwd()
|
|
|
622
1087
|
else throw error;
|
|
623
1088
|
}
|
|
624
1089
|
}
|
|
625
|
-
} else for (const fp of
|
|
1090
|
+
} else for (const fp of CONFIG_FILE_PATHS_AZURE) {
|
|
626
1091
|
const filePath = path.join(rootDir, fp);
|
|
627
1092
|
if (existsSync(filePath)) {
|
|
628
1093
|
logger.debug(`Found configuration file cloned at ${filePath}`);
|
|
@@ -631,7 +1096,7 @@ async function getDependabotConfig({ url, token, remote, rootDir = process.cwd()
|
|
|
631
1096
|
break;
|
|
632
1097
|
} else logger.trace(`No configuration file cloned at ${filePath}`);
|
|
633
1098
|
}
|
|
634
|
-
if (!configContents || !configPath || typeof configContents !== "string") throw new Error(`Configuration file not found at possible locations: ${
|
|
1099
|
+
if (!configContents || !configPath || typeof configContents !== "string") throw new Error(`Configuration file not found at possible locations: ${CONFIG_FILE_PATHS_AZURE.join(", ")}`);
|
|
635
1100
|
else logger.trace("Configuration file contents read.");
|
|
636
1101
|
return await parseDependabotConfig({
|
|
637
1102
|
configContents,
|
|
@@ -641,252 +1106,45 @@ async function getDependabotConfig({ url, token, remote, rootDir = process.cwd()
|
|
|
641
1106
|
}
|
|
642
1107
|
|
|
643
1108
|
//#endregion
|
|
644
|
-
//#region src/azure/
|
|
645
|
-
const
|
|
646
|
-
"
|
|
647
|
-
"
|
|
648
|
-
"
|
|
649
|
-
"
|
|
650
|
-
"
|
|
651
|
-
"
|
|
652
|
-
"
|
|
653
|
-
"
|
|
654
|
-
"merge",
|
|
655
|
-
"lock",
|
|
656
|
-
"rollback",
|
|
657
|
-
"sourceRename",
|
|
658
|
-
"targetRename",
|
|
659
|
-
"property",
|
|
660
|
-
"all"
|
|
661
|
-
]);
|
|
662
|
-
const AZDO_PULL_REQUEST_MERGE_STRATEGIES = [
|
|
663
|
-
"noFastForward",
|
|
664
|
-
"squash",
|
|
665
|
-
"rebase",
|
|
666
|
-
"rebaseMerge"
|
|
667
|
-
];
|
|
668
|
-
const AzdoPullRequestMergeStrategySchema = z.enum(AZDO_PULL_REQUEST_MERGE_STRATEGIES);
|
|
669
|
-
const AzdoCommentThreadStatusSchema = z.enum([
|
|
670
|
-
"unknown",
|
|
671
|
-
"active",
|
|
672
|
-
"fixed",
|
|
673
|
-
"wontFix",
|
|
674
|
-
"closed",
|
|
675
|
-
"byDesign",
|
|
676
|
-
"pending"
|
|
677
|
-
]);
|
|
678
|
-
const AzdoCommentTypeSchema = z.enum([
|
|
679
|
-
"unknown",
|
|
680
|
-
"text",
|
|
681
|
-
"codeChange",
|
|
682
|
-
"system"
|
|
683
|
-
]);
|
|
684
|
-
const AzdoPullRequestAsyncStatusSchema = z.enum([
|
|
685
|
-
"notSet",
|
|
686
|
-
"queued",
|
|
687
|
-
"conflicts",
|
|
688
|
-
"succeeded",
|
|
689
|
-
"rejectedByPolicy",
|
|
690
|
-
"failure"
|
|
691
|
-
]);
|
|
692
|
-
const AzdoPullRequestStatusSchema = z.enum([
|
|
693
|
-
"notSet",
|
|
694
|
-
"active",
|
|
695
|
-
"abandoned",
|
|
696
|
-
"completed",
|
|
697
|
-
"all"
|
|
1109
|
+
//#region src/azure/events.ts
|
|
1110
|
+
const AzdoEventTypeSchema = z.enum([
|
|
1111
|
+
"git.push",
|
|
1112
|
+
"git.pullrequest.updated",
|
|
1113
|
+
"git.pullrequest.merged",
|
|
1114
|
+
"git.repo.created",
|
|
1115
|
+
"git.repo.deleted",
|
|
1116
|
+
"git.repo.renamed",
|
|
1117
|
+
"git.repo.statuschanged",
|
|
1118
|
+
"ms.vss-code.git-pullrequest-comment-event"
|
|
698
1119
|
]);
|
|
699
|
-
const
|
|
1120
|
+
const AzdoEventProjectSchema = z.object({
|
|
700
1121
|
id: z.string(),
|
|
701
1122
|
name: z.string(),
|
|
702
|
-
|
|
703
|
-
url: z.string(),
|
|
704
|
-
state: z.enum([
|
|
705
|
-
"deleting",
|
|
706
|
-
"new",
|
|
707
|
-
"wellFormed",
|
|
708
|
-
"createPending",
|
|
709
|
-
"all",
|
|
710
|
-
"unchanged",
|
|
711
|
-
"deleted"
|
|
712
|
-
]),
|
|
713
|
-
_links: z.object({
|
|
714
|
-
self: z.object({ href: z.string() }),
|
|
715
|
-
collection: z.object({ href: z.string() }),
|
|
716
|
-
web: z.object({ href: z.string() })
|
|
717
|
-
}).optional()
|
|
1123
|
+
url: z.string()
|
|
718
1124
|
});
|
|
719
|
-
const
|
|
1125
|
+
const AzdoEventRepositorySchema = z.object({
|
|
720
1126
|
id: z.string(),
|
|
721
1127
|
name: z.string(),
|
|
1128
|
+
project: AzdoEventProjectSchema,
|
|
722
1129
|
defaultBranch: z.string().optional(),
|
|
723
|
-
|
|
724
|
-
isDisabled: z.boolean().optional(),
|
|
725
|
-
isFork: z.boolean().optional(),
|
|
726
|
-
url: z.string(),
|
|
727
|
-
remoteUrl: z.string(),
|
|
728
|
-
webUrl: z.string()
|
|
729
|
-
});
|
|
730
|
-
const AzdoIdentitySchema = z.object({
|
|
731
|
-
id: z.string(),
|
|
732
|
-
displayName: z.string(),
|
|
733
|
-
url: z.string()
|
|
734
|
-
});
|
|
735
|
-
const AzdoIdentityRefSchema = z.object({
|
|
736
|
-
id: z.string().optional(),
|
|
737
|
-
displayName: z.string().optional(),
|
|
738
|
-
url: z.string().optional()
|
|
739
|
-
});
|
|
740
|
-
const AzdoConnectionDataSchema = z.object({
|
|
741
|
-
authenticatedUser: AzdoIdentitySchema,
|
|
742
|
-
authorizedUser: AzdoIdentitySchema
|
|
743
|
-
});
|
|
744
|
-
const AzdoGitUserDateSchema = z.object({
|
|
745
|
-
name: z.string(),
|
|
746
|
-
email: z.string(),
|
|
747
|
-
date: z.string().optional()
|
|
748
|
-
});
|
|
749
|
-
const AzdoGitRefSchema = z.object({
|
|
750
|
-
name: z.string(),
|
|
751
|
-
objectId: z.string(),
|
|
752
|
-
isLocked: z.boolean().optional()
|
|
753
|
-
});
|
|
754
|
-
const AzdoGitRefUpdateResultSchema = AzdoGitRefSchema.extend({
|
|
755
|
-
oldObjectId: z.string(),
|
|
756
|
-
newObjectId: z.string(),
|
|
757
|
-
success: z.boolean(),
|
|
758
|
-
customMessage: z.string().optional()
|
|
759
|
-
});
|
|
760
|
-
const AzdoGitChangeSchema = z.object({
|
|
761
|
-
changeType: AzdoVersionControlChangeTypeSchema,
|
|
762
|
-
newContent: z.object({
|
|
763
|
-
content: z.string(),
|
|
764
|
-
contentType: z.enum(["rawtext", "base64encoded"])
|
|
765
|
-
}).optional()
|
|
766
|
-
});
|
|
767
|
-
const AzdoGitCommitRefSchema = z.object({
|
|
768
|
-
commitId: z.string().optional(),
|
|
769
|
-
author: AzdoGitUserDateSchema.optional(),
|
|
770
|
-
committer: AzdoGitUserDateSchema.optional(),
|
|
771
|
-
changes: AzdoGitChangeSchema.array()
|
|
1130
|
+
remoteUrl: z.string()
|
|
772
1131
|
});
|
|
773
|
-
const
|
|
1132
|
+
const AzdoEventCodePushResourceSchema = z.object({
|
|
1133
|
+
repository: AzdoEventRepositorySchema,
|
|
774
1134
|
commits: AzdoGitCommitRefSchema.array(),
|
|
775
|
-
refUpdates: AzdoGitRefSchema.array()
|
|
776
|
-
});
|
|
777
|
-
const AzdoGitPushCreateSchema = z.object({
|
|
778
1135
|
refUpdates: z.object({
|
|
779
1136
|
name: z.string(),
|
|
780
|
-
oldObjectId: z.string(),
|
|
781
|
-
newObjectId: z.string().
|
|
1137
|
+
oldObjectId: z.string().nullish(),
|
|
1138
|
+
newObjectId: z.string().nullish()
|
|
782
1139
|
}).array(),
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
author: AzdoGitUserDateSchema.optional(),
|
|
786
|
-
changes: AzdoGitChangeSchema.extend({ item: z.object({ path: z.string() }) }).array()
|
|
787
|
-
}).array()
|
|
788
|
-
});
|
|
789
|
-
const AzdoGitBranchStatsSchema = z.object({
|
|
790
|
-
aheadCount: z.number(),
|
|
791
|
-
behindCount: z.number()
|
|
792
|
-
});
|
|
793
|
-
const AzdoRepositoryItemSchema = z.object({
|
|
794
|
-
latestProcessedChange: AzdoGitCommitRefSchema.optional(),
|
|
795
|
-
content: z.string().optional()
|
|
796
|
-
});
|
|
797
|
-
const AzdoPullRequestSchema = z.object({
|
|
798
|
-
pullRequestId: z.number(),
|
|
799
|
-
status: AzdoPullRequestStatusSchema,
|
|
800
|
-
isDraft: z.boolean(),
|
|
801
|
-
sourceRefName: z.string(),
|
|
802
|
-
targetRefName: z.string(),
|
|
803
|
-
lastMergeCommit: AzdoGitCommitRefSchema,
|
|
804
|
-
lastMergeSourceCommit: AzdoGitCommitRefSchema,
|
|
805
|
-
mergeStatus: AzdoPullRequestAsyncStatusSchema,
|
|
806
|
-
autoCompleteSetBy: AzdoIdentityRefSchema.optional(),
|
|
807
|
-
closedBy: AzdoIdentityRefSchema.optional()
|
|
808
|
-
});
|
|
809
|
-
const AdoPropertiesSchema = z.record(z.string(), z.object({
|
|
810
|
-
$type: z.string(),
|
|
811
|
-
$value: z.string()
|
|
812
|
-
}));
|
|
813
|
-
const AzdoIdentityRefWithVoteSchema = z.object({
|
|
814
|
-
id: z.string().optional(),
|
|
815
|
-
displayName: z.string().optional(),
|
|
816
|
-
vote: z.number().optional(),
|
|
817
|
-
hasDeclined: z.boolean().optional(),
|
|
818
|
-
isFlagged: z.boolean().optional(),
|
|
819
|
-
isRequired: z.boolean().optional()
|
|
820
|
-
});
|
|
821
|
-
const AzdoPullRequestCommentSchema = z.object({
|
|
822
|
-
id: z.number(),
|
|
823
|
-
parentCommentId: z.number().nullable(),
|
|
824
|
-
content: z.string(),
|
|
825
|
-
commentType: AzdoCommentTypeSchema,
|
|
826
|
-
publishedDate: z.string(),
|
|
827
|
-
author: AzdoIdentityRefSchema.optional()
|
|
828
|
-
});
|
|
829
|
-
const AzdoPullRequestCommentThreadSchema = z.object({
|
|
830
|
-
id: z.number(),
|
|
831
|
-
comments: AzdoPullRequestCommentSchema.array(),
|
|
832
|
-
status: AzdoCommentThreadStatusSchema
|
|
833
|
-
});
|
|
834
|
-
const AzdoSubscriptionSchema = z.object({
|
|
835
|
-
id: z.string().optional(),
|
|
836
|
-
status: z.enum([
|
|
837
|
-
"enabled",
|
|
838
|
-
"onProbation",
|
|
839
|
-
"disabledByUser",
|
|
840
|
-
"disabledBySystem",
|
|
841
|
-
"disabledByInactiveIdentity"
|
|
842
|
-
]),
|
|
843
|
-
publisherId: z.string(),
|
|
844
|
-
publisherInputs: z.record(z.string(), z.string()),
|
|
845
|
-
consumerId: z.string().optional(),
|
|
846
|
-
consumerActionId: z.string().optional(),
|
|
847
|
-
consumerInputs: z.record(z.string(), z.string()),
|
|
848
|
-
eventType: z.string(),
|
|
849
|
-
resourceVersion: z.string(),
|
|
850
|
-
eventDescription: z.string().optional(),
|
|
851
|
-
actionDescription: z.string().optional()
|
|
852
|
-
});
|
|
853
|
-
const AzdoSubscriptionsQueryResponseSchema = z.object({ results: AzdoSubscriptionSchema.array() });
|
|
854
|
-
const AzdoSubscriptionsQueryInputFilterSchema = z.object({ conditions: z.object({
|
|
855
|
-
caseSensitive: z.boolean().optional(),
|
|
856
|
-
inputId: z.string().optional(),
|
|
857
|
-
inputValue: z.string().optional(),
|
|
858
|
-
operator: z.enum(["equals", "notEquals"])
|
|
859
|
-
}).array().optional() });
|
|
860
|
-
const AzdoSubscriptionsQuerySchema = z.object({
|
|
861
|
-
consumerActionId: z.string().optional(),
|
|
862
|
-
consumerId: z.string().optional(),
|
|
863
|
-
consumerInputFilters: AzdoSubscriptionsQueryInputFilterSchema.array().optional(),
|
|
864
|
-
eventType: z.string().optional(),
|
|
865
|
-
publisherId: z.string().optional(),
|
|
866
|
-
publisherInputFilters: AzdoSubscriptionsQueryInputFilterSchema.array().optional(),
|
|
867
|
-
subscriberId: z.string().optional()
|
|
868
|
-
});
|
|
869
|
-
const AzdoEventTypeSchema = z.enum([
|
|
870
|
-
"git.push",
|
|
871
|
-
"git.pullrequest.updated",
|
|
872
|
-
"git.pullrequest.merged",
|
|
873
|
-
"ms.vss-code.git-pullrequest-comment-event"
|
|
874
|
-
]);
|
|
875
|
-
const AzdoEventRepositorySchema = z.object({
|
|
876
|
-
id: z.string(),
|
|
877
|
-
name: z.string(),
|
|
878
|
-
project: z.object({
|
|
879
|
-
id: z.string(),
|
|
880
|
-
name: z.string(),
|
|
881
|
-
url: z.string()
|
|
882
|
-
}),
|
|
883
|
-
defaultBranch: z.string().optional(),
|
|
884
|
-
remoteUrl: z.string()
|
|
1140
|
+
pushId: z.number(),
|
|
1141
|
+
url: z.string()
|
|
885
1142
|
});
|
|
886
1143
|
const AzdoEventPullRequestResourceSchema = z.object({
|
|
887
1144
|
repository: AzdoEventRepositorySchema,
|
|
888
1145
|
pullRequestId: z.number(),
|
|
889
1146
|
status: AzdoPullRequestStatusSchema,
|
|
1147
|
+
createdBy: AzdoIdentityRefSchema,
|
|
890
1148
|
title: z.string(),
|
|
891
1149
|
sourceRefName: z.string(),
|
|
892
1150
|
targetRefName: z.string(),
|
|
@@ -894,21 +1152,37 @@ const AzdoEventPullRequestResourceSchema = z.object({
|
|
|
894
1152
|
mergeId: z.string(),
|
|
895
1153
|
url: z.string()
|
|
896
1154
|
});
|
|
1155
|
+
const AzdoEventRepositoryCreatedResourceSchema = z.object({ repository: AzdoEventRepositorySchema });
|
|
1156
|
+
const AzdoEventRepositoryDeletedResourceSchema = z.object({
|
|
1157
|
+
project: AzdoEventProjectSchema,
|
|
1158
|
+
repositoryId: z.string(),
|
|
1159
|
+
repositoryName: z.string(),
|
|
1160
|
+
isHardDelete: z.boolean()
|
|
1161
|
+
});
|
|
1162
|
+
const AzdoEventRepositoryRenamedResourceSchema = z.object({
|
|
1163
|
+
oldName: z.string(),
|
|
1164
|
+
newName: z.string(),
|
|
1165
|
+
repository: AzdoEventRepositorySchema
|
|
1166
|
+
});
|
|
1167
|
+
const AzdoEventRepositoryStatusChangedResourceSchema = z.object({
|
|
1168
|
+
disabled: z.boolean(),
|
|
1169
|
+
repository: AzdoEventRepositorySchema
|
|
1170
|
+
});
|
|
897
1171
|
const AzdoEventPullRequestCommentEventResourceSchema = z.object({
|
|
898
1172
|
pullRequest: AzdoEventPullRequestResourceSchema,
|
|
899
1173
|
comment: AzdoPullRequestCommentSchema
|
|
900
1174
|
});
|
|
901
|
-
const AzdoEventCodePushResourceSchema = z.object({
|
|
902
|
-
repository: AzdoEventRepositorySchema,
|
|
903
|
-
refUpdates: z.object({
|
|
904
|
-
name: z.string(),
|
|
905
|
-
oldObjectId: z.string().nullish(),
|
|
906
|
-
newObjectId: z.string().nullish()
|
|
907
|
-
}).array()
|
|
908
|
-
});
|
|
909
1175
|
const AzdoEventSchema = z.object({
|
|
910
1176
|
subscriptionId: z.string(),
|
|
911
|
-
notificationId: z.number()
|
|
1177
|
+
notificationId: z.number(),
|
|
1178
|
+
id: z.string(),
|
|
1179
|
+
publisherId: z.string(),
|
|
1180
|
+
resourceVersion: z.enum([
|
|
1181
|
+
"1.0",
|
|
1182
|
+
"1.0-preview.1",
|
|
1183
|
+
"2.0"
|
|
1184
|
+
]),
|
|
1185
|
+
createdDate: z.coerce.date()
|
|
912
1186
|
}).and(z.discriminatedUnion("eventType", [
|
|
913
1187
|
z.object({
|
|
914
1188
|
eventType: z.literal("git.push"),
|
|
@@ -922,6 +1196,22 @@ const AzdoEventSchema = z.object({
|
|
|
922
1196
|
eventType: z.literal("git.pullrequest.merged"),
|
|
923
1197
|
resource: AzdoEventPullRequestResourceSchema
|
|
924
1198
|
}),
|
|
1199
|
+
z.object({
|
|
1200
|
+
eventType: z.literal("git.repo.created"),
|
|
1201
|
+
resource: AzdoEventRepositoryCreatedResourceSchema
|
|
1202
|
+
}),
|
|
1203
|
+
z.object({
|
|
1204
|
+
eventType: z.literal("git.repo.deleted"),
|
|
1205
|
+
resource: AzdoEventRepositoryDeletedResourceSchema
|
|
1206
|
+
}),
|
|
1207
|
+
z.object({
|
|
1208
|
+
eventType: z.literal("git.repo.renamed"),
|
|
1209
|
+
resource: AzdoEventRepositoryRenamedResourceSchema
|
|
1210
|
+
}),
|
|
1211
|
+
z.object({
|
|
1212
|
+
eventType: z.literal("git.repo.statuschanged"),
|
|
1213
|
+
resource: AzdoEventRepositoryStatusChangedResourceSchema
|
|
1214
|
+
}),
|
|
925
1215
|
z.object({
|
|
926
1216
|
eventType: z.literal("ms.vss-code.git-pullrequest-comment-event"),
|
|
927
1217
|
resource: AzdoEventPullRequestCommentEventResourceSchema
|
|
@@ -1001,5 +1291,5 @@ function extractVirtualDirectory(organisationUrl) {
|
|
|
1001
1291
|
}
|
|
1002
1292
|
|
|
1003
1293
|
//#endregion
|
|
1004
|
-
export { ANONYMOUS_USER_ID,
|
|
1294
|
+
export { ANONYMOUS_USER_ID, API_VERSION, API_VERSION_PREVIEW, AZDO_PULL_REQUEST_MERGE_STRATEGIES, AzdoCommentThreadStatusSchema, AzdoCommentTypeSchema, AzdoConnectionDataSchema, AzdoEventCodePushResourceSchema, AzdoEventPullRequestCommentEventResourceSchema, AzdoEventPullRequestResourceSchema, AzdoEventRepositoryCreatedResourceSchema, AzdoEventRepositoryDeletedResourceSchema, AzdoEventRepositoryRenamedResourceSchema, AzdoEventRepositorySchema, AzdoEventRepositoryStatusChangedResourceSchema, AzdoEventSchema, AzdoEventTypeSchema, AzdoGitBranchStatsSchema, AzdoGitChangeSchema, AzdoGitCommitDiffsSchema, AzdoGitCommitRefSchema, AzdoGitPushCreateSchema, AzdoGitPushSchema, AzdoGitRefSchema, AzdoGitRefUpdateResultSchema, AzdoGitRefUpdateSchema, AzdoGitUserDateSchema, AzdoIdentityRefSchema, AzdoIdentityRefWithVoteSchema, AzdoIdentitySchema, AzdoProjectSchema, AzdoPropertiesSchema, AzdoPullRequestAsyncStatusSchema, AzdoPullRequestCommentSchema, AzdoPullRequestCommentThreadSchema, AzdoPullRequestMergeStrategySchema, AzdoPullRequestSchema, AzdoPullRequestStatusSchema, AzdoRepositoryItemSchema, AzdoRepositorySchema, AzdoSubscriptionSchema, AzdoSubscriptionsQueryInputFilterSchema, AzdoSubscriptionsQueryResponseSchema, AzdoSubscriptionsQuerySchema, AzdoVersionControlChangeTypeSchema, AzureDevOpsClient, AzureDevOpsClientWrapper, PR_DESCRIPTION_MAX_LENGTH, PR_PROPERTY_DEPENDABOT_DEPENDENCIES, PR_PROPERTY_DEPENDABOT_PACKAGE_MANAGER, PR_PROPERTY_MICROSOFT_GIT_SOURCE_REF_NAME, buildPullRequestProperties, extractOrganizationUrl, extractProjectUrl, extractRepositoryUrl, getDependabotConfig, getPullRequestChangedFiles, getPullRequestForDependencyNames, parsePullRequestProperties };
|
|
1005
1295
|
//# sourceMappingURL=index.mjs.map
|