renovate 44.99.0 → 44.101.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/modules/manager/bun/artifacts.js +25 -22
- package/dist/modules/manager/bun/artifacts.js.map +1 -1
- package/dist/modules/manager/deno/artifacts.js +38 -35
- package/dist/modules/manager/deno/artifacts.js.map +1 -1
- package/dist/modules/manager/devbox/artifacts.js +6 -6
- package/dist/modules/manager/devbox/artifacts.js.map +1 -1
- package/dist/modules/manager/dockerfile/apk.js +3 -65
- package/dist/modules/manager/dockerfile/apk.js.map +1 -1
- package/dist/modules/manager/dockerfile/deb.js +108 -0
- package/dist/modules/manager/dockerfile/deb.js.map +1 -0
- package/dist/modules/manager/dockerfile/extract.js +2 -1
- package/dist/modules/manager/dockerfile/extract.js.map +1 -1
- package/dist/modules/manager/dockerfile/index.js +6 -1
- package/dist/modules/manager/dockerfile/index.js.map +1 -1
- package/dist/modules/manager/dockerfile/run-command.js +92 -0
- package/dist/modules/manager/dockerfile/run-command.js.map +1 -0
- package/dist/modules/manager/fingerprint.generated.js +3 -3
- package/dist/modules/manager/fingerprint.generated.js.map +1 -1
- package/dist/modules/manager/npm/artifacts.js +20 -22
- package/dist/modules/manager/npm/artifacts.js.map +1 -1
- package/dist/modules/manager/npm/post-update/index.js +113 -116
- package/dist/modules/manager/npm/post-update/index.js.map +1 -1
- package/dist/modules/manager/npm/utils.js +15 -1
- package/dist/modules/manager/npm/utils.js.map +1 -1
- package/dist/modules/manager/types.d.ts +6 -2
- package/dist/modules/manager/util.js +9 -2
- package/dist/modules/manager/util.js.map +1 -1
- package/package.json +1 -1
- package/renovate-schema.json +2 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import "../../../constants/error-messages.js";
|
|
2
2
|
import { GlobalConfig } from "../../../config/global.js";
|
|
3
3
|
import { logger } from "../../../logger/index.js";
|
|
4
|
-
import {
|
|
4
|
+
import { readLocalFile } from "../../../util/fs/index.js";
|
|
5
5
|
import { exec } from "../../../util/exec/index.js";
|
|
6
|
-
import { artifactErrorResult,
|
|
6
|
+
import { artifactErrorResult, resolveToolConstraint, updateLockFile } from "../util.js";
|
|
7
7
|
import { processHostRules } from "../npm/post-update/rules.js";
|
|
8
|
-
import {
|
|
8
|
+
import { withNpmrcHostRules } from "../npm/utils.js";
|
|
9
9
|
import { isEmptyArray } from "@sindresorhus/is";
|
|
10
10
|
import upath from "upath";
|
|
11
11
|
//#region lib/modules/manager/bun/artifacts.ts
|
|
@@ -28,27 +28,30 @@ async function updateArtifacts(updateArtifact) {
|
|
|
28
28
|
return null;
|
|
29
29
|
}
|
|
30
30
|
const pkgFileDir = upath.dirname(packageFileName);
|
|
31
|
-
const npmrcContent = await getNpmrcContent(pkgFileDir);
|
|
32
31
|
const { additionalNpmrcContent } = processHostRules();
|
|
33
|
-
await updateNpmrcContent(pkgFileDir, npmrcContent, additionalNpmrcContent);
|
|
34
32
|
try {
|
|
35
|
-
await
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
33
|
+
return await withNpmrcHostRules(pkgFileDir, additionalNpmrcContent, async () => {
|
|
34
|
+
let cmd = "bun install";
|
|
35
|
+
if (!GlobalConfig.get("allowScripts") || config.ignoreScripts) cmd += " --ignore-scripts";
|
|
36
|
+
const execOptions = {
|
|
37
|
+
cwdFile: lockFileName,
|
|
38
|
+
docker: {},
|
|
39
|
+
toolConstraints: [{
|
|
40
|
+
toolName: "bun",
|
|
41
|
+
constraint: await resolveToolConstraint(config, "bun")
|
|
42
|
+
}]
|
|
43
|
+
};
|
|
44
|
+
return await updateLockFile({
|
|
45
|
+
lockFileName,
|
|
46
|
+
existingLockFileContent: oldLockFileContent,
|
|
47
|
+
packageFile: {
|
|
48
|
+
path: packageFileName,
|
|
49
|
+
contents: newPackageFileContent
|
|
50
|
+
},
|
|
51
|
+
deleteLockFile: isLockFileMaintenance,
|
|
52
|
+
run: () => exec(cmd, execOptions)
|
|
53
|
+
});
|
|
54
|
+
});
|
|
52
55
|
} catch (err) {
|
|
53
56
|
if (err.message === "temporary-error") throw err;
|
|
54
57
|
logger.warn({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifacts.js","names":[],"sources":["../../../../lib/modules/manager/bun/artifacts.ts"],"sourcesContent":["import { isEmptyArray } from '@sindresorhus/is';\nimport upath from 'upath';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { TEMPORARY_ERROR } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { exec } from '../../../util/exec/index.ts';\nimport type { ExecOptions } from '../../../util/exec/types.ts';\nimport {
|
|
1
|
+
{"version":3,"file":"artifacts.js","names":[],"sources":["../../../../lib/modules/manager/bun/artifacts.ts"],"sourcesContent":["import { isEmptyArray } from '@sindresorhus/is';\nimport upath from 'upath';\nimport { GlobalConfig } from '../../../config/global.ts';\nimport { TEMPORARY_ERROR } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { exec } from '../../../util/exec/index.ts';\nimport type { ExecOptions } from '../../../util/exec/types.ts';\nimport { readLocalFile } from '../../../util/fs/index.ts';\nimport { processHostRules } from '../npm/post-update/rules.ts';\nimport { withNpmrcHostRules } from '../npm/utils.ts';\nimport type { UpdateArtifact, UpdateArtifactsResult } from '../types.ts';\nimport {\n artifactErrorResult,\n resolveToolConstraint,\n updateLockFile,\n} from '../util.ts';\n\nexport async function updateArtifacts(\n updateArtifact: UpdateArtifact,\n): Promise<UpdateArtifactsResult[] | null> {\n const { packageFileName, updatedDeps, newPackageFileContent, config } =\n updateArtifact;\n logger.debug(`bun.updateArtifacts(${packageFileName})`);\n const { isLockFileMaintenance } = config;\n\n if (isEmptyArray(updatedDeps) && !isLockFileMaintenance) {\n logger.debug('No updated bun deps - returning null');\n return null;\n }\n\n // Find the first bun dependency in order to handle mixed manager updates,\n // eventually falling back to the first lock file from config.\n const lockFileName =\n updatedDeps.find((dep) => dep.manager === 'bun')?.lockFiles?.[0] ??\n config.lockFiles?.[0];\n\n if (!lockFileName) {\n logger.debug(`bun: No lock file found`);\n return null;\n }\n\n const oldLockFileContent = await readLocalFile(lockFileName);\n if (!oldLockFileContent) {\n logger.debug(`No ${lockFileName} found`);\n return null;\n }\n\n const pkgFileDir = upath.dirname(packageFileName);\n const { additionalNpmrcContent } = processHostRules();\n\n try {\n return await withNpmrcHostRules(\n pkgFileDir,\n additionalNpmrcContent,\n async () => {\n let cmd = 'bun install';\n\n if (!GlobalConfig.get('allowScripts') || config.ignoreScripts) {\n cmd += ' --ignore-scripts';\n }\n\n const execOptions: ExecOptions = {\n cwdFile: lockFileName,\n docker: {},\n toolConstraints: [\n {\n toolName: 'bun',\n constraint: await resolveToolConstraint(config, 'bun'),\n },\n ],\n };\n\n return await updateLockFile({\n lockFileName,\n existingLockFileContent: oldLockFileContent,\n packageFile: {\n path: packageFileName,\n contents: newPackageFileContent,\n },\n deleteLockFile: isLockFileMaintenance,\n run: () => exec(cmd, execOptions),\n });\n },\n );\n } catch (err) {\n if (err.message === TEMPORARY_ERROR) {\n throw err;\n }\n logger.warn({ lockfile: lockFileName, err }, `Failed to update lock file`);\n return artifactErrorResult(lockFileName, err);\n }\n}\n"],"mappings":";;;;;;;;;;;AAiBA,eAAsB,gBACpB,gBACyC;CACzC,MAAM,EAAE,iBAAiB,aAAa,uBAAuB,WAC3D;CACF,OAAO,MAAM,uBAAuB,gBAAgB,EAAE;CACtD,MAAM,EAAE,0BAA0B;CAElC,IAAI,aAAa,WAAW,KAAK,CAAC,uBAAuB;EACvD,OAAO,MAAM,sCAAsC;EACnD,OAAO;CACT;CAIA,MAAM,eACJ,YAAY,MAAM,QAAQ,IAAI,YAAY,KAAK,CAAC,EAAE,YAAY,MAC9D,OAAO,YAAY;CAErB,IAAI,CAAC,cAAc;EACjB,OAAO,MAAM,yBAAyB;EACtC,OAAO;CACT;CAEA,MAAM,qBAAqB,MAAM,cAAc,YAAY;CAC3D,IAAI,CAAC,oBAAoB;EACvB,OAAO,MAAM,MAAM,aAAa,OAAO;EACvC,OAAO;CACT;CAEA,MAAM,aAAa,MAAM,QAAQ,eAAe;CAChD,MAAM,EAAE,2BAA2B,iBAAiB;CAEpD,IAAI;EACF,OAAO,MAAM,mBACX,YACA,wBACA,YAAY;GACV,IAAI,MAAM;GAEV,IAAI,CAAC,aAAa,IAAI,cAAc,KAAK,OAAO,eAC9C,OAAO;GAGT,MAAM,cAA2B;IAC/B,SAAS;IACT,QAAQ,CAAC;IACT,iBAAiB,CACf;KACE,UAAU;KACV,YAAY,MAAM,sBAAsB,QAAQ,KAAK;IACvD,CACF;GACF;GAEA,OAAO,MAAM,eAAe;IAC1B;IACA,yBAAyB;IACzB,aAAa;KACX,MAAM;KACN,UAAU;IACZ;IACA,gBAAgB;IAChB,WAAW,KAAK,KAAK,WAAW;GAClC,CAAC;EACH,CACF;CACF,SAAS,KAAK;EACZ,IAAI,IAAI,YAAA,mBACN,MAAM;EAER,OAAO,KAAK;GAAE,UAAU;GAAc;EAAI,GAAG,4BAA4B;EACzE,OAAO,oBAAoB,cAAc,GAAG;CAC9C;AACF"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import "../../../constants/error-messages.js";
|
|
2
2
|
import { logger } from "../../../logger/index.js";
|
|
3
3
|
import { findAll } from "../../../util/host-rules.js";
|
|
4
|
-
import {
|
|
4
|
+
import { readLocalFile } from "../../../util/fs/index.js";
|
|
5
5
|
import { exec } from "../../../util/exec/index.js";
|
|
6
|
-
import { artifactError, artifactErrorResult,
|
|
6
|
+
import { artifactError, artifactErrorResult, resolveToolConstraint, updateLockFile } from "../util.js";
|
|
7
7
|
import { processHostRules } from "../npm/post-update/rules.js";
|
|
8
|
-
import {
|
|
8
|
+
import { withNpmrcHostRules } from "../npm/utils.js";
|
|
9
9
|
import { isEmptyArray } from "@sindresorhus/is";
|
|
10
10
|
import { quote } from "shlex";
|
|
11
11
|
import upath from "upath";
|
|
@@ -13,7 +13,7 @@ import upath from "upath";
|
|
|
13
13
|
async function updateArtifacts(updateArtifact) {
|
|
14
14
|
const { packageFileName, updatedDeps, newPackageFileContent, config } = updateArtifact;
|
|
15
15
|
logger.debug(`deno.updateArtifacts(${packageFileName})`);
|
|
16
|
-
const isLockFileMaintenance = config
|
|
16
|
+
const { isLockFileMaintenance } = config;
|
|
17
17
|
if (isEmptyArray(updatedDeps) && !isLockFileMaintenance) {
|
|
18
18
|
logger.debug("No updated deno deps - returning null");
|
|
19
19
|
return null;
|
|
@@ -38,38 +38,41 @@ async function updateArtifacts(updateArtifact) {
|
|
|
38
38
|
}
|
|
39
39
|
const pkgFileDir = upath.dirname(packageFileName);
|
|
40
40
|
const { additionalNpmrcContent } = processHostRules();
|
|
41
|
-
const npmrcContent = await getNpmrcContent(pkgFileDir);
|
|
42
|
-
await updateNpmrcContent(pkgFileDir, npmrcContent, additionalNpmrcContent);
|
|
43
41
|
try {
|
|
44
|
-
await
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
42
|
+
return await withNpmrcHostRules(pkgFileDir, additionalNpmrcContent, async () => {
|
|
43
|
+
const execOptions = {
|
|
44
|
+
cwdFile: updatedDeps.find((dep) => dep.managerData?.importMapReferrer)?.managerData?.importMapReferrer ?? packageFileName,
|
|
45
|
+
docker: {},
|
|
46
|
+
toolConstraints: [{
|
|
47
|
+
toolName: "deno",
|
|
48
|
+
constraint: await resolveToolConstraint(config, "deno")
|
|
49
|
+
}]
|
|
50
|
+
};
|
|
51
|
+
let command = "deno install --frozen=false";
|
|
52
|
+
const defaultImportHosts = [
|
|
53
|
+
"deno.land:443",
|
|
54
|
+
"esm.sh:443",
|
|
55
|
+
"jsr.io:443",
|
|
56
|
+
"cdn.jsdelivr.net:443",
|
|
57
|
+
"raw.githubusercontent.com:443",
|
|
58
|
+
"gist.githubusercontent.com:443"
|
|
59
|
+
];
|
|
60
|
+
const additionalImportHosts = findAll({ hostType: "npm" }).filter((rule) => rule.resolvedHost).map((rule) => rule.resolvedHost);
|
|
61
|
+
if (additionalImportHosts.length > 0) {
|
|
62
|
+
const importHosts = [.../* @__PURE__ */ new Set([...defaultImportHosts, ...additionalImportHosts])].join(",");
|
|
63
|
+
command += ` --allow-import=${quote(importHosts)}`;
|
|
64
|
+
}
|
|
65
|
+
return await updateLockFile({
|
|
66
|
+
lockFileName,
|
|
67
|
+
existingLockFileContent: oldLockFileContent,
|
|
68
|
+
packageFile: {
|
|
69
|
+
path: packageFileName,
|
|
70
|
+
contents: newPackageFileContent
|
|
71
|
+
},
|
|
72
|
+
deleteLockFile: isLockFileMaintenance,
|
|
73
|
+
run: () => exec(command, execOptions)
|
|
74
|
+
});
|
|
75
|
+
});
|
|
73
76
|
} catch (err) {
|
|
74
77
|
if (err.message === "temporary-error") throw err;
|
|
75
78
|
logger.warn({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifacts.js","names":["hostRules\n
|
|
1
|
+
{"version":3,"file":"artifacts.js","names":["hostRules\n .findAll"],"sources":["../../../../lib/modules/manager/deno/artifacts.ts"],"sourcesContent":["import { isEmptyArray } from '@sindresorhus/is';\nimport { quote } from 'shlex';\nimport upath from 'upath';\nimport { TEMPORARY_ERROR } from '../../../constants/error-messages.ts';\nimport { logger } from '../../../logger/index.ts';\nimport { exec } from '../../../util/exec/index.ts';\nimport type { ExecOptions } from '../../../util/exec/types.ts';\nimport { readLocalFile } from '../../../util/fs/index.ts';\nimport * as hostRules from '../../../util/host-rules.ts';\nimport { processHostRules } from '../npm/post-update/rules.ts';\nimport { withNpmrcHostRules } from '../npm/utils.ts';\nimport type { UpdateArtifact, UpdateArtifactsResult } from '../types.ts';\nimport {\n artifactError,\n artifactErrorResult,\n resolveToolConstraint,\n updateLockFile,\n} from '../util.ts';\nimport type { DenoManagerData } from './types.ts';\n\nexport async function updateArtifacts(\n updateArtifact: UpdateArtifact<DenoManagerData>,\n): Promise<UpdateArtifactsResult[] | null> {\n const { packageFileName, updatedDeps, newPackageFileContent, config } =\n updateArtifact;\n logger.debug(`deno.updateArtifacts(${packageFileName})`);\n const { isLockFileMaintenance } = config;\n\n if (isEmptyArray(updatedDeps) && !isLockFileMaintenance) {\n logger.debug('No updated deno deps - returning null');\n return null;\n }\n\n // falling back for lockFileMaintenance\n const lockFileName = updatedDeps[0]?.lockFiles?.[0] ?? config.lockFiles?.[0];\n\n if (!lockFileName) {\n logger.debug('No lock file found. Skipping artifact update.');\n return null;\n }\n\n const oldLockFileContent = await readLocalFile(lockFileName);\n if (!oldLockFileContent) {\n logger.debug(`Failed to read ${lockFileName}. Skipping artifact update.`);\n return [artifactError(lockFileName, `Failed to read \"${lockFileName}\"`)];\n }\n\n for (const updateDep of updatedDeps) {\n if (\n updateDep.depType === 'tasks' ||\n updateDep.depType === 'tasks.command'\n ) {\n logger.warn(\n {\n depType: updateDep.depType,\n depName: updateDep.depName,\n lockFileName,\n },\n \"Dependency can't be updated with a lock file\",\n );\n return [\n artifactError(\n lockFileName,\n `depType: \"${updateDep.depType}\", depName: \"${updateDep.depName}\" can't be updated with a lock file: \"${lockFileName}\"`,\n ),\n ];\n }\n }\n\n const pkgFileDir = upath.dirname(packageFileName);\n const { additionalNpmrcContent } = processHostRules();\n\n try {\n return await withNpmrcHostRules(\n pkgFileDir,\n additionalNpmrcContent,\n async () => {\n // run from its referred deno.json/deno.jsonc location if import map is used\n const importMapReferrerDep = updatedDeps.find(\n (dep) => dep.managerData?.importMapReferrer,\n );\n const cwdFile =\n importMapReferrerDep?.managerData?.importMapReferrer ??\n packageFileName;\n\n const execOptions: ExecOptions = {\n cwdFile,\n docker: {},\n toolConstraints: [\n {\n toolName: 'deno',\n constraint: await resolveToolConstraint(config, 'deno'),\n },\n ],\n };\n\n // \"deno install\" don't execute lifecycle scripts of package.json by default\n // https://docs.deno.com/runtime/reference/cli/install/#native-node.js-addons\n // deno.json(c) could have the `lock.frozen` field\n // we should always override the `frozen` flag due to if it would be specified true\n let command = 'deno install --frozen=false';\n\n // defaults as per https://docs.deno.com/runtime/fundamentals/security/#importing-from-the-web\n const defaultImportHosts = [\n 'deno.land:443',\n 'esm.sh:443',\n 'jsr.io:443',\n 'cdn.jsdelivr.net:443',\n 'raw.githubusercontent.com:443',\n 'gist.githubusercontent.com:443',\n ];\n const additionalImportHosts = hostRules\n .findAll({ hostType: 'npm' })\n .filter((rule) => rule.resolvedHost)\n .map((rule) => rule.resolvedHost);\n\n if (additionalImportHosts.length > 0) {\n // combine default and additional import hosts, removing duplicates\n const importHosts = [\n ...new Set([...defaultImportHosts, ...additionalImportHosts]),\n ].join(',');\n\n command += ` --allow-import=${quote(importHosts)}`;\n }\n\n // TODO: appending `--lockfile-only` is better to reduce disk usage\n // https://docs.deno.com/runtime/reference/cli/install/#options-lockfile-only\n return await updateLockFile({\n lockFileName,\n existingLockFileContent: oldLockFileContent,\n packageFile: {\n path: packageFileName,\n contents: newPackageFileContent,\n },\n deleteLockFile: isLockFileMaintenance,\n run: () => exec(command, execOptions),\n });\n },\n );\n } catch (err) {\n if (err.message === TEMPORARY_ERROR) {\n throw err;\n }\n logger.warn({ lockfile: lockFileName, err }, `Failed to update lock file`);\n return artifactErrorResult(lockFileName, err);\n }\n}\n"],"mappings":";;;;;;;;;;;;AAoBA,eAAsB,gBACpB,gBACyC;CACzC,MAAM,EAAE,iBAAiB,aAAa,uBAAuB,WAC3D;CACF,OAAO,MAAM,wBAAwB,gBAAgB,EAAE;CACvD,MAAM,EAAE,0BAA0B;CAElC,IAAI,aAAa,WAAW,KAAK,CAAC,uBAAuB;EACvD,OAAO,MAAM,uCAAuC;EACpD,OAAO;CACT;CAGA,MAAM,eAAe,YAAY,EAAE,EAAE,YAAY,MAAM,OAAO,YAAY;CAE1E,IAAI,CAAC,cAAc;EACjB,OAAO,MAAM,+CAA+C;EAC5D,OAAO;CACT;CAEA,MAAM,qBAAqB,MAAM,cAAc,YAAY;CAC3D,IAAI,CAAC,oBAAoB;EACvB,OAAO,MAAM,kBAAkB,aAAa,4BAA4B;EACxE,OAAO,CAAC,cAAc,cAAc,mBAAmB,aAAa,EAAE,CAAC;CACzE;CAEA,KAAK,MAAM,aAAa,aACtB,IACE,UAAU,YAAY,WACtB,UAAU,YAAY,iBACtB;EACA,OAAO,KACL;GACE,SAAS,UAAU;GACnB,SAAS,UAAU;GACnB;EACF,GACA,8CACF;EACA,OAAO,CACL,cACE,cACA,aAAa,UAAU,QAAQ,eAAe,UAAU,QAAQ,wCAAwC,aAAa,EACvH,CACF;CACF;CAGF,MAAM,aAAa,MAAM,QAAQ,eAAe;CAChD,MAAM,EAAE,2BAA2B,iBAAiB;CAEpD,IAAI;EACF,OAAO,MAAM,mBACX,YACA,wBACA,YAAY;GASV,MAAM,cAA2B;IAC/B,SAR2B,YAAY,MACtC,QAAQ,IAAI,aAAa,iBAGP,CAAC,EAAE,aAAa,qBACnC;IAIA,QAAQ,CAAC;IACT,iBAAiB,CACf;KACE,UAAU;KACV,YAAY,MAAM,sBAAsB,QAAQ,MAAM;IACxD,CACF;GACF;GAMA,IAAI,UAAU;GAGd,MAAM,qBAAqB;IACzB;IACA;IACA;IACA;IACA;IACA;GACF;GACA,MAAM,wBAAwBA,QACnB,EAAE,UAAU,MAAM,CAAC,CAAC,CAC5B,QAAQ,SAAS,KAAK,YAAY,CAAC,CACnC,KAAK,SAAS,KAAK,YAAY;GAElC,IAAI,sBAAsB,SAAS,GAAG;IAEpC,MAAM,cAAc,CAClB,mBAAG,IAAI,IAAI,CAAC,GAAG,oBAAoB,GAAG,qBAAqB,CAAC,CAC9D,CAAC,CAAC,KAAK,GAAG;IAEV,WAAW,mBAAmB,MAAM,WAAW;GACjD;GAIA,OAAO,MAAM,eAAe;IAC1B;IACA,yBAAyB;IACzB,aAAa;KACX,MAAM;KACN,UAAU;IACZ;IACA,gBAAgB;IAChB,WAAW,KAAK,SAAS,WAAW;GACtC,CAAC;EACH,CACF;CACF,SAAS,KAAK;EACZ,IAAI,IAAI,YAAA,mBACN,MAAM;EAER,OAAO,KAAK;GAAE,UAAU;GAAc;EAAI,GAAG,4BAA4B;EACzE,OAAO,oBAAoB,cAAc,GAAG;CAC9C;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { logger } from "../../../logger/index.js";
|
|
2
2
|
import { getSiblingFileName, readLocalFile } from "../../../util/fs/index.js";
|
|
3
3
|
import { exec } from "../../../util/exec/index.js";
|
|
4
|
-
import { artifactErrorResult,
|
|
4
|
+
import { artifactErrorResult, resolveToolConstraint, updateLockFile } from "../util.js";
|
|
5
5
|
import { isNonEmptyArray } from "@sindresorhus/is";
|
|
6
6
|
import { quote } from "shlex";
|
|
7
7
|
import semver from "semver";
|
|
@@ -47,11 +47,11 @@ async function updateArtifacts({ config, packageFileName, updatedDeps }) {
|
|
|
47
47
|
return null;
|
|
48
48
|
}
|
|
49
49
|
try {
|
|
50
|
-
await
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
return await updateLockFile({
|
|
51
|
+
lockFileName,
|
|
52
|
+
existingLockFileContent: oldLockFileContent,
|
|
53
|
+
run: () => exec(cmd, execOptions)
|
|
54
|
+
});
|
|
55
55
|
} catch (err) {
|
|
56
56
|
logger.warn({ err }, "Error updating devbox.lock");
|
|
57
57
|
return artifactErrorResult(lockFileName, err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifacts.js","names":[],"sources":["../../../../lib/modules/manager/devbox/artifacts.ts"],"sourcesContent":["import { isNonEmptyArray } from '@sindresorhus/is';\nimport semver from 'semver';\nimport { quote } from 'shlex';\nimport { logger } from '../../../logger/index.ts';\nimport { exec } from '../../../util/exec/index.ts';\nimport type { ExecOptions } from '../../../util/exec/types.ts';\nimport { getSiblingFileName, readLocalFile } from '../../../util/fs/index.ts';\nimport type { UpdateArtifact, UpdateArtifactsResult } from '../types.ts';\nimport {\n artifactErrorResult,\n
|
|
1
|
+
{"version":3,"file":"artifacts.js","names":[],"sources":["../../../../lib/modules/manager/devbox/artifacts.ts"],"sourcesContent":["import { isNonEmptyArray } from '@sindresorhus/is';\nimport semver from 'semver';\nimport { quote } from 'shlex';\nimport { logger } from '../../../logger/index.ts';\nimport { exec } from '../../../util/exec/index.ts';\nimport type { ExecOptions } from '../../../util/exec/types.ts';\nimport { getSiblingFileName, readLocalFile } from '../../../util/fs/index.ts';\nimport type { UpdateArtifact, UpdateArtifactsResult } from '../types.ts';\nimport {\n artifactErrorResult,\n resolveToolConstraint,\n updateLockFile,\n} from '../util.ts';\n\nexport async function updateArtifacts({\n config,\n packageFileName,\n updatedDeps,\n}: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {\n const lockFileName = getSiblingFileName(packageFileName, 'devbox.lock');\n const existingLockFileContent = await readLocalFile(lockFileName, 'utf8');\n if (!existingLockFileContent) {\n logger.debug('No devbox.lock found');\n return null;\n }\n\n const nixConstraint = await resolveToolConstraint(config, 'nix');\n const devboxConstraint = await resolveToolConstraint(config, 'devbox');\n\n const supportsNoInstall = devboxConstraint\n ? semver.intersects(devboxConstraint, '>=0.14.0')\n : true;\n\n const execOptions: ExecOptions = {\n cwdFile: packageFileName,\n toolConstraints: [\n // we are required to install nix because devbox spawns nix commands internally\n // https://github.com/renovatebot/renovate/discussions/35382\n // https://github.com/jetify-com/devbox/issues/2585\n {\n toolName: 'nix',\n constraint: nixConstraint,\n },\n {\n toolName: 'devbox',\n constraint: devboxConstraint,\n },\n ],\n docker: {},\n };\n\n const cmd: string[] = [];\n if (config.isLockFileMaintenance) {\n cmd.push(\n supportsNoInstall ? 'devbox update --no-install' : 'devbox update',\n );\n } else if (isNonEmptyArray(updatedDeps)) {\n if (supportsNoInstall) {\n const updateCommands: string[] = updatedDeps\n .map(\n (dep) =>\n dep.depName && `devbox update ${quote(dep.depName)} --no-install`,\n )\n .filter((dep): dep is string => Boolean(dep));\n if (updateCommands.length) {\n cmd.push(...updateCommands);\n } else {\n logger.trace('No updated devbox packages - returning null');\n return null;\n }\n } else {\n cmd.push('devbox install');\n }\n } else {\n logger.trace('No updated devbox packages - returning null');\n return null;\n }\n\n const oldLockFileContent = await readLocalFile(lockFileName);\n if (!oldLockFileContent) {\n logger.trace(`No ${lockFileName} found`);\n return null;\n }\n\n try {\n return await updateLockFile({\n lockFileName,\n existingLockFileContent: oldLockFileContent,\n run: () => exec(cmd, execOptions),\n });\n } catch (err) {\n logger.warn({ err }, 'Error updating devbox.lock');\n return artifactErrorResult(lockFileName, err);\n }\n}\n"],"mappings":";;;;;;;;AAcA,eAAsB,gBAAgB,EACpC,QACA,iBACA,eAC0D;CAC1D,MAAM,eAAe,mBAAmB,iBAAiB,aAAa;CAEtE,IAAI,CAAC,MADiC,cAAc,cAAc,MAAM,GAC1C;EAC5B,OAAO,MAAM,sBAAsB;EACnC,OAAO;CACT;CAEA,MAAM,gBAAgB,MAAM,sBAAsB,QAAQ,KAAK;CAC/D,MAAM,mBAAmB,MAAM,sBAAsB,QAAQ,QAAQ;CAErE,MAAM,oBAAoB,mBACtB,OAAO,WAAW,kBAAkB,UAAU,IAC9C;CAEJ,MAAM,cAA2B;EAC/B,SAAS;EACT,iBAAiB,CAIf;GACE,UAAU;GACV,YAAY;EACd,GACA;GACE,UAAU;GACV,YAAY;EACd,CACF;EACA,QAAQ,CAAC;CACX;CAEA,MAAM,MAAgB,CAAC;CACvB,IAAI,OAAO,uBACT,IAAI,KACF,oBAAoB,+BAA+B,eACrD;MACK,IAAI,gBAAgB,WAAW,GAAG;EACvC,IAAI,mBAAmB;GACrB,MAAM,iBAA2B,YAC9B,KACE,QACC,IAAI,WAAW,iBAAiB,MAAM,IAAI,OAAO,EAAE,cACvD,CAAC,CACA,QAAQ,QAAuB,QAAQ,GAAG,CAAC;GAC9C,IAAI,eAAe,QACjB,IAAI,KAAK,GAAG,cAAc;QACrB;IACL,OAAO,MAAM,6CAA6C;IAC1D,OAAO;GACT;EACF,OACE,IAAI,KAAK,gBAAgB;CAE7B,OAAO;EACL,OAAO,MAAM,6CAA6C;EAC1D,OAAO;CACT;CAEA,MAAM,qBAAqB,MAAM,cAAc,YAAY;CAC3D,IAAI,CAAC,oBAAoB;EACvB,OAAO,MAAM,MAAM,aAAa,OAAO;EACvC,OAAO;CACT;CAEA,IAAI;EACF,OAAO,MAAM,eAAe;GAC1B;GACA,yBAAyB;GACzB,WAAW,KAAK,KAAK,WAAW;EAClC,CAAC;CACH,SAAS,KAAK;EACZ,OAAO,KAAK,EAAE,IAAI,GAAG,4BAA4B;EACjD,OAAO,oBAAoB,cAAc,GAAG;CAC9C;AACF"}
|
|
@@ -1,21 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { regEx } from "../../../util/regex.js";
|
|
2
2
|
import { logger } from "../../../logger/index.js";
|
|
3
3
|
import { api } from "../../versioning/apk/index.js";
|
|
4
4
|
import { ApkDatasource } from "../../datasource/apk/index.js";
|
|
5
|
-
import {
|
|
5
|
+
import { parseRunCommands } from "./run-command.js";
|
|
6
6
|
//#region lib/modules/manager/dockerfile/apk.ts
|
|
7
|
-
/** Shell operators which start a new command */
|
|
8
|
-
const commandSeparators = [
|
|
9
|
-
"&&",
|
|
10
|
-
"||",
|
|
11
|
-
";",
|
|
12
|
-
"|",
|
|
13
|
-
"&",
|
|
14
|
-
"(",
|
|
15
|
-
")",
|
|
16
|
-
"{",
|
|
17
|
-
"}"
|
|
18
|
-
];
|
|
19
7
|
/**
|
|
20
8
|
* `apk` options which consume the following argument, so that the argument is
|
|
21
9
|
* not mistaken for a package name.
|
|
@@ -107,12 +95,6 @@ function extractApkAddArgs(tokens) {
|
|
|
107
95
|
return deps;
|
|
108
96
|
}
|
|
109
97
|
/**
|
|
110
|
-
* The `RUN` keyword and its flags, e.g. `RUN --mount=type=cache,target=/x `.
|
|
111
|
-
*
|
|
112
|
-
* Stripping these leaves the shell command that the instruction runs.
|
|
113
|
-
*/
|
|
114
|
-
const runPrefixRegex = regEx(/^[ \t]*(?:ONBUILD[ \t]+)?RUN[ \t]+(?:--[a-z]\S*[ \t]+)*/i);
|
|
115
|
-
/**
|
|
116
98
|
* Extracts APK packages pinned by `apk add` in a `RUN` instruction, e.g.
|
|
117
99
|
*
|
|
118
100
|
* ```dockerfile
|
|
@@ -125,51 +107,7 @@ const runPrefixRegex = regEx(/^[ \t]*(?:ONBUILD[ \t]+)?RUN[ \t]+(?:--[a-z]\S*[ \
|
|
|
125
107
|
* @param escapeChar the Dockerfile escape character, already regex-escaped
|
|
126
108
|
*/
|
|
127
109
|
function extractApkDeps(instruction, escapeChar) {
|
|
128
|
-
|
|
129
|
-
const runPrefix = runPrefixRegex.exec(joined)?.[0];
|
|
130
|
-
if (!runPrefix) return [];
|
|
131
|
-
const command = joined.slice(runPrefix.length);
|
|
132
|
-
if (!command.includes("apk")) return [];
|
|
133
|
-
let tokens;
|
|
134
|
-
try {
|
|
135
|
-
tokens = split(command);
|
|
136
|
-
} catch (err) {
|
|
137
|
-
logger.debug({
|
|
138
|
-
err,
|
|
139
|
-
command
|
|
140
|
-
}, "Failed to tokenize Dockerfile RUN command");
|
|
141
|
-
return [];
|
|
142
|
-
}
|
|
143
|
-
const deps = [];
|
|
144
|
-
let current = [];
|
|
145
|
-
for (const token of tokens) {
|
|
146
|
-
if (token.startsWith("#")) break;
|
|
147
|
-
if (commandSeparators.includes(token)) {
|
|
148
|
-
deps.push(...extractApkCommand(current));
|
|
149
|
-
current = [];
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
if (token.endsWith(";")) {
|
|
153
|
-
current.push(token.slice(0, -1));
|
|
154
|
-
deps.push(...extractApkCommand(current));
|
|
155
|
-
current = [];
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
current.push(token);
|
|
159
|
-
}
|
|
160
|
-
deps.push(...extractApkCommand(current));
|
|
161
|
-
return deps;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Finds the `apk` invocation in the tokens of a shell command, wherever it
|
|
165
|
-
* sits - so it's found whether it's prefixed by a shell keyword
|
|
166
|
-
* (`do`/`then`/...), a variable assignment (`DEBUG=1 apk add ...`), or a
|
|
167
|
-
* wrapper program (`sudo`/`chroot /mnt`/`timeout 30`/...).
|
|
168
|
-
*/
|
|
169
|
-
function extractApkCommand(tokens) {
|
|
170
|
-
const index = tokens.findIndex((token) => token === "apk" || token.endsWith("/apk"));
|
|
171
|
-
if (index === -1) return [];
|
|
172
|
-
return extractApkAddArgs(tokens.slice(index + 1));
|
|
110
|
+
return parseRunCommands(instruction, escapeChar, ["apk"]).flatMap(extractApkAddArgs);
|
|
173
111
|
}
|
|
174
112
|
//#endregion
|
|
175
113
|
export { extractApkDeps };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apk.js","names":["apkVersioning"],"sources":["../../../../lib/modules/manager/dockerfile/apk.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"apk.js","names":["apkVersioning"],"sources":["../../../../lib/modules/manager/dockerfile/apk.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { ApkDatasource } from '../../datasource/apk/index.ts';\nimport { api as apkVersioning } from '../../versioning/apk/index.ts';\nimport type { PackageDependency } from '../types.ts';\nimport { parseRunCommands } from './run-command.ts';\n\n/**\n * `apk` options which consume the following argument, so that the argument is\n * not mistaken for a package name.\n *\n * Options given as `--opt=value` are a single token, so they need no entry here.\n */\nconst optionsWithValue = new Set([\n '-X',\n '--repository',\n '-t',\n '--virtual',\n '-p',\n '--root',\n '--arch',\n '--cache-dir',\n '--cache-max-age',\n '--keys-dir',\n '--repositories-file',\n '--progress-fd',\n '--timeout',\n '--wait',\n]);\n\n/**\n * An `apk` package specification, e.g. `bash`, `bash=5.2.37-r2`, `bash>5.2` or\n * `nodejs@edge=22.13.1-r0`.\n *\n * `apk` builds the constraint operator from its characters, so they may be\n * given in any order and may repeat - see the `apk` versioning module.\n *\n * The `@repoTag` suffix pins the package to a tagged repository from\n * `/etc/apk/repositories`, and is part of the spec rather than of the name.\n */\nconst apkSpecRegex = regEx(\n /^(?<name>[a-zA-Z0-9][\\w.+-]*)(?:@(?<repoTag>[\\w.-]+))?(?:(?<operator>[<>=~]+)(?<version>.+))?$/,\n);\n\nfunction parseSpec(spec: string): PackageDependency | null {\n const groups = apkSpecRegex.exec(spec)?.groups;\n if (!groups) {\n logger.trace({ spec }, 'Skipping unparseable apk package spec');\n return null;\n }\n\n const { name, operator, version } = groups;\n // the `apk` datasource defaults to `apk` versioning, so the constraint is\n // read the same way here as it is during the lookup\n const dep: PackageDependency = {\n datasource: ApkDatasource.id,\n depName: name,\n };\n\n if (!operator) {\n // Renovate has nothing to update until the user constrains the version\n dep.skipReason = 'unspecified-version';\n return dep;\n }\n\n if (version.includes('$')) {\n dep.skipReason = 'contains-variable';\n return dep;\n }\n\n // rejects an unparseable version, and the `><` identity hash operator\n const constraint = operator + version;\n if (!apkVersioning.isValid(constraint)) {\n dep.skipReason = 'unsupported-version';\n return dep;\n }\n\n // An exact pin reads better as a plain version, so the `=` stays in the\n // replaceString rather than becoming part of the value we report\n const isPin = apkVersioning.isSingleVersion(constraint);\n const currentValue = isPin ? version : constraint;\n\n dep.currentValue = currentValue;\n dep.replaceString = spec;\n // Only the value is templated, so a `@repoTag` in the spec is preserved\n dep.autoReplaceStringTemplate = `${spec.slice(0, -currentValue.length)}{{{newValue}}}`;\n return dep;\n}\n\n/** Package specs which are not registry lookups, and so are silently ignored */\nfunction isIgnoredSpec(spec: string): boolean {\n return (\n // conflict markers, e.g. `apk add foo !bar`\n spec.startsWith('!') ||\n // virtual package names, e.g. `apk add .build-deps`\n spec.startsWith('.') ||\n // local or remote `.apk` files, e.g. `apk add ./foo-1.2.3-r0.apk`\n spec.includes('/') ||\n // provider dependencies, e.g. `so:libc.musl-x86_64.so.1`, `cmd:node`\n spec.includes(':')\n );\n}\n\nfunction extractApkAddArgs(tokens: string[]): PackageDependency[] {\n const deps: PackageDependency[] = [];\n let subCommandFound = false;\n\n for (let i = 0; i < tokens.length; i += 1) {\n const token = tokens[i];\n\n if (token.startsWith('-')) {\n if (optionsWithValue.has(token)) {\n i += 1;\n }\n continue;\n }\n\n if (!subCommandFound) {\n // `apk` accepts global options before the sub-command, so the first\n // non-option token is the sub-command\n if (token !== 'add') {\n return [];\n }\n subCommandFound = true;\n continue;\n }\n\n if (isIgnoredSpec(token)) {\n logger.trace({ spec: token }, 'Skipping apk package spec');\n continue;\n }\n\n const dep = parseSpec(token);\n if (dep) {\n deps.push(dep);\n }\n }\n\n return deps;\n}\n\n/**\n * Extracts APK packages pinned by `apk add` in a `RUN` instruction, e.g.\n *\n * ```dockerfile\n * RUN apk add --no-cache \\\n * bash=5.2.37-r2 \\\n * rsyslog=8.2412.0-r1\n * ```\n *\n * @param instruction the full `RUN` instruction, including any line continuations\n * @param escapeChar the Dockerfile escape character, already regex-escaped\n */\nexport function extractApkDeps(\n instruction: string,\n escapeChar: string,\n): PackageDependency[] {\n return parseRunCommands(instruction, escapeChar, ['apk']).flatMap(\n extractApkAddArgs,\n );\n}\n"],"mappings":";;;;;;;;;;;;AAaA,MAAM,mCAAmB,IAAI,IAAI;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;;;AAYD,MAAM,eAAe,MACnB,gGACF;AAEA,SAAS,UAAU,MAAwC;CACzD,MAAM,SAAS,aAAa,KAAK,IAAI,CAAC,EAAE;CACxC,IAAI,CAAC,QAAQ;EACX,OAAO,MAAM,EAAE,KAAK,GAAG,uCAAuC;EAC9D,OAAO;CACT;CAEA,MAAM,EAAE,MAAM,UAAU,YAAY;CAGpC,MAAM,MAAyB;EAC7B,YAAY,cAAc;EAC1B,SAAS;CACX;CAEA,IAAI,CAAC,UAAU;EAEb,IAAI,aAAa;EACjB,OAAO;CACT;CAEA,IAAI,QAAQ,SAAS,GAAG,GAAG;EACzB,IAAI,aAAa;EACjB,OAAO;CACT;CAGA,MAAM,aAAa,WAAW;CAC9B,IAAI,CAACA,IAAc,QAAQ,UAAU,GAAG;EACtC,IAAI,aAAa;EACjB,OAAO;CACT;CAKA,MAAM,eADQA,IAAc,gBAAgB,UACnB,IAAI,UAAU;CAEvC,IAAI,eAAe;CACnB,IAAI,gBAAgB;CAEpB,IAAI,4BAA4B,GAAG,KAAK,MAAM,GAAG,CAAC,aAAa,MAAM,EAAE;CACvE,OAAO;AACT;;AAGA,SAAS,cAAc,MAAuB;CAC5C,OAEE,KAAK,WAAW,GAAG,KAEnB,KAAK,WAAW,GAAG,KAEnB,KAAK,SAAS,GAAG,KAEjB,KAAK,SAAS,GAAG;AAErB;AAEA,SAAS,kBAAkB,QAAuC;CAChE,MAAM,OAA4B,CAAC;CACnC,IAAI,kBAAkB;CAEtB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;EACzC,MAAM,QAAQ,OAAO;EAErB,IAAI,MAAM,WAAW,GAAG,GAAG;GACzB,IAAI,iBAAiB,IAAI,KAAK,GAC5B,KAAK;GAEP;EACF;EAEA,IAAI,CAAC,iBAAiB;GAGpB,IAAI,UAAU,OACZ,OAAO,CAAC;GAEV,kBAAkB;GAClB;EACF;EAEA,IAAI,cAAc,KAAK,GAAG;GACxB,OAAO,MAAM,EAAE,MAAM,MAAM,GAAG,2BAA2B;GACzD;EACF;EAEA,MAAM,MAAM,UAAU,KAAK;EAC3B,IAAI,KACF,KAAK,KAAK,GAAG;CAEjB;CAEA,OAAO;AACT;;;;;;;;;;;;;AAcA,SAAgB,eACd,aACA,YACqB;CACrB,OAAO,iBAAiB,aAAa,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,QACxD,iBACF;AACF"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { regEx } from "../../../util/regex.js";
|
|
2
|
+
import { logger } from "../../../logger/index.js";
|
|
3
|
+
import { api } from "../../versioning/deb/index.js";
|
|
4
|
+
import { DebDatasource } from "../../datasource/deb/index.js";
|
|
5
|
+
import { parseRunCommands } from "./run-command.js";
|
|
6
|
+
//#region lib/modules/manager/dockerfile/deb.ts
|
|
7
|
+
/**
|
|
8
|
+
* `apt` options which consume the following argument, so that the argument is
|
|
9
|
+
* not mistaken for a package name.
|
|
10
|
+
*
|
|
11
|
+
* Options given as `--opt=value` are a single token, so they need no entry here.
|
|
12
|
+
*/
|
|
13
|
+
const optionsWithValue = /* @__PURE__ */ new Set([
|
|
14
|
+
"-o",
|
|
15
|
+
"--option",
|
|
16
|
+
"-c",
|
|
17
|
+
"--config-file",
|
|
18
|
+
"-t",
|
|
19
|
+
"--target-release",
|
|
20
|
+
"--default-release",
|
|
21
|
+
"-a",
|
|
22
|
+
"--host-architecture",
|
|
23
|
+
"--build-profiles"
|
|
24
|
+
]);
|
|
25
|
+
/**
|
|
26
|
+
* An `apt` package specification, e.g. `curl`, `curl=8.5.0-2ubuntu10.6`,
|
|
27
|
+
* `curl:amd64=8.5.0-2ubuntu10.6` or `curl/bookworm-backports`.
|
|
28
|
+
*
|
|
29
|
+
* The `:arch` qualifier selects the architecture to install for, and the
|
|
30
|
+
* `/release` suffix picks the suite to install from - both are part of the
|
|
31
|
+
* spec rather than of the package name.
|
|
32
|
+
*/
|
|
33
|
+
const debSpecRegex = regEx(/^(?<name>[a-z0-9][a-z0-9+.-]*)(?::(?<arch>[a-z0-9][a-z0-9-]*))?(?:=(?<version>.+)|\/(?<release>[a-z0-9][\w.-]*))?$/);
|
|
34
|
+
function parseSpec(spec) {
|
|
35
|
+
const groups = debSpecRegex.exec(spec)?.groups;
|
|
36
|
+
if (!groups) {
|
|
37
|
+
logger.trace({ spec }, "Skipping unparseable apt package spec");
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const { name, version } = groups;
|
|
41
|
+
const dep = {
|
|
42
|
+
datasource: DebDatasource.id,
|
|
43
|
+
depName: name
|
|
44
|
+
};
|
|
45
|
+
if (!version) {
|
|
46
|
+
dep.skipReason = "unspecified-version";
|
|
47
|
+
return dep;
|
|
48
|
+
}
|
|
49
|
+
if (version.includes("$")) {
|
|
50
|
+
dep.skipReason = "contains-variable";
|
|
51
|
+
return dep;
|
|
52
|
+
}
|
|
53
|
+
if (!api.isSingleVersion(version)) {
|
|
54
|
+
dep.skipReason = "unsupported-version";
|
|
55
|
+
return dep;
|
|
56
|
+
}
|
|
57
|
+
dep.currentValue = version;
|
|
58
|
+
dep.replaceString = spec;
|
|
59
|
+
dep.autoReplaceStringTemplate = `${spec.slice(0, -version.length)}{{{newValue}}}`;
|
|
60
|
+
return dep;
|
|
61
|
+
}
|
|
62
|
+
/** Package specs which are not registry lookups, and so are silently ignored */
|
|
63
|
+
function isIgnoredSpec(spec) {
|
|
64
|
+
return spec.endsWith(".deb") || spec.startsWith(".") || spec.startsWith("/") || spec.endsWith("-") || spec.endsWith("+");
|
|
65
|
+
}
|
|
66
|
+
function extractAptInstallArgs(tokens) {
|
|
67
|
+
const deps = [];
|
|
68
|
+
let subCommandFound = false;
|
|
69
|
+
for (let i = 0; i < tokens.length; i += 1) {
|
|
70
|
+
const token = tokens[i];
|
|
71
|
+
if (token.startsWith("-")) {
|
|
72
|
+
if (optionsWithValue.has(token)) i += 1;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (!subCommandFound) {
|
|
76
|
+
if (token !== "install") return [];
|
|
77
|
+
subCommandFound = true;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (isIgnoredSpec(token)) {
|
|
81
|
+
logger.trace({ spec: token }, "Skipping apt package spec");
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const dep = parseSpec(token);
|
|
85
|
+
if (dep) deps.push(dep);
|
|
86
|
+
}
|
|
87
|
+
return deps;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Extracts Debian packages pinned by `apt install` or `apt-get install` in a
|
|
91
|
+
* `RUN` instruction, e.g.
|
|
92
|
+
*
|
|
93
|
+
* ```dockerfile
|
|
94
|
+
* RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
95
|
+
* curl=8.5.0-2ubuntu10.6 \
|
|
96
|
+
* git=1:2.43.0-1ubuntu7.3
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* @param instruction the full `RUN` instruction, including any line continuations
|
|
100
|
+
* @param escapeChar the Dockerfile escape character, already regex-escaped
|
|
101
|
+
*/
|
|
102
|
+
function extractDebDeps(instruction, escapeChar) {
|
|
103
|
+
return parseRunCommands(instruction, escapeChar, ["apt", "apt-get"]).flatMap(extractAptInstallArgs);
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
export { extractDebDeps };
|
|
107
|
+
|
|
108
|
+
//# sourceMappingURL=deb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deb.js","names":["debVersioning"],"sources":["../../../../lib/modules/manager/dockerfile/deb.ts"],"sourcesContent":["import { logger } from '../../../logger/index.ts';\nimport { regEx } from '../../../util/regex.ts';\nimport { DebDatasource } from '../../datasource/deb/index.ts';\nimport { api as debVersioning } from '../../versioning/deb/index.ts';\nimport type { PackageDependency } from '../types.ts';\nimport { parseRunCommands } from './run-command.ts';\n\n/**\n * `apt` options which consume the following argument, so that the argument is\n * not mistaken for a package name.\n *\n * Options given as `--opt=value` are a single token, so they need no entry here.\n */\nconst optionsWithValue = new Set([\n '-o',\n '--option',\n '-c',\n '--config-file',\n '-t',\n '--target-release',\n '--default-release',\n '-a',\n '--host-architecture',\n '--build-profiles',\n]);\n\n/**\n * An `apt` package specification, e.g. `curl`, `curl=8.5.0-2ubuntu10.6`,\n * `curl:amd64=8.5.0-2ubuntu10.6` or `curl/bookworm-backports`.\n *\n * The `:arch` qualifier selects the architecture to install for, and the\n * `/release` suffix picks the suite to install from - both are part of the\n * spec rather than of the package name.\n */\nconst debSpecRegex = regEx(\n /^(?<name>[a-z0-9][a-z0-9+.-]*)(?::(?<arch>[a-z0-9][a-z0-9-]*))?(?:=(?<version>.+)|\\/(?<release>[a-z0-9][\\w.-]*))?$/,\n);\n\nfunction parseSpec(spec: string): PackageDependency | null {\n const groups = debSpecRegex.exec(spec)?.groups;\n if (!groups) {\n logger.trace({ spec }, 'Skipping unparseable apt package spec');\n return null;\n }\n\n const { name, version } = groups;\n const dep: PackageDependency = {\n datasource: DebDatasource.id,\n depName: name,\n };\n\n if (!version) {\n // a bare name, or one only pinned to a suite, leaves Renovate nothing to\n // update\n dep.skipReason = 'unspecified-version';\n return dep;\n }\n\n if (version.includes('$')) {\n dep.skipReason = 'contains-variable';\n return dep;\n }\n\n // `apt` also accepts a wildcard such as `curl=8.5.*`, which is not a version\n // we can compare against the releases we find\n if (!debVersioning.isSingleVersion(version)) {\n dep.skipReason = 'unsupported-version';\n return dep;\n }\n\n dep.currentValue = version;\n dep.replaceString = spec;\n // Only the version is templated, so an `:arch` in the spec is preserved\n dep.autoReplaceStringTemplate = `${spec.slice(0, -version.length)}{{{newValue}}}`;\n return dep;\n}\n\n/** Package specs which are not registry lookups, and so are silently ignored */\nfunction isIgnoredSpec(spec: string): boolean {\n return (\n // local or remote `.deb` files, e.g. `apt install ./curl_8.5.0-2_amd64.deb`\n spec.endsWith('.deb') ||\n spec.startsWith('.') ||\n spec.startsWith('/') ||\n // the `-` removes a package and the `+` installs one, e.g.\n // `apt install curl vim-`\n spec.endsWith('-') ||\n spec.endsWith('+')\n );\n}\n\nfunction extractAptInstallArgs(tokens: string[]): PackageDependency[] {\n const deps: PackageDependency[] = [];\n let subCommandFound = false;\n\n for (let i = 0; i < tokens.length; i += 1) {\n const token = tokens[i];\n\n if (token.startsWith('-')) {\n if (optionsWithValue.has(token)) {\n i += 1;\n }\n continue;\n }\n\n if (!subCommandFound) {\n // `apt` accepts global options before the sub-command, so the first\n // non-option token is the sub-command\n if (token !== 'install') {\n return [];\n }\n subCommandFound = true;\n continue;\n }\n\n if (isIgnoredSpec(token)) {\n logger.trace({ spec: token }, 'Skipping apt package spec');\n continue;\n }\n\n const dep = parseSpec(token);\n if (dep) {\n deps.push(dep);\n }\n }\n\n return deps;\n}\n\n/**\n * Extracts Debian packages pinned by `apt install` or `apt-get install` in a\n * `RUN` instruction, e.g.\n *\n * ```dockerfile\n * RUN apt-get update && apt-get install -y --no-install-recommends \\\n * curl=8.5.0-2ubuntu10.6 \\\n * git=1:2.43.0-1ubuntu7.3\n * ```\n *\n * @param instruction the full `RUN` instruction, including any line continuations\n * @param escapeChar the Dockerfile escape character, already regex-escaped\n */\nexport function extractDebDeps(\n instruction: string,\n escapeChar: string,\n): PackageDependency[] {\n return parseRunCommands(instruction, escapeChar, ['apt', 'apt-get']).flatMap(\n extractAptInstallArgs,\n );\n}\n"],"mappings":";;;;;;;;;;;;AAaA,MAAM,mCAAmB,IAAI,IAAI;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;AAUD,MAAM,eAAe,MACnB,oHACF;AAEA,SAAS,UAAU,MAAwC;CACzD,MAAM,SAAS,aAAa,KAAK,IAAI,CAAC,EAAE;CACxC,IAAI,CAAC,QAAQ;EACX,OAAO,MAAM,EAAE,KAAK,GAAG,uCAAuC;EAC9D,OAAO;CACT;CAEA,MAAM,EAAE,MAAM,YAAY;CAC1B,MAAM,MAAyB;EAC7B,YAAY,cAAc;EAC1B,SAAS;CACX;CAEA,IAAI,CAAC,SAAS;EAGZ,IAAI,aAAa;EACjB,OAAO;CACT;CAEA,IAAI,QAAQ,SAAS,GAAG,GAAG;EACzB,IAAI,aAAa;EACjB,OAAO;CACT;CAIA,IAAI,CAACA,IAAc,gBAAgB,OAAO,GAAG;EAC3C,IAAI,aAAa;EACjB,OAAO;CACT;CAEA,IAAI,eAAe;CACnB,IAAI,gBAAgB;CAEpB,IAAI,4BAA4B,GAAG,KAAK,MAAM,GAAG,CAAC,QAAQ,MAAM,EAAE;CAClE,OAAO;AACT;;AAGA,SAAS,cAAc,MAAuB;CAC5C,OAEE,KAAK,SAAS,MAAM,KACpB,KAAK,WAAW,GAAG,KACnB,KAAK,WAAW,GAAG,KAGnB,KAAK,SAAS,GAAG,KACjB,KAAK,SAAS,GAAG;AAErB;AAEA,SAAS,sBAAsB,QAAuC;CACpE,MAAM,OAA4B,CAAC;CACnC,IAAI,kBAAkB;CAEtB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;EACzC,MAAM,QAAQ,OAAO;EAErB,IAAI,MAAM,WAAW,GAAG,GAAG;GACzB,IAAI,iBAAiB,IAAI,KAAK,GAC5B,KAAK;GAEP;EACF;EAEA,IAAI,CAAC,iBAAiB;GAGpB,IAAI,UAAU,WACZ,OAAO,CAAC;GAEV,kBAAkB;GAClB;EACF;EAEA,IAAI,cAAc,KAAK,GAAG;GACxB,OAAO,MAAM,EAAE,MAAM,MAAM,GAAG,2BAA2B;GACzD;EACF;EAEA,MAAM,MAAM,UAAU,KAAK;EAC3B,IAAI,KACF,KAAK,KAAK,GAAG;CAEjB;CAEA,OAAO;AACT;;;;;;;;;;;;;;AAeA,SAAgB,eACd,aACA,YACqB;CACrB,OAAO,iBAAiB,aAAa,YAAY,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,QACnE,qBACF;AACF"}
|
|
@@ -6,6 +6,7 @@ import { api, id } from "../../versioning/debian/index.js";
|
|
|
6
6
|
import { id as id$1 } from "../../versioning/ubuntu/index.js";
|
|
7
7
|
import { DockerDatasource } from "../../datasource/docker/index.js";
|
|
8
8
|
import { extractApkDeps } from "./apk.js";
|
|
9
|
+
import { extractDebDeps } from "./deb.js";
|
|
9
10
|
import { isNonEmptyStringAndNotWhitespace, isNumericString, isString } from "@sindresorhus/is";
|
|
10
11
|
//#region lib/modules/manager/dockerfile/extract.ts
|
|
11
12
|
const variableMarker = "$";
|
|
@@ -239,7 +240,7 @@ function extractPackageFile(content, _packageFile, config) {
|
|
|
239
240
|
deps.push(dep);
|
|
240
241
|
}
|
|
241
242
|
}
|
|
242
|
-
for (const dep of extractApkDeps(instruction, escapeChar)) {
|
|
243
|
+
for (const dep of [...extractApkDeps(instruction, escapeChar), ...extractDebDeps(instruction, escapeChar)]) {
|
|
243
244
|
dep.depType = "install";
|
|
244
245
|
deps.push(dep);
|
|
245
246
|
}
|