@paklo/runner 0.2.3 → 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.
- package/dist/{api-client-d6QdRcLh.d.mts → api-client-M8F9t7II.d.mts} +4 -4
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/local/azure/index.d.mts +3 -3
- package/dist/local/azure/index.mjs +21 -22
- package/dist/local/azure/index.mjs.map +1 -1
- package/dist/local/index.d.mts +2 -2
- package/dist/local/index.mjs +1 -2
- package/dist/{run-6mbbqgXi.mjs → run-BtSPCvKv.mjs} +7 -6
- package/dist/run-BtSPCvKv.mjs.map +1 -0
- package/dist/{server-c_7NJEi8.d.mts → server-BSQEzdZw.d.mts} +19 -19
- package/dist/{server-0h2jXnjg.mjs → server-M1ps5BVd.mjs} +6 -6
- package/dist/server-M1ps5BVd.mjs.map +1 -0
- package/package.json +5 -5
- package/dist/logger-DSV-e8-Y.mjs +0 -3
- package/dist/run-6mbbqgXi.mjs.map +0 -1
- package/dist/server-0h2jXnjg.mjs.map +0 -1
|
@@ -3,16 +3,16 @@ import { InnerApiClient } from "@paklo/core/http";
|
|
|
3
3
|
|
|
4
4
|
//#region src/params.d.ts
|
|
5
5
|
declare class JobParameters {
|
|
6
|
-
readonly jobId:
|
|
6
|
+
readonly jobId: string;
|
|
7
7
|
readonly jobToken: string;
|
|
8
8
|
readonly credentialsToken: string;
|
|
9
9
|
readonly dependabotApiUrl: string;
|
|
10
10
|
readonly dependabotApiDockerUrl: string;
|
|
11
11
|
readonly updaterImage: string;
|
|
12
|
-
constructor(jobId:
|
|
12
|
+
constructor(jobId: string, jobToken: string, credentialsToken: string, dependabotApiUrl: string, dependabotApiDockerUrl: string, updaterImage: string);
|
|
13
13
|
}
|
|
14
14
|
declare function getJobParameters(input: {
|
|
15
|
-
jobId?: string
|
|
15
|
+
jobId?: string;
|
|
16
16
|
jobToken?: string;
|
|
17
17
|
credentialsToken?: string;
|
|
18
18
|
dependabotApiUrl?: string;
|
|
@@ -45,4 +45,4 @@ declare class ApiClient {
|
|
|
45
45
|
}
|
|
46
46
|
//#endregion
|
|
47
47
|
export { JobParameters as a, SecretMasker as i, CredentialFetchingError as n, getJobParameters as o, JobDetailsFetchingError as r, ApiClient as t };
|
|
48
|
-
//# sourceMappingURL=api-client-
|
|
48
|
+
//# sourceMappingURL=api-client-M8F9t7II.d.mts.map
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as JobParameters, i as SecretMasker, n as CredentialFetchingError, o as getJobParameters, r as JobDetailsFetchingError, t as ApiClient } from "./api-client-
|
|
1
|
+
import { a as JobParameters, i as SecretMasker, n as CredentialFetchingError, o as getJobParameters, r as JobDetailsFetchingError, t as ApiClient } from "./api-client-M8F9t7II.mjs";
|
|
2
2
|
import { DependabotCredential, DependabotJobConfig, DependabotProxyConfig, FileFetcherInput, FileUpdaterInput } from "@paklo/core/dependabot";
|
|
3
3
|
import Docker, { Container, Network } from "dockerode";
|
|
4
4
|
import { UsageTelemetryRequestData } from "@paklo/core/usage";
|
|
@@ -47,7 +47,7 @@ declare class ProxyBuilder {
|
|
|
47
47
|
private readonly proxyImage;
|
|
48
48
|
private readonly cachedMode;
|
|
49
49
|
constructor(docker: Docker, proxyImage: string, cachedMode: boolean);
|
|
50
|
-
run(jobId:
|
|
50
|
+
run(jobId: string, jobToken: string, dependabotApiUrl: string, credentials: DependabotCredential[]): Promise<Proxy>;
|
|
51
51
|
private ensureNetwork;
|
|
52
52
|
private buildProxyConfig;
|
|
53
53
|
private generateCertificateAuthority;
|
|
@@ -61,7 +61,7 @@ declare class JobRunnerUpdaterError extends Error {}
|
|
|
61
61
|
type RunJobOptions = {
|
|
62
62
|
dependabotApiUrl: string;
|
|
63
63
|
dependabotApiDockerUrl?: string;
|
|
64
|
-
jobId:
|
|
64
|
+
jobId: string;
|
|
65
65
|
jobToken: string;
|
|
66
66
|
credentialsToken: string;
|
|
67
67
|
updaterImage?: string;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
1
|
+
import { _ as updaterImageName, a as UpdaterBuilder, b as CredentialFetchingError, c as getJobParameters, d as ContainerRuntimeError, f as ContainerService, g as repositoryName, h as hasDigest, i as Updater, l as ImageService, m as digestName, n as JobRunnerUpdaterError, o as ProxyBuilder, p as PROXY_IMAGE_NAME, r as runJob, s as JobParameters, t as JobRunnerImagingError, u as getOrgFromImage, v as updaterImages, x as JobDetailsFetchingError, y as ApiClient } from "./run-BtSPCvKv.mjs";
|
|
2
|
+
import { logger } from "@paklo/core/logger";
|
|
3
3
|
import Docker from "dockerode";
|
|
4
4
|
|
|
5
5
|
//#region src/cleanup.ts
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["error: unknown"],"sources":["../src/cleanup.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["error: unknown"],"sources":["../src/cleanup.ts"],"sourcesContent":["import { logger } from '@paklo/core/logger';\nimport Docker from 'dockerode';\nimport { digestName, hasDigest, PROXY_IMAGE_NAME, repositoryName, updaterImages } from './docker-tags';\n\n// Code below is borrowed and adapted from dependabot-action\n\n// This method performs housekeeping checks to remove Docker artifacts\n// which were left behind by old versions or any jobs\n// which may have crashed before deleting their own containers or networks\n//\n// cutoff - a Go duration string to pass to the Docker API's 'until' argument, default '24h'\nexport async function cleanup(cutoff = '24h'): Promise<void> {\n if (process.env.DEPENDABOT_DISABLE_CLEANUP === '1') {\n return;\n }\n\n try {\n const docker = new Docker();\n const untilFilter = { until: [cutoff] };\n logger.info(`Pruning networks older than ${cutoff}`);\n await docker.pruneNetworks({ filters: untilFilter });\n logger.info(`Pruning containers older than ${cutoff}`);\n await docker.pruneContainers({ filters: untilFilter });\n await Promise.all(\n updaterImages().map(async (image) => {\n return cleanupOldImageVersions(docker, image);\n }),\n );\n await cleanupOldImageVersions(docker, PROXY_IMAGE_NAME);\n } catch (error: unknown) {\n if (error instanceof Error) {\n logger.error(`Error cleaning up: ${error.message}`);\n }\n }\n}\n\nexport async function cleanupOldImageVersions(docker: Docker, imageName: string): Promise<void> {\n const repo = repositoryName(imageName);\n const options = {\n filters: `{\"reference\":[\"${repo}\"]}`,\n };\n\n logger.info(`Cleaning up images for ${repo}`);\n\n docker.listImages(options, async (err, imageInfoList) => {\n if (imageInfoList && imageInfoList.length > 0) {\n for (const imageInfo of imageInfoList) {\n // The given imageName is expected to be a tag + digest, however to avoid any surprises in future\n // we fail over to check for a match on just tags as well.\n //\n // This means we won't remove any image which matches an imageName of either of these notations:\n // - dependabot/image:$TAG@sha256:$REF (current implementation)\n // - dependabot/image:v1\n //\n // Without checking imageInfo.RepoTags for a match, we would actually remove the latter even if\n // this was the active version.\n if (imageMatches(imageInfo, imageName)) {\n logger.info(`Skipping current image ${imageInfo.Id}`);\n continue;\n }\n\n logger.info(`Removing image ${imageInfo.Id}`);\n try {\n await docker.getImage(imageInfo.Id).remove();\n } catch (error: unknown) {\n if (error instanceof Error) {\n logger.info(`Unable to remove ${imageInfo.Id} -- ${error.message}`);\n }\n }\n }\n }\n });\n}\n\nfunction imageMatches(imageInfo: Docker.ImageInfo, imageName: string): boolean {\n if (hasDigest(imageName)) {\n return imageInfo.RepoDigests ? imageInfo.RepoDigests.includes(digestName(imageName)) : false;\n }\n return imageInfo.RepoTags ? imageInfo.RepoTags.includes(imageName) : false;\n}\n"],"mappings":";;;;;AAWA,eAAsB,QAAQ,SAAS,OAAsB;AAC3D,KAAI,QAAQ,IAAI,+BAA+B,IAC7C;AAGF,KAAI;EACF,MAAM,SAAS,IAAI,QAAQ;EAC3B,MAAM,cAAc,EAAE,OAAO,CAAC,OAAO,EAAE;AACvC,SAAO,KAAK,+BAA+B,SAAS;AACpD,QAAM,OAAO,cAAc,EAAE,SAAS,aAAa,CAAC;AACpD,SAAO,KAAK,iCAAiC,SAAS;AACtD,QAAM,OAAO,gBAAgB,EAAE,SAAS,aAAa,CAAC;AACtD,QAAM,QAAQ,IACZ,eAAe,CAAC,IAAI,OAAO,UAAU;AACnC,UAAO,wBAAwB,QAAQ,MAAM;IAC7C,CACH;AACD,QAAM,wBAAwB,QAAQ,iBAAiB;UAChDA,OAAgB;AACvB,MAAI,iBAAiB,MACnB,QAAO,MAAM,sBAAsB,MAAM,UAAU;;;AAKzD,eAAsB,wBAAwB,QAAgB,WAAkC;CAC9F,MAAM,OAAO,eAAe,UAAU;CACtC,MAAM,UAAU,EACd,SAAS,kBAAkB,KAAK,MACjC;AAED,QAAO,KAAK,0BAA0B,OAAO;AAE7C,QAAO,WAAW,SAAS,OAAO,KAAK,kBAAkB;AACvD,MAAI,iBAAiB,cAAc,SAAS,EAC1C,MAAK,MAAM,aAAa,eAAe;AAUrC,OAAI,aAAa,WAAW,UAAU,EAAE;AACtC,WAAO,KAAK,0BAA0B,UAAU,KAAK;AACrD;;AAGF,UAAO,KAAK,kBAAkB,UAAU,KAAK;AAC7C,OAAI;AACF,UAAM,OAAO,SAAS,UAAU,GAAG,CAAC,QAAQ;YACrCA,OAAgB;AACvB,QAAI,iBAAiB,MACnB,QAAO,KAAK,oBAAoB,UAAU,GAAG,MAAM,MAAM,UAAU;;;GAK3E;;AAGJ,SAAS,aAAa,WAA6B,WAA4B;AAC7E,KAAI,UAAU,UAAU,CACtB,QAAO,UAAU,cAAc,UAAU,YAAY,SAAS,WAAW,UAAU,CAAC,GAAG;AAEzF,QAAO,UAAU,WAAW,UAAU,SAAS,SAAS,UAAU,GAAG"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "../../api-client-
|
|
2
|
-
import { a as LocalJobsRunner, i as LocalDependabotServerOptions, n as LocalDependabotServer, o as LocalJobsRunnerOptions, s as RunJobsResult } from "../../server-
|
|
1
|
+
import "../../api-client-M8F9t7II.mjs";
|
|
2
|
+
import { a as LocalJobsRunner, i as LocalDependabotServerOptions, n as LocalDependabotServer, o as LocalJobsRunnerOptions, s as RunJobsResult } from "../../server-BSQEzdZw.mjs";
|
|
3
3
|
import { DependabotRequest } from "@paklo/core/dependabot";
|
|
4
4
|
import { AzureDevOpsRepositoryUrl, AzureDevOpsWebApiClient, IPullRequestProperties } from "@paklo/core/azure";
|
|
5
5
|
|
|
@@ -18,7 +18,7 @@ type AzureLocalDependabotServerOptions = LocalDependabotServerOptions & {
|
|
|
18
18
|
declare class AzureLocalDependabotServer extends LocalDependabotServer {
|
|
19
19
|
private readonly options;
|
|
20
20
|
constructor(options: AzureLocalDependabotServerOptions);
|
|
21
|
-
protected handle(id:
|
|
21
|
+
protected handle(id: string, request: DependabotRequest): Promise<boolean>;
|
|
22
22
|
}
|
|
23
23
|
//#endregion
|
|
24
24
|
//#region src/local/azure/runner.d.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { n as LocalJobsRunner, t as LocalDependabotServer } from "../../server-0h2jXnjg.mjs";
|
|
1
|
+
import { r as runJob } from "../../run-BtSPCvKv.mjs";
|
|
2
|
+
import { n as LocalJobsRunner, t as LocalDependabotServer } from "../../server-M1ps5BVd.mjs";
|
|
4
3
|
import { DependabotJobBuilder, getBranchNameForUpdate, mapPackageEcosystemToPackageManager } from "@paklo/core/dependabot";
|
|
4
|
+
import { logger } from "@paklo/core/logger";
|
|
5
5
|
import { readFile } from "node:fs/promises";
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { AzureDevOpsWebApiClient, DEVOPS_PR_PROPERTY_MICROSOFT_GIT_SOURCE_REF_NAME, GitPullRequestMergeStrategy, buildPullRequestProperties, getPullRequestChangedFilesForOutputData, getPullRequestCloseReasonForOutputData, getPullRequestDependenciesPropertyValueForOutputData, getPullRequestDescription, getPullRequestForDependencyNames, normalizeBranchName, parsePullRequestProperties } from "@paklo/core/azure";
|
|
@@ -285,7 +285,6 @@ var AzureLocalJobsRunner = class extends LocalJobsRunner {
|
|
|
285
285
|
experiments,
|
|
286
286
|
debug: false
|
|
287
287
|
});
|
|
288
|
-
let jobId;
|
|
289
288
|
let job;
|
|
290
289
|
let credentials;
|
|
291
290
|
let jobToken;
|
|
@@ -294,10 +293,10 @@ var AzureLocalJobsRunner = class extends LocalJobsRunner {
|
|
|
294
293
|
let dependencyNamesToUpdate = [];
|
|
295
294
|
const securityUpdatesOnly = update["open-pull-requests-limit"] === 0;
|
|
296
295
|
if (securityUpdatesOnly) {
|
|
297
|
-
({
|
|
296
|
+
({job, credentials} = builder.forDependenciesList({ command }));
|
|
298
297
|
({jobToken, credentialsToken} = this.makeTokens());
|
|
299
298
|
server.add({
|
|
300
|
-
id:
|
|
299
|
+
id: job.id,
|
|
301
300
|
update,
|
|
302
301
|
job,
|
|
303
302
|
jobToken,
|
|
@@ -307,14 +306,14 @@ var AzureLocalJobsRunner = class extends LocalJobsRunner {
|
|
|
307
306
|
await runJob({
|
|
308
307
|
dependabotApiUrl,
|
|
309
308
|
dependabotApiDockerUrl,
|
|
310
|
-
jobId,
|
|
309
|
+
jobId: job.id,
|
|
311
310
|
jobToken,
|
|
312
311
|
credentialsToken,
|
|
313
312
|
updaterImage,
|
|
314
313
|
secretMasker,
|
|
315
314
|
usage: makeUsageData(job)
|
|
316
315
|
});
|
|
317
|
-
const packagesToCheckForVulnerabilities = server.requests(
|
|
316
|
+
const packagesToCheckForVulnerabilities = server.requests(job.id).find((o) => o.type === "update_dependency_list")?.data.dependencies?.map((d) => ({
|
|
318
317
|
name: d.name,
|
|
319
318
|
version: d.version
|
|
320
319
|
}));
|
|
@@ -337,17 +336,17 @@ var AzureLocalJobsRunner = class extends LocalJobsRunner {
|
|
|
337
336
|
if (dependencyNamesToUpdate.length) logger.trace(dependencyNamesToUpdate);
|
|
338
337
|
} else {
|
|
339
338
|
logger.info(`No vulnerabilities detected for update ${update["package-ecosystem"]} in ${update.directory}`);
|
|
340
|
-
server.clear(
|
|
339
|
+
server.clear(job.id);
|
|
341
340
|
continue;
|
|
342
341
|
}
|
|
343
|
-
server.clear(
|
|
342
|
+
server.clear(job.id);
|
|
344
343
|
}
|
|
345
344
|
const openPullRequestsLimit = update["open-pull-requests-limit"];
|
|
346
345
|
const openPullRequestsCount = Object.entries(existingPullRequestsForPackageManager).length;
|
|
347
346
|
if (!(openPullRequestsLimit > 0 && openPullRequestsCount >= openPullRequestsLimit)) {
|
|
348
347
|
const dependenciesHaveVulnerabilities = dependencyNamesToUpdate.length && securityVulnerabilities.length;
|
|
349
348
|
if (!securityUpdatesOnly || dependenciesHaveVulnerabilities) {
|
|
350
|
-
({
|
|
349
|
+
({job, credentials} = builder.forUpdate({
|
|
351
350
|
command,
|
|
352
351
|
dependencyNamesToUpdate,
|
|
353
352
|
existingPullRequests: existingPullRequestDependenciesForPackageManager,
|
|
@@ -355,7 +354,7 @@ var AzureLocalJobsRunner = class extends LocalJobsRunner {
|
|
|
355
354
|
}));
|
|
356
355
|
({jobToken, credentialsToken} = this.makeTokens());
|
|
357
356
|
server.add({
|
|
358
|
-
id:
|
|
357
|
+
id: job.id,
|
|
359
358
|
update,
|
|
360
359
|
job,
|
|
361
360
|
jobToken,
|
|
@@ -365,17 +364,17 @@ var AzureLocalJobsRunner = class extends LocalJobsRunner {
|
|
|
365
364
|
const { success, message } = await runJob({
|
|
366
365
|
dependabotApiUrl,
|
|
367
366
|
dependabotApiDockerUrl,
|
|
368
|
-
jobId,
|
|
367
|
+
jobId: job.id,
|
|
369
368
|
jobToken,
|
|
370
369
|
credentialsToken,
|
|
371
370
|
updaterImage,
|
|
372
371
|
secretMasker,
|
|
373
372
|
usage: makeUsageData(job)
|
|
374
373
|
});
|
|
375
|
-
const affectedPrs = server.allAffectedPrs(
|
|
376
|
-
server.clear(
|
|
374
|
+
const affectedPrs = server.allAffectedPrs(job.id);
|
|
375
|
+
server.clear(job.id);
|
|
377
376
|
results.push({
|
|
378
|
-
id:
|
|
377
|
+
id: job.id,
|
|
379
378
|
success,
|
|
380
379
|
message,
|
|
381
380
|
affectedPrs
|
|
@@ -384,7 +383,7 @@ var AzureLocalJobsRunner = class extends LocalJobsRunner {
|
|
|
384
383
|
} else logger.warn(`Skipping update for ${packageEcosystem} packages as the open pull requests limit (${openPullRequestsLimit}) has already been reached`);
|
|
385
384
|
const numberOfPullRequestsToUpdate = Object.keys(existingPullRequestsForPackageManager).length;
|
|
386
385
|
if (numberOfPullRequestsToUpdate > 0) if (!dryRun) for (const pullRequestId in existingPullRequestsForPackageManager) {
|
|
387
|
-
({
|
|
386
|
+
({job, credentials} = builder.forUpdate({
|
|
388
387
|
command,
|
|
389
388
|
existingPullRequests: existingPullRequestDependenciesForPackageManager,
|
|
390
389
|
pullRequestToUpdate: existingPullRequestsForPackageManager[pullRequestId],
|
|
@@ -392,7 +391,7 @@ var AzureLocalJobsRunner = class extends LocalJobsRunner {
|
|
|
392
391
|
}));
|
|
393
392
|
({jobToken, credentialsToken} = this.makeTokens());
|
|
394
393
|
server.add({
|
|
395
|
-
id:
|
|
394
|
+
id: job.id,
|
|
396
395
|
update,
|
|
397
396
|
job,
|
|
398
397
|
jobToken,
|
|
@@ -402,17 +401,17 @@ var AzureLocalJobsRunner = class extends LocalJobsRunner {
|
|
|
402
401
|
const { success, message } = await runJob({
|
|
403
402
|
dependabotApiUrl,
|
|
404
403
|
dependabotApiDockerUrl,
|
|
405
|
-
jobId,
|
|
404
|
+
jobId: job.id,
|
|
406
405
|
jobToken,
|
|
407
406
|
credentialsToken,
|
|
408
407
|
updaterImage,
|
|
409
408
|
secretMasker,
|
|
410
409
|
usage: makeUsageData(job)
|
|
411
410
|
});
|
|
412
|
-
const affectedPrs = server.allAffectedPrs(
|
|
413
|
-
server.clear(
|
|
411
|
+
const affectedPrs = server.allAffectedPrs(job.id);
|
|
412
|
+
server.clear(job.id);
|
|
414
413
|
results.push({
|
|
415
|
-
id:
|
|
414
|
+
id: job.id,
|
|
416
415
|
success,
|
|
417
416
|
message,
|
|
418
417
|
affectedPrs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["updates: DependabotUpdate[]","results: RunJobsResult","jobId: number | undefined","job: DependabotJobConfig | undefined","credentials: DependabotCredential[] | undefined","jobToken: string","credentialsToken: string","securityVulnerabilities: SecurityVulnerability[]","dependencyNamesToUpdate: string[]","packagesToCheckForVulnerabilities: Package[] | undefined"],"sources":["../../../src/local/azure/server.ts","../../../src/local/azure/runner.ts"],"sourcesContent":["import type { AzureDevOpsRepositoryUrl, AzureDevOpsWebApiClient, IPullRequestProperties } from '@paklo/core/azure';\nimport {\n buildPullRequestProperties,\n GitPullRequestMergeStrategy,\n getPullRequestChangedFilesForOutputData,\n getPullRequestCloseReasonForOutputData,\n getPullRequestDependenciesPropertyValueForOutputData,\n getPullRequestDescription,\n getPullRequestForDependencyNames,\n parsePullRequestProperties,\n} from '@paklo/core/azure';\nimport { type DependabotRequest, getBranchNameForUpdate } from '@paklo/core/dependabot';\nimport { logger } from '@/logger';\nimport { LocalDependabotServer, type LocalDependabotServerOptions } from '../server';\n\nexport type AzureLocalDependabotServerOptions = LocalDependabotServerOptions & {\n url: AzureDevOpsRepositoryUrl;\n authorClient: AzureDevOpsWebApiClient;\n autoApprove: boolean;\n approverClient?: AzureDevOpsWebApiClient;\n setAutoComplete: boolean;\n mergeStrategy?: string;\n autoCompleteIgnoreConfigIds: number[];\n existingBranchNames: string[] | undefined;\n existingPullRequests: IPullRequestProperties[];\n};\n\nexport class AzureLocalDependabotServer extends LocalDependabotServer {\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: options is used\n private readonly options: AzureLocalDependabotServerOptions;\n\n constructor(options: AzureLocalDependabotServerOptions) {\n super(options);\n this.options = options;\n }\n\n protected override async handle(id: number, request: DependabotRequest): Promise<boolean> {\n await super.handle(id, request); // common logic\n\n const { options, affectedPullRequestIds } = this;\n const {\n url,\n authorClient,\n approverClient,\n existingBranchNames,\n existingPullRequests,\n autoApprove,\n mergeStrategy,\n setAutoComplete,\n autoCompleteIgnoreConfigIds,\n author,\n debug,\n dryRun,\n } = options;\n\n const { type, data } = request;\n const job = await this.job(id);\n if (!job) {\n logger.error(`No job found for ID '${id}', cannot process request of type '${type}'`);\n return false;\n }\n const { 'package-manager': packageManager } = job;\n logger.info(`Processing '${type}' for job ID '${id}'`);\n if (debug) {\n logger.debug(JSON.stringify(data));\n }\n\n const update = this.update(id)!; // exists because job exists\n const { project, repository } = url;\n\n switch (type) {\n // Documentation on the 'data' model for each output type can be found here:\n // See: https://github.com/dependabot/cli/blob/main/internal/model/update.go\n\n case 'create_pull_request': {\n const title = data['pr-title'];\n if (dryRun) {\n logger.warn(`Skipping pull request creation of '${title}' as 'dryRun' is set to 'true'`);\n return true;\n }\n\n // Skip if active pull request limit reached.\n const openPullRequestsLimit = update['open-pull-requests-limit']!;\n\n // Parse the Dependabot metadata for the existing pull requests that are related to this update\n // Dependabot will use this to determine if we need to create new pull requests or update/close existing ones\n const existingPullRequestsForPackageManager = parsePullRequestProperties(existingPullRequests, packageManager);\n const existingPullRequestsCount = Object.entries(existingPullRequestsForPackageManager).length;\n const openPullRequestsCount = affectedPullRequestIds.get(id)!.created.length + existingPullRequestsCount;\n const hasReachedOpenPullRequestLimit =\n openPullRequestsLimit > 0 && openPullRequestsCount >= openPullRequestsLimit;\n\n if (hasReachedOpenPullRequestLimit) {\n logger.warn(\n `Skipping pull request creation of '${title}' as the open pull requests limit (${openPullRequestsLimit}) has been reached`,\n );\n return true;\n }\n\n const changedFiles = getPullRequestChangedFilesForOutputData(data);\n const dependencies = getPullRequestDependenciesPropertyValueForOutputData(data);\n const targetBranch = update['target-branch'] || (await authorClient.getDefaultBranch(project, repository));\n const sourceBranch = getBranchNameForUpdate(\n update['package-ecosystem'],\n targetBranch,\n update.directory || update.directories?.find((dir) => changedFiles[0]?.path?.startsWith(dir)),\n !Array.isArray(dependencies) ? dependencies['dependency-group-name'] : undefined,\n !Array.isArray(dependencies) ? dependencies.dependencies : dependencies,\n update['pull-request-branch-name']?.separator,\n );\n\n // Check if the source branch already exists or conflicts with an existing branch\n const existingBranch = existingBranchNames?.find((branch) => sourceBranch === branch) || [];\n if (existingBranch.length) {\n logger.error(\n `Unable to create pull request '${title}' as source branch '${sourceBranch}' already exists; Delete the existing branch and try again.`,\n );\n return false;\n }\n const conflictingBranches = existingBranchNames?.filter((branch) => sourceBranch.startsWith(branch)) || [];\n if (conflictingBranches.length) {\n logger.error(\n `Unable to create pull request '${title}' as source branch '${sourceBranch}' would conflict with existing branch(es) '${conflictingBranches.join(', ')}'; Delete the conflicting branch(es) and try again.`,\n );\n return false;\n }\n\n // Create a new pull request\n const newPullRequestId = await authorClient.createPullRequest({\n project: project,\n repository: repository,\n source: {\n commit: data['base-commit-sha'] || job.source.commit!,\n branch: sourceBranch,\n },\n target: {\n branch: targetBranch!,\n },\n author,\n title,\n description: getPullRequestDescription(packageManager, data['pr-body'], data.dependencies),\n commitMessage: data['commit-message'],\n autoComplete: setAutoComplete\n ? {\n ignorePolicyConfigIds: autoCompleteIgnoreConfigIds,\n mergeStrategy: (() => {\n switch (mergeStrategy) {\n case 'noFastForward':\n return GitPullRequestMergeStrategy.NoFastForward;\n case 'squash':\n return GitPullRequestMergeStrategy.Squash;\n case 'rebase':\n return GitPullRequestMergeStrategy.Rebase;\n case 'rebaseMerge':\n return GitPullRequestMergeStrategy.RebaseMerge;\n default:\n return GitPullRequestMergeStrategy.Squash;\n }\n })(),\n }\n : undefined,\n assignees: update.assignees,\n labels: update.labels?.map((label) => label?.trim()) || [],\n workItems: update.milestone ? [update.milestone] : [],\n changes: changedFiles,\n properties: buildPullRequestProperties(packageManager, dependencies),\n });\n\n // Auto-approve the pull request, if required\n if (autoApprove && approverClient && newPullRequestId) {\n await approverClient.approvePullRequest({\n project: project,\n repository: repository,\n pullRequestId: newPullRequestId,\n });\n }\n\n // Store the new pull request ID, so we can keep track of the total number of open pull requests\n if (newPullRequestId && newPullRequestId > 0) {\n affectedPullRequestIds.get(id)!.created.push(newPullRequestId);\n return true;\n } else {\n return false;\n }\n }\n\n case 'update_pull_request': {\n if (dryRun) {\n logger.warn(`Skipping pull request update as 'dryRun' is set to 'true'`);\n return true;\n }\n\n // Find the pull request to update\n const pullRequestToUpdate = getPullRequestForDependencyNames(\n existingPullRequests,\n packageManager,\n data['dependency-names'],\n );\n if (!pullRequestToUpdate) {\n logger.error(\n `Could not find pull request to update for package manager '${packageManager}' with dependencies '${data['dependency-names'].join(', ')}'`,\n );\n return false;\n }\n\n // Update the pull request\n const pullRequestWasUpdated = await authorClient.updatePullRequest({\n project: project,\n repository: repository,\n pullRequestId: pullRequestToUpdate.id,\n commit: data['base-commit-sha'] || job.source.commit!,\n author,\n changes: getPullRequestChangedFilesForOutputData(data),\n skipIfDraft: true,\n skipIfCommitsFromAuthorsOtherThan: author.email,\n skipIfNotBehindTargetBranch: true,\n });\n\n // Re-approve the pull request, if required\n if (autoApprove && approverClient && pullRequestWasUpdated) {\n await approverClient.approvePullRequest({\n project: project,\n repository: repository,\n pullRequestId: pullRequestToUpdate.id,\n });\n }\n\n if (pullRequestWasUpdated) {\n affectedPullRequestIds.get(id)!.updated.push(pullRequestToUpdate.id);\n return true;\n }\n return false;\n }\n\n case 'close_pull_request': {\n if (dryRun) {\n logger.warn(`Skipping pull request closure as 'dryRun' is set to 'true'`);\n return true;\n }\n\n // Find the pull request to close\n const pullRequestToClose = getPullRequestForDependencyNames(\n existingPullRequests,\n packageManager,\n data['dependency-names'],\n );\n if (!pullRequestToClose) {\n logger.error(\n `Could not find pull request to close for package manager '${packageManager}' with dependencies '${data['dependency-names'].join(', ')}'`,\n );\n return false;\n }\n\n // TODO: GitHub Dependabot will close with reason \"Superseded by ${new_pull_request_id}\" when another PR supersedes it.\n // How do we detect this? Do we need to?\n\n // Close the pull request\n const success = await authorClient.abandonPullRequest({\n project: project,\n repository: repository,\n pullRequestId: pullRequestToClose.id,\n comment: getPullRequestCloseReasonForOutputData(data),\n deleteSourceBranch: true,\n });\n if (success) {\n affectedPullRequestIds.get(id)!.closed.push(pullRequestToClose.id);\n return true;\n }\n return false;\n }\n\n // No action required\n case 'update_dependency_list':\n case 'mark_as_processed':\n case 'record_ecosystem_versions':\n case 'record_ecosystem_meta':\n case 'increment_metric':\n case 'record_metrics':\n return true;\n\n case 'record_update_job_error':\n logger.error(`Update job error: ${data['error-type']} ${JSON.stringify(data['error-details'])}`);\n return true;\n\n case 'record_update_job_unknown_error':\n logger.error(`Update job unknown error: ${data['error-type']}, ${JSON.stringify(data['error-details'])}`);\n return true;\n\n default:\n logger.warn(`Unknown dependabot output type '${type}', ignoring...`);\n return true;\n }\n }\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport {\n AzureDevOpsWebApiClient,\n DEVOPS_PR_PROPERTY_MICROSOFT_GIT_SOURCE_REF_NAME,\n type IPullRequestProperties,\n normalizeBranchName,\n parsePullRequestProperties,\n} from '@paklo/core/azure';\nimport {\n type DependabotCredential,\n DependabotJobBuilder,\n type DependabotJobConfig,\n type DependabotUpdate,\n mapPackageEcosystemToPackageManager,\n} from '@paklo/core/dependabot';\nimport {\n filterVulnerabilities,\n GitHubSecurityAdvisoryClient,\n getGhsaPackageEcosystemFromDependabotPackageManager,\n type Package,\n type SecurityVulnerability,\n SecurityVulnerabilitySchema,\n} from '@paklo/core/github';\nimport { logger } from '@/logger';\nimport { type RunJobOptions, runJob } from '../../run';\nimport { LocalJobsRunner, type LocalJobsRunnerOptions, type RunJobsResult } from '../runner';\nimport { AzureLocalDependabotServer, type AzureLocalDependabotServerOptions } from './server';\n\nexport type AzureLocalJobsRunnerOptions = LocalJobsRunnerOptions &\n Omit<\n AzureLocalDependabotServerOptions,\n 'authorClient' | 'approverClient' | 'existingBranchNames' | 'existingPullRequests'\n > & {\n port?: number;\n securityAdvisoriesFile?: string;\n gitToken: string;\n githubToken?: string;\n autoApproveToken?: string;\n };\n\nexport class AzureLocalJobsRunner extends LocalJobsRunner {\n // biome-ignore-start lint/correctness/noUnusedPrivateClassMembers: variables are used\n private readonly options: AzureLocalJobsRunnerOptions;\n private readonly authorClient: AzureDevOpsWebApiClient;\n private readonly approverClient?: AzureDevOpsWebApiClient;\n // biome-ignore-end lint/correctness/noUnusedPrivateClassMembers: variables are used\n\n constructor(options: AzureLocalJobsRunnerOptions) {\n super({ ...options });\n this.options = options;\n const { url, gitToken, autoApprove, debug } = this.options;\n\n // Initialise the DevOps API clients (one for authoring the other for auto-approving (if configured))\n this.authorClient = new AzureDevOpsWebApiClient(url, gitToken, debug);\n this.approverClient = autoApprove\n ? new AzureDevOpsWebApiClient(url, options.autoApproveToken || gitToken, debug)\n : undefined;\n }\n\n public override async run(): Promise<RunJobsResult> {\n await super.run(); // common logic\n\n const {\n options: { url, port, config, targetUpdateIds, command },\n authorClient,\n approverClient,\n } = this;\n\n // Print a warning about multi-ecosystem updates not being fully supported\n // TODO: Implement full support for multi-ecosystem updates (not sure this will be possible on the local model)\n if (config['multi-ecosystem-groups'] || config.updates?.some((u) => u['multi-ecosystem-group'])) {\n logger.warn(\n 'Multi-ecosystem updates are not working yet. Only parsing and validation is supported at this time.',\n );\n }\n\n // Print a warning about missing schedules\n // TODO: remove this and enforce schedules on or after 2025-Nov-30\n if (config.updates?.some((u) => !u.schedule)) {\n logger.warn(\n `\n Some updates are missing a schedule configuration.\n This tool will require all updates to have a schedule on or after 2025-Nov-30.\n `,\n );\n }\n\n // Print a warning about the required workarounds for security-only updates, if any update is configured as such\n // TODO: If and when Dependabot supports a better way to do security-only updates, remove this.\n if (config.updates?.some((u) => u['open-pull-requests-limit'] === 0)) {\n logger.warn(\n 'Security-only updates incur a slight performance overhead due to limitations in Dependabot CLI. For more info, see: https://github.com/mburumaxwell/dependabot-azure-devops/blob/main/README.md#configuring-security-advisories-and-known-vulnerabilities',\n );\n }\n\n // Fetch the active pull requests created by the author user\n const existingBranchNames = await authorClient.getBranchNames(url.project, url.repository);\n const existingPullRequests = await authorClient.getActivePullRequestProperties(\n url.project,\n url.repository,\n await authorClient.getUserId(),\n );\n\n // Prepare local server\n const serverOptions: AzureLocalDependabotServerOptions = {\n authorClient,\n approverClient,\n existingBranchNames,\n existingPullRequests,\n ...this.options,\n };\n const server = new AzureLocalDependabotServer(serverOptions);\n server.start(port);\n // give the server a second to start\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n // The API urls is constant when working in this CLI. Asking people to setup NGROK or similar just to get\n // HTTPS for the job token to be used is too much hassle.\n // Using same value for dependabotApiUrl and dependabotApiDockerUrl so as to capture /record_metrics calls.\n const dependabotApiUrl = `http://host.docker.internal:${server.port}/api`;\n const dependabotApiDockerUrl = dependabotApiUrl;\n\n // If update identifiers are specified, select them; otherwise handle all\n let updates: DependabotUpdate[] = [];\n if (targetUpdateIds && targetUpdateIds.length > 0) {\n for (const id of targetUpdateIds) {\n const upd = config.updates[id];\n if (!upd) {\n logger.warn(\n `\n Unable to find target update id '${id}'.\n This value should be a zero based index of the update in your config file.\n Expected range: 0-${config.updates.length - 1}\n `,\n );\n } else {\n updates.push(upd);\n }\n }\n } else {\n updates = config.updates;\n }\n\n try {\n // Abandon all pull requests where the source branch has been deleted\n await this.abandonPullRequestsWhereSourceRefIsDeleted(existingBranchNames, existingPullRequests);\n\n // Perform updates for each of the [targeted] update blocks in dependabot.yaml\n return await this.performUpdates(\n server,\n updates,\n existingPullRequests,\n dependabotApiUrl,\n dependabotApiDockerUrl,\n command,\n );\n } finally {\n server.stop();\n }\n }\n\n /**\n * Abandon all pull requests where the source branch has been deleted.\n * @param existingBranchNames The names of the existing branches.\n * @param existingPullRequests The existing pull requests.\n */\n private async abandonPullRequestsWhereSourceRefIsDeleted(\n existingBranchNames?: string[],\n existingPullRequests?: IPullRequestProperties[],\n ): Promise<void> {\n if (!existingBranchNames || !existingPullRequests) return;\n\n const {\n options: { url, dryRun },\n authorClient,\n } = this;\n for (const pullRequestIndex in existingPullRequests) {\n const pullRequest = existingPullRequests[pullRequestIndex]!;\n const pullRequestSourceRefName = normalizeBranchName(\n pullRequest.properties?.find((x) => x.name === DEVOPS_PR_PROPERTY_MICROSOFT_GIT_SOURCE_REF_NAME)?.value,\n );\n if (pullRequestSourceRefName && !existingBranchNames.includes(pullRequestSourceRefName)) {\n // The source branch for the pull request has been deleted; abandon the pull request (if not dry run)\n if (!dryRun) {\n logger.warn(\n `Detected source branch for PR #${pullRequest.id} has been deleted; The pull request will be abandoned`,\n );\n await authorClient.abandonPullRequest({\n project: url.project,\n repository: url.repository,\n pullRequestId: pullRequest.id,\n // comment:\n // 'OK, I won't notify you again about this release, but will get in touch when a new version is available. ' +\n // 'If you'd rather skip all updates until the next major or minor version, add an ' +\n // '[`ignore` condition](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#ignore--) ' +\n // 'with the desired `update-types` to your config file.',\n comment:\n 'It might be a good idea to add an ' +\n '[`ignore` condition](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#ignore--) ' +\n 'with the desired `update-types` to your config file.',\n });\n }\n // Remove the pull request from the list of existing pull requests to ensures that we don't attempt to update it later in the process.\n existingPullRequests.splice(existingPullRequests.indexOf(pullRequest), 1);\n }\n }\n }\n\n /**\n * Performs the updates.\n * @param server The local Dependabot server.\n * @param updates The updates to perform.\n * @param existingPullRequests The existing pull requests.\n */\n private async performUpdates(\n server: AzureLocalDependabotServer,\n updates: DependabotUpdate[],\n existingPullRequests: IPullRequestProperties[],\n dependabotApiUrl: string,\n dependabotApiDockerUrl?: string,\n command?: DependabotJobConfig['command'],\n ): Promise<RunJobsResult> {\n const {\n options: { url, gitToken, githubToken, experiments, config, dryRun, securityAdvisoriesFile, secretMasker },\n } = this;\n\n const results: RunJobsResult = [];\n\n function makeUsageData(job: DependabotJobConfig): RunJobOptions['usage'] {\n return {\n trigger: 'user',\n provider: job.source.provider,\n owner: url.value.toString(),\n project: `${url.value.toString().replace(/\\/$/, '')}/${url.project}`,\n 'package-manager': job['package-manager'],\n };\n }\n\n for (const update of updates) {\n const packageEcosystem = update['package-ecosystem'];\n const packageManager = mapPackageEcosystemToPackageManager(packageEcosystem);\n\n // If there is an updater image, replace the placeholder in it\n let { updaterImage } = this.options;\n updaterImage = updaterImage?.replace(/\\{ecosystem\\}/i, packageEcosystem);\n\n // Parse the Dependabot metadata for the existing pull requests that are related to this update\n // Dependabot will use this to determine if we need to create new pull requests or update/close existing ones\n const existingPullRequestsForPackageManager = parsePullRequestProperties(existingPullRequests, packageManager);\n const existingPullRequestDependenciesForPackageManager = Object.values(existingPullRequestsForPackageManager);\n\n const builder = new DependabotJobBuilder({\n source: { provider: 'azure', ...url },\n config,\n update,\n systemAccessToken: gitToken,\n githubToken,\n experiments,\n debug: false,\n });\n\n let jobId: number | undefined;\n let job: DependabotJobConfig | undefined;\n let credentials: DependabotCredential[] | undefined;\n let jobToken: string;\n let credentialsToken: string;\n\n // If this is a security-only update (i.e. 'open-pull-requests-limit: 0'), then we first need to discover the dependencies\n // that need updating and check each one for vulnerabilities. This is because Dependabot requires the list of vulnerable dependencies\n // to be supplied in the job definition of security-only update job, it will not automatically discover them like a versioned update does.\n // https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/configuring-dependabot-security-updates#overriding-the-default-behavior-with-a-configuration-file\n let securityVulnerabilities: SecurityVulnerability[] = [];\n let dependencyNamesToUpdate: string[] = [];\n const securityUpdatesOnly = update['open-pull-requests-limit'] === 0;\n if (securityUpdatesOnly) {\n // Run an update job to discover all dependencies\n ({ jobId, job, credentials } = builder.forDependenciesList({ command }));\n ({ jobToken, credentialsToken } = this.makeTokens());\n server.add({ id: jobId, update, job, jobToken, credentialsToken, credentials });\n await runJob({\n dependabotApiUrl,\n dependabotApiDockerUrl,\n jobId,\n jobToken,\n credentialsToken,\n updaterImage,\n secretMasker,\n usage: makeUsageData(job),\n });\n\n const outputs = server.requests(jobId);\n const packagesToCheckForVulnerabilities: Package[] | undefined = outputs!\n .find((o) => o.type === 'update_dependency_list')\n ?.data.dependencies?.map((d) => ({ name: d.name, version: d.version }));\n if (packagesToCheckForVulnerabilities?.length) {\n logger.info(\n `Detected ${packagesToCheckForVulnerabilities.length} dependencies; Checking for vulnerabilities...`,\n );\n\n // parse security advisories from file (private)\n if (securityAdvisoriesFile) {\n const filePath = securityAdvisoriesFile;\n if (existsSync(filePath)) {\n const fileContents = await readFile(filePath, 'utf-8');\n securityVulnerabilities = await SecurityVulnerabilitySchema.array().parseAsync(JSON.parse(fileContents));\n } else {\n logger.info(`Private security advisories file '${filePath}' does not exist`);\n }\n }\n if (githubToken) {\n const ghsaClient = new GitHubSecurityAdvisoryClient(githubToken);\n const githubVulnerabilities = await ghsaClient.getSecurityVulnerabilitiesAsync(\n getGhsaPackageEcosystemFromDependabotPackageManager(packageManager),\n packagesToCheckForVulnerabilities || [],\n );\n securityVulnerabilities.push(...githubVulnerabilities);\n } else {\n logger.info(\n 'GitHub access token is not provided; Checking for vulnerabilities from GitHub is skipped. ' +\n 'This is not an issue if you are using private security advisories file.',\n );\n }\n\n securityVulnerabilities = filterVulnerabilities(securityVulnerabilities);\n\n // Only update dependencies that have vulnerabilities\n dependencyNamesToUpdate = Array.from(new Set(securityVulnerabilities.map((v) => v.package.name)));\n logger.info(\n `Detected ${securityVulnerabilities.length} vulnerabilities affecting ${dependencyNamesToUpdate.length} dependencies`,\n );\n if (dependencyNamesToUpdate.length) {\n logger.trace(dependencyNamesToUpdate);\n }\n } else {\n logger.info(`No vulnerabilities detected for update ${update['package-ecosystem']} in ${update.directory}`);\n server.clear(jobId);\n continue; // nothing more to do for this update\n }\n\n server.clear(jobId);\n }\n\n // Run an update job for \"all dependencies\"; this will create new pull requests for dependencies that need updating\n const openPullRequestsLimit = update['open-pull-requests-limit']!;\n const openPullRequestsCount = Object.entries(existingPullRequestsForPackageManager).length;\n const hasReachedOpenPullRequestLimit =\n openPullRequestsLimit > 0 && openPullRequestsCount >= openPullRequestsLimit;\n if (!hasReachedOpenPullRequestLimit) {\n const dependenciesHaveVulnerabilities = dependencyNamesToUpdate.length && securityVulnerabilities.length;\n if (!securityUpdatesOnly || dependenciesHaveVulnerabilities) {\n ({ jobId, job, credentials } = builder.forUpdate({\n command,\n dependencyNamesToUpdate,\n existingPullRequests: existingPullRequestDependenciesForPackageManager,\n securityVulnerabilities,\n }));\n ({ jobToken, credentialsToken } = this.makeTokens());\n server.add({ id: jobId, update, job, jobToken, credentialsToken, credentials });\n const { success, message } = await runJob({\n dependabotApiUrl,\n dependabotApiDockerUrl,\n jobId,\n jobToken,\n credentialsToken,\n updaterImage,\n secretMasker,\n usage: makeUsageData(job),\n });\n const affectedPrs = server.allAffectedPrs(jobId);\n server.clear(jobId);\n results.push({ id: jobId, success, message, affectedPrs });\n } else {\n logger.info('Nothing to update; dependencies are not affected by any known vulnerability');\n }\n } else {\n logger.warn(\n `Skipping update for ${packageEcosystem} packages as the open pull requests limit (${openPullRequestsLimit}) has already been reached`,\n );\n }\n\n // If there are existing pull requests, run an update job for each one; this will resolve merge conflicts and close pull requests that are no longer needed\n const numberOfPullRequestsToUpdate = Object.keys(existingPullRequestsForPackageManager).length;\n if (numberOfPullRequestsToUpdate > 0) {\n if (!dryRun) {\n for (const pullRequestId in existingPullRequestsForPackageManager) {\n ({ jobId, job, credentials } = builder.forUpdate({\n command,\n existingPullRequests: existingPullRequestDependenciesForPackageManager,\n pullRequestToUpdate: existingPullRequestsForPackageManager[pullRequestId]!,\n securityVulnerabilities,\n }));\n ({ jobToken, credentialsToken } = this.makeTokens());\n server.add({ id: jobId, update, job, jobToken, credentialsToken, credentials });\n const { success, message } = await runJob({\n dependabotApiUrl,\n dependabotApiDockerUrl,\n jobId,\n jobToken,\n credentialsToken,\n updaterImage,\n secretMasker,\n usage: makeUsageData(job),\n });\n const affectedPrs = server.allAffectedPrs(jobId);\n server.clear(jobId);\n results.push({ id: jobId, success, message, affectedPrs });\n }\n } else {\n logger.warn(\n `Skipping update of ${numberOfPullRequestsToUpdate} existing ${packageEcosystem} package pull request(s) as 'dryRun' is set to 'true'`,\n );\n }\n }\n }\n\n return results;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["updates: DependabotUpdate[]","results: RunJobsResult","job: DependabotJobConfig | undefined","credentials: DependabotCredential[] | undefined","jobToken: string","credentialsToken: string","securityVulnerabilities: SecurityVulnerability[]","dependencyNamesToUpdate: string[]","packagesToCheckForVulnerabilities: Package[] | undefined"],"sources":["../../../src/local/azure/server.ts","../../../src/local/azure/runner.ts"],"sourcesContent":["import type { AzureDevOpsRepositoryUrl, AzureDevOpsWebApiClient, IPullRequestProperties } from '@paklo/core/azure';\nimport {\n buildPullRequestProperties,\n GitPullRequestMergeStrategy,\n getPullRequestChangedFilesForOutputData,\n getPullRequestCloseReasonForOutputData,\n getPullRequestDependenciesPropertyValueForOutputData,\n getPullRequestDescription,\n getPullRequestForDependencyNames,\n parsePullRequestProperties,\n} from '@paklo/core/azure';\nimport { type DependabotRequest, getBranchNameForUpdate } from '@paklo/core/dependabot';\nimport { logger } from '@paklo/core/logger';\nimport { LocalDependabotServer, type LocalDependabotServerOptions } from '../server';\n\nexport type AzureLocalDependabotServerOptions = LocalDependabotServerOptions & {\n url: AzureDevOpsRepositoryUrl;\n authorClient: AzureDevOpsWebApiClient;\n autoApprove: boolean;\n approverClient?: AzureDevOpsWebApiClient;\n setAutoComplete: boolean;\n mergeStrategy?: string;\n autoCompleteIgnoreConfigIds: number[];\n existingBranchNames: string[] | undefined;\n existingPullRequests: IPullRequestProperties[];\n};\n\nexport class AzureLocalDependabotServer extends LocalDependabotServer {\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: options is used\n private readonly options: AzureLocalDependabotServerOptions;\n\n constructor(options: AzureLocalDependabotServerOptions) {\n super(options);\n this.options = options;\n }\n\n protected override async handle(id: string, request: DependabotRequest): Promise<boolean> {\n await super.handle(id, request); // common logic\n\n const { options, affectedPullRequestIds } = this;\n const {\n url,\n authorClient,\n approverClient,\n existingBranchNames,\n existingPullRequests,\n autoApprove,\n mergeStrategy,\n setAutoComplete,\n autoCompleteIgnoreConfigIds,\n author,\n debug,\n dryRun,\n } = options;\n\n const { type, data } = request;\n const job = await this.job(id);\n if (!job) {\n logger.error(`No job found for ID '${id}', cannot process request of type '${type}'`);\n return false;\n }\n const { 'package-manager': packageManager } = job;\n logger.info(`Processing '${type}' for job ID '${id}'`);\n if (debug) {\n logger.debug(JSON.stringify(data));\n }\n\n const update = this.update(id)!; // exists because job exists\n const { project, repository } = url;\n\n switch (type) {\n // Documentation on the 'data' model for each output type can be found here:\n // See: https://github.com/dependabot/cli/blob/main/internal/model/update.go\n\n case 'create_pull_request': {\n const title = data['pr-title'];\n if (dryRun) {\n logger.warn(`Skipping pull request creation of '${title}' as 'dryRun' is set to 'true'`);\n return true;\n }\n\n // Skip if active pull request limit reached.\n const openPullRequestsLimit = update['open-pull-requests-limit']!;\n\n // Parse the Dependabot metadata for the existing pull requests that are related to this update\n // Dependabot will use this to determine if we need to create new pull requests or update/close existing ones\n const existingPullRequestsForPackageManager = parsePullRequestProperties(existingPullRequests, packageManager);\n const existingPullRequestsCount = Object.entries(existingPullRequestsForPackageManager).length;\n const openPullRequestsCount = affectedPullRequestIds.get(id)!.created.length + existingPullRequestsCount;\n const hasReachedOpenPullRequestLimit =\n openPullRequestsLimit > 0 && openPullRequestsCount >= openPullRequestsLimit;\n\n if (hasReachedOpenPullRequestLimit) {\n logger.warn(\n `Skipping pull request creation of '${title}' as the open pull requests limit (${openPullRequestsLimit}) has been reached`,\n );\n return true;\n }\n\n const changedFiles = getPullRequestChangedFilesForOutputData(data);\n const dependencies = getPullRequestDependenciesPropertyValueForOutputData(data);\n const targetBranch = update['target-branch'] || (await authorClient.getDefaultBranch(project, repository));\n const sourceBranch = getBranchNameForUpdate(\n update['package-ecosystem'],\n targetBranch,\n update.directory || update.directories?.find((dir) => changedFiles[0]?.path?.startsWith(dir)),\n !Array.isArray(dependencies) ? dependencies['dependency-group-name'] : undefined,\n !Array.isArray(dependencies) ? dependencies.dependencies : dependencies,\n update['pull-request-branch-name']?.separator,\n );\n\n // Check if the source branch already exists or conflicts with an existing branch\n const existingBranch = existingBranchNames?.find((branch) => sourceBranch === branch) || [];\n if (existingBranch.length) {\n logger.error(\n `Unable to create pull request '${title}' as source branch '${sourceBranch}' already exists; Delete the existing branch and try again.`,\n );\n return false;\n }\n const conflictingBranches = existingBranchNames?.filter((branch) => sourceBranch.startsWith(branch)) || [];\n if (conflictingBranches.length) {\n logger.error(\n `Unable to create pull request '${title}' as source branch '${sourceBranch}' would conflict with existing branch(es) '${conflictingBranches.join(', ')}'; Delete the conflicting branch(es) and try again.`,\n );\n return false;\n }\n\n // Create a new pull request\n const newPullRequestId = await authorClient.createPullRequest({\n project: project,\n repository: repository,\n source: {\n commit: data['base-commit-sha'] || job.source.commit!,\n branch: sourceBranch,\n },\n target: {\n branch: targetBranch!,\n },\n author,\n title,\n description: getPullRequestDescription(packageManager, data['pr-body'], data.dependencies),\n commitMessage: data['commit-message'],\n autoComplete: setAutoComplete\n ? {\n ignorePolicyConfigIds: autoCompleteIgnoreConfigIds,\n mergeStrategy: (() => {\n switch (mergeStrategy) {\n case 'noFastForward':\n return GitPullRequestMergeStrategy.NoFastForward;\n case 'squash':\n return GitPullRequestMergeStrategy.Squash;\n case 'rebase':\n return GitPullRequestMergeStrategy.Rebase;\n case 'rebaseMerge':\n return GitPullRequestMergeStrategy.RebaseMerge;\n default:\n return GitPullRequestMergeStrategy.Squash;\n }\n })(),\n }\n : undefined,\n assignees: update.assignees,\n labels: update.labels?.map((label) => label?.trim()) || [],\n workItems: update.milestone ? [update.milestone] : [],\n changes: changedFiles,\n properties: buildPullRequestProperties(packageManager, dependencies),\n });\n\n // Auto-approve the pull request, if required\n if (autoApprove && approverClient && newPullRequestId) {\n await approverClient.approvePullRequest({\n project: project,\n repository: repository,\n pullRequestId: newPullRequestId,\n });\n }\n\n // Store the new pull request ID, so we can keep track of the total number of open pull requests\n if (newPullRequestId && newPullRequestId > 0) {\n affectedPullRequestIds.get(id)!.created.push(newPullRequestId);\n return true;\n } else {\n return false;\n }\n }\n\n case 'update_pull_request': {\n if (dryRun) {\n logger.warn(`Skipping pull request update as 'dryRun' is set to 'true'`);\n return true;\n }\n\n // Find the pull request to update\n const pullRequestToUpdate = getPullRequestForDependencyNames(\n existingPullRequests,\n packageManager,\n data['dependency-names'],\n );\n if (!pullRequestToUpdate) {\n logger.error(\n `Could not find pull request to update for package manager '${packageManager}' with dependencies '${data['dependency-names'].join(', ')}'`,\n );\n return false;\n }\n\n // Update the pull request\n const pullRequestWasUpdated = await authorClient.updatePullRequest({\n project: project,\n repository: repository,\n pullRequestId: pullRequestToUpdate.id,\n commit: data['base-commit-sha'] || job.source.commit!,\n author,\n changes: getPullRequestChangedFilesForOutputData(data),\n skipIfDraft: true,\n skipIfCommitsFromAuthorsOtherThan: author.email,\n skipIfNotBehindTargetBranch: true,\n });\n\n // Re-approve the pull request, if required\n if (autoApprove && approverClient && pullRequestWasUpdated) {\n await approverClient.approvePullRequest({\n project: project,\n repository: repository,\n pullRequestId: pullRequestToUpdate.id,\n });\n }\n\n if (pullRequestWasUpdated) {\n affectedPullRequestIds.get(id)!.updated.push(pullRequestToUpdate.id);\n return true;\n }\n return false;\n }\n\n case 'close_pull_request': {\n if (dryRun) {\n logger.warn(`Skipping pull request closure as 'dryRun' is set to 'true'`);\n return true;\n }\n\n // Find the pull request to close\n const pullRequestToClose = getPullRequestForDependencyNames(\n existingPullRequests,\n packageManager,\n data['dependency-names'],\n );\n if (!pullRequestToClose) {\n logger.error(\n `Could not find pull request to close for package manager '${packageManager}' with dependencies '${data['dependency-names'].join(', ')}'`,\n );\n return false;\n }\n\n // TODO: GitHub Dependabot will close with reason \"Superseded by ${new_pull_request_id}\" when another PR supersedes it.\n // How do we detect this? Do we need to?\n\n // Close the pull request\n const success = await authorClient.abandonPullRequest({\n project: project,\n repository: repository,\n pullRequestId: pullRequestToClose.id,\n comment: getPullRequestCloseReasonForOutputData(data),\n deleteSourceBranch: true,\n });\n if (success) {\n affectedPullRequestIds.get(id)!.closed.push(pullRequestToClose.id);\n return true;\n }\n return false;\n }\n\n // No action required\n case 'update_dependency_list':\n case 'mark_as_processed':\n case 'record_ecosystem_versions':\n case 'record_ecosystem_meta':\n case 'increment_metric':\n case 'record_metrics':\n return true;\n\n case 'record_update_job_error':\n logger.error(`Update job error: ${data['error-type']} ${JSON.stringify(data['error-details'])}`);\n return true;\n\n case 'record_update_job_unknown_error':\n logger.error(`Update job unknown error: ${data['error-type']}, ${JSON.stringify(data['error-details'])}`);\n return true;\n\n default:\n logger.warn(`Unknown dependabot output type '${type}', ignoring...`);\n return true;\n }\n }\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport {\n AzureDevOpsWebApiClient,\n DEVOPS_PR_PROPERTY_MICROSOFT_GIT_SOURCE_REF_NAME,\n type IPullRequestProperties,\n normalizeBranchName,\n parsePullRequestProperties,\n} from '@paklo/core/azure';\nimport {\n type DependabotCredential,\n DependabotJobBuilder,\n type DependabotJobConfig,\n type DependabotUpdate,\n mapPackageEcosystemToPackageManager,\n} from '@paklo/core/dependabot';\nimport {\n filterVulnerabilities,\n GitHubSecurityAdvisoryClient,\n getGhsaPackageEcosystemFromDependabotPackageManager,\n type Package,\n type SecurityVulnerability,\n SecurityVulnerabilitySchema,\n} from '@paklo/core/github';\nimport { logger } from '@paklo/core/logger';\nimport { type RunJobOptions, runJob } from '../../run';\nimport { LocalJobsRunner, type LocalJobsRunnerOptions, type RunJobsResult } from '../runner';\nimport { AzureLocalDependabotServer, type AzureLocalDependabotServerOptions } from './server';\n\nexport type AzureLocalJobsRunnerOptions = LocalJobsRunnerOptions &\n Omit<\n AzureLocalDependabotServerOptions,\n 'authorClient' | 'approverClient' | 'existingBranchNames' | 'existingPullRequests'\n > & {\n port?: number;\n securityAdvisoriesFile?: string;\n gitToken: string;\n githubToken?: string;\n autoApproveToken?: string;\n };\n\nexport class AzureLocalJobsRunner extends LocalJobsRunner {\n // biome-ignore-start lint/correctness/noUnusedPrivateClassMembers: variables are used\n private readonly options: AzureLocalJobsRunnerOptions;\n private readonly authorClient: AzureDevOpsWebApiClient;\n private readonly approverClient?: AzureDevOpsWebApiClient;\n // biome-ignore-end lint/correctness/noUnusedPrivateClassMembers: variables are used\n\n constructor(options: AzureLocalJobsRunnerOptions) {\n super({ ...options });\n this.options = options;\n const { url, gitToken, autoApprove, debug } = this.options;\n\n // Initialise the DevOps API clients (one for authoring the other for auto-approving (if configured))\n this.authorClient = new AzureDevOpsWebApiClient(url, gitToken, debug);\n this.approverClient = autoApprove\n ? new AzureDevOpsWebApiClient(url, options.autoApproveToken || gitToken, debug)\n : undefined;\n }\n\n public override async run(): Promise<RunJobsResult> {\n await super.run(); // common logic\n\n const {\n options: { url, port, config, targetUpdateIds, command },\n authorClient,\n approverClient,\n } = this;\n\n // Print a warning about multi-ecosystem updates not being fully supported\n // TODO: Implement full support for multi-ecosystem updates (not sure this will be possible on the local model)\n if (config['multi-ecosystem-groups'] || config.updates?.some((u) => u['multi-ecosystem-group'])) {\n logger.warn(\n 'Multi-ecosystem updates are not working yet. Only parsing and validation is supported at this time.',\n );\n }\n\n // Print a warning about missing schedules\n // TODO: remove this and enforce schedules on or after 2025-Nov-30\n if (config.updates?.some((u) => !u.schedule)) {\n logger.warn(\n `\n Some updates are missing a schedule configuration.\n This tool will require all updates to have a schedule on or after 2025-Nov-30.\n `,\n );\n }\n\n // Print a warning about the required workarounds for security-only updates, if any update is configured as such\n // TODO: If and when Dependabot supports a better way to do security-only updates, remove this.\n if (config.updates?.some((u) => u['open-pull-requests-limit'] === 0)) {\n logger.warn(\n 'Security-only updates incur a slight performance overhead due to limitations in Dependabot CLI. For more info, see: https://github.com/mburumaxwell/dependabot-azure-devops/blob/main/README.md#configuring-security-advisories-and-known-vulnerabilities',\n );\n }\n\n // Fetch the active pull requests created by the author user\n const existingBranchNames = await authorClient.getBranchNames(url.project, url.repository);\n const existingPullRequests = await authorClient.getActivePullRequestProperties(\n url.project,\n url.repository,\n await authorClient.getUserId(),\n );\n\n // Prepare local server\n const serverOptions: AzureLocalDependabotServerOptions = {\n authorClient,\n approverClient,\n existingBranchNames,\n existingPullRequests,\n ...this.options,\n };\n const server = new AzureLocalDependabotServer(serverOptions);\n server.start(port);\n // give the server a second to start\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n // The API urls is constant when working in this CLI. Asking people to setup NGROK or similar just to get\n // HTTPS for the job token to be used is too much hassle.\n // Using same value for dependabotApiUrl and dependabotApiDockerUrl so as to capture /record_metrics calls.\n const dependabotApiUrl = `http://host.docker.internal:${server.port}/api`;\n const dependabotApiDockerUrl = dependabotApiUrl;\n\n // If update identifiers are specified, select them; otherwise handle all\n let updates: DependabotUpdate[] = [];\n if (targetUpdateIds && targetUpdateIds.length > 0) {\n for (const id of targetUpdateIds) {\n const upd = config.updates[id];\n if (!upd) {\n logger.warn(\n `\n Unable to find target update id '${id}'.\n This value should be a zero based index of the update in your config file.\n Expected range: 0-${config.updates.length - 1}\n `,\n );\n } else {\n updates.push(upd);\n }\n }\n } else {\n updates = config.updates;\n }\n\n try {\n // Abandon all pull requests where the source branch has been deleted\n await this.abandonPullRequestsWhereSourceRefIsDeleted(existingBranchNames, existingPullRequests);\n\n // Perform updates for each of the [targeted] update blocks in dependabot.yaml\n return await this.performUpdates(\n server,\n updates,\n existingPullRequests,\n dependabotApiUrl,\n dependabotApiDockerUrl,\n command,\n );\n } finally {\n server.stop();\n }\n }\n\n /**\n * Abandon all pull requests where the source branch has been deleted.\n * @param existingBranchNames The names of the existing branches.\n * @param existingPullRequests The existing pull requests.\n */\n private async abandonPullRequestsWhereSourceRefIsDeleted(\n existingBranchNames?: string[],\n existingPullRequests?: IPullRequestProperties[],\n ): Promise<void> {\n if (!existingBranchNames || !existingPullRequests) return;\n\n const {\n options: { url, dryRun },\n authorClient,\n } = this;\n for (const pullRequestIndex in existingPullRequests) {\n const pullRequest = existingPullRequests[pullRequestIndex]!;\n const pullRequestSourceRefName = normalizeBranchName(\n pullRequest.properties?.find((x) => x.name === DEVOPS_PR_PROPERTY_MICROSOFT_GIT_SOURCE_REF_NAME)?.value,\n );\n if (pullRequestSourceRefName && !existingBranchNames.includes(pullRequestSourceRefName)) {\n // The source branch for the pull request has been deleted; abandon the pull request (if not dry run)\n if (!dryRun) {\n logger.warn(\n `Detected source branch for PR #${pullRequest.id} has been deleted; The pull request will be abandoned`,\n );\n await authorClient.abandonPullRequest({\n project: url.project,\n repository: url.repository,\n pullRequestId: pullRequest.id,\n // comment:\n // 'OK, I won't notify you again about this release, but will get in touch when a new version is available. ' +\n // 'If you'd rather skip all updates until the next major or minor version, add an ' +\n // '[`ignore` condition](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#ignore--) ' +\n // 'with the desired `update-types` to your config file.',\n comment:\n 'It might be a good idea to add an ' +\n '[`ignore` condition](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#ignore--) ' +\n 'with the desired `update-types` to your config file.',\n });\n }\n // Remove the pull request from the list of existing pull requests to ensures that we don't attempt to update it later in the process.\n existingPullRequests.splice(existingPullRequests.indexOf(pullRequest), 1);\n }\n }\n }\n\n /**\n * Performs the updates.\n * @param server The local Dependabot server.\n * @param updates The updates to perform.\n * @param existingPullRequests The existing pull requests.\n */\n private async performUpdates(\n server: AzureLocalDependabotServer,\n updates: DependabotUpdate[],\n existingPullRequests: IPullRequestProperties[],\n dependabotApiUrl: string,\n dependabotApiDockerUrl?: string,\n command?: DependabotJobConfig['command'],\n ): Promise<RunJobsResult> {\n const {\n options: { url, gitToken, githubToken, experiments, config, dryRun, securityAdvisoriesFile, secretMasker },\n } = this;\n\n const results: RunJobsResult = [];\n\n function makeUsageData(job: DependabotJobConfig): RunJobOptions['usage'] {\n return {\n trigger: 'user',\n provider: job.source.provider,\n owner: url.value.toString(),\n project: `${url.value.toString().replace(/\\/$/, '')}/${url.project}`,\n 'package-manager': job['package-manager'],\n };\n }\n\n for (const update of updates) {\n const packageEcosystem = update['package-ecosystem'];\n const packageManager = mapPackageEcosystemToPackageManager(packageEcosystem);\n\n // If there is an updater image, replace the placeholder in it\n let { updaterImage } = this.options;\n updaterImage = updaterImage?.replace(/\\{ecosystem\\}/i, packageEcosystem);\n\n // Parse the Dependabot metadata for the existing pull requests that are related to this update\n // Dependabot will use this to determine if we need to create new pull requests or update/close existing ones\n const existingPullRequestsForPackageManager = parsePullRequestProperties(existingPullRequests, packageManager);\n const existingPullRequestDependenciesForPackageManager = Object.values(existingPullRequestsForPackageManager);\n\n const builder = new DependabotJobBuilder({\n source: { provider: 'azure', ...url },\n config,\n update,\n systemAccessToken: gitToken,\n githubToken,\n experiments,\n debug: false,\n });\n\n let job: DependabotJobConfig | undefined;\n let credentials: DependabotCredential[] | undefined;\n let jobToken: string;\n let credentialsToken: string;\n\n // If this is a security-only update (i.e. 'open-pull-requests-limit: 0'), then we first need to discover the dependencies\n // that need updating and check each one for vulnerabilities. This is because Dependabot requires the list of vulnerable dependencies\n // to be supplied in the job definition of security-only update job, it will not automatically discover them like a versioned update does.\n // https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/configuring-dependabot-security-updates#overriding-the-default-behavior-with-a-configuration-file\n let securityVulnerabilities: SecurityVulnerability[] = [];\n let dependencyNamesToUpdate: string[] = [];\n const securityUpdatesOnly = update['open-pull-requests-limit'] === 0;\n if (securityUpdatesOnly) {\n // Run an update job to discover all dependencies\n ({ job, credentials } = builder.forDependenciesList({ command }));\n ({ jobToken, credentialsToken } = this.makeTokens());\n server.add({ id: job.id, update, job, jobToken, credentialsToken, credentials });\n await runJob({\n dependabotApiUrl,\n dependabotApiDockerUrl,\n jobId: job.id,\n jobToken,\n credentialsToken,\n updaterImage,\n secretMasker,\n usage: makeUsageData(job),\n });\n\n const outputs = server.requests(job.id);\n const packagesToCheckForVulnerabilities: Package[] | undefined = outputs!\n .find((o) => o.type === 'update_dependency_list')\n ?.data.dependencies?.map((d) => ({ name: d.name, version: d.version }));\n if (packagesToCheckForVulnerabilities?.length) {\n logger.info(\n `Detected ${packagesToCheckForVulnerabilities.length} dependencies; Checking for vulnerabilities...`,\n );\n\n // parse security advisories from file (private)\n if (securityAdvisoriesFile) {\n const filePath = securityAdvisoriesFile;\n if (existsSync(filePath)) {\n const fileContents = await readFile(filePath, 'utf-8');\n securityVulnerabilities = await SecurityVulnerabilitySchema.array().parseAsync(JSON.parse(fileContents));\n } else {\n logger.info(`Private security advisories file '${filePath}' does not exist`);\n }\n }\n if (githubToken) {\n const ghsaClient = new GitHubSecurityAdvisoryClient(githubToken);\n const githubVulnerabilities = await ghsaClient.getSecurityVulnerabilitiesAsync(\n getGhsaPackageEcosystemFromDependabotPackageManager(packageManager),\n packagesToCheckForVulnerabilities || [],\n );\n securityVulnerabilities.push(...githubVulnerabilities);\n } else {\n logger.info(\n 'GitHub access token is not provided; Checking for vulnerabilities from GitHub is skipped. ' +\n 'This is not an issue if you are using private security advisories file.',\n );\n }\n\n securityVulnerabilities = filterVulnerabilities(securityVulnerabilities);\n\n // Only update dependencies that have vulnerabilities\n dependencyNamesToUpdate = Array.from(new Set(securityVulnerabilities.map((v) => v.package.name)));\n logger.info(\n `Detected ${securityVulnerabilities.length} vulnerabilities affecting ${dependencyNamesToUpdate.length} dependencies`,\n );\n if (dependencyNamesToUpdate.length) {\n logger.trace(dependencyNamesToUpdate);\n }\n } else {\n logger.info(`No vulnerabilities detected for update ${update['package-ecosystem']} in ${update.directory}`);\n server.clear(job.id);\n continue; // nothing more to do for this update\n }\n\n server.clear(job.id);\n }\n\n // Run an update job for \"all dependencies\"; this will create new pull requests for dependencies that need updating\n const openPullRequestsLimit = update['open-pull-requests-limit']!;\n const openPullRequestsCount = Object.entries(existingPullRequestsForPackageManager).length;\n const hasReachedOpenPullRequestLimit =\n openPullRequestsLimit > 0 && openPullRequestsCount >= openPullRequestsLimit;\n if (!hasReachedOpenPullRequestLimit) {\n const dependenciesHaveVulnerabilities = dependencyNamesToUpdate.length && securityVulnerabilities.length;\n if (!securityUpdatesOnly || dependenciesHaveVulnerabilities) {\n ({ job, credentials } = builder.forUpdate({\n command,\n dependencyNamesToUpdate,\n existingPullRequests: existingPullRequestDependenciesForPackageManager,\n securityVulnerabilities,\n }));\n ({ jobToken, credentialsToken } = this.makeTokens());\n server.add({ id: job.id, update, job, jobToken, credentialsToken, credentials });\n const { success, message } = await runJob({\n dependabotApiUrl,\n dependabotApiDockerUrl,\n jobId: job.id,\n jobToken,\n credentialsToken,\n updaterImage,\n secretMasker,\n usage: makeUsageData(job),\n });\n const affectedPrs = server.allAffectedPrs(job.id);\n server.clear(job.id);\n results.push({ id: job.id, success, message, affectedPrs });\n } else {\n logger.info('Nothing to update; dependencies are not affected by any known vulnerability');\n }\n } else {\n logger.warn(\n `Skipping update for ${packageEcosystem} packages as the open pull requests limit (${openPullRequestsLimit}) has already been reached`,\n );\n }\n\n // If there are existing pull requests, run an update job for each one; this will resolve merge conflicts and close pull requests that are no longer needed\n const numberOfPullRequestsToUpdate = Object.keys(existingPullRequestsForPackageManager).length;\n if (numberOfPullRequestsToUpdate > 0) {\n if (!dryRun) {\n for (const pullRequestId in existingPullRequestsForPackageManager) {\n ({ job, credentials } = builder.forUpdate({\n command,\n existingPullRequests: existingPullRequestDependenciesForPackageManager,\n pullRequestToUpdate: existingPullRequestsForPackageManager[pullRequestId]!,\n securityVulnerabilities,\n }));\n ({ jobToken, credentialsToken } = this.makeTokens());\n server.add({ id: job.id, update, job, jobToken, credentialsToken, credentials });\n const { success, message } = await runJob({\n dependabotApiUrl,\n dependabotApiDockerUrl,\n jobId: job.id,\n jobToken,\n credentialsToken,\n updaterImage,\n secretMasker,\n usage: makeUsageData(job),\n });\n const affectedPrs = server.allAffectedPrs(job.id);\n server.clear(job.id);\n results.push({ id: job.id, success, message, affectedPrs });\n }\n } else {\n logger.warn(\n `Skipping update of ${numberOfPullRequestsToUpdate} existing ${packageEcosystem} package pull request(s) as 'dryRun' is set to 'true'`,\n );\n }\n }\n }\n\n return results;\n }\n}\n"],"mappings":"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"}
|
package/dist/local/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "../api-client-
|
|
2
|
-
import { a as LocalJobsRunner, i as LocalDependabotServerOptions, n as LocalDependabotServer, o as LocalJobsRunnerOptions, r as LocalDependabotServerAddOptions, s as RunJobsResult, t as AffectedPullRequestIds } from "../server-
|
|
1
|
+
import "../api-client-M8F9t7II.mjs";
|
|
2
|
+
import { a as LocalJobsRunner, i as LocalDependabotServerOptions, n as LocalDependabotServer, o as LocalJobsRunnerOptions, r as LocalDependabotServerAddOptions, s as RunJobsResult, t as AffectedPullRequestIds } from "../server-BSQEzdZw.mjs";
|
|
3
3
|
export { AffectedPullRequestIds, LocalDependabotServer, LocalDependabotServerAddOptions, LocalDependabotServerOptions, LocalJobsRunner, LocalJobsRunnerOptions, RunJobsResult };
|
package/dist/local/index.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import { n as LocalJobsRunner, t as LocalDependabotServer } from "../server-0h2jXnjg.mjs";
|
|
1
|
+
import { n as LocalJobsRunner, t as LocalDependabotServer } from "../server-M1ps5BVd.mjs";
|
|
3
2
|
|
|
4
3
|
export { LocalDependabotServer, LocalJobsRunner };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as logger } from "./logger-DSV-e8-Y.mjs";
|
|
2
1
|
import { DependabotCredentialSchema, DependabotJobConfigSchema } from "@paklo/core/dependabot";
|
|
3
2
|
import { HEADER_NAME_AUTHORIZATION, HttpRequestError, InnerApiClient, isErrorTemporaryFailure } from "@paklo/core/http";
|
|
3
|
+
import { logger } from "@paklo/core/logger";
|
|
4
4
|
import Docker from "dockerode";
|
|
5
5
|
import { pack } from "tar-stream";
|
|
6
6
|
import stream, { Readable } from "node:stream";
|
|
@@ -119,7 +119,7 @@ var ApiClient = class {
|
|
|
119
119
|
|
|
120
120
|
//#endregion
|
|
121
121
|
//#region ../../dependabot-action/docker/containers.json
|
|
122
|
-
var proxy = "ghcr.io/github/dependabot-update-job-proxy/dependabot-update-job-proxy:v2.0.
|
|
122
|
+
var proxy = "ghcr.io/github/dependabot-update-job-proxy/dependabot-update-job-proxy:v2.0.20251113195050@sha256:617ff0562ba63ab27eef421637d04581cc0b0659d996200bf31b11a0855ae0a5";
|
|
123
123
|
var containers_default = {
|
|
124
124
|
proxy,
|
|
125
125
|
bundler: "ghcr.io/dependabot/dependabot-updater-bundler:v2.0.20250916161401@sha256:cb1b48a4e2862bd9a2ebb1bb7f2eb1b28bd0099060925951618e07a96c191e5c",
|
|
@@ -148,7 +148,8 @@ var containers_default = {
|
|
|
148
148
|
vcpkg: "ghcr.io/dependabot/dependabot-updater-vcpkg:v2.0.20250916161401@sha256:40355d74ad784932730577475faee9f21ef863c3cec7b7d2817cc5621f3b1dd7",
|
|
149
149
|
helm: "ghcr.io/dependabot/dependabot-updater-helm:v2.0.20250916161401@sha256:42fe3e7a6bac84271dec7ec41ac0067ff7d1cffb8e5f63dbe5eec849b5bc433b",
|
|
150
150
|
julia: "ghcr.io/dependabot/dependabot-updater-julia:v2.0.20251023204638@sha256:49caaedd3e594c3056fa4f811ddc70da174a4d4dcd4726687ca626f844987d82",
|
|
151
|
-
bazel: "ghcr.io/dependabot/dependabot-updater-bazel:v2.0.20251027153627@sha256:ab86da3697ccff56c345c37d820ff72003ba242b41bf3309f44af08fd85aa538"
|
|
151
|
+
bazel: "ghcr.io/dependabot/dependabot-updater-bazel:v2.0.20251027153627@sha256:ab86da3697ccff56c345c37d820ff72003ba242b41bf3309f44af08fd85aa538",
|
|
152
|
+
opentofu: "ghcr.io/dependabot/dependabot-updater-opentofu:v2.0.20251114105702@sha256:9c33300c7a987367cf203bd7dda689029b093c0c95cc58b05c1cf9c6b4c652f7"
|
|
152
153
|
};
|
|
153
154
|
|
|
154
155
|
//#endregion
|
|
@@ -356,7 +357,7 @@ var JobParameters = class {
|
|
|
356
357
|
}
|
|
357
358
|
};
|
|
358
359
|
function getJobParameters(input) {
|
|
359
|
-
return new JobParameters(
|
|
360
|
+
return new JobParameters(input.jobId, input.jobToken, input.credentialsToken, input.dependabotApiUrl, input.dependabotApiDockerUrl, input.updaterImage);
|
|
360
361
|
}
|
|
361
362
|
|
|
362
363
|
//#endregion
|
|
@@ -536,7 +537,7 @@ var ProxyBuilder = class {
|
|
|
536
537
|
|
|
537
538
|
//#endregion
|
|
538
539
|
//#region package.json
|
|
539
|
-
var version = "0.
|
|
540
|
+
var version = "0.3.0";
|
|
540
541
|
|
|
541
542
|
//#endregion
|
|
542
543
|
//#region src/updater-builder.ts
|
|
@@ -769,4 +770,4 @@ async function runJob(options) {
|
|
|
769
770
|
|
|
770
771
|
//#endregion
|
|
771
772
|
export { updaterImageName as _, UpdaterBuilder as a, CredentialFetchingError as b, getJobParameters as c, ContainerRuntimeError as d, ContainerService as f, repositoryName as g, hasDigest as h, Updater as i, ImageService as l, digestName as m, JobRunnerUpdaterError as n, ProxyBuilder as o, PROXY_IMAGE_NAME as p, runJob as r, JobParameters as s, JobRunnerImagingError as t, getOrgFromImage as u, updaterImages as v, JobDetailsFetchingError as x, ApiClient as y };
|
|
772
|
-
//# sourceMappingURL=run-
|
|
773
|
+
//# sourceMappingURL=run-BtSPCvKv.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-BtSPCvKv.mjs","names":["client: InnerApiClient","params: JobParameters","credentialsToken: string","secretMasker: SecretMasker","error: unknown","dockerContainerConfig.proxy","dockerContainerConfig","stream","stream","docker","e: unknown","jobId: string","jobToken: string","credentialsToken: string","dependabotApiUrl: string","dependabotApiDockerUrl: string","updaterImage: string","CA_CERT_INPUT_PATH","docker: Docker","proxyImage: string","cachedMode: boolean","stream","docker: Docker","jobParams: JobParameters","input: FileFetcherInput | FileUpdaterInput","proxy: Proxy","updaterImage: string","updaterImage: string","proxyImage: string","params: JobParameters","job: DependabotJobConfig","credentials: DependabotCredential[]","proxy","unique: Set<string>","result: DependabotCredential[]","obj: any","message: string | undefined","sendMetricsWithPackageManager: MetricReporter","err: unknown","data: UsageTelemetryRequestData","packageJson.version"],"sources":["../src/api-client.ts","../../../dependabot-action/docker/containers.json","../src/docker-tags.ts","../src/utils.ts","../src/container-service.ts","../src/image-service.ts","../src/params.ts","../src/proxy.ts","../package.json","../src/updater-builder.ts","../src/updater.ts","../src/run.ts"],"sourcesContent":["import type { DependabotMetric, DependabotRecordUpdateJobError } from '@paklo/core/dependabot';\nimport {\n type DependabotCredential,\n DependabotCredentialSchema,\n type DependabotJobConfig,\n DependabotJobConfigSchema,\n} from '@paklo/core/dependabot';\nimport {\n HEADER_NAME_AUTHORIZATION,\n HttpRequestError,\n type InnerApiClient,\n type InnerRequestOptions,\n isErrorTemporaryFailure,\n type ResourceResponse,\n} from '@paklo/core/http';\nimport { logger } from '@paklo/core/logger';\nimport type { JobParameters } from './params';\n\nexport class JobDetailsFetchingError extends Error {}\nexport class CredentialFetchingError extends Error {}\nexport type SecretMasker = (value: string) => void;\n\nexport class ApiClient {\n private jobToken: string;\n constructor(\n private readonly client: InnerApiClient,\n readonly params: JobParameters,\n jobToken: string,\n private readonly credentialsToken: string,\n private readonly secretMasker: SecretMasker,\n ) {\n this.jobToken = jobToken;\n }\n\n // We use a static unknown SHA when marking a job as complete from the action\n // to remain in parity with the existing runner.\n UnknownSha = {\n 'base-commit-sha': 'unknown',\n };\n\n // Getter for jobToken\n getJobToken(): string {\n return this.jobToken;\n }\n\n async getJobDetails(): Promise<DependabotJobConfig> {\n try {\n const res = await this.getWithRetry<DependabotJobConfig>(\n `/update_jobs/${this.params.jobId}/details`,\n this.jobToken,\n { schema: DependabotJobConfigSchema },\n );\n if (res.status !== 200) {\n throw new JobDetailsFetchingError(\n `fetching job details: unexpected status code: ${res.status}: ${JSON.stringify(res.error)}`,\n );\n }\n if (!res.data) {\n throw new JobDetailsFetchingError(`fetching job details: missing response`);\n }\n\n return res.data;\n } catch (error) {\n if (error instanceof JobDetailsFetchingError) {\n throw error;\n } else if (error instanceof HttpRequestError) {\n throw new JobDetailsFetchingError(\n `fetching job details: unexpected status code: ${error.code}: ${error.message}`,\n );\n } else if (error instanceof Error) {\n throw new JobDetailsFetchingError(`fetching job details: ${error.name}: ${error.message}`);\n }\n throw error;\n }\n }\n\n async getCredentials(): Promise<DependabotCredential[]> {\n try {\n const res = await this.getWithRetry<DependabotCredential[]>(\n `/update_jobs/${this.params.jobId}/credentials`,\n this.credentialsToken,\n { schema: DependabotCredentialSchema.array() },\n );\n\n if (res.status !== 200) {\n throw new CredentialFetchingError(\n `fetching credentials: unexpected status code: ${res.status}: ${JSON.stringify(res.error)}`,\n );\n }\n if (!res.data) {\n throw new CredentialFetchingError(`fetching credentials: missing response`);\n }\n\n // Mask any secrets we've just retrieved from environment logs\n for (const credential of res.data) {\n if (credential.password) {\n this.secretMasker(credential.password);\n }\n if (credential.token) {\n this.secretMasker(credential.token);\n }\n if (credential['auth-key']) {\n this.secretMasker(credential['auth-key']);\n }\n }\n\n return res.data;\n } catch (error: unknown) {\n if (error instanceof CredentialFetchingError) {\n throw error;\n } else if (error instanceof HttpRequestError) {\n throw new CredentialFetchingError(\n `fetching credentials: unexpected status code: ${error.code}: ${error.message}`,\n );\n } else if (error instanceof Error) {\n throw new CredentialFetchingError(`fetching credentials: ${error.name}: ${error.message}`);\n }\n throw error;\n }\n }\n\n async reportJobError(error: DependabotRecordUpdateJobError): Promise<void> {\n const res = await this.client.post(`/update_jobs/${this.params.jobId}/record_update_job_error`, {\n payload: error,\n headers: {\n [HEADER_NAME_AUTHORIZATION]: this.jobToken,\n },\n });\n if (res.status !== 204) {\n throw new Error(`Unexpected status code: ${res.status}`);\n }\n }\n\n async markJobAsProcessed(): Promise<void> {\n const res = await this.client.patch(`/update_jobs/${this.params.jobId}/mark_as_processed`, {\n payload: this.UnknownSha,\n headers: {\n [HEADER_NAME_AUTHORIZATION]: this.jobToken,\n },\n });\n if (res.status !== 204) {\n throw new Error(`Unexpected status code: ${res.status}`);\n }\n }\n\n async sendMetrics(\n name: string,\n metricType: 'increment' | 'gauge',\n value: number,\n additionalTags: Record<string, string> = {},\n ): Promise<void> {\n try {\n await this.reportMetrics([\n {\n metric: `dependabot.action.${name}`,\n type: metricType,\n value,\n tags: additionalTags,\n },\n ]);\n logger.info(`Successfully sent metric (dependabot.action.${name}) to remote API endpoint`);\n } catch (error) {\n // metrics should typically not cause critical path failure so we log the\n // failure and continue with the job\n logger.warn(`Metrics reporting failed: ${(error as Error).message}`);\n }\n }\n\n async reportMetrics(metrics: DependabotMetric[]): Promise<void> {\n const res = await this.client.post(`/update_jobs/${this.params.jobId}/record_metrics`, {\n payload: { data: metrics },\n headers: {\n [HEADER_NAME_AUTHORIZATION]: this.jobToken,\n },\n });\n\n if (res.status !== 204) {\n throw new Error(`Unexpected status code: ${res.status}`);\n }\n }\n\n private async getWithRetry<T>(\n url: string,\n token: string,\n options?: Omit<InnerRequestOptions<T>, 'headers'>,\n ): Promise<ResourceResponse<T>> {\n let attempt = 1;\n const delayMs = 1000 * 2 ** attempt;\n\n const execute = async (): Promise<ResourceResponse<T>> => {\n try {\n const res = await this.client.get<T>(url, {\n headers: { Authorization: token },\n ...options,\n });\n\n // Check that the request was successful\n const { status, statusText } = res;\n if (status < 200 || status > 299) {\n throw new HttpRequestError(`HTTP GET '${url}' failed: ${status} ${statusText}`, status);\n }\n\n return res;\n } catch (e) {\n const error = e as Error;\n\n if (isErrorTemporaryFailure(error)) {\n if (attempt >= 3) throw error;\n logger.warn(`Retrying failed request in ${delayMs}ms...`);\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n\n attempt++;\n return execute();\n }\n throw error;\n }\n };\n\n return execute();\n }\n}\n","{\n \"proxy\": \"ghcr.io/github/dependabot-update-job-proxy/dependabot-update-job-proxy:v2.0.20251113195050@sha256:617ff0562ba63ab27eef421637d04581cc0b0659d996200bf31b11a0855ae0a5\",\n \"bundler\": \"ghcr.io/dependabot/dependabot-updater-bundler:v2.0.20250916161401@sha256:cb1b48a4e2862bd9a2ebb1bb7f2eb1b28bd0099060925951618e07a96c191e5c\",\n \"cargo\": \"ghcr.io/dependabot/dependabot-updater-cargo:v2.0.20250916161401@sha256:dc8823384d8fd864f8b7867b553df3489b658b236e9bbfad49606c819d9bc450\",\n \"composer\": \"ghcr.io/dependabot/dependabot-updater-composer:v2.0.20250916161401@sha256:9d9304ed225f1ed0614d55d1c10398c93476cff6e295bb912816ed323d5ad0d0\",\n \"pub\": \"ghcr.io/dependabot/dependabot-updater-pub:v2.0.20250916161401@sha256:2955d6f1d77cc9ca12cf8e2fa5c919b3d5a79c403a2aad94550f2955e233a0c4\",\n \"docker\": \"ghcr.io/dependabot/dependabot-updater-docker:v2.0.20250916161401@sha256:411a5eb299308037ec396b51b0ecdb7f4ee3deeeb392202becc1a333a6dbab25\",\n \"elm\": \"ghcr.io/dependabot/dependabot-updater-elm:v2.0.20250916161401@sha256:67924991be2870fc9cf26bcb031146a46e4b9812173000b4e45acdb929fd0085\",\n \"github_actions\": \"ghcr.io/dependabot/dependabot-updater-github-actions:v2.0.20250916161401@sha256:675a96888497d8b47328ede0f2163722a90b901c7116e719830573c64b8c2465\",\n \"submodules\": \"ghcr.io/dependabot/dependabot-updater-gitsubmodule:v2.0.20250916161401@sha256:deae36a972cfc284dde6e8b6a923dbb81bc794b8c8a67ea652dcf7e71caab710\",\n \"go_modules\": \"ghcr.io/dependabot/dependabot-updater-gomod:v2.0.20250916161401@sha256:21bbf01be40bd53ccc6efd137aa309a1b895dcfab4eb62d85611d94806db8b58\",\n \"gradle\": \"ghcr.io/dependabot/dependabot-updater-gradle:v2.0.20250916161401@sha256:7482ff1cb4cf222a2a96741c8c506609eedc93f0e4cd7c38fe73e4a804413134\",\n \"maven\": \"ghcr.io/dependabot/dependabot-updater-maven:v2.0.20250916161401@sha256:b444c349e9ae8ec3bec9eef411ea830e8fa168c9ee0397e8c86eb140ea933167\",\n \"hex\": \"ghcr.io/dependabot/dependabot-updater-mix:v2.0.20250916161401@sha256:32b74d14082a0b89c9d8bcdde92a3d2b18f5798b6d9bcf2080855373c3f45c1f\",\n \"nuget\": \"ghcr.io/dependabot/dependabot-updater-nuget:v2.0.20250916161401@sha256:9fb516772dffa7a014c20a8dde909ccb25a323d7039a58346401a4500ce64657\",\n \"npm_and_yarn\": \"ghcr.io/dependabot/dependabot-updater-npm:v2.0.20250916161401@sha256:7d13ce84d26210659dbb5fd4b9c0d72b34786ca02063737cba5d228ad55af273\",\n \"pip\": \"ghcr.io/dependabot/dependabot-updater-pip:v2.0.20250916161401@sha256:a05999d53df5ea7141aafde806bd7e1a25dc23087528aea0b482a86363956937\",\n \"rust_toolchain\": \"ghcr.io/dependabot/dependabot-updater-rust-toolchain:v2.0.20250916161401@sha256:1688181ea18f1736ff80e6fe9bb17de3508b3ea890c20493e82cd9a68f6a5387\",\n \"swift\": \"ghcr.io/dependabot/dependabot-updater-swift:v2.0.20250916161401@sha256:622971aba7877711401d021bc0ecfeb98cbd39767b0c45dcf150b86536968743\",\n \"terraform\": \"ghcr.io/dependabot/dependabot-updater-terraform:v2.0.20250916161401@sha256:82c7cef04f54a20a6c47426f9ff48b7767757e715db5fa0a1b0357ced50bbf6c\",\n \"devcontainers\": \"ghcr.io/dependabot/dependabot-updater-devcontainers:v2.0.20250916161401@sha256:5691a9bec5b9c91879318323ed53d22d7c73c540376bb2e0d74704e9651e9897\",\n \"dotnet_sdk\": \"ghcr.io/dependabot/dependabot-updater-dotnet-sdk:v2.0.20250916161401@sha256:10febb67dbcdf4e50985412d65e1fd4a364f7402e184cfcd67b63d295a6c4e80\",\n \"bun\": \"ghcr.io/dependabot/dependabot-updater-bun:v2.0.20250915234339@sha256:fba1acd818ca0101f71ba34f04c8b7c36abf8e63de5feb05037b42f6406950fa\",\n \"docker_compose\": \"ghcr.io/dependabot/dependabot-updater-docker-compose:v2.0.20250916161401@sha256:a0fc653bedf0e600d85a3f7bc0eee7ec7bee99f6875d4faf6e30e2c69ea36dbe\",\n \"uv\": \"ghcr.io/dependabot/dependabot-updater-uv:v2.0.20250916161401@sha256:441fe91d1ed3ba9c148abe5dc3a3d83f12805326da5c037d76b86695c247c1cb\",\n \"vcpkg\": \"ghcr.io/dependabot/dependabot-updater-vcpkg:v2.0.20250916161401@sha256:40355d74ad784932730577475faee9f21ef863c3cec7b7d2817cc5621f3b1dd7\",\n \"helm\": \"ghcr.io/dependabot/dependabot-updater-helm:v2.0.20250916161401@sha256:42fe3e7a6bac84271dec7ec41ac0067ff7d1cffb8e5f63dbe5eec849b5bc433b\",\n \"julia\": \"ghcr.io/dependabot/dependabot-updater-julia:v2.0.20251023204638@sha256:49caaedd3e594c3056fa4f811ddc70da174a4d4dcd4726687ca626f844987d82\",\n \"bazel\": \"ghcr.io/dependabot/dependabot-updater-bazel:v2.0.20251027153627@sha256:ab86da3697ccff56c345c37d820ff72003ba242b41bf3309f44af08fd85aa538\",\n \"opentofu\": \"ghcr.io/dependabot/dependabot-updater-opentofu:v2.0.20251114105702@sha256:9c33300c7a987367cf203bd7dda689029b093c0c95cc58b05c1cf9c6b4c652f7\"\n}","import dockerContainerConfig from '../../../dependabot-action/docker/containers.json';\n\nexport const PROXY_IMAGE_NAME = dockerContainerConfig.proxy;\n\nexport function updaterImageName(packageManager: string): string {\n return dockerContainerConfig[packageManager as keyof typeof dockerContainerConfig];\n}\n\nconst updaterRegex = /ghcr.io\\/dependabot\\/dependabot-updater-([\\w+])/;\n\nexport function updaterImages(): string[] {\n return Object.values(dockerContainerConfig).filter((image) => image.match(updaterRegex));\n}\n\nconst imageNamePattern =\n '^(?<repository>(([a-zA-Z0-9._-]+([:[0-9]+[^/]))?([a-zA-Z0-9._/-]+)?))(:[a-zA-Z0-9._/-]+)?(?<digest>@sha256:[a-zA-Z0-9]{64})?$';\n\nexport function repositoryName(imageName: string): string {\n const match = imageName.match(imageNamePattern);\n\n if (match?.groups) {\n return match.groups.repository!;\n } else {\n throw Error('invalid image name');\n }\n}\n\nexport function hasDigest(imageName: string): boolean {\n const match = imageName.match(imageNamePattern);\n\n if (match?.groups) {\n if (match?.groups.digest) {\n return true;\n }\n return false;\n } else {\n throw Error('invalid image name');\n }\n}\n\nexport function digestName(imageName: string): string {\n const match = imageName.match(imageNamePattern);\n\n if (match?.groups) {\n return match.groups.repository! + match.groups.digest;\n } else {\n throw Error('invalid image name');\n }\n}\n","import stream, { type Writable } from 'node:stream';\n\n// Code below is borrowed and adapted from dependabot-action\n\nexport const outStream = (prefix: string): Writable => {\n return new stream.Writable({\n write(chunk, _, next) {\n process.stderr.write(`${prefix} | ${chunk.toString()}`);\n next();\n },\n });\n};\n\nexport const errStream = (prefix: string): Writable => {\n return new stream.Writable({\n write(chunk, _, next) {\n process.stderr.write(`${prefix} | ${chunk.toString()}`);\n next();\n },\n });\n};\n\n/**\n * Extracts the SHA from an updater image string.\n * @param updaterImage - Image string in the format \"image:sha\" or \"registry/image:sha\"\n * @returns The SHA part after the last colon, or null if no colon is found\n */\nexport const extractUpdaterSha = (updaterImage: string): string | null => {\n const match = updaterImage.match(/:([^:]*)$/);\n return match ? match[1]! : null;\n};\n","import type { DependabotProxyConfig, FileFetcherInput, FileUpdaterInput } from '@paklo/core/dependabot';\nimport { logger } from '@paklo/core/logger';\nimport type { Container } from 'dockerode';\nimport { pack } from 'tar-stream';\nimport { errStream, outStream } from './utils';\n\n// Code below is borrowed and adapted from dependabot-action\n\nexport class ContainerRuntimeError extends Error {}\n\nconst RWX_ALL = 0o777;\n\nexport const ContainerService = {\n async storeInput(\n name: string,\n path: string,\n container: Container,\n input: FileFetcherInput | FileUpdaterInput | DependabotProxyConfig,\n ): Promise<void> {\n const tar = pack();\n tar.entry({ name, mode: RWX_ALL }, JSON.stringify(input));\n tar.finalize();\n await container.putArchive(tar, { path });\n },\n\n async storeCert(name: string, path: string, container: Container, cert: string): Promise<void> {\n const tar = pack();\n tar.entry({ name }, cert);\n tar.finalize();\n await container.putArchive(tar, { path });\n },\n\n async run(container: Container, command?: string): Promise<boolean> {\n try {\n // Start the container\n await container.start();\n logger.info(`Started container ${container.id}`);\n\n // Check if this is a dependabot container (has the expected structure)\n const containerInfo = await container.inspect();\n const isDependabotContainer = containerInfo.Config?.Env?.some((env) => env.startsWith('DEPENDABOT_JOB_ID='));\n\n if (isDependabotContainer) {\n // For dependabot containers, run CA certificates update as root first\n await this.execCommand(container, ['/usr/sbin/update-ca-certificates'], 'root');\n\n // Then run the dependabot commands as dependabot user\n const dependabotCommands = [\n 'mkdir -p /home/dependabot/dependabot-updater/output',\n '$DEPENDABOT_HOME/dependabot-updater/bin/run fetch_files',\n ];\n\n if (command === 'graph') {\n dependabotCommands.push('$DEPENDABOT_HOME/dependabot-updater/bin/run update_graph');\n } else {\n dependabotCommands.push('$DEPENDABOT_HOME/dependabot-updater/bin/run update_files');\n }\n\n for (const cmd of dependabotCommands) {\n await this.execCommand(container, ['/bin/sh', '-c', cmd], 'dependabot');\n }\n } else {\n // For test containers and other containers, just wait for completion\n const outcome = await container.wait();\n if (outcome.StatusCode !== 0) {\n throw new Error(`Container exited with code ${outcome.StatusCode}`);\n }\n }\n\n return true;\n } catch (error) {\n logger.info(`Failure running container ${container.id}: ${error}`);\n throw new ContainerRuntimeError('The updater encountered one or more errors.');\n } finally {\n try {\n await container.remove({ v: true, force: true });\n logger.info(`Cleaned up container ${container.id}`);\n } catch (error) {\n logger.info(`Failed to clean up container ${container.id}: ${error}`);\n }\n }\n },\n\n async execCommand(container: Container, cmd: string[], user: string): Promise<void> {\n const exec = await container.exec({\n Cmd: cmd,\n User: user,\n AttachStdout: true,\n AttachStderr: true,\n });\n\n const stream = await exec.start({});\n\n // Wait for the stream to end\n await new Promise<void>((resolve, reject) => {\n container.modem.demuxStream(stream, outStream('updater'), errStream('updater'));\n\n stream.on('end', () => {\n resolve();\n });\n\n stream.on('error', (error) => {\n reject(error);\n });\n });\n\n // Wait a bit for the exec to complete properly\n await new Promise((resolve) => setTimeout(resolve, 100));\n\n const inspection = await exec.inspect();\n if (inspection.ExitCode !== 0) {\n throw new Error(`Command failed with exit code ${inspection.ExitCode}: ${cmd.join(' ')}`);\n }\n },\n};\n","import { Readable } from 'node:stream';\nimport { logger } from '@paklo/core/logger';\nimport Docker from 'dockerode';\n\nconst MAX_RETRIES = 5; // Maximum number of retries\nconst INITIAL_DELAY_MS = 2000; // Initial delay in milliseconds for backoff\n\n// Code below is borrowed and adapted from dependabot-action\n\nconst sleep = async (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst endOfStream = async (docker: Docker, stream: Readable): Promise<void> => {\n return new Promise((resolve, reject) => {\n docker.modem.followProgress(stream, (err: Error | null) => (err ? reject(err) : resolve(undefined)));\n });\n};\n\nexport function getOrgFromImage(imageName: string): string {\n const parts = imageName.split('/');\n if (parts.length >= 3 && parts[0] === 'ghcr.io') {\n return parts[1]!; // The domain is always the second part\n }\n return 'unknown'; // Fallback case if structure is unexpected\n}\n\nexport type MetricReporter = (\n metricName: string,\n metricType: 'increment' | 'gauge',\n value: number,\n additionalTags?: Record<string, string>,\n) => Promise<void>;\n\n/** Fetch the configured updater image, if it isn't already available. */\nexport const ImageService = {\n async pull(imageName: string, sendMetric?: MetricReporter, force = false): Promise<void> {\n /*\n This method fetches images hosts on GitHub infrastructure.\n\n We expose the `fetch_image` utility method to allow us to pull in arbitrary images for unit tests.\n */\n if (!(imageName.startsWith('ghcr.io/') || imageName.startsWith('docker.pkg.github.com/'))) {\n throw new Error('Only images distributed via docker.pkg.github.com or ghcr.io can be fetched');\n }\n\n const docker = new Docker();\n const org = getOrgFromImage(imageName);\n try {\n const image = await docker.getImage(imageName).inspect();\n if (!force) {\n logger.info(`Resolved ${imageName} to existing ${image.RepoDigests}`);\n return;\n } // else fallthrough to pull\n } catch (e: unknown) {\n if (e instanceof Error && !e.message.includes('no such image')) {\n throw e;\n } // else fallthrough to pull\n }\n\n const auth = {}; // Images are public so not authentication info is required\n await this.fetchImageWithRetry(imageName, auth, docker, sendMetric, org);\n },\n\n /* Retrieve the image using the auth details provided, if any with retry and backoff */\n async fetchImageWithRetry(\n imageName: string,\n auth = {},\n docker = new Docker(),\n sendMetric: MetricReporter | undefined,\n org: string,\n ): Promise<void> {\n let attempt = 0;\n\n while (attempt < MAX_RETRIES) {\n try {\n logger.info(`Pulling image ${imageName} (attempt ${attempt + 1})...`);\n /* To avoid sending metrics during unit tests (fetch_image) */\n if (sendMetric) {\n await sendMetric('ghcr_image_pull', 'increment', 1, {\n org,\n });\n }\n const stream = await docker.pull(imageName, { authconfig: auth });\n await endOfStream(docker, new Readable().wrap(stream));\n logger.info(`Pulled image ${imageName}`);\n return; // Exit on success\n } catch (error) {\n if (!(error instanceof Error)) throw error; // Ensure error is an instance of Error\n\n // Handle 429 Too Many Requests separately\n if (\n error.message.includes('429 Too Many Requests') ||\n error.message.toLowerCase().includes('too many requests')\n ) {\n attempt++; // Only increment attempt on 429\n if (attempt >= MAX_RETRIES) {\n logger.error(`Failed to pull image ${imageName} after ${MAX_RETRIES} attempts.`);\n throw error;\n }\n\n // Add jitter to avoid synchronization issues\n // biome-ignore lint/style/useExponentiationOperator: This is clearer for now\n const baseDelay = INITIAL_DELAY_MS * Math.pow(2, attempt);\n const jitter = Math.random() * baseDelay;\n const delay = baseDelay / 2 + jitter;\n\n logger.warn(`Received Too Many Requests error. Retrying in ${(delay / 1000).toFixed(2)} seconds...`);\n await sleep(delay);\n } else {\n // Non-429 errors should NOT be retried\n logger.error(`Fatal error pulling image ${imageName}: ${error.message}`);\n throw error; // Exit immediately\n }\n }\n }\n },\n};\n","// Code below is borrowed and adapted from dependabot-action\n\n/*\n `jobId` is intentionally a string even though we copied from code that used number\n We generate the job identifiers using Snowflake which produces bigint\n and bigint cannot be serialized to JSON, so we use string everywhere instead.\n The hosted dependabot possible uses auto-incrementing numbers for jobIds in their database,\n but not all databases support this.\n*/\n\nexport class JobParameters {\n constructor(\n readonly jobId: string,\n readonly jobToken: string,\n readonly credentialsToken: string,\n readonly dependabotApiUrl: string,\n readonly dependabotApiDockerUrl: string,\n readonly updaterImage: string,\n ) {}\n}\n\nexport function getJobParameters(input: {\n jobId?: string;\n jobToken?: string;\n credentialsToken?: string;\n dependabotApiUrl?: string;\n dependabotApiDockerUrl?: string;\n updaterImage?: string;\n}): JobParameters | null {\n return new JobParameters(\n input.jobId as string,\n input.jobToken as string,\n input.credentialsToken as string,\n input.dependabotApiUrl as string,\n input.dependabotApiDockerUrl as string,\n input.updaterImage as string,\n );\n}\n","import { readFile } from 'node:fs/promises';\nimport type { CertificateAuthority, DependabotCredential, DependabotProxyConfig } from '@paklo/core/dependabot';\nimport { logger } from '@paklo/core/logger';\nimport type Docker from 'dockerode';\nimport type { Container, Network } from 'dockerode';\nimport { ContainerService } from './container-service';\nimport { errStream, outStream } from './utils';\n\n// Code below is borrowed and adapted from dependabot-action\n\nexport type Proxy = {\n container: Container;\n network: Network;\n networkName: string;\n url: () => Promise<string>;\n cert: string;\n shutdown: () => Promise<void>;\n};\n\nconst KEY_SIZE = 2048;\nconst KEY_EXPIRY_YEARS = 2;\nconst CONFIG_FILE_PATH = '/';\nconst CONFIG_FILE_NAME = 'config.json';\nconst CA_CERT_INPUT_PATH = '/usr/local/share/ca-certificates';\nconst CUSTOM_CA_CERT_NAME = 'custom-ca-cert.crt';\nconst CERT_SUBJECT = [\n { name: 'commonName', value: 'Dependabot Internal CA' },\n { name: 'organizationName', value: 'GitHub Inc.' },\n { shortName: 'OU', value: 'Dependabot' },\n { name: 'countryName', value: 'US' },\n { shortName: 'ST', value: 'California' },\n { name: 'localityName', value: 'San Francisco' },\n];\n\nexport class ProxyBuilder {\n constructor(\n private readonly docker: Docker,\n private readonly proxyImage: string,\n private readonly cachedMode: boolean,\n ) {}\n\n async run(\n jobId: string,\n jobToken: string,\n dependabotApiUrl: string,\n credentials: DependabotCredential[],\n ): Promise<Proxy> {\n const name = `dependabot-job-${jobId}-proxy`;\n const config = await this.buildProxyConfig(credentials);\n const cert = config.ca.cert;\n\n const externalNetworkName = `dependabot-job-${jobId}-external-network`;\n const externalNetwork = await this.ensureNetwork(externalNetworkName, false);\n\n const internalNetworkName = `dependabot-job-${jobId}-internal-network`;\n const internalNetwork = await this.ensureNetwork(internalNetworkName, true);\n\n const container = await this.createContainer(\n jobId,\n jobToken,\n dependabotApiUrl,\n name,\n externalNetwork,\n internalNetwork,\n internalNetworkName,\n );\n\n await ContainerService.storeInput(CONFIG_FILE_NAME, CONFIG_FILE_PATH, container, config);\n\n const customCAPath = this.customCAPath();\n if (customCAPath) {\n logger.info('Detected custom CA certificate, adding to proxy');\n\n const customCert = (await readFile(customCAPath, 'utf8')).toString();\n await ContainerService.storeCert(CUSTOM_CA_CERT_NAME, CA_CERT_INPUT_PATH, container, customCert);\n }\n\n const stream = await container.attach({\n stream: true,\n stdout: true,\n stderr: true,\n });\n container.modem.demuxStream(stream, outStream(' proxy'), errStream(' proxy'));\n\n const url = async (): Promise<string> => {\n const containerInfo = await container.inspect();\n\n if (containerInfo.State.Running === true) {\n const ipAddress = containerInfo.NetworkSettings.Networks[`${internalNetworkName}`]!.IPAddress;\n return `http://${ipAddress}:1080`;\n } else {\n throw new Error(\"proxy container isn't running\");\n }\n };\n\n return {\n container,\n network: internalNetwork,\n networkName: internalNetworkName,\n url,\n cert,\n shutdown: async () => {\n await container.stop();\n await container.remove();\n await Promise.all([externalNetwork.remove(), internalNetwork.remove()]);\n },\n };\n }\n\n private async ensureNetwork(name: string, internal = true): Promise<Network> {\n const networks = await this.docker.listNetworks({\n filters: JSON.stringify({ name: [name] }),\n });\n if (networks.length > 0) {\n return this.docker.getNetwork(networks[0]!.Id);\n } else {\n return await this.docker.createNetwork({ Name: name, Internal: internal });\n }\n }\n\n private async buildProxyConfig(credentials: DependabotCredential[]): Promise<DependabotProxyConfig> {\n const ca = await this.generateCertificateAuthority();\n\n const config: DependabotProxyConfig = { all_credentials: credentials, ca };\n\n return config;\n }\n\n private async generateCertificateAuthority(): Promise<CertificateAuthority> {\n // node-forge is a CommonJS module, so we need to import it dynamically\n const {\n default: { md, pki },\n } = await import('node-forge');\n const keys = pki.rsa.generateKeyPair(KEY_SIZE);\n const cert = pki.createCertificate();\n\n cert.publicKey = keys.publicKey;\n cert.serialNumber = '01';\n cert.validity.notBefore = new Date();\n cert.validity.notAfter = new Date();\n cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + KEY_EXPIRY_YEARS);\n\n cert.setSubject(CERT_SUBJECT);\n cert.setIssuer(CERT_SUBJECT);\n\n cert.setExtensions([\n {\n name: 'basicConstraints',\n cA: true,\n critical: true,\n },\n {\n name: 'keyUsage',\n digitalSignature: true,\n keyEncipherment: true,\n keyCertSign: true,\n cRLSign: true,\n critical: true,\n },\n {\n name: 'extKeyUsage',\n serverAuth: true,\n clientAuth: true,\n },\n {\n name: 'subjectKeyIdentifier',\n },\n {\n name: 'authorityKeyIdentifier',\n keyIdentifier: true,\n authorityCertIssuer: true,\n authorityCertSerialNumber: cert.serialNumber,\n },\n ]);\n\n cert.sign(keys.privateKey, md.sha256.create());\n\n const pem = pki.certificateToPem(cert);\n const key = pki.privateKeyToPem(keys.privateKey);\n return { cert: pem, key };\n }\n\n private async createContainer(\n jobId: string,\n jobToken: string,\n dependabotApiUrl: string,\n containerName: string,\n externalNetwork: Network,\n internalNetwork: Network,\n internalNetworkName: string,\n ): Promise<Container> {\n const container = await this.docker.createContainer({\n Image: this.proxyImage,\n name: containerName,\n AttachStdout: true,\n AttachStderr: true,\n Env: [\n `http_proxy=${process.env.http_proxy || process.env.HTTP_PROXY || ''}`,\n `https_proxy=${process.env.https_proxy || process.env.HTTPS_PROXY || ''}`,\n `no_proxy=${process.env.no_proxy || process.env.NO_PROXY || ''}`,\n `JOB_ID=${jobId}`,\n `JOB_TOKEN=${jobToken}`,\n `PROXY_CACHE=${this.cachedMode ? 'true' : 'false'}`,\n `DEPENDABOT_API_URL=${dependabotApiUrl}`,\n `ACTIONS_ID_TOKEN_REQUEST_TOKEN=${process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN || ''}`,\n `ACTIONS_ID_TOKEN_REQUEST_URL=${process.env.ACTIONS_ID_TOKEN_REQUEST_URL || ''}`,\n ],\n Entrypoint: ['sh', '-c', '/usr/sbin/update-ca-certificates && /update-job-proxy'],\n\n HostConfig: {\n NetworkMode: internalNetworkName,\n ExtraHosts: ['host.docker.internal:host-gateway'], // needed for Docker on Linux\n },\n });\n\n await externalNetwork.connect({ Container: container.id });\n\n logger.info(`Created proxy container: ${container.id}`);\n return container;\n }\n\n private customCAPath(): string | undefined {\n if ('CUSTOM_CA_PATH' in process.env) {\n return process.env.CUSTOM_CA_PATH;\n }\n // default to node.js configuration\n return process.env.NODE_EXTRA_CA_CERTS;\n }\n}\n","{\n \"name\": \"@paklo/runner\",\n \"version\": \"0.3.0\",\n \"sideEffects\": false,\n \"type\": \"module\",\n \"author\": \"mburumaxwell\",\n \"license\": \"AGPL-3.0-later\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.mts\",\n \"import\": \"./dist/index.mjs\"\n },\n \"./local\": {\n \"types\": \"./dist/local/index.d.mts\",\n \"import\": \"./dist/local/index.mjs\"\n },\n \"./local/azure\": {\n \"types\": \"./dist/local/azure/index.d.mts\",\n \"import\": \"./dist/local/azure/index.mjs\"\n }\n },\n \"files\": [\n \"dist\",\n \"package.json\"\n ],\n \"scripts\": {\n \"dev\": \"tsdown --watch\",\n \"prebuild\": \"tsc\",\n \"build\": \"tsdown\",\n \"lint\": \"biome check\",\n \"test\": \"vitest\",\n \"clean\": \"rimraf .turbo dist\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/mburumaxwell/dependabot-azure-devops.git\",\n \"directory\": \"packages/runner\"\n },\n \"keywords\": [\n \"dependabot\",\n \"azure\",\n \"devops\",\n \"paklo\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/mburumaxwell/dependabot-azure-devops/issues\"\n },\n \"homepage\": \"https://github.com/mburumaxwell/dependabot-azure-devops#readme\",\n \"dependencies\": {\n \"@hono/node-server\": \"1.19.6\",\n \"@paklo/core\": \"workspace:*\",\n \"dockerode\": \"4.0.9\",\n \"node-forge\": \"1.3.1\",\n \"tar-stream\": \"3.1.7\"\n },\n \"devDependencies\": {\n \"@types/dockerode\": \"3.3.46\",\n \"@types/node\": \"24.10.1\",\n \"@types/node-forge\": \"1.3.14\",\n \"@types/tar-stream\": \"3.1.4\",\n \"tsdown\": \"0.16.5\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","// biome-ignore-all lint/suspicious/noShadowRestrictedNames: Proxy is okay\n\nimport type { FileFetcherInput, FileUpdaterInput } from '@paklo/core/dependabot';\nimport { logger } from '@paklo/core/logger';\nimport type Docker from 'dockerode';\nimport type { Container } from 'dockerode';\nimport { ContainerService } from './container-service';\nimport type { JobParameters } from './params';\nimport type { Proxy } from './proxy';\nimport { extractUpdaterSha } from './utils';\n\nconst JOB_OUTPUT_FILENAME = 'output.json';\nconst JOB_OUTPUT_PATH = '/home/dependabot/dependabot-updater/output';\nconst JOB_INPUT_FILENAME = 'job.json';\nconst JOB_INPUT_PATH = `/home/dependabot/dependabot-updater`;\nconst REPO_CONTENTS_PATH = '/home/dependabot/dependabot-updater/repo';\nconst CA_CERT_INPUT_PATH = '/usr/local/share/ca-certificates';\nconst CA_CERT_FILENAME = 'dbot-ca.crt';\nconst UPDATER_MAX_MEMORY = 8 * 1024 * 1024 * 1024; // 8GB in bytes\n\n// Code below is borrowed and adapted from dependabot-action\n\nexport class UpdaterBuilder {\n constructor(\n private readonly docker: Docker,\n private readonly jobParams: JobParameters,\n private readonly input: FileFetcherInput | FileUpdaterInput,\n private readonly proxy: Proxy,\n\n private readonly updaterImage: string,\n ) {}\n\n async run(containerName: string): Promise<Container> {\n const proxyUrl = await this.proxy.url();\n const updaterSha = extractUpdaterSha(this.updaterImage);\n\n const envVars = [\n `GITHUB_ACTIONS=${process.env.GITHUB_ACTIONS}`,\n `DEPENDABOT_JOB_ID=${this.jobParams.jobId}`,\n `DEPENDABOT_JOB_TOKEN=`,\n `DEPENDABOT_JOB_PATH=${JOB_INPUT_PATH}/${JOB_INPUT_FILENAME}`,\n `DEPENDABOT_OPEN_TIMEOUT_IN_SECONDS=15`,\n `DEPENDABOT_OUTPUT_PATH=${JOB_OUTPUT_PATH}/${JOB_OUTPUT_FILENAME}`,\n `DEPENDABOT_REPO_CONTENTS_PATH=${REPO_CONTENTS_PATH}`,\n `DEPENDABOT_API_URL=${this.jobParams.dependabotApiDockerUrl}`,\n `SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt`,\n `http_proxy=${proxyUrl}`,\n `HTTP_PROXY=${proxyUrl}`,\n `https_proxy=${proxyUrl}`,\n `HTTPS_PROXY=${proxyUrl}`,\n `UPDATER_ONE_CONTAINER=1`,\n `ENABLE_CONNECTIVITY_CHECK=${process.env.DEPENDABOT_ENABLE_CONNECTIVITY_CHECK || '1'}`,\n\n // for updates relying on .NET (e.g. NuGet) and running on macOS (e.g. dev laptop or local MacMini),\n // we need to disable WriteXorExecute to avoid issues with emulation of Linux containers on macOS hosts\n // with Apple Silicon (M1/M2) chips\n // See - https://github.com/dotnet/runtime/issues/103063#issuecomment-2149599940\n // - https://github.com/dependabot/dependabot-core/issues/5037\n ...(process.platform === 'darwin' ? [`DOTNET_EnableWriteXorExecute=0`] : []),\n ];\n\n // Add DEPENDABOT_UPDATER_SHA if we successfully extracted a SHA\n if (updaterSha !== null) {\n envVars.push(`DEPENDABOT_UPDATER_SHA=${updaterSha}`);\n }\n\n const container = await this.docker.createContainer({\n Image: this.updaterImage,\n name: containerName,\n AttachStdout: true,\n AttachStderr: true,\n User: 'dependabot',\n Env: envVars,\n Cmd: ['/bin/sh'],\n Tty: true,\n HostConfig: {\n Memory: UPDATER_MAX_MEMORY,\n NetworkMode: this.proxy.networkName,\n },\n });\n\n await ContainerService.storeCert(CA_CERT_FILENAME, CA_CERT_INPUT_PATH, container, this.proxy.cert);\n\n await ContainerService.storeInput(JOB_INPUT_FILENAME, JOB_INPUT_PATH, container, this.input);\n\n logger.info(`Created container: ${container.id}`);\n return container;\n }\n}\n","// biome-ignore-all lint/suspicious/noShadowRestrictedNames: Proxy is okay\n\nimport type {\n DependabotCredential,\n DependabotJobConfig,\n FileFetcherInput,\n FileUpdaterInput,\n} from '@paklo/core/dependabot';\nimport Docker, { type Container } from 'dockerode';\nimport { ContainerService } from './container-service';\nimport type { JobParameters } from './params';\nimport { type Proxy, ProxyBuilder } from './proxy';\nimport { UpdaterBuilder } from './updater-builder';\n\n// Code below is borrowed and adapted from dependabot-action\n\nexport class Updater {\n docker: Docker;\n\n constructor(\n private readonly updaterImage: string,\n private readonly proxyImage: string,\n private readonly params: JobParameters,\n private readonly job: DependabotJobConfig,\n private readonly credentials: DependabotCredential[],\n ) {\n this.docker = new Docker();\n this.job['credentials-metadata'] = this.generateCredentialsMetadata();\n }\n\n /**\n * Execute an update job and report the result to Dependabot API.\n */\n async runUpdater(): Promise<boolean> {\n const cachedMode = Object.hasOwn(this.job.experiments, 'proxy-cached') === true;\n\n const proxyBuilder = new ProxyBuilder(this.docker, this.proxyImage, cachedMode);\n\n const proxy = await proxyBuilder.run(\n this.params.jobId,\n this.params.jobToken,\n this.params.dependabotApiUrl,\n this.credentials,\n );\n await proxy.container.start();\n\n try {\n await this.runUpdate(proxy);\n return true;\n } finally {\n await this.cleanup(proxy);\n }\n }\n\n private generateCredentialsMetadata(): DependabotCredential[] {\n const unique: Set<string> = new Set();\n const result: DependabotCredential[] = [];\n for (const credential of this.credentials) {\n if (credential.type === 'jit_access') {\n continue;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: necessary\n const obj: any = { type: credential.type };\n if (credential.host !== undefined) {\n obj.host = credential.host;\n }\n if (credential.registry !== undefined) {\n obj.registry = credential.registry;\n }\n if (credential.url !== undefined) {\n obj.url = credential.url;\n }\n this.setRegistryFromUrl(obj, credential);\n if (credential['index-url'] !== undefined) {\n obj['index-url'] = credential['index-url'];\n }\n this.setIndexUrlFromUrl(obj, credential);\n if (credential['env-key'] !== undefined) {\n obj['env-key'] = credential['env-key'];\n }\n if (credential.organization !== undefined) {\n obj.organization = credential.organization;\n }\n if (credential['replaces-base'] !== undefined) {\n obj['replaces-base'] = credential['replaces-base'];\n }\n if (credential['public-key-fingerprint'] !== undefined) {\n obj['public-key-fingerprint'] = credential['public-key-fingerprint'];\n }\n if (credential.repo !== undefined) {\n obj.repo = credential.repo;\n }\n const key = JSON.stringify(obj);\n if (!unique.has(key)) {\n unique.add(key);\n result.push(obj as DependabotCredential);\n }\n }\n return result;\n }\n\n private setRegistryFromUrl(obj: DependabotCredential, credential: DependabotCredential): void {\n const typesThatUseRegistryAsHost = ['npm_registry', 'composer_repository', 'docker_registry'];\n\n if (!typesThatUseRegistryAsHost.includes(credential.type)) {\n return;\n }\n\n if (!credential.registry && credential.url) {\n try {\n const parsedURL = new URL(credential.url);\n obj.registry = parsedURL.hostname;\n if (credential.type === 'npm_registry') {\n obj.registry += parsedURL.pathname;\n }\n } catch {\n // If the URL is invalid, we skip setting the registry\n // as it will fall back to the default registry for the given type (e.g., npm, Docker, or Composer).\n }\n }\n }\n\n private setIndexUrlFromUrl(obj: DependabotCredential, credential: DependabotCredential): void {\n if (credential.type !== 'python_index') {\n return;\n }\n if (credential['index-url']) {\n return;\n }\n if (credential.url) {\n try {\n obj['index-url'] = credential.url;\n } catch {\n // If the URL is invalid, we skip setting the index-url\n // as it will fall back to the default index URL for pip.\n }\n }\n }\n\n private async runUpdate(proxy: Proxy): Promise<void> {\n const name = `dependabot-job-${this.params.jobId}`;\n const container = await this.createContainer(proxy, name, {\n job: this.job,\n });\n\n await ContainerService.run(container, this.job.command);\n }\n\n private async createContainer(\n proxy: Proxy,\n containerName: string,\n input: FileFetcherInput | FileUpdaterInput,\n ): Promise<Container> {\n const builder = new UpdaterBuilder(this.docker, this.params, input, proxy, this.updaterImage);\n return builder.run(containerName);\n }\n\n private async cleanup(proxy: Proxy): Promise<void> {\n await proxy.shutdown();\n }\n}\n","import crypto from 'node:crypto';\nimport os from 'node:os';\n\nimport { InnerApiClient } from '@paklo/core/http';\nimport { logger } from '@paklo/core/logger';\nimport type { UsageTelemetryRequestData } from '@paklo/core/usage';\nimport packageJson from '../package.json';\nimport { ApiClient, CredentialFetchingError, type SecretMasker } from './api-client';\nimport { PROXY_IMAGE_NAME, updaterImageName } from './docker-tags';\nimport { ImageService, type MetricReporter } from './image-service';\nimport { getJobParameters } from './params';\nimport { Updater } from './updater';\n\nexport class JobRunnerImagingError extends Error {}\nexport class JobRunnerUpdaterError extends Error {}\n\nexport type RunJobOptions = {\n dependabotApiUrl: string;\n dependabotApiDockerUrl?: string;\n jobId: string;\n jobToken: string;\n credentialsToken: string;\n updaterImage?: string;\n secretMasker: SecretMasker;\n usage: Pick<UsageTelemetryRequestData, 'trigger' | 'provider' | 'owner' | 'project' | 'package-manager'>;\n};\nexport type RunJobResult = { success: true; message?: string } | { success: false; message: string };\n\nexport async function runJob(options: RunJobOptions): Promise<RunJobResult> {\n const { jobId, dependabotApiUrl, dependabotApiDockerUrl, jobToken, credentialsToken, secretMasker, usage } = options;\n\n const started = new Date();\n let success = false;\n let message: string | undefined;\n try {\n const params = getJobParameters({\n jobId,\n jobToken,\n credentialsToken,\n dependabotApiUrl,\n dependabotApiDockerUrl: dependabotApiDockerUrl ?? dependabotApiUrl,\n updaterImage: options.updaterImage,\n })!;\n\n // if dependabotApiUrl contains \"host.docker.internal\", we need to replace it with \"localhost\" for local calls\n const baseUrl = dependabotApiUrl.replace('host.docker.internal', 'localhost');\n const client = new InnerApiClient({ baseUrl });\n const apiClient = new ApiClient(client, params, jobToken, credentialsToken, secretMasker);\n\n // If we fail to succeed in fetching the job details, we cannot be sure the job has entered a 'processing' state,\n // so we do not try attempt to report back an exception if this fails and instead rely on the workflow run\n // webhook as it anticipates scenarios where jobs have failed while 'enqueued'.\n const job = await apiClient.getJobDetails();\n\n // The params can specify which updater image to use. If it doesn't, fall back to the pinned version.\n const updaterImage = params.updaterImage || updaterImageName(job['package-manager']);\n\n // The sendMetrics function is used to send metrics to the API client.\n // It uses the package manager as a tag to identify the metric.\n const sendMetricsWithPackageManager: MetricReporter = async (name, metricType, value, additionalTags = {}) => {\n try {\n await apiClient.sendMetrics(name, metricType, value, {\n package_manager: job['package-manager'],\n ...additionalTags,\n });\n } catch (error) {\n logger.warn(`Metric sending failed for ${name}: ${(error as Error).message}`);\n }\n };\n\n const credentials = (await apiClient.getCredentials()) || [];\n\n const updater = new Updater(updaterImage, PROXY_IMAGE_NAME, params, job, credentials);\n\n try {\n // Using sendMetricsWithPackageManager wrapper to inject package manager tag to\n // avoid passing additional parameters to ImageService.pull method\n await ImageService.pull(updaterImage, sendMetricsWithPackageManager);\n await ImageService.pull(PROXY_IMAGE_NAME, sendMetricsWithPackageManager);\n } catch (err: unknown) {\n if (err instanceof Error) {\n throw new JobRunnerImagingError(err.message);\n }\n }\n\n try {\n await updater.runUpdater();\n } catch (err: unknown) {\n if (err instanceof Error) {\n throw new JobRunnerUpdaterError(err.message);\n }\n }\n success = true;\n } catch (err) {\n if (err instanceof JobRunnerImagingError) {\n message = `Error fetching updater images: ${err.message}`;\n } else if (err instanceof JobRunnerUpdaterError) {\n message = `Error running updater: ${err.message}`;\n } else if (err instanceof CredentialFetchingError) {\n message = `Dependabot was unable to retrieve job credentials: ${err.message}`;\n } else {\n message = `Unknown error: ${(err as Error).message}`;\n }\n }\n\n const duration = Date.now() - started.getTime();\n const data: UsageTelemetryRequestData = {\n ...usage,\n host: {\n platform: os.platform(),\n release: os.release(),\n arch: os.arch(),\n 'machine-hash': crypto.createHash('sha256').update(os.hostname()).digest('hex'),\n },\n version: packageJson.version,\n id: jobId,\n started,\n duration,\n success,\n };\n try {\n const json = JSON.stringify(data);\n logger.debug(`Usage telemetry data: ${json}`);\n const resp = await fetch('https://www.paklo.app/api/usage-telemetry', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: json,\n });\n if (!resp.ok) {\n logger.debug(`Failed to send usage telemetry data: ${resp.status} ${resp.statusText}`);\n }\n } catch (err) {\n logger.debug(`Failed to send usage telemetry data: ${(err as Error).message}`);\n // ignore\n }\n\n logger.info(`Update job ${jobId} completed`);\n return { success, message: message! };\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { i as SecretMasker } from "./api-client-
|
|
1
|
+
import { i as SecretMasker } from "./api-client-M8F9t7II.mjs";
|
|
2
2
|
import { CreateApiServerAppOptions, DependabotConfig, DependabotCredential, DependabotExperiments, DependabotJobConfig, DependabotRequest, DependabotTokenType, DependabotUpdate, GitAuthor } from "@paklo/core/dependabot";
|
|
3
3
|
|
|
4
4
|
//#region src/local/runner.d.ts
|
|
5
5
|
type RunJobsResult = {
|
|
6
|
-
id:
|
|
6
|
+
id: string;
|
|
7
7
|
success: boolean;
|
|
8
8
|
message?: string;
|
|
9
9
|
affectedPrs: number[];
|
|
@@ -31,7 +31,7 @@ declare abstract class LocalJobsRunner {
|
|
|
31
31
|
//#region src/local/server.d.ts
|
|
32
32
|
type LocalDependabotServerAddOptions = {
|
|
33
33
|
/** The ID of the dependabot job. */
|
|
34
|
-
id:
|
|
34
|
+
id: string;
|
|
35
35
|
/** The dependabot update associated with the job. */
|
|
36
36
|
update: DependabotUpdate;
|
|
37
37
|
/** The dependabot job configuration. */
|
|
@@ -62,14 +62,15 @@ declare abstract class LocalDependabotServer {
|
|
|
62
62
|
private readonly credentialTokens;
|
|
63
63
|
private readonly jobCredentials;
|
|
64
64
|
private readonly receivedRequests;
|
|
65
|
-
protected readonly affectedPullRequestIds: Map<
|
|
65
|
+
protected readonly affectedPullRequestIds: Map<string, AffectedPullRequestIds>;
|
|
66
66
|
constructor(options: LocalDependabotServerOptions);
|
|
67
67
|
start(port?: number): void;
|
|
68
68
|
stop(): void;
|
|
69
69
|
get url(): string;
|
|
70
70
|
get port(): number;
|
|
71
|
-
get jobs(): Map<
|
|
72
|
-
|
|
71
|
+
get jobs(): Map<string, {
|
|
72
|
+
id: string;
|
|
73
|
+
'package-manager': "bundler" | "cargo" | "composer" | "pub" | "docker" | "elm" | "github_actions" | "submodules" | "go_modules" | "gradle" | "maven" | "hex" | "nuget" | "npm_and_yarn" | "pip" | "rust_toolchain" | "swift" | "terraform" | "devcontainers" | "dotnet_sdk" | "bun" | "docker_compose" | "uv" | "vcpkg" | "helm" | "julia" | "bazel" | "opentofu";
|
|
73
74
|
'allowed-updates': {
|
|
74
75
|
'dependency-name'?: string | null | undefined;
|
|
75
76
|
'dependency-type'?: string | null | undefined;
|
|
@@ -110,7 +111,7 @@ declare abstract class LocalDependabotServer {
|
|
|
110
111
|
}[];
|
|
111
112
|
'security-updates-only': boolean;
|
|
112
113
|
source: {
|
|
113
|
-
provider: "azure";
|
|
114
|
+
provider: "azure" | "gitlab" | "bitbucket";
|
|
114
115
|
repo: string;
|
|
115
116
|
directory?: string | null | undefined;
|
|
116
117
|
directories?: string[] | null | undefined;
|
|
@@ -128,7 +129,6 @@ declare abstract class LocalDependabotServer {
|
|
|
128
129
|
'prefix-development'?: string | null | undefined;
|
|
129
130
|
'include-scope'?: boolean | null | undefined;
|
|
130
131
|
};
|
|
131
|
-
id?: number | undefined;
|
|
132
132
|
command?: "version" | "graph" | "recreate" | undefined;
|
|
133
133
|
'dependency-groups'?: {
|
|
134
134
|
name: string;
|
|
@@ -167,64 +167,64 @@ declare abstract class LocalDependabotServer {
|
|
|
167
167
|
* @param id - The ID of the dependabot job to get.
|
|
168
168
|
* @returns The dependabot job, or undefined if not found.
|
|
169
169
|
*/
|
|
170
|
-
job(id:
|
|
170
|
+
job(id: string): Promise<DependabotJobConfig | undefined>;
|
|
171
171
|
/**
|
|
172
172
|
* Gets a dependabot update by ID of the job.
|
|
173
173
|
* @param id - The ID of the dependabot job to get.
|
|
174
174
|
* @returns The dependabot update, or undefined if not found.
|
|
175
175
|
*/
|
|
176
|
-
update(id:
|
|
176
|
+
update(id: string): DependabotUpdate | undefined;
|
|
177
177
|
/**
|
|
178
178
|
* Gets a token by ID of the job.
|
|
179
179
|
* @param id - The ID of the dependabot job to get.
|
|
180
180
|
* @returns The job token, or undefined if not found.
|
|
181
181
|
*/
|
|
182
|
-
token(id:
|
|
182
|
+
token(id: string, type: DependabotTokenType): string | undefined;
|
|
183
183
|
/**
|
|
184
184
|
* Gets the credentials for a dependabot job by ID.
|
|
185
185
|
* @param id - The ID of the dependabot job to get credentials for.
|
|
186
186
|
* @returns The credentials for the job, or undefined if not found.
|
|
187
187
|
*/
|
|
188
|
-
credentials(id:
|
|
188
|
+
credentials(id: string): Promise<DependabotCredential[] | undefined>;
|
|
189
189
|
/**
|
|
190
190
|
* Gets the received requests for a dependabot job by ID.
|
|
191
191
|
* @param id - The ID of the dependabot job to get requests for.
|
|
192
192
|
* @returns The received requests for the job, or undefined if not found.
|
|
193
193
|
*/
|
|
194
|
-
requests(id:
|
|
194
|
+
requests(id: string): DependabotRequest[] | undefined;
|
|
195
195
|
/**
|
|
196
196
|
* Gets the IDs of pull requests affected by a dependabot job by ID.
|
|
197
197
|
* @param id - The ID of the dependabot job to get affected pull request IDs for.
|
|
198
198
|
* @returns The affected pull request IDs for the job, or undefined if not found.
|
|
199
199
|
*/
|
|
200
|
-
affectedPrs(id:
|
|
200
|
+
affectedPrs(id: string): AffectedPullRequestIds | undefined;
|
|
201
201
|
/**
|
|
202
202
|
* Gets all IDs of pull requests affected by a dependabot job by ID.
|
|
203
203
|
* @param id - The ID of the dependabot job to get affected pull request IDs for.
|
|
204
204
|
* @returns The affected pull request IDs for the job, or undefined if not found.
|
|
205
205
|
*/
|
|
206
|
-
allAffectedPrs(id:
|
|
206
|
+
allAffectedPrs(id: string): number[];
|
|
207
207
|
/**
|
|
208
208
|
* Clears all data associated with a dependabot job by ID.
|
|
209
209
|
* This should be called when the job is no longer needed.
|
|
210
210
|
* @param id - The ID of the dependabot job to clear.
|
|
211
211
|
*/
|
|
212
|
-
clear(id:
|
|
212
|
+
clear(id: string): void;
|
|
213
213
|
/**
|
|
214
214
|
* Authenticates a dependabot job.
|
|
215
215
|
* @param id - The ID of the dependabot job.
|
|
216
216
|
* @param value - The authentication value (e.g., API key).
|
|
217
217
|
* @returns A promise that resolves to a boolean indicating whether the authentication was successful.
|
|
218
218
|
*/
|
|
219
|
-
protected authenticate(type: DependabotTokenType, id:
|
|
219
|
+
protected authenticate(type: DependabotTokenType, id: string, value: string): Promise<boolean>;
|
|
220
220
|
/**
|
|
221
221
|
* Handles a dependabot request.
|
|
222
222
|
* @param id - The ID of the dependabot job.
|
|
223
223
|
* @param request - The dependabot request to handle.
|
|
224
224
|
* @returns A promise that resolves to the result of handling the request.
|
|
225
225
|
*/
|
|
226
|
-
protected handle(id:
|
|
226
|
+
protected handle(id: string, request: DependabotRequest): Promise<boolean>;
|
|
227
227
|
}
|
|
228
228
|
//#endregion
|
|
229
229
|
export { LocalJobsRunner as a, LocalDependabotServerOptions as i, LocalDependabotServer as n, LocalJobsRunnerOptions as o, LocalDependabotServerAddOptions as r, RunJobsResult as s, AffectedPullRequestIds as t };
|
|
230
|
-
//# sourceMappingURL=server-
|
|
230
|
+
//# sourceMappingURL=server-BSQEzdZw.d.mts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as logger } from "./logger-DSV-e8-Y.mjs";
|
|
2
1
|
import { createApiServerApp } from "@paklo/core/dependabot";
|
|
3
|
-
import {
|
|
2
|
+
import { logger } from "@paklo/core/logger";
|
|
3
|
+
import { Keygen } from "@paklo/core/keygen";
|
|
4
4
|
import { createAdaptorServer } from "@hono/node-server";
|
|
5
5
|
|
|
6
6
|
//#region src/local/runner.ts
|
|
@@ -12,13 +12,13 @@ var LocalJobsRunner = class {
|
|
|
12
12
|
makeTokens() {
|
|
13
13
|
const { jobTokenOverride, credentialsTokenOverride } = this.opt;
|
|
14
14
|
return {
|
|
15
|
-
jobToken: jobTokenOverride ??
|
|
16
|
-
credentialsToken: credentialsTokenOverride ??
|
|
15
|
+
jobToken: jobTokenOverride ?? Keygen.generate(),
|
|
16
|
+
credentialsToken: credentialsTokenOverride ?? Keygen.generate()
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
run() {
|
|
20
20
|
return Promise.resolve([{
|
|
21
|
-
id: -1,
|
|
21
|
+
id: "-1",
|
|
22
22
|
success: false,
|
|
23
23
|
affectedPrs: []
|
|
24
24
|
}]);
|
|
@@ -201,4 +201,4 @@ var LocalDependabotServer = class {
|
|
|
201
201
|
|
|
202
202
|
//#endregion
|
|
203
203
|
export { LocalJobsRunner as n, LocalDependabotServer as t };
|
|
204
|
-
//# sourceMappingURL=server-
|
|
204
|
+
//# sourceMappingURL=server-M1ps5BVd.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-M1ps5BVd.mjs","names":[],"sources":["../src/local/runner.ts","../src/local/server.ts"],"sourcesContent":["import type { DependabotConfig, DependabotExperiments, DependabotJobConfig } from '@paklo/core/dependabot';\nimport { Keygen } from '@paklo/core/keygen';\nimport type { SecretMasker } from '../api-client';\n\nexport type RunJobsResult = { id: string; success: boolean; message?: string; affectedPrs: number[] }[];\n\nexport type LocalJobsRunnerOptions = {\n jobTokenOverride?: string;\n credentialsTokenOverride?: string;\n secretMasker: SecretMasker;\n\n config: DependabotConfig;\n targetUpdateIds?: number[];\n experiments: DependabotExperiments;\n updaterImage?: string;\n command?: DependabotJobConfig['command'];\n};\n\nexport abstract class LocalJobsRunner {\n private readonly opt: LocalJobsRunnerOptions;\n\n constructor(options: LocalJobsRunnerOptions) {\n this.opt = options;\n }\n\n protected makeTokens() {\n const { jobTokenOverride, credentialsTokenOverride } = this.opt;\n return {\n jobToken: jobTokenOverride ?? Keygen.generate(),\n credentialsToken: credentialsTokenOverride ?? Keygen.generate(),\n };\n }\n\n public run(): Promise<RunJobsResult> {\n return Promise.resolve([{ id: '-1', success: false, affectedPrs: [] }]);\n }\n}\n","import type { AddressInfo } from 'node:net';\nimport { createAdaptorServer } from '@hono/node-server';\nimport {\n type CreateApiServerAppOptions,\n createApiServerApp,\n type DependabotCredential,\n type DependabotJobConfig,\n type DependabotRequest,\n type DependabotTokenType,\n type DependabotUpdate,\n type GitAuthor,\n} from '@paklo/core/dependabot';\nimport { logger } from '@paklo/core/logger';\n\nexport type LocalDependabotServerAddOptions = {\n /** The ID of the dependabot job. */\n id: string;\n /** The dependabot update associated with the job. */\n update: DependabotUpdate;\n /** The dependabot job configuration. */\n job: DependabotJobConfig;\n /** The authentication token for the job. */\n jobToken: string;\n /** The authentication token for the job. */\n credentialsToken: string;\n /** The credentials associated with the job. */\n credentials: DependabotCredential[];\n};\n\nexport type AffectedPullRequestIds = {\n created: number[];\n updated: number[];\n closed: number[];\n};\n\nexport type LocalDependabotServerOptions = Omit<\n CreateApiServerAppOptions,\n 'authenticate' | 'getJob' | 'getCredentials' | 'handle'\n> & {\n author: GitAuthor;\n debug: boolean;\n dryRun: boolean;\n};\nexport abstract class LocalDependabotServer {\n private readonly hostname = 'localhost';\n private readonly server: ReturnType<typeof createAdaptorServer>;\n private readonly trackedJobs = new Map<string, DependabotJobConfig>();\n private readonly updates = new Map<string, DependabotUpdate>();\n private readonly jobTokens = new Map<string, string>();\n private readonly credentialTokens = new Map<string, string>();\n private readonly jobCredentials = new Map<string, DependabotCredential[]>();\n private readonly receivedRequests = new Map<string, DependabotRequest[]>();\n\n protected readonly affectedPullRequestIds = new Map<string, AffectedPullRequestIds>();\n\n constructor(options: LocalDependabotServerOptions) {\n const app = createApiServerApp({\n ...options,\n authenticate: this.authenticate.bind(this),\n getJob: this.job.bind(this),\n getCredentials: this.credentials.bind(this),\n handle: this.handle.bind(this),\n });\n this.server = createAdaptorServer({\n ...app,\n // Workaround for hono not respecting x-forwarded-proto header\n // https://github.com/honojs/node-server/issues/146#issuecomment-3153435672\n fetch: (req) => {\n const url = new URL(req.url);\n url.protocol = req.headers.get('x-forwarded-proto') ?? url.protocol;\n return app.fetch(new Request(url, req));\n },\n });\n }\n\n start(port?: number) {\n // listening to 'localhost' will result to IpV6 only but we need it to be all local\n // interfaces, otherwise containers cannot reach it using host.docker.internal\n this.server.listen(port, '0.0.0.0', () => {\n const info = this.server.address() as AddressInfo;\n logger.info(`API server listening on http://${this.hostname}:${info.port}`);\n });\n }\n\n stop() {\n this.server.close(() => logger.info('API server closed'));\n }\n\n get url() {\n const info = this.server.address() as AddressInfo;\n return `http://${this.hostname}:${info.port}`;\n }\n\n get port() {\n const info = this.server.address() as AddressInfo;\n return info.port;\n }\n\n get jobs() {\n return this.trackedJobs;\n }\n\n /**\n * Adds a dependabot job.\n * @param value - The dependabot job details.\n */\n add(value: LocalDependabotServerAddOptions) {\n const { id, update, job, jobToken, credentialsToken, credentials } = value;\n const {\n trackedJobs,\n updates,\n jobTokens,\n credentialTokens,\n jobCredentials,\n receivedRequests,\n affectedPullRequestIds,\n } = this;\n trackedJobs.set(id, job);\n updates.set(id, update);\n jobTokens.set(id, jobToken);\n credentialTokens.set(id, credentialsToken);\n jobCredentials.set(id, credentials);\n receivedRequests.set(id, []);\n affectedPullRequestIds.set(id, { created: [], updated: [], closed: [] });\n }\n\n /**\n * Gets a dependabot job by ID.\n * @param id - The ID of the dependabot job to get.\n * @returns The dependabot job, or undefined if not found.\n */\n job(id: string): Promise<DependabotJobConfig | undefined> {\n return Promise.resolve(this.trackedJobs.get(id));\n }\n\n /**\n * Gets a dependabot update by ID of the job.\n * @param id - The ID of the dependabot job to get.\n * @returns The dependabot update, or undefined if not found.\n */\n update(id: string): DependabotUpdate | undefined {\n return this.updates.get(id);\n }\n\n /**\n * Gets a token by ID of the job.\n * @param id - The ID of the dependabot job to get.\n * @returns The job token, or undefined if not found.\n */\n token(id: string, type: DependabotTokenType): string | undefined {\n return type === 'job' ? this.jobTokens.get(id) : this.credentialTokens.get(id);\n }\n\n /**\n * Gets the credentials for a dependabot job by ID.\n * @param id - The ID of the dependabot job to get credentials for.\n * @returns The credentials for the job, or undefined if not found.\n */\n credentials(id: string): Promise<DependabotCredential[] | undefined> {\n return Promise.resolve(this.jobCredentials.get(id));\n }\n\n /**\n * Gets the received requests for a dependabot job by ID.\n * @param id - The ID of the dependabot job to get requests for.\n * @returns The received requests for the job, or undefined if not found.\n */\n requests(id: string): DependabotRequest[] | undefined {\n return this.receivedRequests.get(id);\n }\n\n /**\n * Gets the IDs of pull requests affected by a dependabot job by ID.\n * @param id - The ID of the dependabot job to get affected pull request IDs for.\n * @returns The affected pull request IDs for the job, or undefined if not found.\n */\n affectedPrs(id: string): AffectedPullRequestIds | undefined {\n const { affectedPullRequestIds } = this;\n return affectedPullRequestIds.get(id);\n }\n\n /**\n * Gets all IDs of pull requests affected by a dependabot job by ID.\n * @param id - The ID of the dependabot job to get affected pull request IDs for.\n * @returns The affected pull request IDs for the job, or undefined if not found.\n */\n allAffectedPrs(id: string): number[] {\n const affected = this.affectedPrs(id);\n if (!affected) return [];\n return [...affected.created, ...affected.updated, ...affected.closed];\n }\n\n /**\n * Clears all data associated with a dependabot job by ID.\n * This should be called when the job is no longer needed.\n * @param id - The ID of the dependabot job to clear.\n */\n clear(id: string) {\n this.trackedJobs.delete(id);\n this.updates.delete(id);\n this.jobTokens.delete(id);\n this.credentialTokens.delete(id);\n this.jobCredentials.delete(id);\n this.receivedRequests.delete(id);\n this.affectedPullRequestIds.delete(id);\n }\n\n /**\n * Authenticates a dependabot job.\n * @param id - The ID of the dependabot job.\n * @param value - The authentication value (e.g., API key).\n * @returns A promise that resolves to a boolean indicating whether the authentication was successful.\n */\n protected async authenticate(type: DependabotTokenType, id: string, value: string): Promise<boolean> {\n const token = type === 'job' ? this.jobTokens.get(id) : this.credentialTokens.get(id);\n if (!token) {\n logger.debug(`Authentication failed: ${type} token ${id} not found`);\n return false;\n }\n if (token !== value) {\n logger.debug(`Authentication failed: invalid token for ${type} token ${id}`);\n return false;\n }\n return true;\n }\n\n /**\n * Handles a dependabot request.\n * @param id - The ID of the dependabot job.\n * @param request - The dependabot request to handle.\n * @returns A promise that resolves to the result of handling the request.\n */\n protected handle(id: string, request: DependabotRequest): Promise<boolean> {\n this.receivedRequests.get(id)!.push(request);\n return Promise.resolve(true);\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paklo/runner",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "mburumaxwell",
|
|
@@ -43,14 +43,14 @@
|
|
|
43
43
|
"dockerode": "4.0.9",
|
|
44
44
|
"node-forge": "1.3.1",
|
|
45
45
|
"tar-stream": "3.1.7",
|
|
46
|
-
"@paklo/core": "0.
|
|
46
|
+
"@paklo/core": "0.6.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@types/dockerode": "3.3.
|
|
50
|
-
"@types/node": "24.10.
|
|
49
|
+
"@types/dockerode": "3.3.46",
|
|
50
|
+
"@types/node": "24.10.1",
|
|
51
51
|
"@types/node-forge": "1.3.14",
|
|
52
52
|
"@types/tar-stream": "3.1.4",
|
|
53
|
-
"tsdown": "0.16.
|
|
53
|
+
"tsdown": "0.16.5"
|
|
54
54
|
},
|
|
55
55
|
"publishConfig": {
|
|
56
56
|
"access": "public"
|
package/dist/logger-DSV-e8-Y.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"run-6mbbqgXi.mjs","names":["client: InnerApiClient","params: JobParameters","credentialsToken: string","secretMasker: SecretMasker","error: unknown","dockerContainerConfig.proxy","dockerContainerConfig","stream","stream","docker","e: unknown","jobId: number","jobToken: string","credentialsToken: string","dependabotApiUrl: string","dependabotApiDockerUrl: string","updaterImage: string","CA_CERT_INPUT_PATH","docker: Docker","proxyImage: string","cachedMode: boolean","stream","docker: Docker","jobParams: JobParameters","input: FileFetcherInput | FileUpdaterInput","proxy: Proxy","updaterImage: string","updaterImage: string","proxyImage: string","params: JobParameters","job: DependabotJobConfig","credentials: DependabotCredential[]","proxy","unique: Set<string>","result: DependabotCredential[]","obj: any","message: string | undefined","sendMetricsWithPackageManager: MetricReporter","err: unknown","data: UsageTelemetryRequestData","packageJson.version"],"sources":["../src/api-client.ts","../../../dependabot-action/docker/containers.json","../src/docker-tags.ts","../src/utils.ts","../src/container-service.ts","../src/image-service.ts","../src/params.ts","../src/proxy.ts","../package.json","../src/updater-builder.ts","../src/updater.ts","../src/run.ts"],"sourcesContent":["import type { DependabotMetric, DependabotRecordUpdateJobError } from '@paklo/core/dependabot';\nimport {\n type DependabotCredential,\n DependabotCredentialSchema,\n type DependabotJobConfig,\n DependabotJobConfigSchema,\n} from '@paklo/core/dependabot';\nimport {\n HEADER_NAME_AUTHORIZATION,\n HttpRequestError,\n type InnerApiClient,\n type InnerRequestOptions,\n isErrorTemporaryFailure,\n type ResourceResponse,\n} from '@paklo/core/http';\nimport { logger } from '@/logger';\nimport type { JobParameters } from './params';\n\nexport class JobDetailsFetchingError extends Error {}\nexport class CredentialFetchingError extends Error {}\nexport type SecretMasker = (value: string) => void;\n\nexport class ApiClient {\n private jobToken: string;\n constructor(\n private readonly client: InnerApiClient,\n readonly params: JobParameters,\n jobToken: string,\n private readonly credentialsToken: string,\n private readonly secretMasker: SecretMasker,\n ) {\n this.jobToken = jobToken;\n }\n\n // We use a static unknown SHA when marking a job as complete from the action\n // to remain in parity with the existing runner.\n UnknownSha = {\n 'base-commit-sha': 'unknown',\n };\n\n // Getter for jobToken\n getJobToken(): string {\n return this.jobToken;\n }\n\n async getJobDetails(): Promise<DependabotJobConfig> {\n try {\n const res = await this.getWithRetry<DependabotJobConfig>(\n `/update_jobs/${this.params.jobId}/details`,\n this.jobToken,\n { schema: DependabotJobConfigSchema },\n );\n if (res.status !== 200) {\n throw new JobDetailsFetchingError(\n `fetching job details: unexpected status code: ${res.status}: ${JSON.stringify(res.error)}`,\n );\n }\n if (!res.data) {\n throw new JobDetailsFetchingError(`fetching job details: missing response`);\n }\n\n return res.data;\n } catch (error) {\n if (error instanceof JobDetailsFetchingError) {\n throw error;\n } else if (error instanceof HttpRequestError) {\n throw new JobDetailsFetchingError(\n `fetching job details: unexpected status code: ${error.code}: ${error.message}`,\n );\n } else if (error instanceof Error) {\n throw new JobDetailsFetchingError(`fetching job details: ${error.name}: ${error.message}`);\n }\n throw error;\n }\n }\n\n async getCredentials(): Promise<DependabotCredential[]> {\n try {\n const res = await this.getWithRetry<DependabotCredential[]>(\n `/update_jobs/${this.params.jobId}/credentials`,\n this.credentialsToken,\n { schema: DependabotCredentialSchema.array() },\n );\n\n if (res.status !== 200) {\n throw new CredentialFetchingError(\n `fetching credentials: unexpected status code: ${res.status}: ${JSON.stringify(res.error)}`,\n );\n }\n if (!res.data) {\n throw new CredentialFetchingError(`fetching credentials: missing response`);\n }\n\n // Mask any secrets we've just retrieved from environment logs\n for (const credential of res.data) {\n if (credential.password) {\n this.secretMasker(credential.password);\n }\n if (credential.token) {\n this.secretMasker(credential.token);\n }\n if (credential['auth-key']) {\n this.secretMasker(credential['auth-key']);\n }\n }\n\n return res.data;\n } catch (error: unknown) {\n if (error instanceof CredentialFetchingError) {\n throw error;\n } else if (error instanceof HttpRequestError) {\n throw new CredentialFetchingError(\n `fetching credentials: unexpected status code: ${error.code}: ${error.message}`,\n );\n } else if (error instanceof Error) {\n throw new CredentialFetchingError(`fetching credentials: ${error.name}: ${error.message}`);\n }\n throw error;\n }\n }\n\n async reportJobError(error: DependabotRecordUpdateJobError): Promise<void> {\n const res = await this.client.post(`/update_jobs/${this.params.jobId}/record_update_job_error`, {\n payload: error,\n headers: {\n [HEADER_NAME_AUTHORIZATION]: this.jobToken,\n },\n });\n if (res.status !== 204) {\n throw new Error(`Unexpected status code: ${res.status}`);\n }\n }\n\n async markJobAsProcessed(): Promise<void> {\n const res = await this.client.patch(`/update_jobs/${this.params.jobId}/mark_as_processed`, {\n payload: this.UnknownSha,\n headers: {\n [HEADER_NAME_AUTHORIZATION]: this.jobToken,\n },\n });\n if (res.status !== 204) {\n throw new Error(`Unexpected status code: ${res.status}`);\n }\n }\n\n async sendMetrics(\n name: string,\n metricType: 'increment' | 'gauge',\n value: number,\n additionalTags: Record<string, string> = {},\n ): Promise<void> {\n try {\n await this.reportMetrics([\n {\n metric: `dependabot.action.${name}`,\n type: metricType,\n value,\n tags: additionalTags,\n },\n ]);\n logger.info(`Successfully sent metric (dependabot.action.${name}) to remote API endpoint`);\n } catch (error) {\n // metrics should typically not cause critical path failure so we log the\n // failure and continue with the job\n logger.warn(`Metrics reporting failed: ${(error as Error).message}`);\n }\n }\n\n async reportMetrics(metrics: DependabotMetric[]): Promise<void> {\n const res = await this.client.post(`/update_jobs/${this.params.jobId}/record_metrics`, {\n payload: { data: metrics },\n headers: {\n [HEADER_NAME_AUTHORIZATION]: this.jobToken,\n },\n });\n\n if (res.status !== 204) {\n throw new Error(`Unexpected status code: ${res.status}`);\n }\n }\n\n private async getWithRetry<T>(\n url: string,\n token: string,\n options?: Omit<InnerRequestOptions<T>, 'headers'>,\n ): Promise<ResourceResponse<T>> {\n let attempt = 1;\n const delayMs = 1000 * 2 ** attempt;\n\n const execute = async (): Promise<ResourceResponse<T>> => {\n try {\n const res = await this.client.get<T>(url, {\n headers: { Authorization: token },\n ...options,\n });\n\n // Check that the request was successful\n const { status, statusText } = res;\n if (status < 200 || status > 299) {\n throw new HttpRequestError(`HTTP GET '${url}' failed: ${status} ${statusText}`, status);\n }\n\n return res;\n } catch (e) {\n const error = e as Error;\n\n if (isErrorTemporaryFailure(error)) {\n if (attempt >= 3) throw error;\n logger.warn(`Retrying failed request in ${delayMs}ms...`);\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n\n attempt++;\n return execute();\n }\n throw error;\n }\n };\n\n return execute();\n }\n}\n","{\n \"proxy\": \"ghcr.io/github/dependabot-update-job-proxy/dependabot-update-job-proxy:v2.0.20251023141128@sha256:92726df9e09d44a60e73f86e973bb30ed271819f5c27b4cbe7ba0d929e6913e5\",\n \"bundler\": \"ghcr.io/dependabot/dependabot-updater-bundler:v2.0.20250916161401@sha256:cb1b48a4e2862bd9a2ebb1bb7f2eb1b28bd0099060925951618e07a96c191e5c\",\n \"cargo\": \"ghcr.io/dependabot/dependabot-updater-cargo:v2.0.20250916161401@sha256:dc8823384d8fd864f8b7867b553df3489b658b236e9bbfad49606c819d9bc450\",\n \"composer\": \"ghcr.io/dependabot/dependabot-updater-composer:v2.0.20250916161401@sha256:9d9304ed225f1ed0614d55d1c10398c93476cff6e295bb912816ed323d5ad0d0\",\n \"pub\": \"ghcr.io/dependabot/dependabot-updater-pub:v2.0.20250916161401@sha256:2955d6f1d77cc9ca12cf8e2fa5c919b3d5a79c403a2aad94550f2955e233a0c4\",\n \"docker\": \"ghcr.io/dependabot/dependabot-updater-docker:v2.0.20250916161401@sha256:411a5eb299308037ec396b51b0ecdb7f4ee3deeeb392202becc1a333a6dbab25\",\n \"elm\": \"ghcr.io/dependabot/dependabot-updater-elm:v2.0.20250916161401@sha256:67924991be2870fc9cf26bcb031146a46e4b9812173000b4e45acdb929fd0085\",\n \"github_actions\": \"ghcr.io/dependabot/dependabot-updater-github-actions:v2.0.20250916161401@sha256:675a96888497d8b47328ede0f2163722a90b901c7116e719830573c64b8c2465\",\n \"submodules\": \"ghcr.io/dependabot/dependabot-updater-gitsubmodule:v2.0.20250916161401@sha256:deae36a972cfc284dde6e8b6a923dbb81bc794b8c8a67ea652dcf7e71caab710\",\n \"go_modules\": \"ghcr.io/dependabot/dependabot-updater-gomod:v2.0.20250916161401@sha256:21bbf01be40bd53ccc6efd137aa309a1b895dcfab4eb62d85611d94806db8b58\",\n \"gradle\": \"ghcr.io/dependabot/dependabot-updater-gradle:v2.0.20250916161401@sha256:7482ff1cb4cf222a2a96741c8c506609eedc93f0e4cd7c38fe73e4a804413134\",\n \"maven\": \"ghcr.io/dependabot/dependabot-updater-maven:v2.0.20250916161401@sha256:b444c349e9ae8ec3bec9eef411ea830e8fa168c9ee0397e8c86eb140ea933167\",\n \"hex\": \"ghcr.io/dependabot/dependabot-updater-mix:v2.0.20250916161401@sha256:32b74d14082a0b89c9d8bcdde92a3d2b18f5798b6d9bcf2080855373c3f45c1f\",\n \"nuget\": \"ghcr.io/dependabot/dependabot-updater-nuget:v2.0.20250916161401@sha256:9fb516772dffa7a014c20a8dde909ccb25a323d7039a58346401a4500ce64657\",\n \"npm_and_yarn\": \"ghcr.io/dependabot/dependabot-updater-npm:v2.0.20250916161401@sha256:7d13ce84d26210659dbb5fd4b9c0d72b34786ca02063737cba5d228ad55af273\",\n \"pip\": \"ghcr.io/dependabot/dependabot-updater-pip:v2.0.20250916161401@sha256:a05999d53df5ea7141aafde806bd7e1a25dc23087528aea0b482a86363956937\",\n \"rust_toolchain\": \"ghcr.io/dependabot/dependabot-updater-rust-toolchain:v2.0.20250916161401@sha256:1688181ea18f1736ff80e6fe9bb17de3508b3ea890c20493e82cd9a68f6a5387\",\n \"swift\": \"ghcr.io/dependabot/dependabot-updater-swift:v2.0.20250916161401@sha256:622971aba7877711401d021bc0ecfeb98cbd39767b0c45dcf150b86536968743\",\n \"terraform\": \"ghcr.io/dependabot/dependabot-updater-terraform:v2.0.20250916161401@sha256:82c7cef04f54a20a6c47426f9ff48b7767757e715db5fa0a1b0357ced50bbf6c\",\n \"devcontainers\": \"ghcr.io/dependabot/dependabot-updater-devcontainers:v2.0.20250916161401@sha256:5691a9bec5b9c91879318323ed53d22d7c73c540376bb2e0d74704e9651e9897\",\n \"dotnet_sdk\": \"ghcr.io/dependabot/dependabot-updater-dotnet-sdk:v2.0.20250916161401@sha256:10febb67dbcdf4e50985412d65e1fd4a364f7402e184cfcd67b63d295a6c4e80\",\n \"bun\": \"ghcr.io/dependabot/dependabot-updater-bun:v2.0.20250915234339@sha256:fba1acd818ca0101f71ba34f04c8b7c36abf8e63de5feb05037b42f6406950fa\",\n \"docker_compose\": \"ghcr.io/dependabot/dependabot-updater-docker-compose:v2.0.20250916161401@sha256:a0fc653bedf0e600d85a3f7bc0eee7ec7bee99f6875d4faf6e30e2c69ea36dbe\",\n \"uv\": \"ghcr.io/dependabot/dependabot-updater-uv:v2.0.20250916161401@sha256:441fe91d1ed3ba9c148abe5dc3a3d83f12805326da5c037d76b86695c247c1cb\",\n \"vcpkg\": \"ghcr.io/dependabot/dependabot-updater-vcpkg:v2.0.20250916161401@sha256:40355d74ad784932730577475faee9f21ef863c3cec7b7d2817cc5621f3b1dd7\",\n \"helm\": \"ghcr.io/dependabot/dependabot-updater-helm:v2.0.20250916161401@sha256:42fe3e7a6bac84271dec7ec41ac0067ff7d1cffb8e5f63dbe5eec849b5bc433b\",\n \"julia\": \"ghcr.io/dependabot/dependabot-updater-julia:v2.0.20251023204638@sha256:49caaedd3e594c3056fa4f811ddc70da174a4d4dcd4726687ca626f844987d82\",\n \"bazel\": \"ghcr.io/dependabot/dependabot-updater-bazel:v2.0.20251027153627@sha256:ab86da3697ccff56c345c37d820ff72003ba242b41bf3309f44af08fd85aa538\"\n}","import dockerContainerConfig from '../../../dependabot-action/docker/containers.json';\n\nexport const PROXY_IMAGE_NAME = dockerContainerConfig.proxy;\n\nexport function updaterImageName(packageManager: string): string {\n return dockerContainerConfig[packageManager as keyof typeof dockerContainerConfig];\n}\n\nconst updaterRegex = /ghcr.io\\/dependabot\\/dependabot-updater-([\\w+])/;\n\nexport function updaterImages(): string[] {\n return Object.values(dockerContainerConfig).filter((image) => image.match(updaterRegex));\n}\n\nconst imageNamePattern =\n '^(?<repository>(([a-zA-Z0-9._-]+([:[0-9]+[^/]))?([a-zA-Z0-9._/-]+)?))(:[a-zA-Z0-9._/-]+)?(?<digest>@sha256:[a-zA-Z0-9]{64})?$';\n\nexport function repositoryName(imageName: string): string {\n const match = imageName.match(imageNamePattern);\n\n if (match?.groups) {\n return match.groups.repository!;\n } else {\n throw Error('invalid image name');\n }\n}\n\nexport function hasDigest(imageName: string): boolean {\n const match = imageName.match(imageNamePattern);\n\n if (match?.groups) {\n if (match?.groups.digest) {\n return true;\n }\n return false;\n } else {\n throw Error('invalid image name');\n }\n}\n\nexport function digestName(imageName: string): string {\n const match = imageName.match(imageNamePattern);\n\n if (match?.groups) {\n return match.groups.repository! + match.groups.digest;\n } else {\n throw Error('invalid image name');\n }\n}\n","import stream, { type Writable } from 'node:stream';\n\n// Code below is borrowed and adapted from dependabot-action\n\nexport const outStream = (prefix: string): Writable => {\n return new stream.Writable({\n write(chunk, _, next) {\n process.stderr.write(`${prefix} | ${chunk.toString()}`);\n next();\n },\n });\n};\n\nexport const errStream = (prefix: string): Writable => {\n return new stream.Writable({\n write(chunk, _, next) {\n process.stderr.write(`${prefix} | ${chunk.toString()}`);\n next();\n },\n });\n};\n\n/**\n * Extracts the SHA from an updater image string.\n * @param updaterImage - Image string in the format \"image:sha\" or \"registry/image:sha\"\n * @returns The SHA part after the last colon, or null if no colon is found\n */\nexport const extractUpdaterSha = (updaterImage: string): string | null => {\n const match = updaterImage.match(/:([^:]*)$/);\n return match ? match[1]! : null;\n};\n","import type { DependabotProxyConfig, FileFetcherInput, FileUpdaterInput } from '@paklo/core/dependabot';\nimport type { Container } from 'dockerode';\nimport { pack } from 'tar-stream';\nimport { logger } from '@/logger';\nimport { errStream, outStream } from './utils';\n\n// Code below is borrowed and adapted from dependabot-action\n\nexport class ContainerRuntimeError extends Error {}\n\nconst RWX_ALL = 0o777;\n\nexport const ContainerService = {\n async storeInput(\n name: string,\n path: string,\n container: Container,\n input: FileFetcherInput | FileUpdaterInput | DependabotProxyConfig,\n ): Promise<void> {\n const tar = pack();\n tar.entry({ name, mode: RWX_ALL }, JSON.stringify(input));\n tar.finalize();\n await container.putArchive(tar, { path });\n },\n\n async storeCert(name: string, path: string, container: Container, cert: string): Promise<void> {\n const tar = pack();\n tar.entry({ name }, cert);\n tar.finalize();\n await container.putArchive(tar, { path });\n },\n\n async run(container: Container, command?: string): Promise<boolean> {\n try {\n // Start the container\n await container.start();\n logger.info(`Started container ${container.id}`);\n\n // Check if this is a dependabot container (has the expected structure)\n const containerInfo = await container.inspect();\n const isDependabotContainer = containerInfo.Config?.Env?.some((env) => env.startsWith('DEPENDABOT_JOB_ID='));\n\n if (isDependabotContainer) {\n // For dependabot containers, run CA certificates update as root first\n await this.execCommand(container, ['/usr/sbin/update-ca-certificates'], 'root');\n\n // Then run the dependabot commands as dependabot user\n const dependabotCommands = [\n 'mkdir -p /home/dependabot/dependabot-updater/output',\n '$DEPENDABOT_HOME/dependabot-updater/bin/run fetch_files',\n ];\n\n if (command === 'graph') {\n dependabotCommands.push('$DEPENDABOT_HOME/dependabot-updater/bin/run update_graph');\n } else {\n dependabotCommands.push('$DEPENDABOT_HOME/dependabot-updater/bin/run update_files');\n }\n\n for (const cmd of dependabotCommands) {\n await this.execCommand(container, ['/bin/sh', '-c', cmd], 'dependabot');\n }\n } else {\n // For test containers and other containers, just wait for completion\n const outcome = await container.wait();\n if (outcome.StatusCode !== 0) {\n throw new Error(`Container exited with code ${outcome.StatusCode}`);\n }\n }\n\n return true;\n } catch (error) {\n logger.info(`Failure running container ${container.id}: ${error}`);\n throw new ContainerRuntimeError('The updater encountered one or more errors.');\n } finally {\n try {\n await container.remove({ v: true, force: true });\n logger.info(`Cleaned up container ${container.id}`);\n } catch (error) {\n logger.info(`Failed to clean up container ${container.id}: ${error}`);\n }\n }\n },\n\n async execCommand(container: Container, cmd: string[], user: string): Promise<void> {\n const exec = await container.exec({\n Cmd: cmd,\n User: user,\n AttachStdout: true,\n AttachStderr: true,\n });\n\n const stream = await exec.start({});\n\n // Wait for the stream to end\n await new Promise<void>((resolve, reject) => {\n container.modem.demuxStream(stream, outStream('updater'), errStream('updater'));\n\n stream.on('end', () => {\n resolve();\n });\n\n stream.on('error', (error) => {\n reject(error);\n });\n });\n\n // Wait a bit for the exec to complete properly\n await new Promise((resolve) => setTimeout(resolve, 100));\n\n const inspection = await exec.inspect();\n if (inspection.ExitCode !== 0) {\n throw new Error(`Command failed with exit code ${inspection.ExitCode}: ${cmd.join(' ')}`);\n }\n },\n};\n","import { Readable } from 'node:stream';\nimport Docker from 'dockerode';\n\nimport { logger } from '@/logger';\n\nconst MAX_RETRIES = 5; // Maximum number of retries\nconst INITIAL_DELAY_MS = 2000; // Initial delay in milliseconds for backoff\n\n// Code below is borrowed and adapted from dependabot-action\n\nconst sleep = async (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst endOfStream = async (docker: Docker, stream: Readable): Promise<void> => {\n return new Promise((resolve, reject) => {\n docker.modem.followProgress(stream, (err: Error | null) => (err ? reject(err) : resolve(undefined)));\n });\n};\n\nexport function getOrgFromImage(imageName: string): string {\n const parts = imageName.split('/');\n if (parts.length >= 3 && parts[0] === 'ghcr.io') {\n return parts[1]!; // The domain is always the second part\n }\n return 'unknown'; // Fallback case if structure is unexpected\n}\n\nexport type MetricReporter = (\n metricName: string,\n metricType: 'increment' | 'gauge',\n value: number,\n additionalTags?: Record<string, string>,\n) => Promise<void>;\n\n/** Fetch the configured updater image, if it isn't already available. */\nexport const ImageService = {\n async pull(imageName: string, sendMetric?: MetricReporter, force = false): Promise<void> {\n /*\n This method fetches images hosts on GitHub infrastructure.\n\n We expose the `fetch_image` utility method to allow us to pull in arbitrary images for unit tests.\n */\n if (!(imageName.startsWith('ghcr.io/') || imageName.startsWith('docker.pkg.github.com/'))) {\n throw new Error('Only images distributed via docker.pkg.github.com or ghcr.io can be fetched');\n }\n\n const docker = new Docker();\n const org = getOrgFromImage(imageName);\n try {\n const image = await docker.getImage(imageName).inspect();\n if (!force) {\n logger.info(`Resolved ${imageName} to existing ${image.RepoDigests}`);\n return;\n } // else fallthrough to pull\n } catch (e: unknown) {\n if (e instanceof Error && !e.message.includes('no such image')) {\n throw e;\n } // else fallthrough to pull\n }\n\n const auth = {}; // Images are public so not authentication info is required\n await this.fetchImageWithRetry(imageName, auth, docker, sendMetric, org);\n },\n\n /* Retrieve the image using the auth details provided, if any with retry and backoff */\n async fetchImageWithRetry(\n imageName: string,\n auth = {},\n docker = new Docker(),\n sendMetric: MetricReporter | undefined,\n org: string,\n ): Promise<void> {\n let attempt = 0;\n\n while (attempt < MAX_RETRIES) {\n try {\n logger.info(`Pulling image ${imageName} (attempt ${attempt + 1})...`);\n /* To avoid sending metrics during unit tests (fetch_image) */\n if (sendMetric) {\n await sendMetric('ghcr_image_pull', 'increment', 1, {\n org,\n });\n }\n const stream = await docker.pull(imageName, { authconfig: auth });\n await endOfStream(docker, new Readable().wrap(stream));\n logger.info(`Pulled image ${imageName}`);\n return; // Exit on success\n } catch (error) {\n if (!(error instanceof Error)) throw error; // Ensure error is an instance of Error\n\n // Handle 429 Too Many Requests separately\n if (\n error.message.includes('429 Too Many Requests') ||\n error.message.toLowerCase().includes('too many requests')\n ) {\n attempt++; // Only increment attempt on 429\n if (attempt >= MAX_RETRIES) {\n logger.error(`Failed to pull image ${imageName} after ${MAX_RETRIES} attempts.`);\n throw error;\n }\n\n // Add jitter to avoid synchronization issues\n // biome-ignore lint/style/useExponentiationOperator: This is clearer for now\n const baseDelay = INITIAL_DELAY_MS * Math.pow(2, attempt);\n const jitter = Math.random() * baseDelay;\n const delay = baseDelay / 2 + jitter;\n\n logger.warn(`Received Too Many Requests error. Retrying in ${(delay / 1000).toFixed(2)} seconds...`);\n await sleep(delay);\n } else {\n // Non-429 errors should NOT be retried\n logger.error(`Fatal error pulling image ${imageName}: ${error.message}`);\n throw error; // Exit immediately\n }\n }\n }\n },\n};\n","// Code below is borrowed and adapted from dependabot-action\n\nexport class JobParameters {\n constructor(\n readonly jobId: number,\n readonly jobToken: string,\n readonly credentialsToken: string,\n readonly dependabotApiUrl: string,\n readonly dependabotApiDockerUrl: string,\n readonly updaterImage: string,\n ) {}\n}\n\nexport function getJobParameters(input: {\n jobId?: string | number;\n jobToken?: string;\n credentialsToken?: string;\n dependabotApiUrl?: string;\n dependabotApiDockerUrl?: string;\n updaterImage?: string;\n}): JobParameters | null {\n return new JobParameters(\n parseInt(input.jobId as string, 10),\n input.jobToken as string,\n input.credentialsToken as string,\n input.dependabotApiUrl as string,\n input.dependabotApiDockerUrl as string,\n input.updaterImage as string,\n );\n}\n","import { readFile } from 'node:fs/promises';\nimport type { CertificateAuthority, DependabotCredential, DependabotProxyConfig } from '@paklo/core/dependabot';\nimport type Docker from 'dockerode';\nimport type { Container, Network } from 'dockerode';\nimport { logger } from '@/logger';\nimport { ContainerService } from './container-service';\nimport { errStream, outStream } from './utils';\n\n// Code below is borrowed and adapted from dependabot-action\n\nexport type Proxy = {\n container: Container;\n network: Network;\n networkName: string;\n url: () => Promise<string>;\n cert: string;\n shutdown: () => Promise<void>;\n};\n\nconst KEY_SIZE = 2048;\nconst KEY_EXPIRY_YEARS = 2;\nconst CONFIG_FILE_PATH = '/';\nconst CONFIG_FILE_NAME = 'config.json';\nconst CA_CERT_INPUT_PATH = '/usr/local/share/ca-certificates';\nconst CUSTOM_CA_CERT_NAME = 'custom-ca-cert.crt';\nconst CERT_SUBJECT = [\n { name: 'commonName', value: 'Dependabot Internal CA' },\n { name: 'organizationName', value: 'GitHub Inc.' },\n { shortName: 'OU', value: 'Dependabot' },\n { name: 'countryName', value: 'US' },\n { shortName: 'ST', value: 'California' },\n { name: 'localityName', value: 'San Francisco' },\n];\n\nexport class ProxyBuilder {\n constructor(\n private readonly docker: Docker,\n private readonly proxyImage: string,\n private readonly cachedMode: boolean,\n ) {}\n\n async run(\n jobId: number,\n jobToken: string,\n dependabotApiUrl: string,\n credentials: DependabotCredential[],\n ): Promise<Proxy> {\n const name = `dependabot-job-${jobId}-proxy`;\n const config = await this.buildProxyConfig(credentials);\n const cert = config.ca.cert;\n\n const externalNetworkName = `dependabot-job-${jobId}-external-network`;\n const externalNetwork = await this.ensureNetwork(externalNetworkName, false);\n\n const internalNetworkName = `dependabot-job-${jobId}-internal-network`;\n const internalNetwork = await this.ensureNetwork(internalNetworkName, true);\n\n const container = await this.createContainer(\n jobId,\n jobToken,\n dependabotApiUrl,\n name,\n externalNetwork,\n internalNetwork,\n internalNetworkName,\n );\n\n await ContainerService.storeInput(CONFIG_FILE_NAME, CONFIG_FILE_PATH, container, config);\n\n const customCAPath = this.customCAPath();\n if (customCAPath) {\n logger.info('Detected custom CA certificate, adding to proxy');\n\n const customCert = (await readFile(customCAPath, 'utf8')).toString();\n await ContainerService.storeCert(CUSTOM_CA_CERT_NAME, CA_CERT_INPUT_PATH, container, customCert);\n }\n\n const stream = await container.attach({\n stream: true,\n stdout: true,\n stderr: true,\n });\n container.modem.demuxStream(stream, outStream(' proxy'), errStream(' proxy'));\n\n const url = async (): Promise<string> => {\n const containerInfo = await container.inspect();\n\n if (containerInfo.State.Running === true) {\n const ipAddress = containerInfo.NetworkSettings.Networks[`${internalNetworkName}`]!.IPAddress;\n return `http://${ipAddress}:1080`;\n } else {\n throw new Error(\"proxy container isn't running\");\n }\n };\n\n return {\n container,\n network: internalNetwork,\n networkName: internalNetworkName,\n url,\n cert,\n shutdown: async () => {\n await container.stop();\n await container.remove();\n await Promise.all([externalNetwork.remove(), internalNetwork.remove()]);\n },\n };\n }\n\n private async ensureNetwork(name: string, internal = true): Promise<Network> {\n const networks = await this.docker.listNetworks({\n filters: JSON.stringify({ name: [name] }),\n });\n if (networks.length > 0) {\n return this.docker.getNetwork(networks[0]!.Id);\n } else {\n return await this.docker.createNetwork({ Name: name, Internal: internal });\n }\n }\n\n private async buildProxyConfig(credentials: DependabotCredential[]): Promise<DependabotProxyConfig> {\n const ca = await this.generateCertificateAuthority();\n\n const config: DependabotProxyConfig = { all_credentials: credentials, ca };\n\n return config;\n }\n\n private async generateCertificateAuthority(): Promise<CertificateAuthority> {\n // node-forge is a CommonJS module, so we need to import it dynamically\n const {\n default: { md, pki },\n } = await import('node-forge');\n const keys = pki.rsa.generateKeyPair(KEY_SIZE);\n const cert = pki.createCertificate();\n\n cert.publicKey = keys.publicKey;\n cert.serialNumber = '01';\n cert.validity.notBefore = new Date();\n cert.validity.notAfter = new Date();\n cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + KEY_EXPIRY_YEARS);\n\n cert.setSubject(CERT_SUBJECT);\n cert.setIssuer(CERT_SUBJECT);\n\n cert.setExtensions([\n {\n name: 'basicConstraints',\n cA: true,\n critical: true,\n },\n {\n name: 'keyUsage',\n digitalSignature: true,\n keyEncipherment: true,\n keyCertSign: true,\n cRLSign: true,\n critical: true,\n },\n {\n name: 'extKeyUsage',\n serverAuth: true,\n clientAuth: true,\n },\n {\n name: 'subjectKeyIdentifier',\n },\n {\n name: 'authorityKeyIdentifier',\n keyIdentifier: true,\n authorityCertIssuer: true,\n authorityCertSerialNumber: cert.serialNumber,\n },\n ]);\n\n cert.sign(keys.privateKey, md.sha256.create());\n\n const pem = pki.certificateToPem(cert);\n const key = pki.privateKeyToPem(keys.privateKey);\n return { cert: pem, key };\n }\n\n private async createContainer(\n jobId: number,\n jobToken: string,\n dependabotApiUrl: string,\n containerName: string,\n externalNetwork: Network,\n internalNetwork: Network,\n internalNetworkName: string,\n ): Promise<Container> {\n const container = await this.docker.createContainer({\n Image: this.proxyImage,\n name: containerName,\n AttachStdout: true,\n AttachStderr: true,\n Env: [\n `http_proxy=${process.env.http_proxy || process.env.HTTP_PROXY || ''}`,\n `https_proxy=${process.env.https_proxy || process.env.HTTPS_PROXY || ''}`,\n `no_proxy=${process.env.no_proxy || process.env.NO_PROXY || ''}`,\n `JOB_ID=${jobId}`,\n `JOB_TOKEN=${jobToken}`,\n `PROXY_CACHE=${this.cachedMode ? 'true' : 'false'}`,\n `DEPENDABOT_API_URL=${dependabotApiUrl}`,\n `ACTIONS_ID_TOKEN_REQUEST_TOKEN=${process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN || ''}`,\n `ACTIONS_ID_TOKEN_REQUEST_URL=${process.env.ACTIONS_ID_TOKEN_REQUEST_URL || ''}`,\n ],\n Entrypoint: ['sh', '-c', '/usr/sbin/update-ca-certificates && /update-job-proxy'],\n\n HostConfig: {\n NetworkMode: internalNetworkName,\n ExtraHosts: ['host.docker.internal:host-gateway'], // needed for Docker on Linux\n },\n });\n\n await externalNetwork.connect({ Container: container.id });\n\n logger.info(`Created proxy container: ${container.id}`);\n return container;\n }\n\n private customCAPath(): string | undefined {\n if ('CUSTOM_CA_PATH' in process.env) {\n return process.env.CUSTOM_CA_PATH;\n }\n // default to node.js configuration\n return process.env.NODE_EXTRA_CA_CERTS;\n }\n}\n","{\n \"name\": \"@paklo/runner\",\n \"version\": \"0.2.3\",\n \"sideEffects\": false,\n \"type\": \"module\",\n \"author\": \"mburumaxwell\",\n \"license\": \"AGPL-3.0-later\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.mts\",\n \"import\": \"./dist/index.mjs\"\n },\n \"./local\": {\n \"types\": \"./dist/local/index.d.mts\",\n \"import\": \"./dist/local/index.mjs\"\n },\n \"./local/azure\": {\n \"types\": \"./dist/local/azure/index.d.mts\",\n \"import\": \"./dist/local/azure/index.mjs\"\n }\n },\n \"files\": [\n \"dist\",\n \"package.json\"\n ],\n \"scripts\": {\n \"dev\": \"tsdown --watch\",\n \"prebuild\": \"tsc\",\n \"build\": \"tsdown\",\n \"lint\": \"biome check\",\n \"test\": \"vitest\",\n \"clean\": \"rimraf .turbo dist\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/mburumaxwell/dependabot-azure-devops.git\",\n \"directory\": \"packages/runner\"\n },\n \"keywords\": [\n \"dependabot\",\n \"azure\",\n \"devops\",\n \"paklo\"\n ],\n \"bugs\": {\n \"url\": \"https://github.com/mburumaxwell/dependabot-azure-devops/issues\"\n },\n \"homepage\": \"https://github.com/mburumaxwell/dependabot-azure-devops#readme\",\n \"dependencies\": {\n \"@hono/node-server\": \"1.19.6\",\n \"@paklo/core\": \"workspace:*\",\n \"dockerode\": \"4.0.9\",\n \"node-forge\": \"1.3.1\",\n \"tar-stream\": \"3.1.7\"\n },\n \"devDependencies\": {\n \"@types/dockerode\": \"3.3.45\",\n \"@types/node\": \"24.10.0\",\n \"@types/node-forge\": \"1.3.14\",\n \"@types/tar-stream\": \"3.1.4\",\n \"tsdown\": \"0.16.1\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","// biome-ignore-all lint/suspicious/noShadowRestrictedNames: Proxy is okay\n\nimport type { FileFetcherInput, FileUpdaterInput } from '@paklo/core/dependabot';\nimport type Docker from 'dockerode';\nimport type { Container } from 'dockerode';\nimport { logger } from '@/logger';\nimport { ContainerService } from './container-service';\nimport type { JobParameters } from './params';\nimport type { Proxy } from './proxy';\nimport { extractUpdaterSha } from './utils';\n\nconst JOB_OUTPUT_FILENAME = 'output.json';\nconst JOB_OUTPUT_PATH = '/home/dependabot/dependabot-updater/output';\nconst JOB_INPUT_FILENAME = 'job.json';\nconst JOB_INPUT_PATH = `/home/dependabot/dependabot-updater`;\nconst REPO_CONTENTS_PATH = '/home/dependabot/dependabot-updater/repo';\nconst CA_CERT_INPUT_PATH = '/usr/local/share/ca-certificates';\nconst CA_CERT_FILENAME = 'dbot-ca.crt';\nconst UPDATER_MAX_MEMORY = 8 * 1024 * 1024 * 1024; // 8GB in bytes\n\n// Code below is borrowed and adapted from dependabot-action\n\nexport class UpdaterBuilder {\n constructor(\n private readonly docker: Docker,\n private readonly jobParams: JobParameters,\n private readonly input: FileFetcherInput | FileUpdaterInput,\n private readonly proxy: Proxy,\n\n private readonly updaterImage: string,\n ) {}\n\n async run(containerName: string): Promise<Container> {\n const proxyUrl = await this.proxy.url();\n const updaterSha = extractUpdaterSha(this.updaterImage);\n\n const envVars = [\n `GITHUB_ACTIONS=${process.env.GITHUB_ACTIONS}`,\n `DEPENDABOT_JOB_ID=${this.jobParams.jobId}`,\n `DEPENDABOT_JOB_TOKEN=`,\n `DEPENDABOT_JOB_PATH=${JOB_INPUT_PATH}/${JOB_INPUT_FILENAME}`,\n `DEPENDABOT_OPEN_TIMEOUT_IN_SECONDS=15`,\n `DEPENDABOT_OUTPUT_PATH=${JOB_OUTPUT_PATH}/${JOB_OUTPUT_FILENAME}`,\n `DEPENDABOT_REPO_CONTENTS_PATH=${REPO_CONTENTS_PATH}`,\n `DEPENDABOT_API_URL=${this.jobParams.dependabotApiDockerUrl}`,\n `SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt`,\n `http_proxy=${proxyUrl}`,\n `HTTP_PROXY=${proxyUrl}`,\n `https_proxy=${proxyUrl}`,\n `HTTPS_PROXY=${proxyUrl}`,\n `UPDATER_ONE_CONTAINER=1`,\n `ENABLE_CONNECTIVITY_CHECK=${process.env.DEPENDABOT_ENABLE_CONNECTIVITY_CHECK || '1'}`,\n\n // for updates relying on .NET (e.g. NuGet) and running on macOS (e.g. dev laptop or local MacMini),\n // we need to disable WriteXorExecute to avoid issues with emulation of Linux containers on macOS hosts\n // with Apple Silicon (M1/M2) chips\n // See - https://github.com/dotnet/runtime/issues/103063#issuecomment-2149599940\n // - https://github.com/dependabot/dependabot-core/issues/5037\n ...(process.platform === 'darwin' ? [`DOTNET_EnableWriteXorExecute=0`] : []),\n ];\n\n // Add DEPENDABOT_UPDATER_SHA if we successfully extracted a SHA\n if (updaterSha !== null) {\n envVars.push(`DEPENDABOT_UPDATER_SHA=${updaterSha}`);\n }\n\n const container = await this.docker.createContainer({\n Image: this.updaterImage,\n name: containerName,\n AttachStdout: true,\n AttachStderr: true,\n User: 'dependabot',\n Env: envVars,\n Cmd: ['/bin/sh'],\n Tty: true,\n HostConfig: {\n Memory: UPDATER_MAX_MEMORY,\n NetworkMode: this.proxy.networkName,\n },\n });\n\n await ContainerService.storeCert(CA_CERT_FILENAME, CA_CERT_INPUT_PATH, container, this.proxy.cert);\n\n await ContainerService.storeInput(JOB_INPUT_FILENAME, JOB_INPUT_PATH, container, this.input);\n\n logger.info(`Created container: ${container.id}`);\n return container;\n }\n}\n","// biome-ignore-all lint/suspicious/noShadowRestrictedNames: Proxy is okay\n\nimport type {\n DependabotCredential,\n DependabotJobConfig,\n FileFetcherInput,\n FileUpdaterInput,\n} from '@paklo/core/dependabot';\nimport Docker, { type Container } from 'dockerode';\nimport { ContainerService } from './container-service';\nimport type { JobParameters } from './params';\nimport { type Proxy, ProxyBuilder } from './proxy';\nimport { UpdaterBuilder } from './updater-builder';\n\n// Code below is borrowed and adapted from dependabot-action\n\nexport class Updater {\n docker: Docker;\n\n constructor(\n private readonly updaterImage: string,\n private readonly proxyImage: string,\n private readonly params: JobParameters,\n private readonly job: DependabotJobConfig,\n private readonly credentials: DependabotCredential[],\n ) {\n this.docker = new Docker();\n this.job['credentials-metadata'] = this.generateCredentialsMetadata();\n }\n\n /**\n * Execute an update job and report the result to Dependabot API.\n */\n async runUpdater(): Promise<boolean> {\n const cachedMode = Object.hasOwn(this.job.experiments, 'proxy-cached') === true;\n\n const proxyBuilder = new ProxyBuilder(this.docker, this.proxyImage, cachedMode);\n\n const proxy = await proxyBuilder.run(\n this.params.jobId,\n this.params.jobToken,\n this.params.dependabotApiUrl,\n this.credentials,\n );\n await proxy.container.start();\n\n try {\n await this.runUpdate(proxy);\n return true;\n } finally {\n await this.cleanup(proxy);\n }\n }\n\n private generateCredentialsMetadata(): DependabotCredential[] {\n const unique: Set<string> = new Set();\n const result: DependabotCredential[] = [];\n for (const credential of this.credentials) {\n if (credential.type === 'jit_access') {\n continue;\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: necessary\n const obj: any = { type: credential.type };\n if (credential.host !== undefined) {\n obj.host = credential.host;\n }\n if (credential.registry !== undefined) {\n obj.registry = credential.registry;\n }\n if (credential.url !== undefined) {\n obj.url = credential.url;\n }\n this.setRegistryFromUrl(obj, credential);\n if (credential['index-url'] !== undefined) {\n obj['index-url'] = credential['index-url'];\n }\n this.setIndexUrlFromUrl(obj, credential);\n if (credential['env-key'] !== undefined) {\n obj['env-key'] = credential['env-key'];\n }\n if (credential.organization !== undefined) {\n obj.organization = credential.organization;\n }\n if (credential['replaces-base'] !== undefined) {\n obj['replaces-base'] = credential['replaces-base'];\n }\n if (credential['public-key-fingerprint'] !== undefined) {\n obj['public-key-fingerprint'] = credential['public-key-fingerprint'];\n }\n if (credential.repo !== undefined) {\n obj.repo = credential.repo;\n }\n const key = JSON.stringify(obj);\n if (!unique.has(key)) {\n unique.add(key);\n result.push(obj as DependabotCredential);\n }\n }\n return result;\n }\n\n private setRegistryFromUrl(obj: DependabotCredential, credential: DependabotCredential): void {\n const typesThatUseRegistryAsHost = ['npm_registry', 'composer_repository', 'docker_registry'];\n\n if (!typesThatUseRegistryAsHost.includes(credential.type)) {\n return;\n }\n\n if (!credential.registry && credential.url) {\n try {\n const parsedURL = new URL(credential.url);\n obj.registry = parsedURL.hostname;\n if (credential.type === 'npm_registry') {\n obj.registry += parsedURL.pathname;\n }\n } catch {\n // If the URL is invalid, we skip setting the registry\n // as it will fall back to the default registry for the given type (e.g., npm, Docker, or Composer).\n }\n }\n }\n\n private setIndexUrlFromUrl(obj: DependabotCredential, credential: DependabotCredential): void {\n if (credential.type !== 'python_index') {\n return;\n }\n if (credential['index-url']) {\n return;\n }\n if (credential.url) {\n try {\n obj['index-url'] = credential.url;\n } catch {\n // If the URL is invalid, we skip setting the index-url\n // as it will fall back to the default index URL for pip.\n }\n }\n }\n\n private async runUpdate(proxy: Proxy): Promise<void> {\n const name = `dependabot-job-${this.params.jobId}`;\n const container = await this.createContainer(proxy, name, {\n job: this.job,\n });\n\n await ContainerService.run(container, this.job.command);\n }\n\n private async createContainer(\n proxy: Proxy,\n containerName: string,\n input: FileFetcherInput | FileUpdaterInput,\n ): Promise<Container> {\n const builder = new UpdaterBuilder(this.docker, this.params, input, proxy, this.updaterImage);\n return builder.run(containerName);\n }\n\n private async cleanup(proxy: Proxy): Promise<void> {\n await proxy.shutdown();\n }\n}\n","import crypto from 'node:crypto';\nimport os from 'node:os';\n\nimport { InnerApiClient } from '@paklo/core/http';\nimport type { UsageTelemetryRequestData } from '@paklo/core/usage';\nimport { logger } from '@/logger';\nimport packageJson from '../package.json';\nimport { ApiClient, CredentialFetchingError, type SecretMasker } from './api-client';\nimport { PROXY_IMAGE_NAME, updaterImageName } from './docker-tags';\nimport { ImageService, type MetricReporter } from './image-service';\nimport { getJobParameters } from './params';\nimport { Updater } from './updater';\n\nexport class JobRunnerImagingError extends Error {}\nexport class JobRunnerUpdaterError extends Error {}\n\nexport type RunJobOptions = {\n dependabotApiUrl: string;\n dependabotApiDockerUrl?: string;\n jobId: number;\n jobToken: string;\n credentialsToken: string;\n updaterImage?: string;\n secretMasker: SecretMasker;\n usage: Pick<UsageTelemetryRequestData, 'trigger' | 'provider' | 'owner' | 'project' | 'package-manager'>;\n};\nexport type RunJobResult = { success: true; message?: string } | { success: false; message: string };\n\nexport async function runJob(options: RunJobOptions): Promise<RunJobResult> {\n const { jobId, dependabotApiUrl, dependabotApiDockerUrl, jobToken, credentialsToken, secretMasker, usage } = options;\n\n const started = new Date();\n let success = false;\n let message: string | undefined;\n try {\n const params = getJobParameters({\n jobId,\n jobToken,\n credentialsToken,\n dependabotApiUrl,\n dependabotApiDockerUrl: dependabotApiDockerUrl ?? dependabotApiUrl,\n updaterImage: options.updaterImage,\n })!;\n\n // if dependabotApiUrl contains \"host.docker.internal\", we need to replace it with \"localhost\" for local calls\n const baseUrl = dependabotApiUrl.replace('host.docker.internal', 'localhost');\n const client = new InnerApiClient({ baseUrl });\n const apiClient = new ApiClient(client, params, jobToken, credentialsToken, secretMasker);\n\n // If we fail to succeed in fetching the job details, we cannot be sure the job has entered a 'processing' state,\n // so we do not try attempt to report back an exception if this fails and instead rely on the workflow run\n // webhook as it anticipates scenarios where jobs have failed while 'enqueued'.\n const job = await apiClient.getJobDetails();\n\n // The params can specify which updater image to use. If it doesn't, fall back to the pinned version.\n const updaterImage = params.updaterImage || updaterImageName(job['package-manager']);\n\n // The sendMetrics function is used to send metrics to the API client.\n // It uses the package manager as a tag to identify the metric.\n const sendMetricsWithPackageManager: MetricReporter = async (name, metricType, value, additionalTags = {}) => {\n try {\n await apiClient.sendMetrics(name, metricType, value, {\n package_manager: job['package-manager'],\n ...additionalTags,\n });\n } catch (error) {\n logger.warn(`Metric sending failed for ${name}: ${(error as Error).message}`);\n }\n };\n\n const credentials = (await apiClient.getCredentials()) || [];\n\n const updater = new Updater(updaterImage, PROXY_IMAGE_NAME, params, job, credentials);\n\n try {\n // Using sendMetricsWithPackageManager wrapper to inject package manager tag to\n // avoid passing additional parameters to ImageService.pull method\n await ImageService.pull(updaterImage, sendMetricsWithPackageManager);\n await ImageService.pull(PROXY_IMAGE_NAME, sendMetricsWithPackageManager);\n } catch (err: unknown) {\n if (err instanceof Error) {\n throw new JobRunnerImagingError(err.message);\n }\n }\n\n try {\n await updater.runUpdater();\n } catch (err: unknown) {\n if (err instanceof Error) {\n throw new JobRunnerUpdaterError(err.message);\n }\n }\n success = true;\n } catch (err) {\n if (err instanceof JobRunnerImagingError) {\n message = `Error fetching updater images: ${err.message}`;\n } else if (err instanceof JobRunnerUpdaterError) {\n message = `Error running updater: ${err.message}`;\n } else if (err instanceof CredentialFetchingError) {\n message = `Dependabot was unable to retrieve job credentials: ${err.message}`;\n } else {\n message = `Unknown error: ${(err as Error).message}`;\n }\n }\n\n const duration = Date.now() - started.getTime();\n const data: UsageTelemetryRequestData = {\n ...usage,\n host: {\n platform: os.platform(),\n release: os.release(),\n arch: os.arch(),\n 'machine-hash': crypto.createHash('sha256').update(os.hostname()).digest('hex'),\n },\n version: packageJson.version,\n id: jobId,\n started,\n duration,\n success,\n };\n try {\n const json = JSON.stringify(data);\n logger.debug(`Usage telemetry data: ${json}`);\n const resp = await fetch('https://www.paklo.app/api/usage-telemetry', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: json,\n });\n if (!resp.ok) {\n logger.debug(`Failed to send usage telemetry data: ${resp.status} ${resp.statusText}`);\n }\n } catch (err) {\n logger.debug(`Failed to send usage telemetry data: ${(err as Error).message}`);\n // ignore\n }\n\n logger.info(`Update job ${jobId} completed`);\n return { success, message: message! };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server-0h2jXnjg.mjs","names":[],"sources":["../src/local/runner.ts","../src/local/server.ts"],"sourcesContent":["import type { DependabotConfig, DependabotExperiments, DependabotJobConfig } from '@paklo/core/dependabot';\nimport { generateKey } from '@paklo/core/keygen';\nimport type { SecretMasker } from '../api-client';\n\nexport type RunJobsResult = { id: number; success: boolean; message?: string; affectedPrs: number[] }[];\n\nexport type LocalJobsRunnerOptions = {\n jobTokenOverride?: string;\n credentialsTokenOverride?: string;\n secretMasker: SecretMasker;\n\n config: DependabotConfig;\n targetUpdateIds?: number[];\n experiments: DependabotExperiments;\n updaterImage?: string;\n command?: DependabotJobConfig['command'];\n};\n\nexport abstract class LocalJobsRunner {\n private readonly opt: LocalJobsRunnerOptions;\n\n constructor(options: LocalJobsRunnerOptions) {\n this.opt = options;\n }\n\n protected makeTokens() {\n const { jobTokenOverride, credentialsTokenOverride } = this.opt;\n return {\n jobToken: jobTokenOverride ?? generateKey(),\n credentialsToken: credentialsTokenOverride ?? generateKey(),\n };\n }\n\n public run(): Promise<RunJobsResult> {\n return Promise.resolve([{ id: -1, success: false, affectedPrs: [] }]);\n }\n}\n","import type { AddressInfo } from 'node:net';\nimport { createAdaptorServer } from '@hono/node-server';\nimport {\n type CreateApiServerAppOptions,\n createApiServerApp,\n type DependabotCredential,\n type DependabotJobConfig,\n type DependabotRequest,\n type DependabotTokenType,\n type DependabotUpdate,\n type GitAuthor,\n} from '@paklo/core/dependabot';\nimport { logger } from '@/logger';\n\nexport type LocalDependabotServerAddOptions = {\n /** The ID of the dependabot job. */\n id: number;\n /** The dependabot update associated with the job. */\n update: DependabotUpdate;\n /** The dependabot job configuration. */\n job: DependabotJobConfig;\n /** The authentication token for the job. */\n jobToken: string;\n /** The authentication token for the job. */\n credentialsToken: string;\n /** The credentials associated with the job. */\n credentials: DependabotCredential[];\n};\n\nexport type AffectedPullRequestIds = {\n created: number[];\n updated: number[];\n closed: number[];\n};\n\nexport type LocalDependabotServerOptions = Omit<\n CreateApiServerAppOptions,\n 'authenticate' | 'getJob' | 'getCredentials' | 'handle'\n> & {\n author: GitAuthor;\n debug: boolean;\n dryRun: boolean;\n};\nexport abstract class LocalDependabotServer {\n private readonly hostname = 'localhost';\n private readonly server: ReturnType<typeof createAdaptorServer>;\n private readonly trackedJobs = new Map<number, DependabotJobConfig>();\n private readonly updates = new Map<number, DependabotUpdate>();\n private readonly jobTokens = new Map<number, string>();\n private readonly credentialTokens = new Map<number, string>();\n private readonly jobCredentials = new Map<number, DependabotCredential[]>();\n private readonly receivedRequests = new Map<number, DependabotRequest[]>();\n\n protected readonly affectedPullRequestIds = new Map<number, AffectedPullRequestIds>();\n\n constructor(options: LocalDependabotServerOptions) {\n const app = createApiServerApp({\n ...options,\n authenticate: this.authenticate.bind(this),\n getJob: this.job.bind(this),\n getCredentials: this.credentials.bind(this),\n handle: this.handle.bind(this),\n });\n this.server = createAdaptorServer({\n ...app,\n // Workaround for hono not respecting x-forwarded-proto header\n // https://github.com/honojs/node-server/issues/146#issuecomment-3153435672\n fetch: (req) => {\n const url = new URL(req.url);\n url.protocol = req.headers.get('x-forwarded-proto') ?? url.protocol;\n return app.fetch(new Request(url, req));\n },\n });\n }\n\n start(port?: number) {\n // listening to 'localhost' will result to IpV6 only but we need it to be all local\n // interfaces, otherwise containers cannot reach it using host.docker.internal\n this.server.listen(port, '0.0.0.0', () => {\n const info = this.server.address() as AddressInfo;\n logger.info(`API server listening on http://${this.hostname}:${info.port}`);\n });\n }\n\n stop() {\n this.server.close(() => logger.info('API server closed'));\n }\n\n get url() {\n const info = this.server.address() as AddressInfo;\n return `http://${this.hostname}:${info.port}`;\n }\n\n get port() {\n const info = this.server.address() as AddressInfo;\n return info.port;\n }\n\n get jobs() {\n return this.trackedJobs;\n }\n\n /**\n * Adds a dependabot job.\n * @param value - The dependabot job details.\n */\n add(value: LocalDependabotServerAddOptions) {\n const { id, update, job, jobToken, credentialsToken, credentials } = value;\n const {\n trackedJobs,\n updates,\n jobTokens,\n credentialTokens,\n jobCredentials,\n receivedRequests,\n affectedPullRequestIds,\n } = this;\n trackedJobs.set(id, job);\n updates.set(id, update);\n jobTokens.set(id, jobToken);\n credentialTokens.set(id, credentialsToken);\n jobCredentials.set(id, credentials);\n receivedRequests.set(id, []);\n affectedPullRequestIds.set(id, { created: [], updated: [], closed: [] });\n }\n\n /**\n * Gets a dependabot job by ID.\n * @param id - The ID of the dependabot job to get.\n * @returns The dependabot job, or undefined if not found.\n */\n job(id: number): Promise<DependabotJobConfig | undefined> {\n return Promise.resolve(this.trackedJobs.get(id));\n }\n\n /**\n * Gets a dependabot update by ID of the job.\n * @param id - The ID of the dependabot job to get.\n * @returns The dependabot update, or undefined if not found.\n */\n update(id: number): DependabotUpdate | undefined {\n return this.updates.get(id);\n }\n\n /**\n * Gets a token by ID of the job.\n * @param id - The ID of the dependabot job to get.\n * @returns The job token, or undefined if not found.\n */\n token(id: number, type: DependabotTokenType): string | undefined {\n return type === 'job' ? this.jobTokens.get(id) : this.credentialTokens.get(id);\n }\n\n /**\n * Gets the credentials for a dependabot job by ID.\n * @param id - The ID of the dependabot job to get credentials for.\n * @returns The credentials for the job, or undefined if not found.\n */\n credentials(id: number): Promise<DependabotCredential[] | undefined> {\n return Promise.resolve(this.jobCredentials.get(id));\n }\n\n /**\n * Gets the received requests for a dependabot job by ID.\n * @param id - The ID of the dependabot job to get requests for.\n * @returns The received requests for the job, or undefined if not found.\n */\n requests(id: number): DependabotRequest[] | undefined {\n return this.receivedRequests.get(id);\n }\n\n /**\n * Gets the IDs of pull requests affected by a dependabot job by ID.\n * @param id - The ID of the dependabot job to get affected pull request IDs for.\n * @returns The affected pull request IDs for the job, or undefined if not found.\n */\n affectedPrs(id: number): AffectedPullRequestIds | undefined {\n const { affectedPullRequestIds } = this;\n return affectedPullRequestIds.get(id);\n }\n\n /**\n * Gets all IDs of pull requests affected by a dependabot job by ID.\n * @param id - The ID of the dependabot job to get affected pull request IDs for.\n * @returns The affected pull request IDs for the job, or undefined if not found.\n */\n allAffectedPrs(id: number): number[] {\n const affected = this.affectedPrs(id);\n if (!affected) return [];\n return [...affected.created, ...affected.updated, ...affected.closed];\n }\n\n /**\n * Clears all data associated with a dependabot job by ID.\n * This should be called when the job is no longer needed.\n * @param id - The ID of the dependabot job to clear.\n */\n clear(id: number) {\n this.trackedJobs.delete(id);\n this.updates.delete(id);\n this.jobTokens.delete(id);\n this.credentialTokens.delete(id);\n this.jobCredentials.delete(id);\n this.receivedRequests.delete(id);\n this.affectedPullRequestIds.delete(id);\n }\n\n /**\n * Authenticates a dependabot job.\n * @param id - The ID of the dependabot job.\n * @param value - The authentication value (e.g., API key).\n * @returns A promise that resolves to a boolean indicating whether the authentication was successful.\n */\n protected async authenticate(type: DependabotTokenType, id: number, value: string): Promise<boolean> {\n const token = type === 'job' ? this.jobTokens.get(id) : this.credentialTokens.get(id);\n if (!token) {\n logger.debug(`Authentication failed: ${type} token ${id} not found`);\n return false;\n }\n if (token !== value) {\n logger.debug(`Authentication failed: invalid token for ${type} token ${id}`);\n return false;\n }\n return true;\n }\n\n /**\n * Handles a dependabot request.\n * @param id - The ID of the dependabot job.\n * @param request - The dependabot request to handle.\n * @returns A promise that resolves to the result of handling the request.\n */\n protected handle(id: number, request: DependabotRequest): Promise<boolean> {\n this.receivedRequests.get(id)!.push(request);\n return Promise.resolve(true);\n }\n}\n"],"mappings":"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"}
|