@paklo/core 0.1.0 → 0.3.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.
Files changed (66) hide show
  1. package/dist/{node/azure.d.ts → azure/index.d.ts} +32 -10
  2. package/dist/{node/azure.js → azure/index.js} +39 -19
  3. package/dist/azure/index.js.map +1 -0
  4. package/dist/dependabot/index.d.ts +3 -0
  5. package/dist/dependabot/index.js +6 -0
  6. package/dist/{node/dependabot-BteoKZVy.js → dependabot-B5pw4XDa.js} +11 -5
  7. package/dist/dependabot-B5pw4XDa.js.map +1 -0
  8. package/dist/{node/environment.d.ts → environment/index.d.ts} +1 -1
  9. package/dist/environment/index.js +3 -0
  10. package/dist/environment-DX5CD-dD.js.map +1 -0
  11. package/dist/{node/github.d.ts → github/index.d.ts} +1 -1
  12. package/dist/{node/github.js → github/index.js} +4 -4
  13. package/dist/github/index.js.map +1 -0
  14. package/dist/{node/http.d.ts → http/index.d.ts} +8 -8
  15. package/dist/{node/http.js → http/index.js} +2 -2
  16. package/dist/{node/http-BG_-s47I.js → http-Be3uWaqn.js} +1 -1
  17. package/dist/http-Be3uWaqn.js.map +1 -0
  18. package/dist/{node/index-DP9JfUPG.d.ts → index-Dr0PB1As.d.ts} +392 -69
  19. package/dist/{node/job-Crr4kh3e.js → job-CxYcRj_D.js} +55 -19
  20. package/dist/job-CxYcRj_D.js.map +1 -0
  21. package/dist/logger-bWnHxtAf.js.map +1 -0
  22. package/dist/{node/shared-data.d.ts → shared-data/index.d.ts} +1 -1
  23. package/dist/{node/shared-data.js → shared-data/index.js} +1 -1
  24. package/dist/shared-data/index.js.map +1 -0
  25. package/dist/{node/usage.d.ts → usage.d.ts} +12 -9
  26. package/dist/{node/usage.js → usage.js} +1 -1
  27. package/dist/usage.js.map +1 -0
  28. package/package.json +28 -33
  29. package/dist/browser/defineProperty-ie4tC-F5.js +0 -43
  30. package/dist/browser/environment-DinhzwQn.js +0 -139
  31. package/dist/browser/environment-DinhzwQn.js.map +0 -1
  32. package/dist/browser/environment.d.ts +0 -33
  33. package/dist/browser/environment.js +0 -3
  34. package/dist/browser/github.d.ts +0 -151
  35. package/dist/browser/github.js +0 -199
  36. package/dist/browser/github.js.map +0 -1
  37. package/dist/browser/http.d.ts +0 -121
  38. package/dist/browser/http.js +0 -248
  39. package/dist/browser/http.js.map +0 -1
  40. package/dist/browser/logger-B7HLv660.js +0 -31
  41. package/dist/browser/logger-B7HLv660.js.map +0 -1
  42. package/dist/browser/logger.js +0 -4
  43. package/dist/browser/shared-data.d.ts +0 -22
  44. package/dist/browser/shared-data.js +0 -23
  45. package/dist/browser/shared-data.js.map +0 -1
  46. package/dist/browser/usage.d.ts +0 -99
  47. package/dist/browser/usage.js +0 -383
  48. package/dist/browser/usage.js.map +0 -1
  49. package/dist/node/azure.js.map +0 -1
  50. package/dist/node/dependabot-BteoKZVy.js.map +0 -1
  51. package/dist/node/dependabot.d.ts +0 -3
  52. package/dist/node/dependabot.js +0 -6
  53. package/dist/node/environment-DX5CD-dD.js.map +0 -1
  54. package/dist/node/environment.js +0 -3
  55. package/dist/node/github.js.map +0 -1
  56. package/dist/node/http-BG_-s47I.js.map +0 -1
  57. package/dist/node/job-Crr4kh3e.js.map +0 -1
  58. package/dist/node/logger-bWnHxtAf.js.map +0 -1
  59. package/dist/node/logger.d.ts +0 -23
  60. package/dist/node/shared-data.js.map +0 -1
  61. package/dist/node/usage.js.map +0 -1
  62. /package/dist/{node/environment-DX5CD-dD.js → environment-DX5CD-dD.js} +0 -0
  63. /package/dist/{node/index-3wZw74Ah.d.ts → index-3wZw74Ah.d.ts} +0 -0
  64. /package/dist/{node/logger-bWnHxtAf.js → logger-bWnHxtAf.js} +0 -0
  65. /package/dist/{browser/logger.d.ts → logger.d.ts} +0 -0
  66. /package/dist/{node/logger.js → logger.js} +0 -0
@@ -1,383 +0,0 @@
1
- import { z } from "zod/v4";
2
- import "js-yaml";
3
-
4
- //#region src/dependabot/config.ts
5
- const DependabotRegistrySchema = z.object({
6
- type: z.enum([
7
- "composer-repository",
8
- "docker-registry",
9
- "git",
10
- "hex-organization",
11
- "hex-repository",
12
- "maven-repository",
13
- "npm-registry",
14
- "nuget-feed",
15
- "python-index",
16
- "rubygems-server",
17
- "terraform-registry"
18
- ]),
19
- url: z.string().optional(),
20
- username: z.string().optional(),
21
- password: z.string().optional(),
22
- key: z.string().optional(),
23
- token: z.string().optional(),
24
- "replaces-base": z.boolean().optional(),
25
- host: z.string().optional(),
26
- registry: z.string().optional(),
27
- organization: z.string().optional(),
28
- repo: z.string().optional(),
29
- "public-key-fingerprint": z.string().optional(),
30
- "index-url": z.string().optional(),
31
- "auth-key": z.string().optional(),
32
- "tenant-id": z.string().optional(),
33
- "client-id": z.string().optional()
34
- }).transform((value) => ({
35
- ...value,
36
- type: value.type.replace("-", "_")
37
- }));
38
- const DependabotGroupSchema = z.object({
39
- IDENTIFIER: z.string().check(z.regex(/^[a-zA-Z][a-zA-Z0-9|_-]*[a-zA-Z]$/, { message: "Group identifier must start and end with a letter, and can contain letters, pipes |, underscores _, or hyphens -." })).optional(),
40
- "applies-to": z.enum(["version-updates", "security-updates"]).optional(),
41
- "dependency-type": z.enum(["development", "production"]).optional(),
42
- patterns: z.string().array().optional(),
43
- "exclude-patterns": z.string().array().optional(),
44
- "update-types": z.enum([
45
- "major",
46
- "minor",
47
- "patch"
48
- ]).array().optional()
49
- });
50
- const DependabotAllowConditionSchema = z.object({
51
- "dependency-name": z.string().optional(),
52
- "dependency-type": z.enum([
53
- "direct",
54
- "indirect",
55
- "all",
56
- "production",
57
- "development"
58
- ]).optional(),
59
- "update-type": z.enum(["all", "security"]).optional()
60
- });
61
- const DependabotIgnoreConditionSchema = z.object({
62
- "dependency-name": z.string().optional(),
63
- versions: z.string().array().or(z.string()).optional(),
64
- "update-types": z.enum([
65
- "version-update:semver-major",
66
- "version-update:semver-minor",
67
- "version-update:semver-patch"
68
- ]).array().optional()
69
- }).and(z.record(z.string(), z.any()));
70
- const DependabotScheduleSchema = z.object({
71
- interval: z.enum([
72
- "daily",
73
- "weekly",
74
- "monthly",
75
- "quarterly",
76
- "semiannually",
77
- "yearly",
78
- "cron"
79
- ]),
80
- day: z.enum([
81
- "sunday",
82
- "monday",
83
- "tuesday",
84
- "wednesday",
85
- "thursday",
86
- "friday",
87
- "saturday"
88
- ]).optional().default("monday"),
89
- time: z.string().default("02:00").check(z.regex(/^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/, { message: "Time must be in HH:MM format" })).optional(),
90
- timezone: z.string().optional().default("Etc/UTC").refine((value) => {
91
- try {
92
- Intl.DateTimeFormat(void 0, { timeZone: value });
93
- return true;
94
- } catch {
95
- return false;
96
- }
97
- }, { message: "Invalid IANA time zone" }),
98
- cronjob: z.string().check(z.regex(/^\S+ \S+ \S+ \S+ \S+$/, { message: "Cronjob must be in standard cron format" })).optional()
99
- });
100
- const DependabotCommitMessageSchema = z.object({
101
- prefix: z.string().optional(),
102
- "prefix-development": z.string().optional(),
103
- include: z.string().optional()
104
- });
105
- const DependabotCooldownSchema = z.object({
106
- "default-days": z.number().optional(),
107
- "semver-major-days": z.number().optional(),
108
- "semver-minor-days": z.number().optional(),
109
- "semver-patch-days": z.number().optional(),
110
- include: z.string().array().optional(),
111
- exclude: z.string().array().optional()
112
- });
113
- const DependabotPullRequestBranchNameSchema = z.object({ separator: z.string().optional() });
114
- const PackageEcosystemSchema = z.enum([
115
- "bun",
116
- "bundler",
117
- "cargo",
118
- "composer",
119
- "devcontainers",
120
- "docker",
121
- "docker-compose",
122
- "dotnet-sdk",
123
- "helm",
124
- "mix",
125
- "elm",
126
- "gitsubmodule",
127
- "github-actions",
128
- "gomod",
129
- "gradle",
130
- "maven",
131
- "npm",
132
- "nuget",
133
- "pip",
134
- "pub",
135
- "swift",
136
- "terraform",
137
- "uv",
138
- "pipenv",
139
- "pip-compile",
140
- "poetry",
141
- "pnpm",
142
- "yarn"
143
- ]);
144
- const VersioningStrategySchema = z.enum([
145
- "auto",
146
- "increase",
147
- "increase-if-necessary",
148
- "lockfile-only",
149
- "widen"
150
- ]);
151
- const DependabotUpdateSchema = z.object({
152
- "package-ecosystem": PackageEcosystemSchema,
153
- directory: z.string().optional(),
154
- directories: z.string().array().optional(),
155
- allow: DependabotAllowConditionSchema.array().optional(),
156
- assignees: z.string().array().optional(),
157
- "commit-message": DependabotCommitMessageSchema.optional(),
158
- cooldown: DependabotCooldownSchema.optional(),
159
- groups: z.record(z.string(), DependabotGroupSchema).optional(),
160
- ignore: DependabotIgnoreConditionSchema.array().optional(),
161
- "insecure-external-code-execution": z.enum(["allow", "deny"]).optional(),
162
- labels: z.string().array().optional(),
163
- milestone: z.coerce.string().optional(),
164
- "open-pull-requests-limit": z.number().check(z.int(), z.gte(0)).optional(),
165
- "pull-request-branch-name": DependabotPullRequestBranchNameSchema.optional(),
166
- "rebase-strategy": z.string().optional(),
167
- registries: z.string().array().optional(),
168
- schedule: DependabotScheduleSchema.optional(),
169
- "target-branch": z.string().optional(),
170
- vendor: z.boolean().optional(),
171
- "versioning-strategy": VersioningStrategySchema.optional()
172
- }).transform((value, { addIssue }) => {
173
- if (!value.directory && (!value.directories || value.directories.length === 0)) addIssue("Either 'directory' or 'directories' must be specified in the dependency update configuration.");
174
- if (value.directory && /[*?[\]{}]/.test(value.directory)) addIssue("The 'directory' field must not include glob pattern.");
175
- value["open-pull-requests-limit"] ?? (value["open-pull-requests-limit"] = 5);
176
- return value;
177
- });
178
- /**
179
- * Represents the dependabot.yaml configuration file options.
180
- * See: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#configuration-options-for-dependabotyml
181
- */
182
- const DependabotConfigSchema = z.object({
183
- version: z.number().refine((v) => v === 2, { message: "Only version 2 of dependabot is supported" }),
184
- updates: DependabotUpdateSchema.array().check(z.minLength(1, { message: "At least one update configuration is required" })),
185
- registries: z.record(z.string(), DependabotRegistrySchema).optional(),
186
- "enable-beta-ecosystems": z.boolean().optional()
187
- });
188
-
189
- //#endregion
190
- //#region src/dependabot/job.ts
191
- const DependabotCredentialSchema = z.record(z.string(), z.any());
192
- const CertificateAuthoritySchema = z.object({
193
- cert: z.string(),
194
- key: z.string()
195
- });
196
- const DependabotProxyConfigSchema = z.object({
197
- all_credentials: DependabotCredentialSchema.array(),
198
- ca: CertificateAuthoritySchema
199
- });
200
- const DependabotSourceProviderSchema = z.enum(["azure"]);
201
- const DependabotSourceSchema = z.object({
202
- provider: DependabotSourceProviderSchema,
203
- repo: z.string(),
204
- directory: z.string().nullish(),
205
- directories: z.string().array().nullish(),
206
- branch: z.string().nullish(),
207
- commit: z.string().nullish(),
208
- hostname: z.string().nullish(),
209
- "api-endpoint": z.string().nullish()
210
- });
211
- const DependabotExistingPRSchema = z.object({
212
- "dependency-name": z.string(),
213
- "dependency-version": z.string().nullish(),
214
- directory: z.string().nullish(),
215
- removed: z.boolean().nullish()
216
- });
217
- const DependabotExistingGroupPRSchema = z.object({
218
- "dependency-group-name": z.string(),
219
- dependencies: DependabotExistingPRSchema.array()
220
- });
221
- const DependabotAllowedSchema = z.object({
222
- "dependency-name": z.string().nullish(),
223
- "dependency-type": z.string().nullish(),
224
- "update-type": z.enum(["all", "security"]).optional()
225
- });
226
- const DependabotGroupRuleJobSchema = z.object({
227
- patterns: z.string().array().nullish(),
228
- "exclude-patterns": z.string().array().nullish(),
229
- "dependency-type": z.string().nullish(),
230
- "update-types": z.string().array().nullish()
231
- });
232
- const DependabotGroupJobSchema = z.object({
233
- name: z.string(),
234
- "applies-to": z.string().nullish(),
235
- rules: DependabotGroupRuleJobSchema
236
- });
237
- const DependabotConditionSchema = z.object({
238
- "dependency-name": z.string(),
239
- source: z.string().nullish(),
240
- "update-types": z.string().array().nullish(),
241
- "updated-at": z.coerce.string().nullish(),
242
- "version-requirement": z.string().nullish()
243
- });
244
- const DependabotSecurityAdvisorySchema = z.object({
245
- "dependency-name": z.string(),
246
- "affected-versions": z.string().array(),
247
- "patched-versions": z.string().array().nullish(),
248
- "unaffected-versions": z.string().array()
249
- });
250
- const DependabotRequirementSourceSchema = z.record(z.string(), z.any());
251
- const DependabotRequirementSchema = z.object({
252
- file: z.string().nullish(),
253
- groups: z.string().array().nullish(),
254
- metadata: z.record(z.string(), z.any()).nullish(),
255
- requirement: z.string().nullish(),
256
- source: DependabotRequirementSourceSchema.nullish(),
257
- version: z.string().nullish(),
258
- "previous-version": z.string().nullish()
259
- });
260
- const DependabotDependencySchema = z.object({
261
- name: z.string(),
262
- "previous-requirements": DependabotRequirementSchema.array().nullish(),
263
- "previous-version": z.string().nullish(),
264
- version: z.string().nullish(),
265
- requirements: DependabotRequirementSchema.array().nullish(),
266
- removed: z.boolean().nullish(),
267
- directory: z.string().nullish()
268
- });
269
- const DependabotCommitOptionsSchema = z.object({
270
- prefix: z.string().nullish(),
271
- "prefix-development": z.string().nullish(),
272
- "include-scope": z.boolean().nullish()
273
- });
274
- const DependabotExperimentsSchema = z.record(z.string(), z.union([z.string(), z.boolean()]));
275
- const DependabotPackageManagerSchema = z.enum([
276
- "bun",
277
- "bundler",
278
- "cargo",
279
- "composer",
280
- "devcontainers",
281
- "docker",
282
- "docker_compose",
283
- "dotnet_sdk",
284
- "helm",
285
- "hex",
286
- "elm",
287
- "submodules",
288
- "github_actions",
289
- "go_modules",
290
- "gradle",
291
- "maven",
292
- "npm_and_yarn",
293
- "nuget",
294
- "pip",
295
- "pub",
296
- "swift",
297
- "terraform",
298
- "uv"
299
- ]);
300
- const DependabotCommandSchema = z.enum([
301
- "graph",
302
- "version",
303
- "recreate"
304
- ]);
305
- const DependabotJobConfigSchema = z.object({
306
- id: z.number().optional(),
307
- command: DependabotCommandSchema.optional(),
308
- "package-manager": DependabotPackageManagerSchema,
309
- "allowed-updates": DependabotAllowedSchema.array(),
310
- debug: z.boolean().nullable(),
311
- "dependency-groups": DependabotGroupJobSchema.array().nullish(),
312
- dependencies: z.string().array().nullable(),
313
- "dependency-group-to-refresh": z.string().nullish(),
314
- "existing-pull-requests": DependabotExistingPRSchema.array().array(),
315
- "existing-group-pull-requests": DependabotExistingGroupPRSchema.array(),
316
- experiments: DependabotExperimentsSchema,
317
- "ignore-conditions": DependabotConditionSchema.array(),
318
- "lockfile-only": z.boolean(),
319
- "requirements-update-strategy": z.string().nullable(),
320
- "security-advisories": DependabotSecurityAdvisorySchema.array(),
321
- "security-updates-only": z.boolean(),
322
- source: DependabotSourceSchema,
323
- "update-subdependencies": z.boolean(),
324
- "updating-a-pull-request": z.boolean(),
325
- "vendor-dependencies": z.boolean(),
326
- "reject-external-code": z.boolean().nullish(),
327
- "repo-private": z.boolean(),
328
- "commit-message-options": DependabotCommitOptionsSchema,
329
- "credentials-metadata": DependabotCredentialSchema.array().nullish(),
330
- "max-updater-run-time": z.int().nullish(),
331
- cooldown: DependabotCooldownSchema.nullish(),
332
- "proxy-log-response-body-on-auth-failure": z.boolean().nullish(),
333
- "enable-beta-ecosystems": z.boolean().nullish(),
334
- "multi-ecosystem-update": z.boolean().nullish()
335
- });
336
- const DependabotJobFileSchema = z.object({ job: DependabotJobConfigSchema });
337
-
338
- //#endregion
339
- //#region src/usage.ts
340
- /**
341
- * @example
342
- * ```json
343
- * {
344
- * "host": {
345
- * "platform": "darwin",
346
- * "os": "25.0.0",
347
- * "arch": "arm64",
348
- * "machine-hash": "d3bbb66be2ad9dfab10af69b450f7e7e814ef7bbf1277a6d0df9e1db44ba4f5c"
349
- * },
350
- * "trigger": "user",
351
- * "provider": "azure",
352
- * "owner": "https://dev.azure.com/tingle/",
353
- * "package-manager": "terraform",
354
- * "version": "0.9.0",
355
- * "id": 2850677077,
356
- * "started": "2025-10-03T14:44:00.191Z",
357
- * "duration": 31812,
358
- * "success": true
359
- * }
360
- * ```
361
- */
362
- const UsageTelemetryRequestDataSchema = z.object({
363
- host: z.object({
364
- platform: z.string().max(50),
365
- release: z.string().max(100),
366
- arch: z.string().max(50),
367
- "machine-hash": z.string().max(250)
368
- }),
369
- version: z.string().max(50),
370
- trigger: z.enum(["user", "service"]),
371
- provider: DependabotSourceProviderSchema,
372
- owner: z.url(),
373
- project: z.url().optional(),
374
- "package-manager": DependabotPackageManagerSchema,
375
- id: z.number(),
376
- started: z.coerce.date(),
377
- duration: z.number().min(0),
378
- success: z.boolean()
379
- });
380
-
381
- //#endregion
382
- export { UsageTelemetryRequestDataSchema };
383
- //# sourceMappingURL=usage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"usage.js","names":[],"sources":["../../src/dependabot/config.ts","../../src/dependabot/job.ts","../../src/usage.ts"],"sourcesContent":["import * as yaml from 'js-yaml';\nimport { z } from 'zod/v4';\n\nimport { convertPlaceholder, type VariableFinderFn } from './placeholder';\n\nexport const DependabotRegistrySchema = z\n .object({\n type: z.enum([\n 'composer-repository',\n 'docker-registry',\n 'git',\n 'hex-organization',\n 'hex-repository',\n 'maven-repository',\n 'npm-registry',\n 'nuget-feed',\n 'python-index',\n 'rubygems-server',\n 'terraform-registry',\n ]),\n url: z.string().optional(),\n username: z.string().optional(),\n password: z.string().optional(),\n key: z.string().optional(),\n token: z.string().optional(),\n 'replaces-base': z.boolean().optional(),\n host: z.string().optional(), // for terraform and composer only\n registry: z.string().optional(), // for npm only\n organization: z.string().optional(), // for hex-organisation only\n repo: z.string().optional(), // for hex-repository only\n 'public-key-fingerprint': z.string().optional(), // for hex-repository only\n 'index-url': z.string().optional(), // for python-index only\n 'auth-key': z.string().optional(), // used by composer-repository, docker-registry, etc\n 'tenant-id': z.string().optional(), // can only be for azure related stuff, not sure\n 'client-id': z.string().optional(), // can only be for azure related stuff, not sure\n })\n // change underscore to dash in the registry key/type\n .transform((value) => ({ ...value, type: value.type.replace('-', '_') }));\nexport type DependabotRegistry = z.infer<typeof DependabotRegistrySchema>;\n\nexport const DependabotGroupSchema = z.object({\n // Define an identifier for the group to use in branch names and pull request titles.\n // This must start and end with a letter, and can contain letters, pipes |, underscores _, or hyphens -.\n IDENTIFIER: z\n .string()\n .check(\n z.regex(/^[a-zA-Z][a-zA-Z0-9|_-]*[a-zA-Z]$/, {\n message:\n 'Group identifier must start and end with a letter, and can contain letters, pipes |, underscores _, or hyphens -.',\n }),\n )\n .optional(),\n 'applies-to': z.enum(['version-updates', 'security-updates']).optional(),\n 'dependency-type': z.enum(['development', 'production']).optional(),\n patterns: z.string().array().optional(),\n 'exclude-patterns': z.string().array().optional(),\n 'update-types': z.enum(['major', 'minor', 'patch']).array().optional(),\n});\nexport type DependabotGroup = z.infer<typeof DependabotGroupSchema>;\n\nexport const DependabotAllowConditionSchema = z.object({\n 'dependency-name': z.string().optional(),\n 'dependency-type': z.enum(['direct', 'indirect', 'all', 'production', 'development']).optional(),\n 'update-type': z.enum(['all', 'security']).optional(),\n});\nexport type DependabotAllowCondition = z.infer<typeof DependabotAllowConditionSchema>;\n\nexport const DependabotIgnoreConditionSchema = z\n .object({\n 'dependency-name': z.string().optional(),\n versions: z.string().array().or(z.string()).optional(),\n 'update-types': z\n .enum(['version-update:semver-major', 'version-update:semver-minor', 'version-update:semver-patch'])\n .array()\n .optional(),\n })\n .and(z.record(z.string(), z.any()));\nexport type DependabotIgnoreCondition = z.infer<typeof DependabotIgnoreConditionSchema>;\n\nexport const DependabotScheduleSchema = z.object({\n interval: z.enum(['daily', 'weekly', 'monthly', 'quarterly', 'semiannually', 'yearly', 'cron']),\n\n day: z\n .enum(['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'])\n .optional()\n .default('monday'),\n\n time: z\n .string()\n .default('02:00')\n .check(z.regex(/^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/, { message: 'Time must be in HH:MM format' }))\n .optional(),\n\n timezone: z\n .string()\n .optional()\n .default('Etc/UTC')\n .refine(\n (value) => {\n try {\n // If tz is not a valid IANA name, this throws a RangeError\n Intl.DateTimeFormat(undefined, { timeZone: value });\n return true;\n } catch {\n return false;\n }\n },\n { message: 'Invalid IANA time zone' },\n ),\n cronjob: z\n .string()\n .check(z.regex(/^\\S+ \\S+ \\S+ \\S+ \\S+$/, { message: 'Cronjob must be in standard cron format' }))\n .optional(),\n});\nexport type DependabotSchedule = z.infer<typeof DependabotScheduleSchema>;\n\nexport const DependabotCommitMessageSchema = z.object({\n prefix: z.string().optional(),\n 'prefix-development': z.string().optional(),\n include: z.string().optional(),\n});\nexport type DependabotCommitMessage = z.infer<typeof DependabotCommitMessageSchema>;\n\nexport const DependabotCooldownSchema = z.object({\n 'default-days': z.number().optional(),\n 'semver-major-days': z.number().optional(),\n 'semver-minor-days': z.number().optional(),\n 'semver-patch-days': z.number().optional(),\n include: z.string().array().optional(),\n exclude: z.string().array().optional(),\n});\nexport type DependabotCooldown = z.infer<typeof DependabotCooldownSchema>;\n\nconst DependabotPullRequestBranchNameSchema = z.object({\n separator: z.string().optional(),\n});\nexport type DependabotPullRequestBranchName = z.infer<typeof DependabotPullRequestBranchNameSchema>;\n\nexport const PackageEcosystemSchema = z.enum([\n 'bun',\n 'bundler',\n 'cargo',\n 'composer',\n 'devcontainers',\n 'docker',\n 'docker-compose',\n 'dotnet-sdk',\n 'helm',\n 'mix',\n 'elm',\n 'gitsubmodule',\n 'github-actions',\n 'gomod',\n 'gradle',\n 'maven',\n 'npm',\n 'nuget',\n 'pip',\n 'pub',\n 'swift',\n 'terraform',\n 'uv',\n\n // Additional aliases, sometimes used for convenience\n 'pipenv',\n 'pip-compile',\n 'poetry',\n 'pnpm',\n 'yarn',\n]);\nexport type PackageEcosystem = z.infer<typeof PackageEcosystemSchema>;\n\nexport const VersioningStrategySchema = z.enum(['auto', 'increase', 'increase-if-necessary', 'lockfile-only', 'widen']);\nexport type VersioningStrategy = z.infer<typeof VersioningStrategySchema>;\n\nexport const DependabotUpdateSchema = z\n .object({\n 'package-ecosystem': PackageEcosystemSchema,\n directory: z.string().optional(),\n directories: z.string().array().optional(),\n allow: DependabotAllowConditionSchema.array().optional(),\n assignees: z.string().array().optional(),\n 'commit-message': DependabotCommitMessageSchema.optional(),\n cooldown: DependabotCooldownSchema.optional(),\n groups: z.record(z.string(), DependabotGroupSchema).optional(),\n ignore: DependabotIgnoreConditionSchema.array().optional(),\n 'insecure-external-code-execution': z.enum(['allow', 'deny']).optional(),\n labels: z.string().array().optional(),\n milestone: z.coerce.string().optional(),\n 'open-pull-requests-limit': z.number().check(z.int(), z.gte(0)).optional(),\n 'pull-request-branch-name': DependabotPullRequestBranchNameSchema.optional(),\n 'rebase-strategy': z.string().optional(),\n registries: z.string().array().optional(),\n schedule: DependabotScheduleSchema.optional(),\n 'target-branch': z.string().optional(),\n vendor: z.boolean().optional(),\n 'versioning-strategy': VersioningStrategySchema.optional(),\n })\n .transform((value, { addIssue }) => {\n // either 'directory' or 'directories' must be specified\n if (!value.directory && (!value.directories || value.directories.length === 0)) {\n addIssue(\"Either 'directory' or 'directories' must be specified in the dependency update configuration.\");\n }\n\n // validate that 'directory' does not contain glob patterns\n if (value.directory && /[*?[\\]{}]/.test(value.directory)) {\n addIssue(\"The 'directory' field must not include glob pattern.\");\n }\n\n value['open-pull-requests-limit'] ??= 5; // default to 5 if not specified\n\n return value;\n });\nexport type DependabotUpdate = z.infer<typeof DependabotUpdateSchema>;\n\n/**\n * Represents the dependabot.yaml configuration file options.\n * See: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#configuration-options-for-dependabotyml\n */\nexport const DependabotConfigSchema = z.object({\n /**\n * Mandatory. configuration file version.\n **/\n version: z.number().refine((v) => v === 2, { message: 'Only version 2 of dependabot is supported' }),\n\n /**\n * Mandatory. Configure how Dependabot updates the versions or project dependencies.\n * Each entry configures the update settings for a particular package manager.\n */\n updates: DependabotUpdateSchema.array().check(\n z.minLength(1, { message: 'At least one update configuration is required' }),\n ),\n\n /**\n * Optional.\n * Specify authentication details to access private package registries.\n */\n registries: z.record(z.string(), DependabotRegistrySchema).optional(),\n\n /**\n * Optional. Enables updates for ecosystems that are not yet generally available.\n * https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#enable-beta-ecosystems-\n */\n 'enable-beta-ecosystems': z.boolean().optional(),\n});\n\nexport type DependabotConfig = z.infer<typeof DependabotConfigSchema>;\n\nexport function parseUpdates(config: DependabotConfig, configPath: string): DependabotUpdate[] {\n const updates: DependabotUpdate[] = [];\n\n // Parse the value of each of the updates obtained from the file\n for (const update of config.updates) {\n // populate the 'ignore' conditions 'source' and 'updated-at' properties, if missing\n // NOTE: 'source' and 'updated-at' are not documented in the dependabot.yml config docs, but are defined in the dependabot-core and dependabot-cli models.\n // Currently they don't appear to add much value to the update process, but are populated here for completeness.\n if (update.ignore) {\n for (const condition of update.ignore) {\n condition.source ??= configPath;\n // we don't know the last updated time, so we use the current time\n condition['updated-at'] ??= new Date().toISOString();\n }\n }\n\n updates.push(update);\n }\n return updates;\n}\n\nexport async function parseRegistries(\n config: DependabotConfig,\n variableFinder: VariableFinderFn,\n): Promise<Record<string, DependabotRegistry>> {\n // Parse the value of each of the registries obtained from the config\n const registries: Record<string, DependabotRegistry> = {};\n for (const [key, registry] of Object.entries(config.registries || {})) {\n const updated = { ...registry };\n const { type } = updated;\n\n // handle special fields for 'hex-organization' types\n if (type === 'hex_organization' && !updated.organization) {\n throw new Error(`The value 'organization' in dependency registry config '${type}' is missing`);\n }\n\n // handle special fields for 'hex-repository' types\n if (type === 'hex_repository' && !updated.repo) {\n throw new Error(`The value 'repo' in dependency registry config '${key}' is missing`);\n }\n\n // parse username, password, key, and token while replacing tokens where necessary\n updated.username = await convertPlaceholder({ input: updated.username, variableFinder: variableFinder });\n updated.password = await convertPlaceholder({ input: updated.password, variableFinder: variableFinder });\n updated.key = await convertPlaceholder({ input: updated.key, variableFinder: variableFinder });\n updated.token = await convertPlaceholder({ input: updated.token, variableFinder: variableFinder });\n\n // parse the url\n const url = updated.url;\n if (!url && type !== 'hex_organization') {\n throw new Error(`The value 'url' in dependency registry config '${key}' is missing`);\n }\n if (url) {\n /*\n * Some credentials do not use the 'url' property in the Ruby updater.\n * The 'host' and 'registry' properties are derived from the given URL.\n * The 'registry' property is derived from the 'url' by stripping off the scheme.\n * The 'host' property is derived from the hostname of the 'url'.\n *\n * 'npm_registry' and 'docker_registry' use 'registry' only.\n * 'terraform_registry' uses 'host' only.\n * 'composer_repository' uses both 'url' and 'host'.\n * 'python_index' uses 'index-url' instead of 'url'.\n */\n\n if (URL.canParse(url)) {\n const parsedUrl = new URL(url);\n\n const addRegistry = type === 'docker_registry' || type === 'npm_registry';\n if (addRegistry) updated.registry = url.replace('https://', '').replace('http://', '');\n\n const addHost = type === 'terraform_registry' || type === 'composer_repository';\n if (addHost) updated.host = parsedUrl.hostname;\n }\n\n if (type === 'python_index') updated['index-url'] = url;\n\n const removeUrl =\n type === 'docker_registry' ||\n type === 'npm_registry' ||\n type === 'terraform_registry' ||\n type === 'python_index';\n if (removeUrl) delete updated.url; // remove the url if not needed\n }\n\n // add to list\n registries[key] = updated;\n }\n return registries;\n}\n\nexport function validateConfiguration(updates: DependabotUpdate[], registries: Record<string, DependabotRegistry>) {\n const configured = Object.keys(registries);\n const referenced: string[] = [];\n for (const u of updates) referenced.push(...(u.registries ?? []));\n\n // ensure there are no configured registries that have not been referenced\n const missingConfiguration = referenced.filter((el) => !configured.includes(el));\n if (missingConfiguration.length > 0) {\n throw new Error(\n `Referenced registries: '${missingConfiguration.join(',')}' have not been configured in the root of dependabot.yml`,\n );\n }\n\n // ensure there are no registries referenced but not configured\n const missingReferences = configured.filter((el) => !referenced.includes(el));\n if (missingReferences.length > 0) {\n throw new Error(`Registries: '${missingReferences.join(',')}' have not been referenced by any update`);\n }\n}\n\n/**\n * Possible paths to the dependabot config file.\n * Remember to prefix with a forward slash when querying API endpoints or where necessary.\n */\nexport const POSSIBLE_CONFIG_FILE_PATHS = [\n '.azuredevops/dependabot.yml',\n '.azuredevops/dependabot.yaml',\n '.github/dependabot.yaml',\n '.github/dependabot.yml',\n];\n\n/**\n * Parse the contents of a dependabot config YAML file\n * @returns {DependabotConfig} config - the dependabot configuration\n */\nexport async function parseDependabotConfig({\n configContents,\n configPath,\n variableFinder,\n}: {\n configContents: string;\n configPath: string;\n variableFinder: VariableFinderFn;\n}): Promise<DependabotConfig> {\n // Load the config\n const loadedConfig = yaml.load(configContents);\n if (loadedConfig === null || typeof loadedConfig !== 'object') {\n throw new Error('Invalid dependabot config object');\n }\n\n // Parse the config\n const config = await DependabotConfigSchema.parseAsync(loadedConfig);\n const updates = parseUpdates(config, configPath);\n const registries = await parseRegistries(config, variableFinder);\n validateConfiguration(updates, registries);\n\n return { ...config, updates, registries };\n}\n","import { z } from 'zod/v4';\nimport { DependabotCooldownSchema } from './config';\n\n// we use nullish() because it does optional() and allows the value to be set to null\n\nexport const DependabotCredentialSchema = z.record(z.string(), z.any());\nexport type DependabotCredential = z.infer<typeof DependabotCredentialSchema>;\n\nexport const CertificateAuthoritySchema = z.object({\n cert: z.string(),\n key: z.string(),\n});\nexport type CertificateAuthority = z.infer<typeof CertificateAuthoritySchema>;\n\nexport const DependabotProxyConfigSchema = z.object({\n all_credentials: DependabotCredentialSchema.array(),\n ca: CertificateAuthoritySchema,\n});\nexport type DependabotProxyConfig = z.infer<typeof DependabotProxyConfigSchema>;\n\nexport const DependabotSourceProviderSchema = z.enum(['azure']);\nexport type DependabotSourceProvider = z.infer<typeof DependabotSourceProviderSchema>;\n\nexport const DependabotSourceSchema = z.object({\n provider: DependabotSourceProviderSchema,\n repo: z.string(),\n directory: z.string().nullish(),\n directories: z.string().array().nullish(),\n branch: z.string().nullish(),\n commit: z.string().nullish(),\n hostname: z.string().nullish(), // Must be provided if api-endpoint is\n 'api-endpoint': z.string().nullish(), // Must be provided if hostname is\n // TODO: refine to ensure either directory or directories is provided\n // TODO: refine to ensure either both hostname and api-endpoint have a value or both are undefined\n});\nexport type DependabotSource = z.infer<typeof DependabotSourceSchema>;\n\nexport const DependabotExistingPRSchema = z.object({\n 'dependency-name': z.string(),\n 'dependency-version': z.string().nullish(),\n directory: z.string().nullish(),\n removed: z.boolean().nullish(),\n});\nexport type DependabotExistingPR = z.infer<typeof DependabotExistingPRSchema>;\n\nexport const DependabotExistingGroupPRSchema = z.object({\n 'dependency-group-name': z.string(),\n dependencies: DependabotExistingPRSchema.array(),\n});\nexport type DependabotExistingGroupPR = z.infer<typeof DependabotExistingGroupPRSchema>;\n\nexport const DependabotAllowedSchema = z.object({\n 'dependency-name': z.string().nullish(),\n 'dependency-type': z.string().nullish(),\n 'update-type': z.enum(['all', 'security']).optional(),\n});\nexport type DependabotAllowed = z.infer<typeof DependabotAllowedSchema>;\n\nexport const DependabotGroupRuleJobSchema = z.object({\n patterns: z.string().array().nullish(),\n 'exclude-patterns': z.string().array().nullish(),\n 'dependency-type': z.string().nullish(),\n 'update-types': z.string().array().nullish(),\n});\nexport type DependabotGroupRuleJob = z.infer<typeof DependabotGroupRuleJobSchema>;\n\nexport const DependabotGroupJobSchema = z.object({\n name: z.string(),\n 'applies-to': z.string().nullish(),\n rules: DependabotGroupRuleJobSchema,\n});\nexport type DependabotGroupJob = z.infer<typeof DependabotGroupJobSchema>;\n\nexport const DependabotConditionSchema = z.object({\n 'dependency-name': z.string(),\n source: z.string().nullish(),\n 'update-types': z.string().array().nullish(),\n 'updated-at': z.coerce.string().nullish(),\n 'version-requirement': z.string().nullish(),\n});\nexport type DependabotCondition = z.infer<typeof DependabotConditionSchema>;\n\nexport const DependabotSecurityAdvisorySchema = z.object({\n 'dependency-name': z.string(),\n 'affected-versions': z.string().array(),\n 'patched-versions': z.string().array().nullish(), // may not be patched as of yet\n 'unaffected-versions': z.string().array(),\n});\nexport type DependabotSecurityAdvisory = z.infer<typeof DependabotSecurityAdvisorySchema>;\n\nexport const DependabotRequirementSourceSchema = z.record(z.string(), z.any());\nexport type DependabotRequirementSource = z.infer<typeof DependabotRequirementSourceSchema>;\n\nexport const DependabotRequirementSchema = z.object({\n file: z.string().nullish(), // e.g. 'requirements.txt' or '/Root.csproj'\n groups: z.string().array().nullish(), // e.g. ['dependencies']\n metadata: z.record(z.string(), z.any()).nullish(),\n requirement: z.string().nullish(), // e.g. '==3.2.0' or '8.1.0'\n source: DependabotRequirementSourceSchema.nullish(),\n version: z.string().nullish(),\n 'previous-version': z.string().nullish(),\n});\nexport type DependabotRequirement = z.infer<typeof DependabotRequirementSchema>;\n\nexport const DependabotDependencySchema = z.object({\n name: z.string(), // e.g. 'django' or 'GraphQL.Server.Ui.Voyager'\n 'previous-requirements': DependabotRequirementSchema.array().nullish(),\n 'previous-version': z.string().nullish(),\n version: z.string().nullish(), // e.g. '5.0.1' or '8.1.0'\n requirements: DependabotRequirementSchema.array().nullish(),\n removed: z.boolean().nullish(),\n directory: z.string().nullish(),\n});\nexport type DependabotDependency = z.infer<typeof DependabotDependencySchema>;\n\nexport const DependabotCommitOptionsSchema = z.object({\n prefix: z.string().nullish(),\n 'prefix-development': z.string().nullish(),\n 'include-scope': z.boolean().nullish(),\n});\nexport type DependabotCommitOptions = z.infer<typeof DependabotCommitOptionsSchema>;\n\nexport const DependabotExperimentsSchema = z.record(z.string(), z.union([z.string(), z.boolean()]));\nexport type DependabotExperiments = z.infer<typeof DependabotExperimentsSchema>;\n\nexport const DependabotPackageManagerSchema = z.enum([\n 'bun',\n 'bundler',\n 'cargo',\n 'composer',\n 'devcontainers',\n 'docker',\n 'docker_compose', // // ecosystem(s): 'docker-compose',\n 'dotnet_sdk', // ecosystem(s): 'dotnet-sdk'\n 'helm',\n 'hex', // ecosystem(s): 'mix'\n 'elm',\n 'submodules', // ecosystem(s): 'gitsubmodule'\n 'github_actions', // ecosystem(s): 'github-actions'\n 'go_modules', // ecosystem(s): 'gomod'\n 'gradle',\n 'maven',\n 'npm_and_yarn', // ecosystem(s): 'npm', 'pnpm', 'yarn'\n 'nuget',\n 'pip', // ecosystem(s): 'pipenv', 'pip-compile', 'poetry'\n 'pub',\n 'swift',\n 'terraform',\n 'uv',\n]);\nexport type DependabotPackageManager = z.infer<typeof DependabotPackageManagerSchema>;\n\nexport const DependabotCommandSchema = z.enum(['graph', 'version', 'recreate']);\nexport type DependabotCommand = z.infer<typeof DependabotCommandSchema>;\n\n// See: https://github.com/dependabot/cli/blob/main/internal/model/job.go\n// https://github.com/dependabot/dependabot-core/blob/main/updater/lib/dependabot/job.rb\nexport const DependabotJobConfigSchema = z.object({\n id: z.number().optional(),\n command: DependabotCommandSchema.optional(),\n 'package-manager': DependabotPackageManagerSchema,\n 'allowed-updates': DependabotAllowedSchema.array(),\n debug: z.boolean().nullable(),\n 'dependency-groups': DependabotGroupJobSchema.array().nullish(),\n dependencies: z.string().array().nullable(),\n 'dependency-group-to-refresh': z.string().nullish(),\n 'existing-pull-requests': DependabotExistingPRSchema.array().array(),\n 'existing-group-pull-requests': DependabotExistingGroupPRSchema.array(),\n experiments: DependabotExperimentsSchema,\n 'ignore-conditions': DependabotConditionSchema.array(),\n 'lockfile-only': z.boolean(),\n 'requirements-update-strategy': z.string().nullable(),\n 'security-advisories': DependabotSecurityAdvisorySchema.array(),\n 'security-updates-only': z.boolean(),\n source: DependabotSourceSchema,\n 'update-subdependencies': z.boolean(),\n 'updating-a-pull-request': z.boolean(),\n 'vendor-dependencies': z.boolean(),\n 'reject-external-code': z.boolean().nullish(),\n 'repo-private': z.boolean(),\n 'commit-message-options': DependabotCommitOptionsSchema,\n 'credentials-metadata': DependabotCredentialSchema.array().nullish(),\n 'max-updater-run-time': z.int().nullish(),\n cooldown: DependabotCooldownSchema.nullish(),\n 'proxy-log-response-body-on-auth-failure': z.boolean().nullish(),\n 'enable-beta-ecosystems': z.boolean().nullish(),\n 'multi-ecosystem-update': z.boolean().nullish(),\n});\nexport type DependabotJobConfig = z.infer<typeof DependabotJobConfigSchema>;\n\nexport const DependabotJobFileSchema = z.object({\n job: DependabotJobConfigSchema,\n});\nexport type DependabotJobFile = z.infer<typeof DependabotJobFileSchema>;\n\n// Code below is borrowed and adapted from dependabot-action\n\n// biome-ignore-start lint/suspicious/noExplicitAny: generic\nexport type FetchedFiles = {\n base_commit_sha: string;\n dependency_files: any[];\n base64_dependency_files: any[];\n};\n// biome-ignore-end lint/suspicious/noExplicitAny: generic\n\nexport type FileFetcherInput = {\n job: DependabotJobConfig;\n};\n\nexport type FileUpdaterInput = FetchedFiles & {\n job: DependabotJobConfig;\n};\n","import { z } from 'zod/v4';\nimport { DependabotPackageManagerSchema, DependabotSourceProviderSchema } from '@/dependabot/job';\n\n/**\n * @example\n * ```json\n * {\n * \"host\": {\n * \"platform\": \"darwin\",\n * \"os\": \"25.0.0\",\n * \"arch\": \"arm64\",\n * \"machine-hash\": \"d3bbb66be2ad9dfab10af69b450f7e7e814ef7bbf1277a6d0df9e1db44ba4f5c\"\n * },\n * \"trigger\": \"user\",\n * \"provider\": \"azure\",\n * \"owner\": \"https://dev.azure.com/tingle/\",\n * \"package-manager\": \"terraform\",\n * \"version\": \"0.9.0\",\n * \"id\": 2850677077,\n * \"started\": \"2025-10-03T14:44:00.191Z\",\n * \"duration\": 31812,\n * \"success\": true\n * }\n * ```\n */\nexport const UsageTelemetryRequestDataSchema = z.object({\n host: z.object({\n platform: z.string().max(50), // e.g. linux, darwin, win32\n release: z.string().max(100), // e.g. 26.0.0, 10.0.19043\n arch: z.string().max(50), // e.g. x64, arm64\n 'machine-hash': z.string().max(250), // e.g. \"d3bbb66be2ad9dfab10af69b450f7e7e814ef7bbf1277a6d0df9e1db44ba4f5c\" for \"Maxwells-MacBook-Pro.local\"\n }),\n version: z.string().max(50),\n trigger: z.enum(['user', 'service']),\n provider: DependabotSourceProviderSchema,\n owner: z.url(),\n project: z.url().optional(), // was added later hence optional for backward compatibility\n 'package-manager': DependabotPackageManagerSchema,\n id: z.number(), // job identifier, for correlation\n started: z.coerce.date(),\n duration: z.number().min(0), // in milliseconds\n success: z.boolean(),\n});\n\n/**\n * @example\n * ```json\n * {\n * \"host\": {\n * \"platform\": \"darwin\",\n * \"os\": \"25.0.0\",\n * \"arch\": \"arm64\",\n * \"machine-hash\": \"d3bbb66be2ad9dfab10af69b450f7e7e814ef7bbf1277a6d0df9e1db44ba4f5c\"\n * },\n * \"trigger\": \"user\",\n * \"provider\": \"azure\",\n * \"owner\": \"https://dev.azure.com/tingle/\",\n * \"package-manager\": \"terraform\",\n * \"version\": \"0.9.0\",\n * \"id\": 2850677077,\n * \"started\": \"2025-10-03T14:44:00.191Z\",\n * \"duration\": 31812,\n * \"success\": true\n * }\n * ```\n */\nexport type UsageTelemetryRequestData = z.infer<typeof UsageTelemetryRequestDataSchema>;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"azure.js","names":["path","reason: string | undefined","reviewers: IdentityRefWithVote[]","body: string | undefined","configPath: undefined | string","configContents: undefined | string","organisation: string","path"],"sources":["../../src/azure/types.ts","../../src/azure/models.ts","../../src/azure/utils.ts","../../src/azure/client.ts","../../src/azure/config.ts","../../src/azure/url-parts.ts"],"sourcesContent":["export enum VersionControlChangeType {\n None = 0,\n Add = 1,\n Edit = 2,\n Encoding = 4,\n Rename = 8,\n Delete = 16,\n Undelete = 32,\n Branch = 64,\n Merge = 128,\n Lock = 256,\n Rollback = 512,\n SourceRename = 1024,\n TargetRename = 2048,\n Property = 4096,\n All = 8191,\n}\n\nexport enum GitPullRequestMergeStrategy {\n NoFastForward = 1,\n Squash = 2,\n Rebase = 3,\n RebaseMerge = 4,\n}\n\nexport enum CommentThreadStatus {\n Unknown = 0,\n Active = 1,\n Fixed = 2,\n WontFix = 3,\n Closed = 4,\n ByDesign = 5,\n Pending = 6,\n}\nexport enum CommentType {\n Unknown = 0,\n Text = 1,\n CodeChange = 2,\n System = 3,\n}\nexport enum ItemContentType {\n RawText = 0,\n Base64Encoded = 1,\n}\nexport enum PullRequestAsyncStatus {\n NotSet = 0,\n Queued = 1,\n Conflicts = 2,\n Succeeded = 3,\n RejectedByPolicy = 4,\n Failure = 5,\n}\nexport enum PullRequestStatus {\n NotSet = 0,\n Active = 1,\n Abandoned = 2,\n Completed = 3,\n All = 4,\n}\nexport interface IdentityRefWithVote {\n id?: string;\n displayName?: string;\n uniqueName?: string;\n url?: string;\n imageUrl?: string;\n vote?: number;\n hasDeclined?: boolean;\n isFlagged?: boolean;\n isRequired?: boolean;\n}\n","import type { GitPullRequestMergeStrategy, VersionControlChangeType } from './types';\n\n/**\n * Pull request property names used to store metadata about the pull request.\n * https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull-request-properties\n */\nexport const DEVOPS_PR_PROPERTY_MICROSOFT_GIT_SOURCE_REF_NAME = 'Microsoft.Git.PullRequest.SourceRefName';\nexport const DEVOPS_PR_PROPERTY_DEPENDABOT_PACKAGE_MANAGER = 'Dependabot.PackageManager';\nexport const DEVOPS_PR_PROPERTY_DEPENDABOT_DEPENDENCIES = 'Dependabot.Dependencies';\n\n/**\n * File change\n */\nexport interface IFileChange {\n changeType: VersionControlChangeType;\n path: string;\n content: string;\n encoding: string;\n}\n\n/**\n * Pull request properties\n */\nexport interface IPullRequestProperties {\n id: number;\n properties?: {\n name: string;\n value: string;\n }[];\n}\n\n/**\n * Pull request creation request\n */\nexport interface ICreatePullRequest {\n project: string;\n repository: string;\n source: {\n commit: string;\n branch: string;\n };\n target: {\n branch: string;\n };\n author?: {\n email: string;\n name: string;\n };\n title: string;\n description: string;\n commitMessage: string;\n autoComplete?: {\n ignorePolicyConfigIds?: number[];\n mergeStrategy?: GitPullRequestMergeStrategy;\n };\n assignees?: string[];\n labels?: string[];\n workItems?: string[];\n changes: IFileChange[];\n properties?: {\n name: string;\n value: string;\n }[];\n}\n\n/**\n * Pull request update request\n */\nexport interface IUpdatePullRequest {\n project: string;\n repository: string;\n pullRequestId: number;\n commit: string;\n author?: {\n email: string;\n name: string;\n };\n changes: IFileChange[];\n skipIfDraft?: boolean;\n skipIfCommitsFromAuthorsOtherThan?: string;\n skipIfNotBehindTargetBranch?: boolean;\n}\n\n/**\n * Pull request approval request\n */\nexport interface IApprovePullRequest {\n project: string;\n repository: string;\n pullRequestId: number;\n}\n\n/**\n * Pull request abandon request\n */\nexport interface IAbandonPullRequest {\n project: string;\n repository: string;\n pullRequestId: number;\n comment?: string;\n deleteSourceBranch?: boolean;\n}\n","import * as path from 'node:path';\n\nimport {\n type DependabotClosePullRequest,\n type DependabotCreatePullRequest,\n type DependabotDependency,\n type DependabotExistingGroupPR,\n DependabotExistingGroupPRSchema,\n type DependabotExistingPR,\n DependabotExistingPRSchema,\n type DependabotUpdatePullRequest,\n} from '@/dependabot';\nimport {\n DEVOPS_PR_PROPERTY_DEPENDABOT_DEPENDENCIES,\n DEVOPS_PR_PROPERTY_DEPENDABOT_PACKAGE_MANAGER,\n type IFileChange,\n type IPullRequestProperties,\n} from './models';\nimport { VersionControlChangeType } from './types';\n\nexport function normalizeFilePath(path: string): string {\n // Convert backslashes to forward slashes, convert './' => '/' and ensure the path starts with a forward slash if it doesn't already, this is how DevOps paths are formatted\n return path\n ?.replace(/\\\\/g, '/')\n ?.replace(/^\\.\\//, '/')\n ?.replace(/^([^/])/, '/$1');\n}\n\nexport function normalizeBranchName(branch?: string): string | undefined {\n // Strip the 'refs/heads/' prefix from the branch name, if present\n return branch?.replace(/^refs\\/heads\\//i, '');\n}\n\nexport const DependenciesPrPropertySchema = DependabotExistingPRSchema.array().or(DependabotExistingGroupPRSchema);\n\nexport function buildPullRequestProperties(\n packageManager: string,\n dependencies: DependabotExistingPR[] | DependabotExistingGroupPR,\n) {\n return [\n {\n name: DEVOPS_PR_PROPERTY_DEPENDABOT_PACKAGE_MANAGER,\n value: packageManager,\n },\n {\n name: DEVOPS_PR_PROPERTY_DEPENDABOT_DEPENDENCIES,\n value: JSON.stringify(dependencies),\n },\n ];\n}\n\nexport function parsePullRequestProperties(\n pullRequests: IPullRequestProperties[],\n packageManager: string | null,\n): Record<string, DependabotExistingPR[] | DependabotExistingGroupPR> {\n return Object.fromEntries(\n pullRequests\n .filter((pr) => {\n return pr.properties?.find(\n (p) =>\n p.name === DEVOPS_PR_PROPERTY_DEPENDABOT_PACKAGE_MANAGER &&\n (packageManager === null || p.value === packageManager),\n );\n })\n .map((pr) => {\n return [\n pr.id,\n DependenciesPrPropertySchema.parse(\n JSON.parse(pr.properties!.find((p) => p.name === DEVOPS_PR_PROPERTY_DEPENDABOT_DEPENDENCIES)!.value),\n ),\n ];\n }),\n );\n}\n\nexport function getPullRequestForDependencyNames(\n existingPullRequests: IPullRequestProperties[],\n packageManager: string,\n dependencyNames: string[],\n): IPullRequestProperties | undefined {\n return existingPullRequests.find((pr) => {\n return (\n pr.properties?.find(\n (p) => p.name === DEVOPS_PR_PROPERTY_DEPENDABOT_PACKAGE_MANAGER && p.value === packageManager,\n ) &&\n pr.properties?.find(\n (p) =>\n p.name === DEVOPS_PR_PROPERTY_DEPENDABOT_DEPENDENCIES &&\n areEqual(getDependencyNames(DependenciesPrPropertySchema.parse(JSON.parse(p.value))), dependencyNames),\n )\n );\n });\n}\n\nfunction getDependencyNames(dependencies: DependabotExistingPR[] | DependabotExistingGroupPR): string[] {\n const deps = Array.isArray(dependencies) ? dependencies : dependencies.dependencies;\n return deps.map((dep) => dep['dependency-name']?.toString());\n}\n\nfunction areEqual(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((name) => b.includes(name));\n}\n\nexport function getPullRequestChangedFilesForOutputData(\n data: DependabotCreatePullRequest | DependabotUpdatePullRequest,\n): IFileChange[] {\n return data['updated-dependency-files']\n .filter((file) => file.type === 'file')\n .map((file) => {\n let changeType = VersionControlChangeType.None;\n if (file.deleted === true) {\n changeType = VersionControlChangeType.Delete;\n } else if (file.operation === 'update') {\n changeType = VersionControlChangeType.Edit;\n } else {\n changeType = VersionControlChangeType.Add;\n }\n return {\n changeType: changeType,\n path: path.join(file.directory, file.name),\n content: file.content,\n encoding: file.content_encoding ?? 'utf8',\n } satisfies IFileChange;\n });\n}\n\nexport function getPullRequestCloseReasonForOutputData(data: DependabotClosePullRequest): string | undefined {\n // The first dependency is the \"lead\" dependency in a multi-dependency update\n const leadDependencyName = data['dependency-names'][0];\n let reason: string | undefined;\n switch (data.reason) {\n case 'dependencies_changed':\n reason = `Looks like the dependencies have changed`;\n break;\n case 'dependency_group_empty':\n reason = `Looks like the dependencies in this group are now empty`;\n break;\n case 'dependency_removed':\n reason = `Looks like ${leadDependencyName} is no longer a dependency`;\n break;\n case 'up_to_date':\n reason = `Looks like ${leadDependencyName} is up-to-date now`;\n break;\n case 'update_no_longer_possible':\n reason = `Looks like ${leadDependencyName} can no longer be updated`;\n break;\n }\n if (reason && reason.length > 0) {\n reason += ', so this is no longer needed.';\n }\n return reason;\n}\n\nexport function getPullRequestDependenciesPropertyValueForOutputData(\n data: DependabotCreatePullRequest,\n): DependabotExistingPR[] | DependabotExistingGroupPR {\n const dependencies = data.dependencies?.map((dep) => {\n return {\n 'dependency-name': dep.name,\n 'dependency-version': dep.version,\n directory: dep.directory,\n };\n });\n const dependencyGroupName = data['dependency-group']?.name;\n if (!dependencyGroupName) return dependencies;\n return {\n 'dependency-group-name': dependencyGroupName,\n dependencies: dependencies,\n } as DependabotExistingGroupPR;\n}\n\nexport function getPullRequestDescription(\n packageManager: string,\n body: string | null | undefined,\n dependencies: DependabotDependency[],\n): string {\n let header = '';\n const footer = '';\n\n // Fix up GitHub mentions encoding issues by removing instances of the zero-width space '\\u200B' as it does not render correctly in Azure DevOps.\n // https://github.com/dependabot/dependabot-core/issues/9572\n // https://github.com/dependabot/dependabot-core/blob/313fcff149b3126cb78b38d15f018907d729f8cc/common/lib/dependabot/pull_request_creator/message_builder/link_and_mention_sanitizer.rb#L245-L252\n const description = (body || '').replace(new RegExp(decodeURIComponent('%EF%BF%BD%EF%BF%BD%EF%BF%BD'), 'g'), '');\n\n // If there is exactly one dependency, add a compatibility score badge to the description header.\n // Compatibility scores are intended for single dependency security updates, not group updates.\n // https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores\n if (dependencies.length === 1) {\n const compatibilityScoreBadges = dependencies.map((dep) => {\n return `![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=${dep.name}&package-manager=${packageManager}&previous-version=${dep['previous-version']}&new-version=${dep.version})`;\n });\n header += `${compatibilityScoreBadges.join(' ')}\\n\\n`;\n }\n\n // Build the full pull request description.\n // The header/footer must not be truncated. If the description is too long, we truncate the body.\n const maxDescriptionLength = 4000;\n const maxDescriptionLengthAfterHeaderAndFooter = maxDescriptionLength - header.length - footer.length;\n return `${header}${description.substring(0, maxDescriptionLengthAfterHeaderAndFooter)}${footer}`;\n}\n","import { HttpRequestError, isErrorTemporaryFailure } from '@/http';\nimport { logger } from '@/logger';\nimport type {\n IAbandonPullRequest,\n IApprovePullRequest,\n ICreatePullRequest,\n IPullRequestProperties,\n IUpdatePullRequest,\n} from './models';\nimport {\n CommentThreadStatus,\n CommentType,\n type IdentityRefWithVote,\n ItemContentType,\n PullRequestAsyncStatus,\n PullRequestStatus,\n} from './types';\nimport type { AzureDevOpsUrl } from './url-parts';\nimport { normalizeBranchName, normalizeFilePath } from './utils';\n\n/** Azure DevOps REST API client. */\nexport class AzureDevOpsWebApiClient {\n private readonly organisationApiUrl: string;\n private readonly identityApiUrl: string;\n private readonly accessToken: string;\n private readonly debug: boolean;\n\n private authenticatedUserId?: string;\n private resolvedUserIds: Record<string, string>;\n\n public static API_VERSION = '5.0'; // this is the same version used by dependabot-core\n public static API_VERSION_PREVIEW = '5.0-preview';\n\n constructor(url: AzureDevOpsUrl, accessToken: string, debug: boolean = false) {\n const organisationApiUrl = url.url.toString();\n this.organisationApiUrl = organisationApiUrl.replace(/\\/$/, ''); // trim trailing slash\n this.identityApiUrl = getIdentityApiUrl(organisationApiUrl).replace(/\\/$/, ''); // trim trailing slash\n this.accessToken = accessToken;\n this.debug = debug;\n this.resolvedUserIds = {};\n }\n\n /**\n * Get the identity of the authenticated user.\n * @returns\n */\n public async getUserId(): Promise<string> {\n if (!this.authenticatedUserId) {\n const connectionData = await this.restApiGet(\n `${this.organisationApiUrl}/_apis/connectiondata`,\n undefined,\n AzureDevOpsWebApiClient.API_VERSION_PREVIEW,\n );\n this.authenticatedUserId = connectionData?.authenticatedUser?.id;\n if (!this.authenticatedUserId) {\n throw new Error('Failed to get authenticated user ID');\n }\n }\n return this.authenticatedUserId;\n }\n\n /**\n * Get the identity id from a user name, email, or group name.\n * Requires scope \"Identity (Read)\" (vso.identity).\n * @param userNameEmailOrGroupName\n * @returns\n */\n public async resolveIdentityId(userNameEmailOrGroupName: string): Promise<string | undefined> {\n if (this.resolvedUserIds[userNameEmailOrGroupName]) {\n return this.resolvedUserIds[userNameEmailOrGroupName];\n }\n try {\n const identities = await this.restApiGet(`${this.identityApiUrl}/_apis/identities`, {\n searchFilter: 'General',\n filterValue: userNameEmailOrGroupName,\n queryMembership: 'None',\n });\n if (!identities?.value || identities.value.length === 0) {\n return undefined;\n }\n this.resolvedUserIds[userNameEmailOrGroupName] = identities.value[0]?.id;\n return this.resolvedUserIds[userNameEmailOrGroupName];\n } catch (e) {\n logger.error(`Failed to resolve user id: ${e}`);\n logger.debug(e); // Dump the error stack trace to help with debugging\n return undefined;\n }\n }\n\n /**\n * Get the default branch for a repository.\n * Requires scope \"Code (Read)\" (vso.code).\n * @param project\n * @param repository\n * @returns\n */\n public async getDefaultBranch(project: string, repository: string): Promise<string | undefined> {\n try {\n const repo = await this.restApiGet(`${this.organisationApiUrl}/${project}/_apis/git/repositories/${repository}`);\n if (!repo) {\n throw new Error(`Repository '${project}/${repository}' not found`);\n }\n\n return normalizeBranchName(repo.defaultBranch);\n } catch (e) {\n logger.error(`Failed to get default branch for '${project}/${repository}': ${e}`);\n logger.debug(e); // Dump the error stack trace to help with debugging\n return undefined;\n }\n }\n\n /**\n * Get the list of branch names for a repository.\n * Requires scope \"Code (Read)\" (vso.code).\n * @param project\n * @param repository\n * @returns\n */\n public async getBranchNames(project: string, repository: string): Promise<string[] | undefined> {\n try {\n const refs = await this.restApiGet(\n `${this.organisationApiUrl}/${project}/_apis/git/repositories/${repository}/refs`,\n );\n if (!refs) {\n throw new Error(`Repository '${project}/${repository}' not found`);\n }\n\n return refs.value?.map((r: { name?: string }) => normalizeBranchName(r.name)) || [];\n } catch (e) {\n logger.error(`Failed to list branch names for '${project}/${repository}': ${e}`);\n logger.debug(e); // Dump the error stack trace to help with debugging\n return undefined;\n }\n }\n\n /**\n * Get the properties for all active pull request created by the supplied user.\n * Requires scope \"Code (Read)\" (vso.code).\n * @param project\n * @param repository\n * @param creator\n * @returns\n */\n public async getActivePullRequestProperties(\n project: string,\n repository: string,\n creator: string,\n ): Promise<IPullRequestProperties[]> {\n try {\n const pullRequests = await this.restApiGet(\n `${this.organisationApiUrl}/${project}/_apis/git/repositories/${repository}/pullrequests`,\n {\n 'searchCriteria.creatorId': isGuid(creator) ? creator : await this.getUserId(),\n 'searchCriteria.status': 'Active',\n },\n );\n if (!pullRequests?.value || pullRequests.value.length === 0) {\n return [];\n }\n\n return await Promise.all(\n pullRequests.value.map(async (pr: { pullRequestId: number }) => {\n const properties = await this.restApiGet(\n `${this.organisationApiUrl}/${project}/_apis/git/repositories/${repository}/pullrequests/${pr.pullRequestId}/properties`,\n );\n return {\n id: pr.pullRequestId,\n properties:\n Object.keys(properties?.value || {}).map((key) => {\n return {\n name: key,\n value: properties.value[key]?.$value,\n };\n }) || [],\n };\n }),\n );\n } catch (e) {\n logger.error(`Failed to list active pull request properties: ${e}`);\n logger.debug(e); // Dump the error stack trace to help with debugging\n return [];\n }\n }\n\n /**\n * Create a new pull request.\n * Requires scope \"Code (Write)\" (vso.code_write).\n * Requires scope \"Identity (Read)\" (vso.identity), if assignees are specified.\n * @param pr\n * @returns\n */\n public async createPullRequest(pr: ICreatePullRequest): Promise<number | null> {\n logger.info(`Creating pull request '${pr.title}'...`);\n try {\n const userId = await this.getUserId();\n\n // Map the list of the pull request reviewer ids\n // NOTE: Azure DevOps does not have a concept of assignees.\n // We treat them as optional reviewers. Branch policies should be used for required reviewers.\n const reviewers: IdentityRefWithVote[] = [];\n if (pr.assignees && pr.assignees.length > 0) {\n for (const assignee of pr.assignees) {\n const identityId = isGuid(assignee) ? assignee : await this.resolveIdentityId(assignee);\n if (identityId && !reviewers.some((r) => r.id === identityId)) {\n reviewers.push({\n id: identityId,\n });\n } else {\n logger.warn(`Unable to resolve assignee identity '${assignee}'`);\n }\n }\n }\n\n // Create the source branch and push a commit with the dependency file changes\n logger.info(` - Pushing ${pr.changes.length} file change(s) to branch '${pr.source.branch}'...`);\n const push = await this.restApiPost(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/pushes`,\n {\n refUpdates: [\n {\n name: `refs/heads/${pr.source.branch}`,\n oldObjectId: pr.source.commit,\n },\n ],\n commits: [\n {\n comment: pr.commitMessage,\n author: pr.author,\n changes: pr.changes.map((change) => {\n return {\n changeType: change.changeType,\n item: {\n path: normalizeFilePath(change.path),\n },\n newContent: {\n content: Buffer.from(change.content, <BufferEncoding>change.encoding).toString('base64'),\n contentType: ItemContentType.Base64Encoded,\n },\n };\n }),\n },\n ],\n },\n );\n if (!push?.commits?.length) {\n throw new Error('Failed to push changes to source branch, no commits were created');\n }\n logger.info(` - Pushed commit: ${push.commits.map((c: { commitId: string }) => c.commitId).join(', ')}.`);\n\n // Create the pull request\n logger.info(` - Creating pull request to merge '${pr.source.branch}' into '${pr.target.branch}'...`);\n const pullRequest = await this.restApiPost(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/pullrequests`,\n {\n sourceRefName: `refs/heads/${pr.source.branch}`,\n targetRefName: `refs/heads/${pr.target.branch}`,\n title: pr.title,\n description: pr.description,\n reviewers: reviewers,\n workItemRefs: pr.workItems?.map((id) => ({ id: id })),\n labels: pr.labels?.map((label) => ({ name: label })),\n },\n );\n if (!pullRequest?.pullRequestId) {\n throw new Error('Failed to create pull request, no pull request id was returned');\n }\n logger.info(` - Created pull request: #${pullRequest.pullRequestId}.`);\n\n // Add the pull request properties\n if (pr.properties && pr.properties.length > 0) {\n logger.info(` - Adding dependency metadata to pull request properties...`);\n const newProperties = await this.restApiPatch(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/pullrequests/${pullRequest.pullRequestId}/properties`,\n pr.properties.map((property) => {\n return {\n op: 'add',\n path: `/${property.name}`,\n value: property.value,\n };\n }),\n 'application/json-patch+json',\n );\n if (!newProperties?.count) {\n throw new Error('Failed to add dependency metadata properties to pull request');\n }\n }\n\n // TODO: Upload the pull request description as a 'changes.md' file attachment?\n // This might be a way to work around the 4000 character limit for PR descriptions, but needs more investigation.\n // https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull-request-attachments/create?view=azure-devops-rest-7.1\n\n // Set the pull request auto-complete status\n if (pr.autoComplete) {\n logger.info(` - Updating auto-complete options...`);\n const updatedPullRequest = await this.restApiPatch(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/pullrequests/${pullRequest.pullRequestId}`,\n {\n autoCompleteSetBy: {\n id: userId,\n },\n completionOptions: {\n autoCompleteIgnoreConfigIds: pr.autoComplete.ignorePolicyConfigIds,\n deleteSourceBranch: true,\n mergeCommitMessage: mergeCommitMessage(pullRequest.pullRequestId, pr.title, pr.description),\n mergeStrategy: pr.autoComplete.mergeStrategy,\n transitionWorkItems: false,\n },\n },\n );\n if (!updatedPullRequest || updatedPullRequest.autoCompleteSetBy?.id !== userId) {\n throw new Error('Failed to set auto-complete on pull request');\n }\n }\n\n logger.info(` - Pull request was created successfully.`);\n return pullRequest.pullRequestId;\n } catch (e) {\n logger.error(`Failed to create pull request: ${e}`);\n logger.debug(e); // Dump the error stack trace to help with debugging\n return null;\n }\n }\n\n /**\n * Update a pull request.\n * Requires scope \"Code (Read & Write)\" (vso.code, vso.code_write).\n * @param pr\n * @returns\n */\n public async updatePullRequest(pr: IUpdatePullRequest): Promise<boolean> {\n logger.info(`Updating pull request #${pr.pullRequestId}...`);\n try {\n // Get the pull request details\n const pullRequest = await this.restApiGet(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/pullrequests/${pr.pullRequestId}`,\n );\n if (!pullRequest) {\n throw new Error(`Pull request #${pr.pullRequestId} not found`);\n }\n\n // Skip if the pull request is a draft\n if (pr.skipIfDraft && pullRequest.isDraft) {\n logger.info(` - Skipping update as pull request is currently marked as a draft.`);\n return true;\n }\n\n // Skip if the pull request has been modified by another author\n if (pr.skipIfCommitsFromAuthorsOtherThan) {\n const commits = await this.restApiGet(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/pullrequests/${pr.pullRequestId}/commits`,\n );\n if (\n commits?.value?.some(\n (c: { author?: { email?: string } }) => c.author?.email !== pr.skipIfCommitsFromAuthorsOtherThan,\n )\n ) {\n logger.info(` - Skipping update as pull request has been modified by another user.`);\n return true;\n }\n }\n\n // Get the branch stats to check if the source branch is behind the target branch\n const stats = await this.restApiGet(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/stats/branches`,\n {\n name: normalizeBranchName(pullRequest.sourceRefName),\n },\n );\n if (stats?.behindCount === undefined) {\n throw new Error(`Failed to get branch stats for '${pullRequest.sourceRefName}'`);\n }\n\n // Skip if the source branch is not behind the target branch\n if (pr.skipIfNotBehindTargetBranch && stats.behindCount === 0) {\n logger.info(` - Skipping update as source branch is not behind target branch.`);\n return true;\n }\n\n // Rebase the target branch into the source branch to reset the \"behind\" count\n const sourceBranchName = normalizeBranchName(pullRequest.sourceRefName);\n const targetBranchName = normalizeBranchName(pullRequest.targetRefName);\n if (stats.behindCount > 0) {\n logger.info(\n ` - Rebasing '${targetBranchName}' into '${sourceBranchName}' (${stats.behindCount} commit(s) behind)...`,\n );\n const rebase = await this.restApiPost(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/refs`,\n [\n {\n name: pullRequest.sourceRefName,\n oldObjectId: pullRequest.lastMergeSourceCommit.commitId,\n newObjectId: pr.commit,\n },\n ],\n );\n if (rebase?.value?.[0]?.success !== true) {\n throw new Error('Failed to rebase the target branch into the source branch');\n }\n }\n\n // Push all file changes to the source branch\n logger.info(` - Pushing ${pr.changes.length} file change(s) to branch '${pullRequest.sourceRefName}'...`);\n const push = await this.restApiPost(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/pushes`,\n {\n refUpdates: [\n {\n name: pullRequest.sourceRefName,\n oldObjectId: pr.commit,\n },\n ],\n commits: [\n {\n comment:\n pullRequest.mergeStatus === PullRequestAsyncStatus.Conflicts\n ? 'Resolve merge conflicts'\n : `Rebase '${sourceBranchName}' onto '${targetBranchName}'`,\n author: pr.author,\n changes: pr.changes.map((change) => {\n return {\n changeType: change.changeType,\n item: {\n path: normalizeFilePath(change.path),\n },\n newContent: {\n content: Buffer.from(change.content, <BufferEncoding>change.encoding).toString('base64'),\n contentType: ItemContentType.Base64Encoded,\n },\n };\n }),\n },\n ],\n },\n );\n if (!push?.commits?.length) {\n throw new Error('Failed to push changes to source branch, no commits were created');\n }\n logger.info(` - Pushed commit: ${push.commits.map((c: { commitId: string }) => c.commitId).join(', ')}.`);\n\n logger.info(` - Pull request was updated successfully.`);\n return true;\n } catch (e) {\n logger.error(`Failed to update pull request: ${e}`);\n logger.debug(e); // Dump the error stack trace to help with debugging\n return false;\n }\n }\n\n /**\n * Approve a pull request.\n * Requires scope \"Code (Write)\" (vso.code_write).\n * @param pr\n * @returns\n */\n public async approvePullRequest(pr: IApprovePullRequest): Promise<boolean> {\n logger.info(`Approving pull request #${pr.pullRequestId}...`);\n try {\n // Approve the pull request\n logger.info(` - Updating reviewer vote on pull request...`);\n const userId = await this.getUserId();\n const userVote = await this.restApiPut(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/pullrequests/${pr.pullRequestId}/reviewers/${userId}`,\n {\n // Vote 10 = \"approved\"; 5 = \"approved with suggestions\"; 0 = \"no vote\"; -5 = \"waiting for author\"; -10 = \"rejected\"\n vote: 10,\n // Reapprove must be set to true after the 2023 August 23 update;\n // Approval of a previous PR iteration does not count in later iterations, which means we must (re)approve every after push to the source branch\n // See: https://learn.microsoft.com/en-us/azure/devops/release-notes/2023/sprint-226-update#new-branch-policy-preventing-users-to-approve-their-own-changes\n // https://github.com/mburumaxwell/dependabot-azure-devops/issues/1069\n isReapprove: true,\n },\n // API version 7.1 is required to use the 'isReapprove' parameter\n // See: https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull-request-reviewers/create-pull-request-reviewer?view=azure-devops-rest-7.1&tabs=HTTP#request-body\n // https://learn.microsoft.com/en-us/azure/devops/integrate/concepts/rest-api-versioning?view=azure-devops#supported-versions\n '7.1',\n );\n if (userVote?.vote !== 10) {\n throw new Error('Failed to approve pull request, vote was not recorded');\n }\n\n logger.info(` - Pull request was approved successfully.`);\n return true;\n } catch (e) {\n logger.error(`Failed to approve pull request: ${e}`);\n logger.debug(e); // Dump the error stack trace to help with debugging\n return false;\n }\n }\n\n /**\n * Abandon a pull request.\n * Requires scope \"Code (Write)\" (vso.code_write).\n * @param pr\n * @returns\n */\n public async abandonPullRequest(pr: IAbandonPullRequest): Promise<boolean> {\n logger.info(`Abandoning pull request #${pr.pullRequestId}...`);\n try {\n const userId = await this.getUserId();\n\n // Add a comment to the pull request, if supplied\n if (pr.comment) {\n logger.info(` - Adding abandonment reason comment to pull request...`);\n const thread = await this.restApiPost(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/pullrequests/${pr.pullRequestId}/threads`,\n {\n status: CommentThreadStatus.Closed,\n comments: [\n {\n author: {\n id: userId,\n },\n content: pr.comment,\n commentType: CommentType.System,\n },\n ],\n },\n );\n if (!thread?.id) {\n throw new Error('Failed to add comment to pull request, thread was not created');\n }\n }\n\n // Abandon the pull request\n logger.info(` - Abandoning pull request...`);\n const abandonedPullRequest = await this.restApiPatch(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/pullrequests/${pr.pullRequestId}`,\n {\n status: PullRequestStatus.Abandoned,\n closedBy: {\n id: userId,\n },\n },\n );\n if (abandonedPullRequest?.status?.toLowerCase() !== 'abandoned') {\n throw new Error('Failed to abandon pull request, status was not updated');\n }\n\n // Delete the source branch if required\n if (pr.deleteSourceBranch) {\n logger.info(` - Deleting source branch...`);\n const deletedBranch = await this.restApiPost(\n `${this.organisationApiUrl}/${pr.project}/_apis/git/repositories/${pr.repository}/refs`,\n [\n {\n name: abandonedPullRequest.sourceRefName,\n oldObjectId: abandonedPullRequest.lastMergeSourceCommit.commitId,\n newObjectId: '0000000000000000000000000000000000000000',\n isLocked: false,\n },\n ],\n );\n if (deletedBranch?.value?.[0]?.success !== true) {\n throw new Error('Failed to delete the source branch');\n }\n }\n\n logger.info(` - Pull request was abandoned successfully.`);\n return true;\n } catch (e) {\n logger.error(`Failed to abandon pull request: ${e}`);\n logger.debug(e); // Dump the error stack trace to help with debugging\n return false;\n }\n }\n\n private async restApiGet(\n url: string,\n params?: Record<string, unknown>,\n apiVersion: string = AzureDevOpsWebApiClient.API_VERSION,\n ) {\n params ??= {};\n const queryString = Object.keys(params)\n .map((key) => `${key}=${params[key]}`)\n .join('&');\n const fullUrl = `${url}?api-version=${apiVersion}${queryString ? `&${queryString}` : ''}`;\n\n return await sendRestApiRequestWithRetry(\n 'GET',\n fullUrl,\n undefined,\n async () => {\n return await fetch(fullUrl, {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n Authorization: `Basic ${Buffer.from(`:${this.accessToken}`).toString('base64')}`,\n },\n });\n },\n this.debug,\n );\n }\n\n private async restApiPost(url: string, data?: unknown, apiVersion: string = AzureDevOpsWebApiClient.API_VERSION) {\n const fullUrl = `${url}?api-version=${apiVersion}`;\n return await sendRestApiRequestWithRetry(\n 'POST',\n fullUrl,\n data,\n async () => {\n return await fetch(fullUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Basic ${Buffer.from(`:${this.accessToken}`).toString('base64')}`,\n },\n body: JSON.stringify(data),\n });\n },\n this.debug,\n );\n }\n\n private async restApiPut(url: string, data?: unknown, apiVersion: string = AzureDevOpsWebApiClient.API_VERSION) {\n const fullUrl = `${url}?api-version=${apiVersion}`;\n return await sendRestApiRequestWithRetry(\n 'PUT',\n fullUrl,\n data,\n async () => {\n return await fetch(fullUrl, {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Basic ${Buffer.from(`:${this.accessToken}`).toString('base64')}`,\n },\n body: JSON.stringify(data),\n });\n },\n this.debug,\n );\n }\n\n private async restApiPatch(\n url: string,\n data?: unknown,\n contentType?: string,\n apiVersion: string = AzureDevOpsWebApiClient.API_VERSION,\n ) {\n const fullUrl = `${url}?api-version=${apiVersion}`;\n return await sendRestApiRequestWithRetry(\n 'PATCH',\n fullUrl,\n data,\n async () => {\n return await fetch(fullUrl, {\n method: 'PATCH',\n headers: {\n 'Content-Type': contentType || 'application/json',\n Authorization: `Basic ${Buffer.from(`:${this.accessToken}`).toString('base64')}`,\n },\n body: JSON.stringify(data),\n });\n },\n this.debug,\n );\n }\n}\n\nfunction mergeCommitMessage(id: number, title: string, description: string): string {\n //\n // The merge commit message should contain the PR number and title for tracking.\n // This is the default behaviour in Azure DevOps.\n // Example:\n // Merged PR 24093: Bump Tingle.Extensions.Logging.LogAnalytics from 3.4.2-ci0005 to 3.4.2-ci0006\n //\n // Bumps [Tingle.Extensions.Logging.LogAnalytics](...) from 3.4.2-ci0005 to 3.4.2-ci0006\n // - [Release notes](....)\n // - [Changelog](....)\n // - [Commits](....)\n //\n // There appears to be a DevOps bug when setting \"completeOptions\" with a \"mergeCommitMessage\" even when truncated to 4000 characters.\n // The error message is:\n // Invalid argument value.\n // Parameter name: Completion options have exceeded the maximum encoded length (4184/4000)\n //\n // The effective limit seems to be about 3500 characters:\n // https://developercommunity.visualstudio.com/t/raise-the-character-limit-for-pull-request-descrip/365708#T-N424531\n //\n return `Merged PR ${id}: ${title}\\n\\n${description}`.slice(0, 3500);\n}\n\nfunction isGuid(guid: string): boolean {\n const regex = /^[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}$/;\n return regex.test(guid);\n}\n\nfunction getIdentityApiUrl(organisationApiUrl: string): string {\n const uri = new URL(organisationApiUrl);\n const hostname = uri.hostname.toLowerCase();\n\n // If the organisation is hosted on Azure DevOps, use the 'vssps.dev.azure.com' domain\n if (hostname === 'dev.azure.com' || hostname.endsWith('.visualstudio.com')) {\n uri.host = 'vssps.dev.azure.com';\n }\n return uri.toString();\n}\n\nexport async function sendRestApiRequestWithRetry(\n method: string,\n url: string,\n payload: unknown,\n requestAsync: () => Promise<Response>,\n isDebug: boolean = false,\n retryCount: number = 3,\n retryDelay: number = 3000,\n) {\n let body: string | undefined;\n try {\n // Send the request, ready the response\n if (isDebug) logger.debug(`🌎 🠊 [${method}] ${url}`);\n const response = await requestAsync();\n body = await response.text();\n const { status: statusCode, statusText: statusMessage } = response;\n if (isDebug) logger.debug(`🌎 🠈 [${statusCode}] ${statusMessage}`);\n\n // Check that the request was successful\n if (statusCode < 200 || statusCode > 299) {\n throw new HttpRequestError(`HTTP ${method} '${url}' failed: ${statusCode} ${statusMessage}`, statusCode);\n }\n\n // Parse the response\n return JSON.parse(body);\n } catch (e) {\n const err = e as Error;\n // Retry the request if the error is a temporary failure\n if (retryCount > 1 && isErrorTemporaryFailure(err)) {\n logger.warn(err.message);\n if (isDebug) logger.debug(`⏳ Retrying request in ${retryDelay}ms...`);\n await new Promise((resolve) => setTimeout(resolve, retryDelay));\n return sendRestApiRequestWithRetry(method, url, payload, requestAsync, isDebug, retryCount - 1, retryDelay);\n }\n\n // In debug mode, log the error, request, and response for debugging\n if (isDebug) {\n if (payload) {\n logger.debug(`REQUEST: ${JSON.stringify(payload)}`);\n }\n if (body) {\n logger.debug(`RESPONSE: ${body}`);\n }\n }\n\n logger.trace(`THROW${e}`);\n throw e;\n }\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport * as path from 'node:path';\n\nimport {\n type DependabotConfig,\n POSSIBLE_CONFIG_FILE_PATHS,\n parseDependabotConfig,\n type VariableFinderFn,\n} from '@/dependabot';\nimport { logger } from '@/logger';\nimport type { AzureDevOpsUrl } from './url-parts';\n\n/**\n * Parse the dependabot config YAML file to specify update configuration.\n * The file should be located at any of `POSSIBLE_CONFIG_FILE_PATHS`.\n *\n * To view YAML file format, visit\n * https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#allow\n *\n * @returns {DependabotConfig} config - the dependabot configuration\n */\nexport async function getDependabotConfig({\n url,\n token,\n remote,\n rootDir = process.cwd(),\n variableFinder,\n}: {\n url: AzureDevOpsUrl;\n token: string;\n /**\n * Whether to fetch the configuration file via the REST API (true) or look for it locally (false).\n */\n remote: boolean;\n rootDir?: string;\n variableFinder: VariableFinderFn;\n}): Promise<DependabotConfig> {\n let configPath: undefined | string;\n let configContents: undefined | string;\n\n /*\n * The configuration file can be available locally if the repository is cloned.\n * Otherwise, we should get it via the API which supports 2 scenarios:\n * 1. Running the pipeline without cloning, which is useful for huge repositories (multiple submodules or large commit log)\n * 2. Running a single pipeline to update multiple repositories https://github.com/mburumaxwell/dependabot-azure-devops/issues/328\n */\n\n if (remote) {\n logger.debug(`Attempting to fetch configuration file via REST API ...`);\n for (const fp of POSSIBLE_CONFIG_FILE_PATHS) {\n // make HTTP request\n const requestUrl = `${url.url}${url.project}/_apis/git/repositories/${url.repository}/items?path=/${fp}`;\n logger.debug(`GET ${requestUrl}`);\n\n try {\n const authHeader = `Basic ${Buffer.from(`x-access-token:${token}`).toString('base64')}`;\n const response = await fetch(requestUrl, {\n headers: {\n Authorization: authHeader,\n Accept: '*/*', // Gotcha!!! without this SH*T fails terribly\n },\n });\n if (response.ok) {\n logger.debug(`Found configuration file at '${requestUrl}'`);\n configContents = await response.text();\n configPath = fp;\n break;\n } else if (response.status === 404) {\n logger.trace(`No configuration file at '${requestUrl}'`);\n // biome-ignore lint/complexity/noUselessContinue: continue is useful here for clarity\n continue;\n } else if (response.status === 401) {\n throw new Error(`No or invalid access token has been provided to access '${requestUrl}'`);\n } else if (response.status === 403) {\n throw new Error(`The access token provided does not have permissions to access '${requestUrl}'`);\n }\n } catch (error) {\n if (error instanceof Error && error.message.includes('access token')) {\n throw error;\n } else {\n throw error;\n }\n }\n }\n } else {\n for (const fp of POSSIBLE_CONFIG_FILE_PATHS) {\n const filePath = path.join(rootDir, fp);\n if (existsSync(filePath)) {\n logger.debug(`Found configuration file cloned at ${filePath}`);\n configContents = await readFile(filePath, 'utf-8');\n configPath = filePath;\n break;\n } else {\n logger.trace(`No configuration file cloned at ${filePath}`);\n }\n }\n }\n\n // Ensure we have file contents. Otherwise throw a well readable error.\n if (!configContents || !configPath || typeof configContents !== 'string') {\n throw new Error(`Configuration file not found at possible locations: ${POSSIBLE_CONFIG_FILE_PATHS.join(', ')}`);\n } else {\n logger.trace('Configuration file contents read.');\n }\n\n return await parseDependabotConfig({ configContents, configPath, variableFinder });\n}\n","export type AzureDevOpsUrl = {\n /** URL of the organisation. This may lack the project name */\n url: URL;\n\n /** Organisation URL hostname */\n hostname: string;\n\n /** Organisation API endpoint URL */\n 'api-endpoint': string;\n\n /** Project ID or Name */\n project: string;\n\n /** Repository ID or Name */\n repository: string;\n\n /** Slug of the repository e.g. `contoso/prj1/_git/repo1`, `tfs/contoso/prj1/_git/repo1` */\n 'repository-slug': string;\n};\n\nexport function extractUrlParts({\n organisationUrl,\n project,\n repository,\n}: {\n organisationUrl: string;\n project: string;\n repository: string;\n}): AzureDevOpsUrl {\n // convert url string into a valid JS URL object\n const url = new URL(organisationUrl);\n const protocol = url.protocol.slice(0, -1);\n let { hostname } = url;\n const visualStudioUrlRegex = /^(?<prefix>\\S+)\\.visualstudio\\.com$/iu;\n if (visualStudioUrlRegex.test(hostname)) hostname = 'dev.azure.com'; // TODO: should we really be converting back to the new hostname?\n\n const organisation: string = extractOrganisation(organisationUrl);\n\n const virtualDirectory = extractVirtualDirectory(url);\n const apiEndpoint = `${protocol}://${hostname}${url.port ? `:${url.port}` : ''}/${virtualDirectory ? `${virtualDirectory}/` : ''}`;\n\n const escapedProject = encodeURI(project); // encode special characters like spaces\n const escapedRepository = encodeURI(repository); // encode special characters like spaces\n const repoSlug = `${virtualDirectory ? `${virtualDirectory}/` : ''}${organisation}/${escapedProject}/_git/${escapedRepository}`;\n\n return {\n url,\n hostname,\n 'api-endpoint': apiEndpoint,\n\n project: escapedProject,\n repository: escapedRepository,\n 'repository-slug': repoSlug,\n };\n}\n\n/**\n * Extract organisation name from organisation URL\n *\n * @param organisationUrl\n *\n * @returns organisation name\n */\nfunction extractOrganisation(organisationUrl: string): string {\n const parts = organisationUrl.split('/');\n\n // Check for on-premise style: https://server.domain.com/tfs/x/\n if (parts.length === 6) return parts[4]!;\n\n // Check for new style: https://dev.azure.com/x/\n if (parts.length === 5) return parts[3]!;\n\n // Check for old style: https://x.visualstudio.com/\n // Get x.visualstudio.com part; Return organisation part (x).\n if (parts.length === 4) return parts[2]!.split('.')[0]!;\n\n throw new Error(`Error parsing organisation from organisation url: '${organisationUrl}'.`);\n}\n\n/**\n * Extract virtual directory from organisation URL\n *\n * Virtual Directories are sometimes used in on-premises\n * @param organisationUrl\n *\n * @returns virtual directory\n *\n * @example URLs typically are like this:`https://server.domain.com/tfs/x/` and `tfs` is the virtual directory\n */\nfunction extractVirtualDirectory(organisationUrl: URL) {\n // extract the pathname from the url then split\n // pathname takes the shape '/tfs/x/'\n const path = organisationUrl.pathname.split('/');\n\n // Virtual Directories are sometimes used in on-premises\n // URLs typically are like this: https://server.domain.com/tfs/x/\n // The pathname extracted looks like this: '/tfs/x/'\n return path.length === 4 ? path[1]! : undefined;\n}\n"],"mappings":"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"}