@platforma-sdk/package-builder-lib 1.4.0 → 1.4.2
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/_virtual/_rolldown/runtime.cjs +2 -3
- package/dist/_virtual/_rolldown/runtime.js +1 -2
- package/dist/core/archive.cjs +1 -2
- package/dist/core/archive.cjs.map +1 -1
- package/dist/core/archive.js +1 -2
- package/dist/core/conda/builder.cjs +1 -2
- package/dist/core/conda/builder.cjs.map +1 -1
- package/dist/core/conda/builder.js +1 -2
- package/dist/core/conda/builder.js.map +1 -1
- package/dist/core/conda/validate-spec.cjs +1 -2
- package/dist/core/conda/validate-spec.js +1 -2
- package/dist/core/core.cjs +11 -12
- package/dist/core/core.cjs.map +1 -1
- package/dist/core/core.d.ts +3 -5
- package/dist/core/core.d.ts.map +1 -1
- package/dist/core/core.js +13 -13
- package/dist/core/core.js.map +1 -1
- package/dist/core/docker-conda.cjs +1 -2
- package/dist/core/docker-conda.js +1 -2
- package/dist/core/docker-coverage.cjs +1 -2
- package/dist/core/docker-coverage.d.ts +1 -3
- package/dist/core/docker-coverage.d.ts.map +1 -1
- package/dist/core/docker-coverage.js +3 -3
- package/dist/core/docker-coverage.js.map +1 -1
- package/dist/core/docker-python.cjs +1 -2
- package/dist/core/docker-python.js +1 -2
- package/dist/core/docker.cjs +3 -5
- package/dist/core/docker.cjs.map +1 -1
- package/dist/core/docker.js +3 -5
- package/dist/core/docker.js.map +1 -1
- package/dist/core/envs.cjs +1 -2
- package/dist/core/envs.d.ts +0 -1
- package/dist/core/envs.js +1 -2
- package/dist/core/package-info.cjs +13 -12
- package/dist/core/package-info.cjs.map +1 -1
- package/dist/core/package-info.d.ts +4 -5
- package/dist/core/package-info.d.ts.map +1 -1
- package/dist/core/package-info.js +13 -12
- package/dist/core/package-info.js.map +1 -1
- package/dist/core/paths.cjs +1 -2
- package/dist/core/paths.cjs.map +1 -1
- package/dist/core/paths.js +1 -2
- package/dist/core/paths.js.map +1 -1
- package/dist/core/push-guard.cjs +1 -2
- package/dist/core/push-guard.cjs.map +1 -1
- package/dist/core/push-guard.d.ts +0 -2
- package/dist/core/push-guard.d.ts.map +1 -1
- package/dist/core/push-guard.js +1 -2
- package/dist/core/resolver.cjs +1 -2
- package/dist/core/resolver.js +1 -2
- package/dist/core/schemas/artifacts.cjs +1 -2
- package/dist/core/schemas/artifacts.d.ts +1 -169
- package/dist/core/schemas/artifacts.d.ts.map +1 -1
- package/dist/core/schemas/artifacts.js +1 -2
- package/dist/core/schemas/entrypoints.cjs +1 -2
- package/dist/core/schemas/entrypoints.d.ts +1 -352
- package/dist/core/schemas/entrypoints.d.ts.map +1 -1
- package/dist/core/schemas/entrypoints.js +1 -2
- package/dist/core/schemas/sw-json.cjs +1 -2
- package/dist/core/schemas/sw-json.js +1 -2
- package/dist/core/storage.cjs +1 -2
- package/dist/core/storage.js +1 -2
- package/dist/core/sw-json-render.cjs +1 -2
- package/dist/core/sw-json-render.js +1 -2
- package/dist/core/util.cjs +1 -2
- package/dist/core/util.cjs.map +1 -1
- package/dist/core/util.d.ts +0 -1
- package/dist/core/util.js +1 -2
- package/dist/defaults.cjs +1 -2
- package/dist/defaults.d.ts +0 -1
- package/dist/defaults.js +1 -2
- package/dist/index.cjs +1 -2
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/package.json +20 -15
- package/src/core/__tests__/docker-build.test.ts +51 -0
- package/src/core/conda/builder.ts +1 -1
- package/src/core/docker.ts +2 -7
|
@@ -6,7 +6,7 @@ import { micromambaDownloadUrl } from "./conda/builder.js";
|
|
|
6
6
|
import { validateCondaSpec } from "./conda/validate-spec.js";
|
|
7
7
|
import * as fs$1 from "node:fs";
|
|
8
8
|
import * as path$1 from "node:path";
|
|
9
|
-
|
|
9
|
+
// src/core/docker-conda.ts
|
|
10
10
|
const tmpSpecFile = "tmp-env-spec-88344b62d74b9307.yaml";
|
|
11
11
|
function generateCondaDockerfileContent(options, arch) {
|
|
12
12
|
const templatePath = assets("conda-dockerfile.template");
|
|
@@ -65,7 +65,6 @@ function verifyDockerOptions(options) {
|
|
|
65
65
|
if (!fs$1.existsSync(options.dockerfile)) throw CLIError(`Dockerfile '${options.dockerfile}' not found`);
|
|
66
66
|
if (!fs$1.existsSync(options.context)) throw CLIError(`Context '${options.context}' not found`);
|
|
67
67
|
}
|
|
68
|
-
//#endregion
|
|
69
68
|
export { prepareDockerOptions, tmpSpecFile };
|
|
70
69
|
|
|
71
70
|
//# sourceMappingURL=docker-conda.js.map
|
|
@@ -2,7 +2,7 @@ const require_defaults = require("../defaults.cjs");
|
|
|
2
2
|
const require_envs = require("./envs.cjs");
|
|
3
3
|
const require_util = require("./util.cjs");
|
|
4
4
|
const require_docker = require("./docker.cjs");
|
|
5
|
-
|
|
5
|
+
// src/core/docker-coverage.ts
|
|
6
6
|
/**
|
|
7
7
|
* The software entrypoints among `entrypoints` that yield no docker image.
|
|
8
8
|
*
|
|
@@ -48,7 +48,6 @@ function assertDockerCoverage(coverage) {
|
|
|
48
48
|
const list = coverage.softwareWithoutDocker.map((name) => ` - ${name}`).join("\n");
|
|
49
49
|
throw require_util.CLIError(`These software entrypoints produce no docker image, so no kubernetes installation can run them:\n${list}\n An image is autogenerated only for 'python' and 'conda' artifacts. Give each entrypoint above an explicit 'docker' block next to its 'binary' one.\n If this package really is meant to be binary-only, declare that with "block-software": { "requireDocker": false }.`);
|
|
50
50
|
}
|
|
51
|
-
//#endregion
|
|
52
51
|
exports.assertDockerCoverage = assertDockerCoverage;
|
|
53
52
|
exports.descriptorHasNoDockerVariant = descriptorHasNoDockerVariant;
|
|
54
53
|
exports.softwareEntrypointsWithoutDocker = softwareEntrypointsWithoutDocker;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Entrypoint
|
|
2
|
-
//#region src/core/docker-coverage.d.ts
|
|
1
|
+
import { Entrypoint } from "./schemas/entrypoints.js";
|
|
3
2
|
export type DockerCoverage = {
|
|
4
3
|
/** Names of software entrypoints that produce no docker image. */
|
|
5
4
|
softwareWithoutDocker: string[];
|
|
@@ -31,5 +30,4 @@ export declare function softwareEntrypointsWithoutDocker(entrypoints: Map<string
|
|
|
31
30
|
export declare function descriptorHasNoDockerVariant(descriptor: unknown): boolean;
|
|
32
31
|
/** Throws when CI is about to describe software that no k8s install can run. */
|
|
33
32
|
export declare function assertDockerCoverage(coverage: DockerCoverage): void;
|
|
34
|
-
//#endregion
|
|
35
33
|
//# sourceMappingURL=docker-coverage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docker-coverage.d.ts","names":[],"sources":["../../src/core/docker-coverage.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"docker-coverage.d.ts","names":["entrypoint.Entrypoint"],"sources":["../../src/core/docker-coverage.ts"],"mappings":";YAwBY;;EAEV;;EAEA;;;;;;;;;;;;;;;wBAgBc,iCACd,aAAa,YAAYA;;;;;;;;;wBAgCX,6BAA6B;;wBAmB7B,qBAAqB,UAAU"}
|
|
@@ -2,7 +2,7 @@ import { NO_SOFTWARE_PLACEHOLDER } from "../defaults.js";
|
|
|
2
2
|
import { isCI } from "./envs.js";
|
|
3
3
|
import { CLIError } from "./util.js";
|
|
4
4
|
import { entrypointName } from "./docker.js";
|
|
5
|
-
|
|
5
|
+
// src/core/docker-coverage.ts
|
|
6
6
|
/**
|
|
7
7
|
* The software entrypoints among `entrypoints` that yield no docker image.
|
|
8
8
|
*
|
|
@@ -45,9 +45,9 @@ function assertDockerCoverage(coverage) {
|
|
|
45
45
|
if (!isCI()) return;
|
|
46
46
|
if (coverage.requirementWaived) return;
|
|
47
47
|
if (coverage.softwareWithoutDocker.length === 0) return;
|
|
48
|
-
|
|
48
|
+
const list = coverage.softwareWithoutDocker.map((name) => ` - ${name}`).join("\n");
|
|
49
|
+
throw CLIError(`These software entrypoints produce no docker image, so no kubernetes installation can run them:\n${list}\n An image is autogenerated only for 'python' and 'conda' artifacts. Give each entrypoint above an explicit 'docker' block next to its 'binary' one.\n If this package really is meant to be binary-only, declare that with "block-software": { "requireDocker": false }.`);
|
|
49
50
|
}
|
|
50
|
-
//#endregion
|
|
51
51
|
export { assertDockerCoverage, descriptorHasNoDockerVariant, softwareEntrypointsWithoutDocker };
|
|
52
52
|
|
|
53
53
|
//# sourceMappingURL=docker-coverage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docker-coverage.js","names":["docker.entrypointName","defaults.NO_SOFTWARE_PLACEHOLDER","envs.isCI","util.CLIError"],"sources":["../../src/core/docker-coverage.ts"],"sourcesContent":["// Guard against releasing software that cannot run where we deploy it.\n//\n// Nothing else requires a docker variant: an image is autogenerated only for\n// `python` and `conda` artifacts (`artifacts.dockerAutogenTypes`), so a `java`,\n// `R` or plain `binary` entrypoint without an explicit `docker:` block writes a\n// descriptor carrying `binary` and nothing else. Every Platforma installation\n// is kubernetes-based, and the k8s runner has no binary fallback — it fails the\n// command with a bare \"docker image is not specified\". CI stays green, the\n// defect surfaces the first time a user runs the block (MILAB-6872).\n//\n// So: in CI, describing a software entrypoint that produces no image is an\n// error, unless the package declares itself binary-only with\n// `\"block-software\": { \"requireDocker\": false }`.\n//\n// The check reads the package's declaration, not what this particular run\n// built: `--variant binary` and other partial builds are legitimate, a\n// misdeclared entrypoint is not.\n\nimport * as defaults from \"../defaults\";\nimport * as docker from \"./docker\";\nimport * as envs from \"./envs\";\nimport type * as entrypoint from \"./schemas/entrypoints\";\nimport * as util from \"./util\";\n\nexport type DockerCoverage = {\n /** Names of software entrypoints that produce no docker image. */\n softwareWithoutDocker: string[];\n /** Package opted out with `\"block-software\": { \"requireDocker\": false }`. */\n requirementWaived: boolean;\n};\n\n/**\n * The software entrypoints among `entrypoints` that yield no docker image.\n *\n * `entrypoints` is expected in the shape `PackageInfo.entrypoints` produces:\n * one entry per declared entrypoint plus a virtual `<name>:docker` companion\n * carrying the image, explicit or autogenerated. So a missing companion is the\n * whole signal.\n *\n * Run environments and assets are not software and never carry an image of\n * their own (a python image bakes its environment in), so they are skipped. So\n * are references, which re-export a descriptor this package neither builds nor\n * can fix — `SwJsonRenderer.copySwJson` warns about those instead.\n */\nexport function softwareEntrypointsWithoutDocker(\n entrypoints: Map<string, entrypoint.Entrypoint>,\n): string[] {\n const uncovered: string[] = [];\n\n for (const [name, ep] of entrypoints.entries()) {\n if (ep.type !== \"software\") continue;\n\n // This entry *is* an image: the virtual companion, or a docker-only entrypoint.\n // Told apart by artifact type rather than by the ':docker' name suffix —\n // entrypoint names are barely constrained, so `main:docker` is a legal name for a\n // declared entrypoint, and reading the suffix as \"generated companion\" would let a\n // binary-only entrypoint hide behind it. Pairing stays consistent either way: a\n // declared `main:docker` is answered by the companion key `main:docker:docker`,\n // which is exactly what PackageInfo generates for it.\n if (ep.artifact.type === \"docker\") continue;\n\n if (entrypoints.has(docker.entrypointName(name))) continue;\n\n uncovered.push(name);\n }\n\n return uncovered;\n}\n\n/**\n * True when an already-rendered descriptor describes runnable software carrying no\n * image — the shape no kubernetes installation can run.\n *\n * Reads the descriptor rather than a package declaration, for the one case where the\n * declaration is out of reach: a reference entrypoint, whose descriptor is copied\n * verbatim from the package that owns it.\n */\nexport function descriptorHasNoDockerVariant(descriptor: unknown): boolean {\n if (typeof descriptor !== \"object\" || descriptor === null) return false;\n\n const d = descriptor as {\n binary?: { registry?: unknown };\n docker?: unknown;\n local?: unknown;\n };\n\n // No `binary` means a run environment or an asset; `docker` means it is covered;\n // `local` is a dev-mode descriptor, which points at a directory rather than a\n // registry and never runs on a cluster.\n if (d.binary === undefined || d.docker !== undefined || d.local !== undefined) return false;\n\n // The `variant=none` placeholder describes a package built without software at all.\n return d.binary.registry !== defaults.NO_SOFTWARE_PLACEHOLDER;\n}\n\n/** Throws when CI is about to describe software that no k8s install can run. */\nexport function assertDockerCoverage(coverage: DockerCoverage): void {\n if (!envs.isCI()) return;\n if (coverage.requirementWaived) return;\n if (coverage.softwareWithoutDocker.length === 0) return;\n\n const list = coverage.softwareWithoutDocker.map((name) => ` - ${name}`).join(\"\\n\");\n\n throw util.CLIError(\n `These software entrypoints produce no docker image, so no kubernetes installation ` +\n `can run them:\\n${list}\\n` +\n ` An image is autogenerated only for 'python' and 'conda' artifacts. Give each ` +\n `entrypoint above an explicit 'docker' block next to its 'binary' one.\\n` +\n ` If this package really is meant to be binary-only, declare that with ` +\n `\"block-software\": { \"requireDocker\": false }.`,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4CA,SAAgB,iCACd,aACU;CACV,MAAM,YAAsB,CAAC;CAE7B,KAAK,MAAM,CAAC,MAAM,OAAO,YAAY,QAAQ,GAAG;EAC9C,IAAI,GAAG,SAAS,YAAY;EAS5B,IAAI,GAAG,SAAS,SAAS,UAAU;EAEnC,IAAI,YAAY,IAAIA,eAAsB,IAAI,CAAC,GAAG;EAElD,UAAU,KAAK,IAAI;CACrB;CAEA,OAAO;AACT;;;;;;;;;AAUA,SAAgB,6BAA6B,YAA8B;CACzE,IAAI,OAAO,eAAe,YAAY,eAAe,MAAM,OAAO;CAElE,MAAM,IAAI;CASV,IAAI,EAAE,WAAW,KAAA,KAAa,EAAE,WAAW,KAAA,KAAa,EAAE,UAAU,KAAA,GAAW,OAAO;CAGtF,OAAO,EAAE,OAAO,aAAaC;AAC/B;;AAGA,SAAgB,qBAAqB,UAAgC;CACnE,IAAI,CAACC,KAAU,GAAG;CAClB,IAAI,SAAS,mBAAmB;CAChC,IAAI,SAAS,sBAAsB,WAAW,GAAG;
|
|
1
|
+
{"version":3,"file":"docker-coverage.js","names":["docker.entrypointName","defaults.NO_SOFTWARE_PLACEHOLDER","envs.isCI","util.CLIError"],"sources":["../../src/core/docker-coverage.ts"],"sourcesContent":["// Guard against releasing software that cannot run where we deploy it.\n//\n// Nothing else requires a docker variant: an image is autogenerated only for\n// `python` and `conda` artifacts (`artifacts.dockerAutogenTypes`), so a `java`,\n// `R` or plain `binary` entrypoint without an explicit `docker:` block writes a\n// descriptor carrying `binary` and nothing else. Every Platforma installation\n// is kubernetes-based, and the k8s runner has no binary fallback — it fails the\n// command with a bare \"docker image is not specified\". CI stays green, the\n// defect surfaces the first time a user runs the block (MILAB-6872).\n//\n// So: in CI, describing a software entrypoint that produces no image is an\n// error, unless the package declares itself binary-only with\n// `\"block-software\": { \"requireDocker\": false }`.\n//\n// The check reads the package's declaration, not what this particular run\n// built: `--variant binary` and other partial builds are legitimate, a\n// misdeclared entrypoint is not.\n\nimport * as defaults from \"../defaults\";\nimport * as docker from \"./docker\";\nimport * as envs from \"./envs\";\nimport type * as entrypoint from \"./schemas/entrypoints\";\nimport * as util from \"./util\";\n\nexport type DockerCoverage = {\n /** Names of software entrypoints that produce no docker image. */\n softwareWithoutDocker: string[];\n /** Package opted out with `\"block-software\": { \"requireDocker\": false }`. */\n requirementWaived: boolean;\n};\n\n/**\n * The software entrypoints among `entrypoints` that yield no docker image.\n *\n * `entrypoints` is expected in the shape `PackageInfo.entrypoints` produces:\n * one entry per declared entrypoint plus a virtual `<name>:docker` companion\n * carrying the image, explicit or autogenerated. So a missing companion is the\n * whole signal.\n *\n * Run environments and assets are not software and never carry an image of\n * their own (a python image bakes its environment in), so they are skipped. So\n * are references, which re-export a descriptor this package neither builds nor\n * can fix — `SwJsonRenderer.copySwJson` warns about those instead.\n */\nexport function softwareEntrypointsWithoutDocker(\n entrypoints: Map<string, entrypoint.Entrypoint>,\n): string[] {\n const uncovered: string[] = [];\n\n for (const [name, ep] of entrypoints.entries()) {\n if (ep.type !== \"software\") continue;\n\n // This entry *is* an image: the virtual companion, or a docker-only entrypoint.\n // Told apart by artifact type rather than by the ':docker' name suffix —\n // entrypoint names are barely constrained, so `main:docker` is a legal name for a\n // declared entrypoint, and reading the suffix as \"generated companion\" would let a\n // binary-only entrypoint hide behind it. Pairing stays consistent either way: a\n // declared `main:docker` is answered by the companion key `main:docker:docker`,\n // which is exactly what PackageInfo generates for it.\n if (ep.artifact.type === \"docker\") continue;\n\n if (entrypoints.has(docker.entrypointName(name))) continue;\n\n uncovered.push(name);\n }\n\n return uncovered;\n}\n\n/**\n * True when an already-rendered descriptor describes runnable software carrying no\n * image — the shape no kubernetes installation can run.\n *\n * Reads the descriptor rather than a package declaration, for the one case where the\n * declaration is out of reach: a reference entrypoint, whose descriptor is copied\n * verbatim from the package that owns it.\n */\nexport function descriptorHasNoDockerVariant(descriptor: unknown): boolean {\n if (typeof descriptor !== \"object\" || descriptor === null) return false;\n\n const d = descriptor as {\n binary?: { registry?: unknown };\n docker?: unknown;\n local?: unknown;\n };\n\n // No `binary` means a run environment or an asset; `docker` means it is covered;\n // `local` is a dev-mode descriptor, which points at a directory rather than a\n // registry and never runs on a cluster.\n if (d.binary === undefined || d.docker !== undefined || d.local !== undefined) return false;\n\n // The `variant=none` placeholder describes a package built without software at all.\n return d.binary.registry !== defaults.NO_SOFTWARE_PLACEHOLDER;\n}\n\n/** Throws when CI is about to describe software that no k8s install can run. */\nexport function assertDockerCoverage(coverage: DockerCoverage): void {\n if (!envs.isCI()) return;\n if (coverage.requirementWaived) return;\n if (coverage.softwareWithoutDocker.length === 0) return;\n\n const list = coverage.softwareWithoutDocker.map((name) => ` - ${name}`).join(\"\\n\");\n\n throw util.CLIError(\n `These software entrypoints produce no docker image, so no kubernetes installation ` +\n `can run them:\\n${list}\\n` +\n ` An image is autogenerated only for 'python' and 'conda' artifacts. Give each ` +\n `entrypoint above an explicit 'docker' block next to its 'binary' one.\\n` +\n ` If this package really is meant to be binary-only, declare that with ` +\n `\"block-software\": { \"requireDocker\": false }.`,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4CA,SAAgB,iCACd,aACU;CACV,MAAM,YAAsB,CAAC;CAE7B,KAAK,MAAM,CAAC,MAAM,OAAO,YAAY,QAAQ,GAAG;EAC9C,IAAI,GAAG,SAAS,YAAY;EAS5B,IAAI,GAAG,SAAS,SAAS,UAAU;EAEnC,IAAI,YAAY,IAAIA,eAAsB,IAAI,CAAC,GAAG;EAElD,UAAU,KAAK,IAAI;CACrB;CAEA,OAAO;AACT;;;;;;;;;AAUA,SAAgB,6BAA6B,YAA8B;CACzE,IAAI,OAAO,eAAe,YAAY,eAAe,MAAM,OAAO;CAElE,MAAM,IAAI;CASV,IAAI,EAAE,WAAW,KAAA,KAAa,EAAE,WAAW,KAAA,KAAa,EAAE,UAAU,KAAA,GAAW,OAAO;CAGtF,OAAO,EAAE,OAAO,aAAaC;AAC/B;;AAGA,SAAgB,qBAAqB,UAAgC;CACnE,IAAI,CAACC,KAAU,GAAG;CAClB,IAAI,SAAS,mBAAmB;CAChC,IAAI,SAAS,sBAAsB,WAAW,GAAG;CAEjD,MAAM,OAAO,SAAS,sBAAsB,KAAK,SAAS,SAAS,MAAM,CAAC,CAAC,KAAK,IAAI;CAEpF,MAAMC,SACJ,oGACoB,KAAK,6QAK3B;AACF"}
|
|
@@ -8,7 +8,7 @@ let node_fs = require("node:fs");
|
|
|
8
8
|
node_fs = require_runtime.__toESM(node_fs, 1);
|
|
9
9
|
let node_path = require("node:path");
|
|
10
10
|
node_path = require_runtime.__toESM(node_path, 1);
|
|
11
|
-
|
|
11
|
+
// src/core/docker-python.ts
|
|
12
12
|
const PYTHON_VERSION_PATTERNS = {
|
|
13
13
|
PY3_PREFIX: /^3\./,
|
|
14
14
|
VERSION_FORMAT: /^3\.\d+(?:\.\d+)?(?:[-+_][a-zA-Z0-9]+|(?:a|b|rc)\d+|[a-zA-Z]+\d+(?:\.[a-zA-Z0-9]+)*)*$/,
|
|
@@ -141,7 +141,6 @@ function pythonVersionToDockerTag(pythonVersion) {
|
|
|
141
141
|
if (parts.length > 2) return `python:${parts[0]}.${parts[1]}-slim`;
|
|
142
142
|
return `python:${pythonVersion}-slim`;
|
|
143
143
|
}
|
|
144
|
-
//#endregion
|
|
145
144
|
exports.getRunEnvironmentPythonInfo = getRunEnvironmentPythonInfo;
|
|
146
145
|
exports.prepareDockerOptions = prepareDockerOptions;
|
|
147
146
|
|
|
@@ -5,7 +5,7 @@ import { assets } from "./paths.js";
|
|
|
5
5
|
import { resolveRunEnvironment } from "./resolver.js";
|
|
6
6
|
import * as fs$1 from "node:fs";
|
|
7
7
|
import * as path$1 from "node:path";
|
|
8
|
-
|
|
8
|
+
// src/core/docker-python.ts
|
|
9
9
|
const PYTHON_VERSION_PATTERNS = {
|
|
10
10
|
PY3_PREFIX: /^3\./,
|
|
11
11
|
VERSION_FORMAT: /^3\.\d+(?:\.\d+)?(?:[-+_][a-zA-Z0-9]+|(?:a|b|rc)\d+|[a-zA-Z]+\d+(?:\.[a-zA-Z0-9]+)*)*$/,
|
|
@@ -138,7 +138,6 @@ function pythonVersionToDockerTag(pythonVersion) {
|
|
|
138
138
|
if (parts.length > 2) return `python:${parts[0]}.${parts[1]}-slim`;
|
|
139
139
|
return `python:${pythonVersion}-slim`;
|
|
140
140
|
}
|
|
141
|
-
//#endregion
|
|
142
141
|
export { getRunEnvironmentPythonInfo, prepareDockerOptions };
|
|
143
142
|
|
|
144
143
|
//# sourceMappingURL=docker-python.js.map
|
package/dist/core/docker.cjs
CHANGED
|
@@ -8,7 +8,7 @@ node_path = require_runtime.__toESM(node_path, 1);
|
|
|
8
8
|
let node_os = require("node:os");
|
|
9
9
|
node_os = require_runtime.__toESM(node_os, 1);
|
|
10
10
|
let node_child_process = require("node:child_process");
|
|
11
|
-
|
|
11
|
+
// src/core/docker.ts
|
|
12
12
|
/**
|
|
13
13
|
* To allow entrypoint keep both docker and binary package at the same time, we create virtual entrypoint with ':docker' suffix,
|
|
14
14
|
* as entrypoints could not keep two different artifacts at the same time.
|
|
@@ -84,8 +84,6 @@ function build(context, dockerfile, tag, softwarePackage, softwareVersion) {
|
|
|
84
84
|
"build",
|
|
85
85
|
"--platform",
|
|
86
86
|
require_defaults.DOCKER_BUILD_PLATFORM,
|
|
87
|
-
"--provenance=false",
|
|
88
|
-
"--sbom=false",
|
|
89
87
|
"-t",
|
|
90
88
|
tag,
|
|
91
89
|
context,
|
|
@@ -101,7 +99,8 @@ function build(context, dockerfile, tag, softwarePackage, softwareVersion) {
|
|
|
101
99
|
stdio: "inherit",
|
|
102
100
|
env: {
|
|
103
101
|
...process.env,
|
|
104
|
-
HOME: process.env.HOME || node_os.homedir()
|
|
102
|
+
HOME: process.env.HOME || node_os.homedir(),
|
|
103
|
+
BUILDX_NO_DEFAULT_ATTESTATIONS: "1"
|
|
105
104
|
}
|
|
106
105
|
});
|
|
107
106
|
if (result.error) throw result.error;
|
|
@@ -205,7 +204,6 @@ function contentHash(contextFullPath, dockerfileFullPath) {
|
|
|
205
204
|
function dockerTag(packageName, contentHash, registry) {
|
|
206
205
|
return `${registry ?? "containers.pl-open.science/milaboratories/pl-containers"}:${packageName.replaceAll("/", ".")}.${contentHash}`;
|
|
207
206
|
}
|
|
208
|
-
//#endregion
|
|
209
207
|
exports.addTag = addTag;
|
|
210
208
|
exports.build = build;
|
|
211
209
|
exports.dockerfileAutogenPath = dockerfileAutogenPath;
|
package/dist/core/docker.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docker.cjs","names":["os","path","fs"],"sources":["../../src/core/docker.ts"],"sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport * as defaults from \"../defaults\";\nimport type * as artifacts from \"./schemas/artifacts\";\nimport * as util from \"./util\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\n\n/**\n * To allow entrypoint keep both docker and binary package at the same time, we create virtual entrypoint with ':docker' suffix,\n * as entrypoints could not keep two different artifacts at the same time.\n */\nexport function entrypointName(name: string): string {\n return name + \":docker\";\n}\n\nexport function isVirtualDockerEntrypointName(name: string): boolean {\n return name.endsWith(\":docker\");\n}\n\nexport function entrypointNameToOrigin(name: string): string {\n if (!isVirtualDockerEntrypointName(name)) {\n return name;\n }\n return name.substring(0, name.length - \":docker\".length);\n}\n\nexport function getImageHash(tag: string): string {\n const result = spawnSync(\n \"docker\",\n [\"image\", \"ls\", \"--filter=reference=\" + tag, \"--format={{.ID}}\"],\n {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n },\n );\n\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`local docker image check failed with status ${result.status}`);\n }\n\n const output = result.stdout.toString().trim();\n if (output.split(\"\\n\").length > 1) {\n throw util.CLIError(\n `package-builder internal logic error: more than one image found by exact tag match: ${output}`,\n );\n }\n\n return output;\n}\n\nexport function getImageEntrypoint(tag: string): string[] {\n const result = spawnSync(\n \"docker\",\n [\"image\", \"inspect\", tag, \"--format\", \"{{ .Config.Entrypoint | json }}\"],\n {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n },\n );\n\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker image inspect' failed with status ${result.status}`);\n }\n\n const output = result.stdout.toString().trim(); // 'null' or '[<string>, ...]' in JSON format\n return (JSON.parse(output) ?? []) as string[];\n}\n\nexport function localImageExists(tag: string): boolean {\n return getImageHash(tag) !== \"\";\n}\n\nexport function remoteImageExists(tag: string): boolean {\n const result = spawnSync(\"docker\", [\"manifest\", \"inspect\", tag], {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n\n if (result.error || result.status !== 0) {\n return false;\n }\n\n return true;\n}\n\nexport function build(\n context: string,\n dockerfile: string,\n tag: string,\n softwarePackage: string,\n softwareVersion: string | undefined,\n) {\n const result = spawnSync(\n \"docker\",\n [\n \"build\",\n // Pin platform so Platforma's linux/amd64 K8s nodes can run the image\n // regardless of host arch (cross-compile via qemu on non-x64 hosts).\n \"--platform\",\n defaults.DOCKER_BUILD_PLATFORM,\n // Disable buildkit's SLSA provenance + SBOM attestations. They embed\n // build-time timestamps into the manifest list, which produces a fresh\n // image digest on every build of identical source. That breaks the\n // content-addressable tag scheme (every dev rebuild re-pushes a new\n // tag) and defeats publishDockerImage's `remoteImageExists` smart-skip.\n \"--provenance=false\",\n \"--sbom=false\",\n \"-t\",\n tag,\n context,\n \"-f\",\n dockerfile,\n \"--label\",\n \"com.milaboratories.package-builder.software=true\",\n \"--label\",\n \"com.milaboratories.package-builder.software.package=\" + softwarePackage,\n \"--label\",\n \"com.milaboratories.package-builder.software.version=\" + softwareVersion,\n ],\n {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n },\n );\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker build' failed with status ${result.status}`);\n }\n}\n\nexport function push(tag: string) {\n const result = spawnSync(\"docker\", [\"push\", tag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n const registry = tag.split(\"/\")[0];\n throw util.CLIError(\n `'docker push ${tag}' failed with status ${result.status}.\\n` +\n `If the error above mentions authentication or denied access, log in first:\\n` +\n ` aws sso login --profile research-poweruser <YOUR_PROFILE:research-poweruser?> \\n` +\n `Then login in docker:` +\n ` aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${registry}\\n` +\n `(for a private ECR use 'aws ecr' and your region instead of 'ecr-public'/us-east-1).`,\n );\n }\n}\n\nexport function addTag(imageIdOrTag: string, newTag: string) {\n const result = spawnSync(\"docker\", [\"image\", \"tag\", imageIdOrTag, newTag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker tag' failed with status ${result.status}`);\n }\n}\n\nexport function removeTag(imageTag: string) {\n const result = spawnSync(\"docker\", [\"image\", \"rm\", imageTag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker image rm' failed with status ${result.status}`);\n }\n}\n\n/**\n * Generate unique content-addressable image tag\n * @param artifactName: artifact name generated from package name and artifact ID (or explicitly set for artifact in .name field)\n * @param imageID: unique image content hash (docker image ID in docker ls)\n * @param registry: custom registry and repository to use for this image\n * @returns full image tag in format: <registry>/repository:<artifactName>.<imageID>\n */\nexport function generateRemoteTagName(\n artifactName: string,\n imageID: string,\n registry?: string,\n): string {\n return dockerTag(artifactName, imageID, registry);\n}\n\n/**\n * Generate unique content-addressable image tag out of directories and Dockerfile.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns full image tag in format: <registry>/repository:<artifactName>.<contentHash>\n */\nexport function generateLocalTagName(packageRoot: string, artifact: artifacts.dockerType): string {\n const dockerfile = dockerfileAbsPath(packageRoot, artifact);\n const context = contextAbsPath(packageRoot, artifact);\n const hash = contentHash(context, dockerfile);\n\n return dockerTag(\"local-image\", hash);\n}\n\n/**\n * Absolute path to autogenerated Dockerfile for given artifact.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifactID: artifact ID\n * @returns absolute path to autogenerated Dockerfile\n */\nexport function dockerfileAutogenPath(packageRoot: string, artifactID: string): string {\n return path.resolve(packageRoot, \"dist\", \"docker\", `Dockerfile-${artifactID}`);\n}\n\n/**\n * Resolve path to Dockerfile.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns absolute path to Dockerfile\n */\nfunction dockerfileAbsPath(packageRoot: string, artifact: artifacts.dockerType): string {\n return path.resolve(packageRoot, artifact.dockerfile ?? \"Dockerfile\");\n}\n\n/**\n * Resolve path to docker build context directory.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns absolute path to docker build context directory\n */\nfunction contextAbsPath(packageRoot: string, artifact: artifacts.dockerType): string {\n if (artifact.context === \"./\" || artifact.context === \".\") {\n throw util.CLIError(\n `Invalid Docker context: \"${artifact.context}\". Context cannot be \"./\" or \".\" - use absolute path or relative path without \"./\" prefix`,\n );\n }\n return path.resolve(packageRoot, artifact.context ?? \".\");\n}\n\n/**\n * Calculate cummulative hash of docker build context directory context and Dockerfile.\n * To speedup hash calculation, we do not read contents of each item in context dir but\n * use metadata (size, mtime, ...).\n *\n * @param contextFullPath: abs path to docker build context\n * @param dockerfileFullPath: abs path to Dockerfile\n * @returns hash of what the keep\n */\nfunction contentHash(contextFullPath: string, dockerfileFullPath: string): string {\n if (!fs.existsSync(dockerfileFullPath)) {\n throw util.CLIError(`Dockerfile '${dockerfileFullPath}' not found`);\n }\n\n if (!fs.existsSync(contextFullPath)) {\n throw util.CLIError(`Context '${contextFullPath}' not found`);\n }\n\n const contextHash = util.hashDirMetaSync(contextFullPath);\n const dockerfileContent = fs.readFileSync(dockerfileFullPath, \"utf8\");\n contextHash.update(dockerfileContent);\n\n return contextHash.digest(\"hex\").slice(0, 12);\n}\n\nfunction dockerTag(packageName: string, contentHash: string, registry?: string): string {\n const dockerRegistry = registry ?? defaults.DOCKER_REGISTRY;\n return `${dockerRegistry}:${packageName.replaceAll(\"/\", \".\")}.${contentHash}`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"docker.cjs","names":["spawnSync","os","path","fs"],"sources":["../../src/core/docker.ts"],"sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport * as defaults from \"../defaults\";\nimport type * as artifacts from \"./schemas/artifacts\";\nimport * as util from \"./util\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\n\n/**\n * To allow entrypoint keep both docker and binary package at the same time, we create virtual entrypoint with ':docker' suffix,\n * as entrypoints could not keep two different artifacts at the same time.\n */\nexport function entrypointName(name: string): string {\n return name + \":docker\";\n}\n\nexport function isVirtualDockerEntrypointName(name: string): boolean {\n return name.endsWith(\":docker\");\n}\n\nexport function entrypointNameToOrigin(name: string): string {\n if (!isVirtualDockerEntrypointName(name)) {\n return name;\n }\n return name.substring(0, name.length - \":docker\".length);\n}\n\nexport function getImageHash(tag: string): string {\n const result = spawnSync(\n \"docker\",\n [\"image\", \"ls\", \"--filter=reference=\" + tag, \"--format={{.ID}}\"],\n {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n },\n );\n\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`local docker image check failed with status ${result.status}`);\n }\n\n const output = result.stdout.toString().trim();\n if (output.split(\"\\n\").length > 1) {\n throw util.CLIError(\n `package-builder internal logic error: more than one image found by exact tag match: ${output}`,\n );\n }\n\n return output;\n}\n\nexport function getImageEntrypoint(tag: string): string[] {\n const result = spawnSync(\n \"docker\",\n [\"image\", \"inspect\", tag, \"--format\", \"{{ .Config.Entrypoint | json }}\"],\n {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n },\n );\n\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker image inspect' failed with status ${result.status}`);\n }\n\n const output = result.stdout.toString().trim(); // 'null' or '[<string>, ...]' in JSON format\n return (JSON.parse(output) ?? []) as string[];\n}\n\nexport function localImageExists(tag: string): boolean {\n return getImageHash(tag) !== \"\";\n}\n\nexport function remoteImageExists(tag: string): boolean {\n const result = spawnSync(\"docker\", [\"manifest\", \"inspect\", tag], {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n\n if (result.error || result.status !== 0) {\n return false;\n }\n\n return true;\n}\n\nexport function build(\n context: string,\n dockerfile: string,\n tag: string,\n softwarePackage: string,\n softwareVersion: string | undefined,\n) {\n const result = spawnSync(\n \"docker\",\n [\n \"build\",\n // Pin platform so Platforma's linux/amd64 K8s nodes can run the image\n // regardless of host arch (cross-compile via qemu on non-x64 hosts).\n \"--platform\",\n defaults.DOCKER_BUILD_PLATFORM,\n \"-t\",\n tag,\n context,\n \"-f\",\n dockerfile,\n \"--label\",\n \"com.milaboratories.package-builder.software=true\",\n \"--label\",\n \"com.milaboratories.package-builder.software.package=\" + softwarePackage,\n \"--label\",\n \"com.milaboratories.package-builder.software.version=\" + softwareVersion,\n ],\n {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n // Disables buildx default provenance so the image ID stays stable; podman ignores it.\n BUILDX_NO_DEFAULT_ATTESTATIONS: \"1\",\n },\n },\n );\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker build' failed with status ${result.status}`);\n }\n}\n\nexport function push(tag: string) {\n const result = spawnSync(\"docker\", [\"push\", tag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n const registry = tag.split(\"/\")[0];\n throw util.CLIError(\n `'docker push ${tag}' failed with status ${result.status}.\\n` +\n `If the error above mentions authentication or denied access, log in first:\\n` +\n ` aws sso login --profile research-poweruser <YOUR_PROFILE:research-poweruser?> \\n` +\n `Then login in docker:` +\n ` aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${registry}\\n` +\n `(for a private ECR use 'aws ecr' and your region instead of 'ecr-public'/us-east-1).`,\n );\n }\n}\n\nexport function addTag(imageIdOrTag: string, newTag: string) {\n const result = spawnSync(\"docker\", [\"image\", \"tag\", imageIdOrTag, newTag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker tag' failed with status ${result.status}`);\n }\n}\n\nexport function removeTag(imageTag: string) {\n const result = spawnSync(\"docker\", [\"image\", \"rm\", imageTag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker image rm' failed with status ${result.status}`);\n }\n}\n\n/**\n * Generate unique content-addressable image tag\n * @param artifactName: artifact name generated from package name and artifact ID (or explicitly set for artifact in .name field)\n * @param imageID: unique image content hash (docker image ID in docker ls)\n * @param registry: custom registry and repository to use for this image\n * @returns full image tag in format: <registry>/repository:<artifactName>.<imageID>\n */\nexport function generateRemoteTagName(\n artifactName: string,\n imageID: string,\n registry?: string,\n): string {\n return dockerTag(artifactName, imageID, registry);\n}\n\n/**\n * Generate unique content-addressable image tag out of directories and Dockerfile.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns full image tag in format: <registry>/repository:<artifactName>.<contentHash>\n */\nexport function generateLocalTagName(packageRoot: string, artifact: artifacts.dockerType): string {\n const dockerfile = dockerfileAbsPath(packageRoot, artifact);\n const context = contextAbsPath(packageRoot, artifact);\n const hash = contentHash(context, dockerfile);\n\n return dockerTag(\"local-image\", hash);\n}\n\n/**\n * Absolute path to autogenerated Dockerfile for given artifact.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifactID: artifact ID\n * @returns absolute path to autogenerated Dockerfile\n */\nexport function dockerfileAutogenPath(packageRoot: string, artifactID: string): string {\n return path.resolve(packageRoot, \"dist\", \"docker\", `Dockerfile-${artifactID}`);\n}\n\n/**\n * Resolve path to Dockerfile.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns absolute path to Dockerfile\n */\nfunction dockerfileAbsPath(packageRoot: string, artifact: artifacts.dockerType): string {\n return path.resolve(packageRoot, artifact.dockerfile ?? \"Dockerfile\");\n}\n\n/**\n * Resolve path to docker build context directory.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns absolute path to docker build context directory\n */\nfunction contextAbsPath(packageRoot: string, artifact: artifacts.dockerType): string {\n if (artifact.context === \"./\" || artifact.context === \".\") {\n throw util.CLIError(\n `Invalid Docker context: \"${artifact.context}\". Context cannot be \"./\" or \".\" - use absolute path or relative path without \"./\" prefix`,\n );\n }\n return path.resolve(packageRoot, artifact.context ?? \".\");\n}\n\n/**\n * Calculate cummulative hash of docker build context directory context and Dockerfile.\n * To speedup hash calculation, we do not read contents of each item in context dir but\n * use metadata (size, mtime, ...).\n *\n * @param contextFullPath: abs path to docker build context\n * @param dockerfileFullPath: abs path to Dockerfile\n * @returns hash of what the keep\n */\nfunction contentHash(contextFullPath: string, dockerfileFullPath: string): string {\n if (!fs.existsSync(dockerfileFullPath)) {\n throw util.CLIError(`Dockerfile '${dockerfileFullPath}' not found`);\n }\n\n if (!fs.existsSync(contextFullPath)) {\n throw util.CLIError(`Context '${contextFullPath}' not found`);\n }\n\n const contextHash = util.hashDirMetaSync(contextFullPath);\n const dockerfileContent = fs.readFileSync(dockerfileFullPath, \"utf8\");\n contextHash.update(dockerfileContent);\n\n return contextHash.digest(\"hex\").slice(0, 12);\n}\n\nfunction dockerTag(packageName: string, contentHash: string, registry?: string): string {\n const dockerRegistry = registry ?? defaults.DOCKER_REGISTRY;\n return `${dockerRegistry}:${packageName.replaceAll(\"/\", \".\")}.${contentHash}`;\n}\n"],"mappings":"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"}
|
package/dist/core/docker.js
CHANGED
|
@@ -4,7 +4,7 @@ import * as fs$1 from "node:fs";
|
|
|
4
4
|
import * as path$1 from "node:path";
|
|
5
5
|
import * as os from "node:os";
|
|
6
6
|
import { spawnSync } from "node:child_process";
|
|
7
|
-
|
|
7
|
+
// src/core/docker.ts
|
|
8
8
|
/**
|
|
9
9
|
* To allow entrypoint keep both docker and binary package at the same time, we create virtual entrypoint with ':docker' suffix,
|
|
10
10
|
* as entrypoints could not keep two different artifacts at the same time.
|
|
@@ -80,8 +80,6 @@ function build(context, dockerfile, tag, softwarePackage, softwareVersion) {
|
|
|
80
80
|
"build",
|
|
81
81
|
"--platform",
|
|
82
82
|
DOCKER_BUILD_PLATFORM,
|
|
83
|
-
"--provenance=false",
|
|
84
|
-
"--sbom=false",
|
|
85
83
|
"-t",
|
|
86
84
|
tag,
|
|
87
85
|
context,
|
|
@@ -97,7 +95,8 @@ function build(context, dockerfile, tag, softwarePackage, softwareVersion) {
|
|
|
97
95
|
stdio: "inherit",
|
|
98
96
|
env: {
|
|
99
97
|
...process.env,
|
|
100
|
-
HOME: process.env.HOME || os.homedir()
|
|
98
|
+
HOME: process.env.HOME || os.homedir(),
|
|
99
|
+
BUILDX_NO_DEFAULT_ATTESTATIONS: "1"
|
|
101
100
|
}
|
|
102
101
|
});
|
|
103
102
|
if (result.error) throw result.error;
|
|
@@ -201,7 +200,6 @@ function contentHash(contextFullPath, dockerfileFullPath) {
|
|
|
201
200
|
function dockerTag(packageName, contentHash, registry) {
|
|
202
201
|
return `${registry ?? "containers.pl-open.science/milaboratories/pl-containers"}:${packageName.replaceAll("/", ".")}.${contentHash}`;
|
|
203
202
|
}
|
|
204
|
-
//#endregion
|
|
205
203
|
export { addTag, build, dockerfileAutogenPath, entrypointName, entrypointNameToOrigin, generateLocalTagName, generateRemoteTagName, getImageEntrypoint, getImageHash, isVirtualDockerEntrypointName, localImageExists, push, remoteImageExists };
|
|
206
204
|
|
|
207
205
|
//# sourceMappingURL=docker.js.map
|
package/dist/core/docker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docker.js","names":["util.CLIError","defaults.DOCKER_BUILD_PLATFORM","path","fs","util.hashDirMetaSync"],"sources":["../../src/core/docker.ts"],"sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport * as defaults from \"../defaults\";\nimport type * as artifacts from \"./schemas/artifacts\";\nimport * as util from \"./util\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\n\n/**\n * To allow entrypoint keep both docker and binary package at the same time, we create virtual entrypoint with ':docker' suffix,\n * as entrypoints could not keep two different artifacts at the same time.\n */\nexport function entrypointName(name: string): string {\n return name + \":docker\";\n}\n\nexport function isVirtualDockerEntrypointName(name: string): boolean {\n return name.endsWith(\":docker\");\n}\n\nexport function entrypointNameToOrigin(name: string): string {\n if (!isVirtualDockerEntrypointName(name)) {\n return name;\n }\n return name.substring(0, name.length - \":docker\".length);\n}\n\nexport function getImageHash(tag: string): string {\n const result = spawnSync(\n \"docker\",\n [\"image\", \"ls\", \"--filter=reference=\" + tag, \"--format={{.ID}}\"],\n {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n },\n );\n\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`local docker image check failed with status ${result.status}`);\n }\n\n const output = result.stdout.toString().trim();\n if (output.split(\"\\n\").length > 1) {\n throw util.CLIError(\n `package-builder internal logic error: more than one image found by exact tag match: ${output}`,\n );\n }\n\n return output;\n}\n\nexport function getImageEntrypoint(tag: string): string[] {\n const result = spawnSync(\n \"docker\",\n [\"image\", \"inspect\", tag, \"--format\", \"{{ .Config.Entrypoint | json }}\"],\n {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n },\n );\n\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker image inspect' failed with status ${result.status}`);\n }\n\n const output = result.stdout.toString().trim(); // 'null' or '[<string>, ...]' in JSON format\n return (JSON.parse(output) ?? []) as string[];\n}\n\nexport function localImageExists(tag: string): boolean {\n return getImageHash(tag) !== \"\";\n}\n\nexport function remoteImageExists(tag: string): boolean {\n const result = spawnSync(\"docker\", [\"manifest\", \"inspect\", tag], {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n\n if (result.error || result.status !== 0) {\n return false;\n }\n\n return true;\n}\n\nexport function build(\n context: string,\n dockerfile: string,\n tag: string,\n softwarePackage: string,\n softwareVersion: string | undefined,\n) {\n const result = spawnSync(\n \"docker\",\n [\n \"build\",\n // Pin platform so Platforma's linux/amd64 K8s nodes can run the image\n // regardless of host arch (cross-compile via qemu on non-x64 hosts).\n \"--platform\",\n defaults.DOCKER_BUILD_PLATFORM,\n // Disable buildkit's SLSA provenance + SBOM attestations. They embed\n // build-time timestamps into the manifest list, which produces a fresh\n // image digest on every build of identical source. That breaks the\n // content-addressable tag scheme (every dev rebuild re-pushes a new\n // tag) and defeats publishDockerImage's `remoteImageExists` smart-skip.\n \"--provenance=false\",\n \"--sbom=false\",\n \"-t\",\n tag,\n context,\n \"-f\",\n dockerfile,\n \"--label\",\n \"com.milaboratories.package-builder.software=true\",\n \"--label\",\n \"com.milaboratories.package-builder.software.package=\" + softwarePackage,\n \"--label\",\n \"com.milaboratories.package-builder.software.version=\" + softwareVersion,\n ],\n {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n },\n );\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker build' failed with status ${result.status}`);\n }\n}\n\nexport function push(tag: string) {\n const result = spawnSync(\"docker\", [\"push\", tag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n const registry = tag.split(\"/\")[0];\n throw util.CLIError(\n `'docker push ${tag}' failed with status ${result.status}.\\n` +\n `If the error above mentions authentication or denied access, log in first:\\n` +\n ` aws sso login --profile research-poweruser <YOUR_PROFILE:research-poweruser?> \\n` +\n `Then login in docker:` +\n ` aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${registry}\\n` +\n `(for a private ECR use 'aws ecr' and your region instead of 'ecr-public'/us-east-1).`,\n );\n }\n}\n\nexport function addTag(imageIdOrTag: string, newTag: string) {\n const result = spawnSync(\"docker\", [\"image\", \"tag\", imageIdOrTag, newTag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker tag' failed with status ${result.status}`);\n }\n}\n\nexport function removeTag(imageTag: string) {\n const result = spawnSync(\"docker\", [\"image\", \"rm\", imageTag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker image rm' failed with status ${result.status}`);\n }\n}\n\n/**\n * Generate unique content-addressable image tag\n * @param artifactName: artifact name generated from package name and artifact ID (or explicitly set for artifact in .name field)\n * @param imageID: unique image content hash (docker image ID in docker ls)\n * @param registry: custom registry and repository to use for this image\n * @returns full image tag in format: <registry>/repository:<artifactName>.<imageID>\n */\nexport function generateRemoteTagName(\n artifactName: string,\n imageID: string,\n registry?: string,\n): string {\n return dockerTag(artifactName, imageID, registry);\n}\n\n/**\n * Generate unique content-addressable image tag out of directories and Dockerfile.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns full image tag in format: <registry>/repository:<artifactName>.<contentHash>\n */\nexport function generateLocalTagName(packageRoot: string, artifact: artifacts.dockerType): string {\n const dockerfile = dockerfileAbsPath(packageRoot, artifact);\n const context = contextAbsPath(packageRoot, artifact);\n const hash = contentHash(context, dockerfile);\n\n return dockerTag(\"local-image\", hash);\n}\n\n/**\n * Absolute path to autogenerated Dockerfile for given artifact.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifactID: artifact ID\n * @returns absolute path to autogenerated Dockerfile\n */\nexport function dockerfileAutogenPath(packageRoot: string, artifactID: string): string {\n return path.resolve(packageRoot, \"dist\", \"docker\", `Dockerfile-${artifactID}`);\n}\n\n/**\n * Resolve path to Dockerfile.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns absolute path to Dockerfile\n */\nfunction dockerfileAbsPath(packageRoot: string, artifact: artifacts.dockerType): string {\n return path.resolve(packageRoot, artifact.dockerfile ?? \"Dockerfile\");\n}\n\n/**\n * Resolve path to docker build context directory.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns absolute path to docker build context directory\n */\nfunction contextAbsPath(packageRoot: string, artifact: artifacts.dockerType): string {\n if (artifact.context === \"./\" || artifact.context === \".\") {\n throw util.CLIError(\n `Invalid Docker context: \"${artifact.context}\". Context cannot be \"./\" or \".\" - use absolute path or relative path without \"./\" prefix`,\n );\n }\n return path.resolve(packageRoot, artifact.context ?? \".\");\n}\n\n/**\n * Calculate cummulative hash of docker build context directory context and Dockerfile.\n * To speedup hash calculation, we do not read contents of each item in context dir but\n * use metadata (size, mtime, ...).\n *\n * @param contextFullPath: abs path to docker build context\n * @param dockerfileFullPath: abs path to Dockerfile\n * @returns hash of what the keep\n */\nfunction contentHash(contextFullPath: string, dockerfileFullPath: string): string {\n if (!fs.existsSync(dockerfileFullPath)) {\n throw util.CLIError(`Dockerfile '${dockerfileFullPath}' not found`);\n }\n\n if (!fs.existsSync(contextFullPath)) {\n throw util.CLIError(`Context '${contextFullPath}' not found`);\n }\n\n const contextHash = util.hashDirMetaSync(contextFullPath);\n const dockerfileContent = fs.readFileSync(dockerfileFullPath, \"utf8\");\n contextHash.update(dockerfileContent);\n\n return contextHash.digest(\"hex\").slice(0, 12);\n}\n\nfunction dockerTag(packageName: string, contentHash: string, registry?: string): string {\n const dockerRegistry = registry ?? defaults.DOCKER_REGISTRY;\n return `${dockerRegistry}:${packageName.replaceAll(\"/\", \".\")}.${contentHash}`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"docker.js","names":["util.CLIError","defaults.DOCKER_BUILD_PLATFORM","path","fs","util.hashDirMetaSync"],"sources":["../../src/core/docker.ts"],"sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport * as defaults from \"../defaults\";\nimport type * as artifacts from \"./schemas/artifacts\";\nimport * as util from \"./util\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\n\n/**\n * To allow entrypoint keep both docker and binary package at the same time, we create virtual entrypoint with ':docker' suffix,\n * as entrypoints could not keep two different artifacts at the same time.\n */\nexport function entrypointName(name: string): string {\n return name + \":docker\";\n}\n\nexport function isVirtualDockerEntrypointName(name: string): boolean {\n return name.endsWith(\":docker\");\n}\n\nexport function entrypointNameToOrigin(name: string): string {\n if (!isVirtualDockerEntrypointName(name)) {\n return name;\n }\n return name.substring(0, name.length - \":docker\".length);\n}\n\nexport function getImageHash(tag: string): string {\n const result = spawnSync(\n \"docker\",\n [\"image\", \"ls\", \"--filter=reference=\" + tag, \"--format={{.ID}}\"],\n {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n },\n );\n\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`local docker image check failed with status ${result.status}`);\n }\n\n const output = result.stdout.toString().trim();\n if (output.split(\"\\n\").length > 1) {\n throw util.CLIError(\n `package-builder internal logic error: more than one image found by exact tag match: ${output}`,\n );\n }\n\n return output;\n}\n\nexport function getImageEntrypoint(tag: string): string[] {\n const result = spawnSync(\n \"docker\",\n [\"image\", \"inspect\", tag, \"--format\", \"{{ .Config.Entrypoint | json }}\"],\n {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n },\n );\n\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker image inspect' failed with status ${result.status}`);\n }\n\n const output = result.stdout.toString().trim(); // 'null' or '[<string>, ...]' in JSON format\n return (JSON.parse(output) ?? []) as string[];\n}\n\nexport function localImageExists(tag: string): boolean {\n return getImageHash(tag) !== \"\";\n}\n\nexport function remoteImageExists(tag: string): boolean {\n const result = spawnSync(\"docker\", [\"manifest\", \"inspect\", tag], {\n stdio: \"pipe\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n\n if (result.error || result.status !== 0) {\n return false;\n }\n\n return true;\n}\n\nexport function build(\n context: string,\n dockerfile: string,\n tag: string,\n softwarePackage: string,\n softwareVersion: string | undefined,\n) {\n const result = spawnSync(\n \"docker\",\n [\n \"build\",\n // Pin platform so Platforma's linux/amd64 K8s nodes can run the image\n // regardless of host arch (cross-compile via qemu on non-x64 hosts).\n \"--platform\",\n defaults.DOCKER_BUILD_PLATFORM,\n \"-t\",\n tag,\n context,\n \"-f\",\n dockerfile,\n \"--label\",\n \"com.milaboratories.package-builder.software=true\",\n \"--label\",\n \"com.milaboratories.package-builder.software.package=\" + softwarePackage,\n \"--label\",\n \"com.milaboratories.package-builder.software.version=\" + softwareVersion,\n ],\n {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n // Disables buildx default provenance so the image ID stays stable; podman ignores it.\n BUILDX_NO_DEFAULT_ATTESTATIONS: \"1\",\n },\n },\n );\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker build' failed with status ${result.status}`);\n }\n}\n\nexport function push(tag: string) {\n const result = spawnSync(\"docker\", [\"push\", tag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n const registry = tag.split(\"/\")[0];\n throw util.CLIError(\n `'docker push ${tag}' failed with status ${result.status}.\\n` +\n `If the error above mentions authentication or denied access, log in first:\\n` +\n ` aws sso login --profile research-poweruser <YOUR_PROFILE:research-poweruser?> \\n` +\n `Then login in docker:` +\n ` aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${registry}\\n` +\n `(for a private ECR use 'aws ecr' and your region instead of 'ecr-public'/us-east-1).`,\n );\n }\n}\n\nexport function addTag(imageIdOrTag: string, newTag: string) {\n const result = spawnSync(\"docker\", [\"image\", \"tag\", imageIdOrTag, newTag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker tag' failed with status ${result.status}`);\n }\n}\n\nexport function removeTag(imageTag: string) {\n const result = spawnSync(\"docker\", [\"image\", \"rm\", imageTag], {\n stdio: \"inherit\",\n env: {\n ...process.env, // PATH variable from parent process affects execution\n HOME: process.env.HOME || os.homedir(), // Ensure HOME is set\n },\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n throw util.CLIError(`'docker image rm' failed with status ${result.status}`);\n }\n}\n\n/**\n * Generate unique content-addressable image tag\n * @param artifactName: artifact name generated from package name and artifact ID (or explicitly set for artifact in .name field)\n * @param imageID: unique image content hash (docker image ID in docker ls)\n * @param registry: custom registry and repository to use for this image\n * @returns full image tag in format: <registry>/repository:<artifactName>.<imageID>\n */\nexport function generateRemoteTagName(\n artifactName: string,\n imageID: string,\n registry?: string,\n): string {\n return dockerTag(artifactName, imageID, registry);\n}\n\n/**\n * Generate unique content-addressable image tag out of directories and Dockerfile.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns full image tag in format: <registry>/repository:<artifactName>.<contentHash>\n */\nexport function generateLocalTagName(packageRoot: string, artifact: artifacts.dockerType): string {\n const dockerfile = dockerfileAbsPath(packageRoot, artifact);\n const context = contextAbsPath(packageRoot, artifact);\n const hash = contentHash(context, dockerfile);\n\n return dockerTag(\"local-image\", hash);\n}\n\n/**\n * Absolute path to autogenerated Dockerfile for given artifact.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifactID: artifact ID\n * @returns absolute path to autogenerated Dockerfile\n */\nexport function dockerfileAutogenPath(packageRoot: string, artifactID: string): string {\n return path.resolve(packageRoot, \"dist\", \"docker\", `Dockerfile-${artifactID}`);\n}\n\n/**\n * Resolve path to Dockerfile.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns absolute path to Dockerfile\n */\nfunction dockerfileAbsPath(packageRoot: string, artifact: artifacts.dockerType): string {\n return path.resolve(packageRoot, artifact.dockerfile ?? \"Dockerfile\");\n}\n\n/**\n * Resolve path to docker build context directory.\n * @param packageRoot: package root path from where to resolve artifact's paths (context, Dockerfile, ...)\n * @param artifact: docker artifact configuration\n * @returns absolute path to docker build context directory\n */\nfunction contextAbsPath(packageRoot: string, artifact: artifacts.dockerType): string {\n if (artifact.context === \"./\" || artifact.context === \".\") {\n throw util.CLIError(\n `Invalid Docker context: \"${artifact.context}\". Context cannot be \"./\" or \".\" - use absolute path or relative path without \"./\" prefix`,\n );\n }\n return path.resolve(packageRoot, artifact.context ?? \".\");\n}\n\n/**\n * Calculate cummulative hash of docker build context directory context and Dockerfile.\n * To speedup hash calculation, we do not read contents of each item in context dir but\n * use metadata (size, mtime, ...).\n *\n * @param contextFullPath: abs path to docker build context\n * @param dockerfileFullPath: abs path to Dockerfile\n * @returns hash of what the keep\n */\nfunction contentHash(contextFullPath: string, dockerfileFullPath: string): string {\n if (!fs.existsSync(dockerfileFullPath)) {\n throw util.CLIError(`Dockerfile '${dockerfileFullPath}' not found`);\n }\n\n if (!fs.existsSync(contextFullPath)) {\n throw util.CLIError(`Context '${contextFullPath}' not found`);\n }\n\n const contextHash = util.hashDirMetaSync(contextFullPath);\n const dockerfileContent = fs.readFileSync(dockerfileFullPath, \"utf8\");\n contextHash.update(dockerfileContent);\n\n return contextHash.digest(\"hex\").slice(0, 12);\n}\n\nfunction dockerTag(packageName: string, contentHash: string, registry?: string): string {\n const dockerRegistry = registry ?? defaults.DOCKER_REGISTRY;\n return `${dockerRegistry}:${packageName.replaceAll(\"/\", \".\")}.${contentHash}`;\n}\n"],"mappings":"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"}
|
package/dist/core/envs.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/core/envs.ts
|
|
2
2
|
var envs_exports = /* @__PURE__ */ require("../_virtual/_rolldown/runtime.cjs").__exportAll({
|
|
3
3
|
CI: () => "CI",
|
|
4
4
|
PL_CONDA_BUILD: () => PL_CONDA_BUILD,
|
|
@@ -56,7 +56,6 @@ function isCI() {
|
|
|
56
56
|
function isRunnerDebug() {
|
|
57
57
|
return process.env["RUNNER_DEBUG"] === "true" || process.env["RUNNER_DEBUG"] === "1";
|
|
58
58
|
}
|
|
59
|
-
//#endregion
|
|
60
59
|
exports.PL_CONDA_BUILD = PL_CONDA_BUILD;
|
|
61
60
|
exports.PL_CONDA_NO_BUILD = PL_CONDA_NO_BUILD;
|
|
62
61
|
exports.PL_DEV_BINARY_UPLOAD_URL = PL_DEV_BINARY_UPLOAD_URL;
|
package/dist/core/envs.d.ts
CHANGED
|
@@ -27,6 +27,5 @@ export declare const CI = "CI";
|
|
|
27
27
|
export declare const RUNNER_DEBUG = "RUNNER_DEBUG";
|
|
28
28
|
export declare function isCI(): boolean;
|
|
29
29
|
export declare function isRunnerDebug(): boolean;
|
|
30
|
-
//#endregion
|
|
31
30
|
export { envs_d_exports };
|
|
32
31
|
//# sourceMappingURL=envs.d.ts.map
|
package/dist/core/envs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
-
|
|
2
|
+
// src/core/envs.ts
|
|
3
3
|
var envs_exports = /* @__PURE__ */ __exportAll({
|
|
4
4
|
CI: () => "CI",
|
|
5
5
|
PL_CONDA_BUILD: () => PL_CONDA_BUILD,
|
|
@@ -57,7 +57,6 @@ function isCI() {
|
|
|
57
57
|
function isRunnerDebug() {
|
|
58
58
|
return process.env["RUNNER_DEBUG"] === "true" || process.env["RUNNER_DEBUG"] === "1";
|
|
59
59
|
}
|
|
60
|
-
//#endregion
|
|
61
60
|
export { PL_CONDA_BUILD, PL_CONDA_NO_BUILD, PL_DEV_BINARY_UPLOAD_URL, PL_DEV_DOCKER_PULL_URL, PL_DEV_DOCKER_PUSH_URL, PL_DOCKER_AUTOPUSH, PL_DOCKER_BUILD, PL_DOCKER_NO_AUTOPUSH, PL_DOCKER_NO_BUILD, PL_DOCKER_REGISTRY, PL_DOCKER_REGISTRY_PUSH_TO, PL_PKG_ARCH, PL_PKG_ARCHIVE, PL_PKG_CONTENT_ROOT, PL_PKG_DEV, PL_PKG_FULL_HASH, PL_PKG_OS, PL_PKG_STORAGE_URL, PL_PKG_VERSION, PL_RELEASE_BINARY_UPLOAD_URL, PL_RELEASE_DOCKER_PULL_URL, PL_RELEASE_DOCKER_PUSH_URL, RUNNER_DEBUG, envs_exports, isCI, isRunnerDebug };
|
|
62
61
|
|
|
63
62
|
//# sourceMappingURL=envs.js.map
|
|
@@ -14,7 +14,7 @@ node_path = require_runtime.__toESM(node_path, 1);
|
|
|
14
14
|
let node_crypto = require("node:crypto");
|
|
15
15
|
let zod_v4 = require("zod/v4");
|
|
16
16
|
let _milaboratories_resolve_helper = require("@milaboratories/resolve-helper");
|
|
17
|
-
|
|
17
|
+
// src/core/package-info.ts
|
|
18
18
|
const storagePresetSchema = zod_v4.z.object({
|
|
19
19
|
downloadURL: zod_v4.z.string().optional(),
|
|
20
20
|
storageURL: zod_v4.z.string().optional()
|
|
@@ -351,16 +351,18 @@ var PackageInfo = class {
|
|
|
351
351
|
downloadURL: registries.default?.downloadURL,
|
|
352
352
|
storageURL: registries.default?.storageURL
|
|
353
353
|
};
|
|
354
|
-
if (registry)
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
354
|
+
if (registry) {
|
|
355
|
+
if (typeof registry === "string") {
|
|
356
|
+
result.name = registry;
|
|
357
|
+
const regDefault = wellKnownRegistries[result.name];
|
|
358
|
+
result.downloadURL = registries[result.name]?.downloadURL ?? regDefault?.downloadURL;
|
|
359
|
+
result.storageURL = registries[result.name]?.storageURL ?? regDefault?.storageURL;
|
|
360
|
+
} else {
|
|
361
|
+
result.name = registry.name;
|
|
362
|
+
const regDefault = wellKnownRegistries[result.name];
|
|
363
|
+
result.downloadURL = registry.downloadURL ?? registries[result.name]?.downloadURL ?? regDefault?.downloadURL;
|
|
364
|
+
result.storageURL = registry.storageURL ?? registries[result.name]?.storageURL ?? regDefault?.storageURL;
|
|
365
|
+
}
|
|
364
366
|
}
|
|
365
367
|
const regNameUpper = result.name.toUpperCase().replaceAll(/[^A-Z0-9_]/g, "_");
|
|
366
368
|
const uploadTo = process.env[`PL_REGISTRY_${regNameUpper}_UPLOAD_URL`];
|
|
@@ -503,7 +505,6 @@ function requireArtifactType(artifact, type, errMsg) {
|
|
|
503
505
|
if (errMsg) errMsg = `${errMsg}: `;
|
|
504
506
|
throw require_util.CLIError(`${errMsg}wrong artifact type: expected '${type}', got '${artifact.type}'`);
|
|
505
507
|
}
|
|
506
|
-
//#endregion
|
|
507
508
|
exports.PackageInfo = PackageInfo;
|
|
508
509
|
|
|
509
510
|
//# sourceMappingURL=package-info.cjs.map
|