@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.
Files changed (79) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +2 -3
  2. package/dist/_virtual/_rolldown/runtime.js +1 -2
  3. package/dist/core/archive.cjs +1 -2
  4. package/dist/core/archive.cjs.map +1 -1
  5. package/dist/core/archive.js +1 -2
  6. package/dist/core/conda/builder.cjs +1 -2
  7. package/dist/core/conda/builder.cjs.map +1 -1
  8. package/dist/core/conda/builder.js +1 -2
  9. package/dist/core/conda/builder.js.map +1 -1
  10. package/dist/core/conda/validate-spec.cjs +1 -2
  11. package/dist/core/conda/validate-spec.js +1 -2
  12. package/dist/core/core.cjs +11 -12
  13. package/dist/core/core.cjs.map +1 -1
  14. package/dist/core/core.d.ts +3 -5
  15. package/dist/core/core.d.ts.map +1 -1
  16. package/dist/core/core.js +13 -13
  17. package/dist/core/core.js.map +1 -1
  18. package/dist/core/docker-conda.cjs +1 -2
  19. package/dist/core/docker-conda.js +1 -2
  20. package/dist/core/docker-coverage.cjs +1 -2
  21. package/dist/core/docker-coverage.d.ts +1 -3
  22. package/dist/core/docker-coverage.d.ts.map +1 -1
  23. package/dist/core/docker-coverage.js +3 -3
  24. package/dist/core/docker-coverage.js.map +1 -1
  25. package/dist/core/docker-python.cjs +1 -2
  26. package/dist/core/docker-python.js +1 -2
  27. package/dist/core/docker.cjs +3 -5
  28. package/dist/core/docker.cjs.map +1 -1
  29. package/dist/core/docker.js +3 -5
  30. package/dist/core/docker.js.map +1 -1
  31. package/dist/core/envs.cjs +1 -2
  32. package/dist/core/envs.d.ts +0 -1
  33. package/dist/core/envs.js +1 -2
  34. package/dist/core/package-info.cjs +13 -12
  35. package/dist/core/package-info.cjs.map +1 -1
  36. package/dist/core/package-info.d.ts +4 -5
  37. package/dist/core/package-info.d.ts.map +1 -1
  38. package/dist/core/package-info.js +13 -12
  39. package/dist/core/package-info.js.map +1 -1
  40. package/dist/core/paths.cjs +1 -2
  41. package/dist/core/paths.cjs.map +1 -1
  42. package/dist/core/paths.js +1 -2
  43. package/dist/core/paths.js.map +1 -1
  44. package/dist/core/push-guard.cjs +1 -2
  45. package/dist/core/push-guard.cjs.map +1 -1
  46. package/dist/core/push-guard.d.ts +0 -2
  47. package/dist/core/push-guard.d.ts.map +1 -1
  48. package/dist/core/push-guard.js +1 -2
  49. package/dist/core/resolver.cjs +1 -2
  50. package/dist/core/resolver.js +1 -2
  51. package/dist/core/schemas/artifacts.cjs +1 -2
  52. package/dist/core/schemas/artifacts.d.ts +1 -169
  53. package/dist/core/schemas/artifacts.d.ts.map +1 -1
  54. package/dist/core/schemas/artifacts.js +1 -2
  55. package/dist/core/schemas/entrypoints.cjs +1 -2
  56. package/dist/core/schemas/entrypoints.d.ts +1 -352
  57. package/dist/core/schemas/entrypoints.d.ts.map +1 -1
  58. package/dist/core/schemas/entrypoints.js +1 -2
  59. package/dist/core/schemas/sw-json.cjs +1 -2
  60. package/dist/core/schemas/sw-json.js +1 -2
  61. package/dist/core/storage.cjs +1 -2
  62. package/dist/core/storage.js +1 -2
  63. package/dist/core/sw-json-render.cjs +1 -2
  64. package/dist/core/sw-json-render.js +1 -2
  65. package/dist/core/util.cjs +1 -2
  66. package/dist/core/util.cjs.map +1 -1
  67. package/dist/core/util.d.ts +0 -1
  68. package/dist/core/util.js +1 -2
  69. package/dist/defaults.cjs +1 -2
  70. package/dist/defaults.d.ts +0 -1
  71. package/dist/defaults.js +1 -2
  72. package/dist/index.cjs +1 -2
  73. package/dist/index.d.ts +0 -2
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +1 -2
  76. package/package.json +20 -15
  77. package/src/core/__tests__/docker-build.test.ts +51 -0
  78. package/src/core/conda/builder.ts +1 -1
  79. 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
- //#region src/core/docker-conda.ts
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
- //#region src/core/docker-coverage.ts
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, entrypoints_d_exports } from "./schemas/entrypoints.js";
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":";;YAwBY;;EAEV;;EAEA;;;;;;;;;;;;;;;wBAgBc,iCACd,aAAa,YAAY;;;;;;;;;wBAgCX,6BAA6B;;wBAmB7B,qBAAqB,UAAU"}
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
- //#region src/core/docker-coverage.ts
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
- throw CLIError(`These software entrypoints produce no docker image, so no kubernetes installation can run them:\n${coverage.softwareWithoutDocker.map((name) => ` - ${name}`).join("\n")}\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 }.`);
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;CAIjD,MAAMC,SACJ,oGAHW,SAAS,sBAAsB,KAAK,SAAS,SAAS,MAAM,CAAC,CAAC,KAAK,IAI1D,EAAK,6QAK3B;AACF"}
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
- //#region src/core/docker-python.ts
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
- //#region src/core/docker-python.ts
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
@@ -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
- //#region src/core/docker.ts
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;
@@ -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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"}
@@ -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
- //#region src/core/docker.ts
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
@@ -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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"}
@@ -1,4 +1,4 @@
1
- //#region src/core/envs.ts
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;
@@ -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
- //#region src/core/envs.ts
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
- //#region src/core/package-info.ts
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) if (typeof registry === "string") {
355
- result.name = registry;
356
- const regDefault = wellKnownRegistries[result.name];
357
- result.downloadURL = registries[result.name]?.downloadURL ?? regDefault?.downloadURL;
358
- result.storageURL = registries[result.name]?.storageURL ?? regDefault?.storageURL;
359
- } else {
360
- result.name = registry.name;
361
- const regDefault = wellKnownRegistries[result.name];
362
- result.downloadURL = registry.downloadURL ?? registries[result.name]?.downloadURL ?? regDefault?.downloadURL;
363
- result.storageURL = registry.storageURL ?? registries[result.name]?.storageURL ?? regDefault?.storageURL;
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