@platforma-sdk/package-builder-lib 1.2.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/core.cjs +35 -0
- package/dist/core/core.cjs.map +1 -1
- package/dist/core/core.d.ts +32 -6
- package/dist/core/core.d.ts.map +1 -1
- package/dist/core/core.js +35 -0
- package/dist/core/core.js.map +1 -1
- package/dist/core/docker-coverage.cjs +56 -0
- package/dist/core/docker-coverage.cjs.map +1 -0
- package/dist/core/docker-coverage.d.ts +35 -0
- package/dist/core/docker-coverage.d.ts.map +1 -0
- package/dist/core/docker-coverage.js +53 -0
- package/dist/core/docker-coverage.js.map +1 -0
- package/dist/core/envs.d.ts +27 -27
- package/dist/core/envs.d.ts.map +1 -1
- package/dist/core/package-info.cjs +6 -1
- package/dist/core/package-info.cjs.map +1 -1
- package/dist/core/package-info.d.ts +6 -6
- package/dist/core/package-info.d.ts.map +1 -1
- package/dist/core/package-info.js +6 -1
- package/dist/core/package-info.js.map +1 -1
- package/dist/core/push-guard.cjs +17 -0
- package/dist/core/push-guard.cjs.map +1 -0
- package/dist/core/push-guard.d.ts +15 -0
- package/dist/core/push-guard.d.ts.map +1 -0
- package/dist/core/push-guard.js +17 -0
- package/dist/core/push-guard.js.map +1 -0
- package/dist/core/schemas/artifacts.d.ts +236 -71
- package/dist/core/schemas/artifacts.d.ts.map +1 -1
- package/dist/core/schemas/entrypoints.d.ts +357 -10
- package/dist/core/schemas/entrypoints.d.ts.map +1 -1
- package/dist/core/sw-json-render.cjs +18 -0
- package/dist/core/sw-json-render.cjs.map +1 -1
- package/dist/core/sw-json-render.js +18 -0
- package/dist/core/sw-json-render.js.map +1 -1
- package/dist/core/util.d.ts +42 -44
- package/dist/core/util.d.ts.map +1 -1
- package/dist/defaults.d.ts +22 -22
- package/dist/defaults.d.ts.map +1 -1
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/core/__tests__/docker-coverage.test.ts +319 -0
- package/src/core/__tests__/publish-docker-images.test.ts +63 -0
- package/src/core/__tests__/push-guard.test.ts +62 -0
- package/src/core/core.ts +51 -0
- package/src/core/docker-coverage.ts +112 -0
- package/src/core/package-info.ts +11 -0
- package/src/core/push-guard.ts +42 -0
- package/src/core/sw-json-render.ts +25 -0
- package/src/index.ts +9 -0
package/dist/core/core.cjs
CHANGED
|
@@ -7,6 +7,7 @@ const require_builder = require("./conda/builder.cjs");
|
|
|
7
7
|
const require_validate_spec = require("./conda/validate-spec.cjs");
|
|
8
8
|
const require_docker_conda = require("./docker-conda.cjs");
|
|
9
9
|
const require_package_info = require("./package-info.cjs");
|
|
10
|
+
const require_docker_coverage = require("./docker-coverage.cjs");
|
|
10
11
|
const require_sw_json_render = require("./sw-json-render.cjs");
|
|
11
12
|
const require_archive = require("./archive.cjs");
|
|
12
13
|
const require_storage = require("./storage.cjs");
|
|
@@ -86,6 +87,18 @@ var Core = class {
|
|
|
86
87
|
get dockerPackages() {
|
|
87
88
|
return new Map(Array.from(this.packages.entries()).filter(([id, _]) => require_docker.isVirtualDockerEntrypointName(id)).filter(([, value]) => value.type === "docker"));
|
|
88
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* The docker artifacts a build would actually produce for this selection.
|
|
92
|
+
*
|
|
93
|
+
* Mirrors the resolution `buildDockerImages` performs, so callers can reason
|
|
94
|
+
* about a build before running it. Note that `ids` are entrypoint names, not
|
|
95
|
+
* docker package keys: `getArtifact(id, "docker")` resolves the `:docker`
|
|
96
|
+
* virtual entrypoint, so a plain set intersection with `dockerPackages`
|
|
97
|
+
* would be wrong.
|
|
98
|
+
*/
|
|
99
|
+
selectedDockerPackages(ids) {
|
|
100
|
+
return (ids ?? Array.from(this.dockerPackages.keys())).filter((id) => this.getArtifact(id, "docker") !== void 0);
|
|
101
|
+
}
|
|
89
102
|
packageHasType(id, type) {
|
|
90
103
|
const pkg = this.packages.get(id);
|
|
91
104
|
if (pkg && pkg.type === type) return true;
|
|
@@ -106,6 +119,27 @@ var Core = class {
|
|
|
106
119
|
return;
|
|
107
120
|
}
|
|
108
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Fails a CI build that would describe software no kubernetes installation can run.
|
|
124
|
+
*
|
|
125
|
+
* `buildSwJsonFiles` calls this on the selection it is about to write, so no path
|
|
126
|
+
* can skip it. Callers may also invoke it up front — the answer comes from the
|
|
127
|
+
* package's declaration alone, so a CI run that is going to fail can fail before
|
|
128
|
+
* it spends minutes building archives and images.
|
|
129
|
+
*
|
|
130
|
+
* Only builds that write a registry descriptor answer for coverage. A dev-local
|
|
131
|
+
* build (`build:dev-local`, and the `test` script's binary-only build) describes
|
|
132
|
+
* software by filesystem path: it never reaches a cluster, so a missing image
|
|
133
|
+
* cannot hurt anyone there, and failing those runs would block a block's tests on
|
|
134
|
+
* a release rule. Release and dev-remote builds do publish, and are checked.
|
|
135
|
+
*/
|
|
136
|
+
assertDockerCoverage(options) {
|
|
137
|
+
if (!require_util.producesRegistryDescriptor(this.buildMode)) return;
|
|
138
|
+
require_docker_coverage.assertDockerCoverage({
|
|
139
|
+
softwareWithoutDocker: require_docker_coverage.softwareEntrypointsWithoutDocker(options?.entrypoints ?? this.entrypoints),
|
|
140
|
+
requirementWaived: !this.pkgInfo.requireDocker
|
|
141
|
+
});
|
|
142
|
+
}
|
|
109
143
|
buildSwJsonFiles(options) {
|
|
110
144
|
const index = this.packageEntrypointsIndex;
|
|
111
145
|
const entrypointNames = options?.entrypoints ?? [];
|
|
@@ -116,6 +150,7 @@ var Core = class {
|
|
|
116
150
|
}
|
|
117
151
|
let entrypoints = Array.from(this.entrypoints.entries());
|
|
118
152
|
if (entrypointNames.length > 0) entrypoints = entrypoints.filter(([epName, _]) => entrypointNames.includes(epName));
|
|
153
|
+
if (!options?.noSoftware && !options?.skipDockerCoverage) this.assertDockerCoverage({ entrypoints: new Map(entrypoints) });
|
|
119
154
|
const infos = options?.noSoftware ? this.renderer.renderPlaceholderEntrypoints(new Map(entrypoints)) : this.renderer.renderSoftwareEntrypoints(this.buildMode, new Map(entrypoints), {
|
|
120
155
|
requireAllArtifacts: options?.requireAllArtifacts,
|
|
121
156
|
fullDirHash: this.fullDirHash
|
package/dist/core/core.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.cjs","names":["PackageInfo","path","fs","tmpSpecFile","fsp","micromamba","readBuiltArtifactInfo","SwJsonRenderer"],"sources":["../../src/core/core.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\nimport yaml from \"yaml\";\nimport type winston from \"winston\";\n\nimport * as defaults from \"../defaults\";\nimport { PackageInfo } from \"./package-info\";\nimport * as artifacts from \"./schemas/artifacts\";\nimport type * as entrypoint from \"./schemas/entrypoints\";\nimport { micromamba } from \"./conda/builder\";\nimport { validateCondaSpec } from \"./conda/validate-spec\";\nimport { SwJsonRenderer, readBuiltArtifactInfo, writeBuiltArtifactInfo } from \"./sw-json-render\";\nimport * as util from \"./util\";\nimport * as archive from \"./archive\";\nimport * as storage from \"./storage\";\nimport * as docker from \"./docker\";\nimport { tmpSpecFile } from \"./docker-conda\";\n\nexport class Core {\n private readonly logger: winston.Logger;\n private _entrypoints: Map<string, entrypoint.Entrypoint> | undefined;\n private _renderer: SwJsonRenderer | undefined;\n\n public readonly pkgInfo: PackageInfo;\n public targetPlatform: util.PlatformType | undefined;\n public allPlatforms: boolean = false;\n public fullDirHash: boolean;\n\n constructor(\n logger: winston.Logger,\n opts?: {\n pkgInfo?: PackageInfo;\n packageRoot?: string;\n },\n ) {\n this.logger = logger;\n this.pkgInfo = opts?.pkgInfo ?? new PackageInfo(logger, { packageRoot: opts?.packageRoot });\n\n this.fullDirHash = false;\n }\n\n public get buildMode(): util.BuildMode {\n return this.pkgInfo.buildMode;\n }\n\n public set buildMode(mode: util.BuildMode) {\n this.pkgInfo.buildMode = mode;\n }\n\n public set version(v: string | undefined) {\n this.pkgInfo.version = v;\n }\n\n public get isPrivate(): boolean {\n return this.pkgInfo.isPrivate;\n }\n\n public binArchivePath(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n os: util.OSType,\n arch: util.ArchType,\n ): string {\n const name = this.pkgInfo.artifactName(artifact);\n const version = this.pkgInfo.artifactVersion(artifact);\n return archive.getPath(this.archiveOptions(artifact, name, version, os, arch, \"tgz\"));\n }\n\n public assetArchivePath(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n os: util.OSType,\n arch: util.ArchType,\n ): string {\n const name = this.pkgInfo.artifactName(artifact);\n const version = this.pkgInfo.artifactVersion(artifact);\n return archive.getPath(this.archiveOptions(artifact, name, version, os, arch, \"zip\"));\n }\n\n public archivePath(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n os: util.OSType,\n arch: util.ArchType,\n ): string {\n if (artifact.type === \"asset\") {\n return this.assetArchivePath(artifact, os, arch);\n }\n\n return this.binArchivePath(artifact, os, arch);\n }\n\n public get entrypoints(): Map<string, entrypoint.Entrypoint> {\n if (!this._entrypoints) {\n this._entrypoints = this.pkgInfo.entrypoints;\n }\n\n return this._entrypoints;\n }\n\n public get packages(): Map<string, artifacts.withId<artifacts.anyArtifactType>> {\n const pkgs = new Map<string, artifacts.withId<artifacts.anyArtifactType>>();\n\n for (const [_, ep] of this.entrypoints.entries()) {\n if (ep.type === \"reference\") {\n // References have no pacakge definitions inside\n continue;\n }\n\n const key =\n ep.artifact.type === \"docker\" ? docker.entrypointName(ep.artifact.id) : ep.artifact.id;\n pkgs.set(key, ep.artifact);\n }\n\n return pkgs;\n }\n\n public get packageEntrypointsIndex(): Map<string, string[]> {\n const result = new Map<string, string[]>();\n\n for (const [epName, ep] of this.entrypoints) {\n if (ep.type === \"reference\") {\n // References have no pacakge definitions inside\n continue;\n }\n\n if (!result.has(ep.artifact.id)) {\n result.set(ep.artifact.id, []);\n }\n\n result.get(ep.artifact.id)!.push(epName);\n }\n\n return result;\n }\n\n public get buildablePackages(): Map<string, artifacts.withId<artifacts.anyArtifactType>> {\n return new Map(\n Array.from(this.packages.entries())\n .filter(([id, _]) => !docker.isVirtualDockerEntrypointName(id)) // do not show virtual docker entrypoints\n .filter(([, value]) => artifacts.isBuildable(value.type)),\n );\n }\n\n public get dockerPackages(): Map<string, artifacts.withId<artifacts.anyArtifactType>> {\n return new Map(\n Array.from(this.packages.entries())\n .filter(([id, _]) => docker.isVirtualDockerEntrypointName(id)) // do not show virtual docker entrypoints\n .filter(([, value]) => value.type === \"docker\"),\n );\n }\n\n public packageHasType(id: string, type: artifacts.artifactType): boolean {\n const pkg = this.packages.get(id);\n if (pkg && pkg.type === type) {\n return true;\n }\n\n // check 'magic' entrypoint name with suffix\n const dockerPkg = this.packages.get(docker.entrypointName(id));\n if (dockerPkg) {\n return true;\n }\n\n return false;\n }\n\n public getArtifact(\n id: string,\n type: \"docker\",\n ): artifacts.withId<artifacts.dockerType> | undefined;\n public getArtifact(\n id: string,\n type: \"archive\",\n ): artifacts.withId<artifacts.anyArtifactType> | undefined;\n public getArtifact(\n id: string,\n type: \"docker\" | \"archive\",\n ): artifacts.withId<artifacts.anyArtifactType> | undefined {\n const artifact = this.packages.get(id);\n\n switch (type) {\n case \"docker\": {\n if (artifact?.type === \"docker\") {\n return artifact;\n }\n // Virtual entrypoint with suffix specially for docker artifacts.\n return this.packages.get(docker.entrypointName(id));\n }\n case \"archive\": {\n if (artifact?.type === \"docker\") {\n return undefined;\n }\n return artifact;\n }\n default: {\n util.assertNever(type);\n return undefined;\n }\n }\n }\n\n // Get entrypoints defined in package.json, transform them to local or release (depending on `buildMode`)\n // sw.json entrypoint descriptors, and write them to ./dist/tengo/sw.json or as.json next to the package.json.\n public buildSwJsonFiles(options?: {\n packageIds?: string[];\n entrypoints?: string[];\n sources?: util.SoftwareSource[];\n requireAllArtifacts?: boolean;\n noSoftware?: boolean;\n }) {\n const index = this.packageEntrypointsIndex;\n\n const entrypointNames = options?.entrypoints ?? [];\n if (options?.packageIds) {\n for (const pkgId of options.packageIds) {\n const packageEntrypoints = index.get(pkgId);\n if (!packageEntrypoints || packageEntrypoints.length === 0) {\n throw util.CLIError(\n `cannot build descriptor for package ${pkgId}: no entrypoints found for package`,\n );\n }\n\n entrypointNames.push(...packageEntrypoints);\n }\n }\n\n let entrypoints = Array.from(this.entrypoints.entries());\n if (entrypointNames.length > 0) {\n entrypoints = entrypoints.filter(([epName, _]) => entrypointNames.includes(epName));\n }\n\n const infos = options?.noSoftware\n ? this.renderer.renderPlaceholderEntrypoints(new Map(entrypoints))\n : this.renderer.renderSoftwareEntrypoints(this.buildMode, new Map(entrypoints), {\n requireAllArtifacts: options?.requireAllArtifacts,\n fullDirHash: this.fullDirHash,\n });\n\n for (const swJson of infos.values()) {\n this.renderer.writeSwJson(swJson);\n }\n\n for (const [epName, ep] of entrypoints) {\n if (ep.type === \"reference\") {\n const srcPath = this.pkgInfo.resolveReference(epName, ep);\n this.renderer.copySwJson(epName, srcPath);\n }\n }\n }\n\n // Point artifact-info at the already-published, version-derived artifact without building or\n // uploading, so buildSwJsonFiles renders a registry descriptor for it. Release mode, binary only.\n public writePublishedArtifactInfo(options?: { ids?: string[] }) {\n const platform = util.currentPlatform();\n for (const [id, artifact] of this.buildablePackages) {\n if (options?.ids && !options.ids.includes(id)) continue;\n\n // Cross-platform archives are stored under a platform-agnostic key; this is the key\n // renderBinaryInfo reads back from.\n const locationKey = artifacts.isCrossPlatform(artifact.type) ? undefined : platform;\n const registry = this.pkgInfo.artifactRegistrySettings(artifact);\n\n writeBuiltArtifactInfo(this.pkgInfo.artifactInfoLocation(id, \"archive\", locationKey), {\n type: artifact.type,\n platform,\n registryURL: registry.downloadURL,\n registryName: registry.name,\n remoteArtifactLocation: this.pkgInfo.artifactArchiveAddressPattern(artifact),\n uploadPath: this.pkgInfo.artifactArchiveFullName(artifact, platform),\n });\n }\n }\n\n public async buildSoftwareArchives(options?: {\n ids?: string[];\n forceBuild?: boolean;\n\n archivePath?: string;\n contentRoot?: string;\n skipIfEmpty?: boolean;\n\n // Automated builds settings\n condaBuild?: boolean;\n }) {\n this.logger.info(`Building package archives...`);\n\n const packagesToBuild = options?.ids ?? Array.from(this.buildablePackages.keys());\n this.logger.debug(`Selected packages:\\n ${packagesToBuild.join(\"\\n \")}`);\n this.logger.debug(`All known packages:\\n ${Array.from(this.packages.keys()).join(\"\\n \")}`);\n\n if (packagesToBuild.length > 1 && options?.archivePath && !options.forceBuild) {\n this.logger.error(\n \"Attempt to build several packages targeting single package archive. This will simply overwrite the archive several times. If you know what you are doing, add '--force' flag\",\n );\n throw util.CLIError(\n \"attempt to build several packages using the same software package archive\",\n );\n }\n\n for (const artifactID of packagesToBuild) {\n const artifact = this.getArtifact(artifactID, \"archive\");\n\n if (!artifact) {\n if (options?.ids) {\n this.logger.warn(`Package '${artifactID}' is not buildable into archive. Skipped.`);\n }\n continue;\n }\n\n if (artifacts.isCrossPlatform(artifact.type)) {\n await this.buildSoftwareArchive(artifact, util.currentPlatform(), options);\n } else if (this.targetPlatform) {\n await this.buildSoftwareArchive(artifact, this.targetPlatform, options);\n } else if (this.allPlatforms) {\n for (const platform of this.pkgInfo.artifactPlatforms(artifact)) {\n await this.buildSoftwareArchive(artifact, platform, options);\n }\n } else {\n await this.buildSoftwareArchive(artifact, util.currentPlatform(), options);\n }\n }\n }\n\n // NOTE: each artifact build consists of 2 components:\n // - built artifact in any shape (archive, docker image, etc)\n // - artifact location file, that contains address of the artifact in registry (docker tag, archive path and so on)\n //\n // artifact may be uploaded to the registry in content-addressable mode, when the artifact location\n // is derived from the actual artifact (software archive, docker image, etc) content.\n // artifact location files are used to build sw.json entrypoint descriptor with correct artifact address.\n public async buildSoftwareArchive(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n platform: util.PlatformType,\n options?: {\n archivePath?: string;\n contentRoot?: string;\n skipIfEmpty?: boolean;\n\n // Automated builds settings\n condaBuild?: boolean;\n },\n ) {\n this.logger.info(`Building software package '${artifact.id}' for platform '${platform}'...`);\n const { os, arch } = util.splitPlatform(platform);\n\n if (!artifacts.archiveArtifactTypes.includes(artifact.type)) {\n if (options?.skipIfEmpty) {\n this.logger.info(` archive build was skipped: package '${artifact.id}' is not buildable`);\n }\n this.logger.error(\n ` not buildable: artifact '${artifact.id}' archive build is impossible for configuration inside '${util.softwareConfigName}'`,\n );\n\n throw util.CLIError(\"not a buildable artifact\");\n }\n\n const contentRoot =\n options?.contentRoot ?? this.pkgInfo.artifactContentRoot(artifact, platform);\n\n if (artifact.type === \"asset\") {\n const archivePath = options?.archivePath ?? this.assetArchivePath(artifact, os, arch);\n await this.createPackageArchive(\"assets\", artifact, archivePath, contentRoot, os, arch);\n return;\n }\n\n const artType = artifact.type;\n switch (artType) {\n case \"conda\": {\n if (options?.condaBuild === undefined || options.condaBuild) {\n // build by default, skip if explicitly disabled\n await this.buildCondaPackage({ artifact, platform, contentRoot });\n } else {\n this.logger.debug(`Conda environment build was skipped.`);\n }\n break;\n }\n }\n\n if (!util.producesRegistryDescriptor(this.buildMode)) {\n this.logger.info(\n ` no need to build software archive in '${this.buildMode}' mode: archive build was skipped`,\n );\n return;\n }\n\n const archivePath = options?.archivePath ?? this.binArchivePath(artifact, os, arch);\n await this.createPackageArchive(\"software\", artifact, archivePath, contentRoot, os, arch);\n }\n\n public buildDockerImages(options?: {\n ids?: string[];\n registry?: string;\n strictPlatformMatching?: boolean; // if true, build docker images only on linux OS and only for supported architectures. Used in CI.\n }) {\n this.logger.info(`Building docker images...`);\n\n const packagesToBuild = options?.ids ?? Array.from(this.dockerPackages.keys());\n this.logger.debug(`Selected packages:\\n ${packagesToBuild.join(\"\\n \")}`);\n this.logger.debug(`All known packages:\\n ${Array.from(this.packages.keys()).join(\"\\n \")}`);\n\n for (const pkgID of packagesToBuild) {\n const artifact = this.getArtifact(pkgID, \"docker\");\n\n if (!artifact) {\n if (options?.ids) {\n this.logger.warn(`Package '${pkgID}' is not buildable into docker image. Skipped.`);\n }\n continue;\n }\n\n // Docker images are always built as linux/amd64 (Platforma's K8s target);\n // on non-x64 hosts pl-pkg cross-compiles via qemu so dev iteration on\n // Macs works. In CI, strictPlatformMatching is set on the caller side\n // and we still want exactly one matrix leg (linux/x64) to do the work —\n // otherwise every arm/windows runner duplicates the build and Windows\n // runners outright fail on 'docker build --platform linux/amd64'.\n if (options?.strictPlatformMatching) {\n if (util.currentOS() !== \"linux\" || util.currentArch() !== \"x64\") {\n this.logger.debug(\n `Docker image build skipped for '${artifact.id}': strict-platform mode requires linux/x64 host`,\n );\n continue;\n }\n }\n\n // Docker software is built as linux/amd64 only (Platforma's K8s target). An explicit\n // non-x64 target cannot be honored — fail clearly instead of silently emitting amd64.\n if (this.targetPlatform && util.splitPlatform(this.targetPlatform).arch !== \"x64\") {\n throw util.CLIError(\n `cannot build docker image '${artifact.id}' for target '${this.targetPlatform}': ` +\n `docker software is built as ${defaults.DOCKER_BUILD_PLATFORM} only`,\n );\n }\n\n this.buildDockerImage(artifact.id, artifact, options?.registry);\n }\n }\n\n // NOTE: each artifact build consists of 2 components:\n // - built artifact in any shape (archive, docker image, etc)\n // - artifact location file, that contains address of the artifact in registry (docker tag, archive path and so on)\n //\n // docker image is uploaded to the registry after build with unique tag that is derived from the actual image content.\n // artifact location files are used to build sw.json entrypoint descriptor with correct artifact address.\n private buildDockerImage(\n pkgID: string,\n artifact: artifacts.withId<artifacts.dockerType>,\n registry?: string,\n ) {\n const dockerfile = path.resolve(this.pkgInfo.packageRoot, artifact.dockerfile ?? \"Dockerfile\");\n const context = path.resolve(this.pkgInfo.packageRoot, artifact.context ?? \".\");\n registry = registry ?? artifact.registry;\n\n if (!fs.existsSync(dockerfile)) {\n throw util.CLIError(`Dockerfile '${dockerfile}' not found`);\n }\n\n if (!fs.existsSync(context)) {\n throw util.CLIError(`Context '${context}' not found`);\n }\n\n const localTag = docker.generateLocalTagName(this.pkgInfo.packageRoot, artifact);\n\n this.logger.info(`Building docker image for '${pkgID}'...`);\n this.logger.debug(` dockerfile: '${dockerfile}'\n context: '${context}'\n localTag: '${localTag}'\n `);\n\n const name = this.pkgInfo.artifactName(artifact);\n\n docker.build(context, dockerfile, localTag, name, this.pkgInfo.version);\n\n const imageHash = docker.getImageHash(localTag);\n const dstTag = docker.generateRemoteTagName(name, imageHash, registry);\n\n this.logger.debug(`Adding destination tag to docker image:\n dstTag: \"${dstTag}\"\n `);\n docker.addTag(localTag, dstTag);\n // do not remove local tag to make 'local' builds to also work with docker.\n\n // Docker images target linux/amd64 regardless of host (see docker.build).\n const artInfoPath = this.pkgInfo.artifactInfoLocation(pkgID, \"docker\", \"x64\");\n writeBuiltArtifactInfo(artInfoPath, {\n type: \"docker\",\n platform: \"linux-x64\",\n remoteArtifactLocation: dstTag,\n entrypoint: docker.getImageEntrypoint(localTag),\n });\n\n this.logger.info(`Docker image is built:\n tag: '${dstTag}'\n location file: '${artInfoPath}'`);\n\n this.logger.debug(`Clearing context directory from temporary files...`);\n if (fs.existsSync(path.join(context, tmpSpecFile))) {\n fs.unlinkSync(path.join(context, tmpSpecFile));\n }\n }\n\n private async buildCondaPackage(opts: {\n artifact: artifacts.withId<artifacts.condaType>;\n platform: util.PlatformType;\n contentRoot: string;\n }) {\n const { artifact, platform, contentRoot } = opts;\n\n if (platform !== util.currentPlatform()) {\n this.logger.warn(\n `Conda package cannot be built cross-platform:\\n` +\n ` current platform is '${util.currentPlatform()}', requested platform is '${platform}'\\n` +\n `Conda environment automatic build was skipped`,\n );\n return;\n }\n\n this.logger.info(`Building conda environment for current platform...`);\n\n const srcSpecPath = path.resolve(this.pkgInfo.packageRoot, artifact.spec);\n if (!fs.existsSync(srcSpecPath)) {\n this.logger.error(\n `Conda environment specification file '${artifact.spec}' not found at '${srcSpecPath}'`,\n );\n throw util.CLIError(\n `Cannot build conda environment '${artifact.id}': no specification file.`,\n );\n }\n\n this.logger.debug(`Validating conda spec file for forbidden channels...`);\n try {\n validateCondaSpec(this.logger, srcSpecPath);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error(errorMessage);\n throw util.CLIError(`Cannot build conda environment '${artifact.id}': ${errorMessage}`);\n }\n\n const micromambaRoot = path.join(contentRoot, defaults.CONDA_DATA_LOCATION);\n const micromambaBin = path.join(contentRoot, \"micromamba\");\n\n this.logger.debug(`Creating micromamba root directory: '${micromambaRoot}'`);\n await fsp.mkdir(micromambaRoot, { recursive: true });\n\n this.logger.debug(`Creating micromamba instance...`);\n const m = new micromamba(\n this.logger,\n micromambaRoot,\n artifact[\"micromamba-version\"],\n micromambaBin,\n );\n\n const resultSpecPath = path.join(contentRoot, defaults.CONDA_FROZEN_ENV_SPEC_FILE);\n\n await m.downloadBinary();\n m.createEnvironment({ specFile: srcSpecPath });\n m.exportEnvironment({ outputFile: resultSpecPath });\n m.deleteEnvironment({});\n\n this.logger.debug(`Conda environment was built at '${micromambaRoot}'.`);\n\n this.logger.debug(`Cutting prefix from conda environment file...`);\n\n const resultSpec = yaml.parse(await fsp.readFile(resultSpecPath, \"utf-8\")) as Record<\n string,\n unknown\n >;\n resultSpec.prefix = undefined; // cut original env location (with path from CI) from the resulting spec file\n\n // Fixup the structure: for empty lists export produces YAML that cannot be then read back on server side for restoration.\n if (!resultSpec.channels) {\n resultSpec.channels = [];\n }\n if (!resultSpec.dependencies) {\n resultSpec.dependencies = [];\n }\n await fsp.writeFile(resultSpecPath, yaml.stringify(resultSpec));\n\n this.logger.debug(`Conda environment file is ready: '${resultSpecPath}'`);\n }\n\n private async createPackageArchive(\n packageContentType: string,\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n archivePath: string,\n contentRoot: string,\n os: util.OSType,\n arch: util.ArchType,\n ) {\n this.logger.debug(` packing ${packageContentType} into a package`);\n if (artifacts.isCrossPlatform(artifact.type)) {\n this.logger.debug(` generating cross-platform package`);\n } else {\n this.logger.debug(` generating package for os='${os}', arch='${arch}'`);\n }\n this.logger.debug(` package content root: '${contentRoot}'`);\n this.logger.debug(` package destination archive: '${archivePath}'`);\n\n await archive.create(this.logger, contentRoot, archivePath);\n\n const artInfoPath = this.pkgInfo.artifactInfoLocation(\n artifact.id,\n \"archive\",\n artifacts.isCrossPlatform(artifact.type) ? undefined : util.joinPlatform(os, arch),\n );\n\n const registry = this.pkgInfo.artifactRegistrySettings(artifact);\n\n writeBuiltArtifactInfo(artInfoPath, {\n type: artifact.type,\n platform: util.joinPlatform(os, arch),\n registryURL: registry.downloadURL,\n registryName: registry.name,\n remoteArtifactLocation: this.pkgInfo.artifactArchiveAddressPattern(artifact),\n uploadPath: this.pkgInfo.artifactArchiveFullName(artifact, util.joinPlatform(os, arch)),\n });\n\n this.logger.info(`${packageContentType} archive is built:\n archive: '${archivePath}'\n location file: '${artInfoPath}'`);\n }\n\n public async publishPackages(options?: {\n ids?: string[];\n\n archivePath?: string;\n storageURL?: string;\n\n failExisting?: boolean; // do not warn if package already exists in storage, fail with error instead.\n forceReupload?: boolean; // re-upload packages even if they already exist in storage\n }) {\n this.logger.info(`Publishing packages...`);\n\n const packagesToPublish = options?.ids ?? Array.from(this.buildablePackages.keys());\n this.logger.debug(`Selected packages:\\n ${packagesToPublish.join(\"\\n \")}`);\n this.logger.debug(`All known packages:\\n ${Array.from(this.packages.keys()).join(\"\\n \")}`);\n\n const uploads: Promise<void>[] = [];\n for (const pkgID of packagesToPublish) {\n const pkg = this.getArtifact(pkgID, \"archive\");\n\n if (!pkg) {\n if (options?.ids) {\n this.logger.warn(\n `Package '${pkgID}' is not buildable into archive. Cannot publish archive artifact.`,\n );\n }\n continue;\n }\n\n if (artifacts.isCrossPlatform(pkg.type)) {\n uploads.push(this.publishPackage(pkg, util.currentPlatform(), options));\n } else if (this.targetPlatform) {\n uploads.push(this.publishPackage(pkg, this.targetPlatform, options));\n } else if (this.allPlatforms) {\n for (const platform of this.pkgInfo.artifactPlatforms(pkg)) {\n uploads.push(this.publishPackage(pkg, platform, options));\n }\n } else {\n uploads.push(this.publishPackage(pkg, util.currentPlatform(), options));\n }\n }\n\n await Promise.all(uploads);\n }\n\n private async publishPackage(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n platform: util.PlatformType,\n options?: {\n archivePath?: string;\n storageURL?: string;\n\n failExisting?: boolean;\n forceReupload?: boolean;\n },\n ) {\n if (artifact.type === \"docker\") {\n this.publishDockerImage(artifact);\n return;\n }\n\n await this.publishArchive(artifact, platform, options);\n }\n\n private async publishArchive(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n platform: util.PlatformType,\n options?: {\n archivePath?: string;\n storageURL?: string;\n failExisting?: boolean;\n forceReupload?: boolean;\n },\n ) {\n const { os, arch } = util.splitPlatform(platform);\n\n const artifactName = this.pkgInfo.artifactName(artifact);\n const registry = this.pkgInfo.artifactRegistrySettings(artifact);\n const storageURL = options?.storageURL ?? registry.storageURL;\n\n const archivePath = options?.archivePath ?? this.archivePath(artifact, os, arch);\n\n const artInfoPath = this.pkgInfo.artifactInfoLocation(\n artifact.id,\n \"archive\",\n artifacts.isCrossPlatform(artifact.type) ? undefined : util.joinPlatform(os, arch),\n );\n const artInfo = readBuiltArtifactInfo(artInfoPath);\n const dstName = artInfo.uploadPath ?? artInfo.remoteArtifactLocation;\n\n if (!storageURL) {\n const regNameUpper = registry.name.toUpperCase().replaceAll(/[^A-Z0-9_]/g, \"_\");\n this.logger.error(`no storage URL is set for registry ${registry.name}`);\n throw util.CLIError(\n `'registry.storageURL' of package '${artifact.id}' is empty. Set it as command option, in '${util.softwareConfigName}' file or via environment variable 'PL_REGISTRY_${regNameUpper}_UPLOAD_URL'`,\n );\n }\n\n this.logger.info(\n `Publishing package '${artifactName}' for platform '${platform}' into registry '${registry.name}'`,\n );\n this.logger.debug(` registry storage URL: '${storageURL}'`);\n this.logger.debug(` archive to publish: '${archivePath}'`);\n this.logger.debug(` target package name: '${dstName}'`);\n\n const s = await storage.initByUrl(storageURL, this.pkgInfo.packageRoot);\n\n const exists = await s.exists(dstName);\n if (exists && !options?.forceReupload) {\n if (options?.failExisting) {\n throw util.CLIError(\n `software package '${dstName}' already exists in registry '${registry.name}'. To re-upload it, use 'force' flag. To not fail, remove 'fail-existing-packages' flag`,\n );\n }\n\n this.logger.warn(\n `software package '${dstName}' already exists in registry '${registry.name}'. Upload was skipped.`,\n );\n return;\n }\n\n const uploads: Promise<void>[] = [];\n\n const archive = fs.createReadStream(archivePath);\n uploads.push(\n s.putFile(dstName, archive).finally(() => {\n archive.close();\n return;\n }),\n );\n\n return Promise.all(uploads).then(() => {\n this.logger.info(`Package '${artifactName}' was published to '${registry.name}:${dstName}'`);\n return;\n });\n }\n\n public publishDockerImages(options?: {\n ids?: string[];\n pushTo?: string;\n strictPlatformMatching?: boolean; // if true, publish docker images only on linux OS and only for supported architectures. Used in CI.\n }) {\n this.logger.info(`Publishing docker images...`);\n\n // Iterate only dockerPackages (matches buildDockerImages). Previously we\n // also iterated buildablePackages.keys(), but for entrypoints with a python\n // or conda binary that autogens a docker image, the binary key (e.g. \"main\")\n // and the virtual docker key (\"main:docker\") both resolve to the same\n // docker artifact via getArtifact's :docker fallback. That caused\n // publishDockerImage to run twice — first push succeeded, second saw the\n // tag in the registry and logged a misleading \"Skipping push...\" line.\n const packagesToPublish = options?.ids ?? Array.from(this.dockerPackages.keys());\n this.logger.debug(`Selected packages:\\n ${packagesToPublish.join(\"\\n \")}`);\n this.logger.debug(`All known packages:\\n ${Array.from(this.packages.keys()).join(\"\\n \")}`);\n\n for (const pkgID of packagesToPublish) {\n const pkg = this.getArtifact(pkgID, \"docker\");\n if (!pkg) {\n if (options?.ids) {\n this.logger.warn(\n `Package '${pkgID}' is not buildable into docker image. Cannot publish docker image.`,\n );\n }\n continue;\n }\n\n // Mirror the gate in buildDockerImages: in strict (CI) mode, only the\n // linux/x64 leg publishes so we don't race parallel pushes of the same\n // tag from arm and windows matrix legs. Dev (non-strict) mode pushes\n // unconditionally — the cross-compile produced a valid linux/amd64\n // image regardless of host.\n if (options?.strictPlatformMatching) {\n if (util.currentOS() !== \"linux\" || util.currentArch() !== \"x64\") {\n this.logger.debug(\n `Docker image publish skipped for '${pkg.id}': strict-platform mode requires linux/x64 host`,\n );\n continue;\n }\n }\n\n this.publishDockerImage(pkg, options?.pushTo);\n }\n }\n\n private publishDockerImage(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n pushTo?: string,\n ) {\n if (artifact.type !== \"docker\") {\n throw util.CLIError(`package '${artifact.id}' is not a docker package`);\n }\n\n // Matches the \"x64\" write in buildDockerImage — docker artifacts are always\n // cross-compiled to linux/amd64 so we look up the x64 descriptor regardless\n // of host.\n const artInfoPath = this.pkgInfo.artifactInfoLocation(artifact.id, \"docker\", \"x64\");\n const artInfo = readBuiltArtifactInfo(artInfoPath);\n const tag = artInfo.remoteArtifactLocation;\n const pushTag = pushTo ? `${pushTo}:${tag.split(\":\").slice(-1)[0]}` : tag;\n\n // Because of turbo caching, we may face situation when no real docker build was executed on CI agent,\n // but image is already in remote registry. We should not fail in such scenarios, calmly skipping docker push step.\n const remoteImageExists = docker.remoteImageExists(pushTag);\n if (remoteImageExists) {\n this.logger.info(\n `Docker image '${tag}' not exists locally but is already in remote registry. Skipping push...`,\n );\n return;\n }\n\n const localImageExists = docker.localImageExists(tag);\n if (!localImageExists) {\n throw util.CLIError(\n `Docker image '${tag}' not exists locally and is not found in remote registry. Publication failed.`,\n );\n }\n\n if (pushTo) {\n docker.addTag(tag, pushTag);\n this.logger.info(`Publishing docker image '${tag}' using alternative tag '${pushTag}'`);\n } else {\n this.logger.info(`Publishing docker image '${tag}' with tag '${pushTag}'`);\n }\n\n docker.push(pushTag);\n }\n\n private get renderer(): SwJsonRenderer {\n if (!this._renderer) {\n this._renderer = new SwJsonRenderer(this.logger, this.pkgInfo);\n }\n\n return this._renderer;\n }\n\n private archiveOptions(\n pkg: artifacts.anyArtifactType,\n name: string,\n version: string,\n os: util.OSType,\n arch: util.ArchType,\n archiveType: archive.archiveType,\n ): archive.archiveOptions {\n return {\n packageRoot: this.pkgInfo.packageRoot,\n packageName: name,\n packageVersion: version,\n\n crossplatform: artifacts.isCrossPlatform(pkg.type),\n os: os,\n arch: arch,\n ext: archiveType,\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"core.cjs","names":["PackageInfo","path","fs","tmpSpecFile","fsp","micromamba","readBuiltArtifactInfo","SwJsonRenderer"],"sources":["../../src/core/core.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\nimport yaml from \"yaml\";\nimport type winston from \"winston\";\n\nimport * as defaults from \"../defaults\";\nimport { PackageInfo } from \"./package-info\";\nimport * as artifacts from \"./schemas/artifacts\";\nimport type * as entrypoint from \"./schemas/entrypoints\";\nimport { micromamba } from \"./conda/builder\";\nimport { validateCondaSpec } from \"./conda/validate-spec\";\nimport { SwJsonRenderer, readBuiltArtifactInfo, writeBuiltArtifactInfo } from \"./sw-json-render\";\nimport * as util from \"./util\";\nimport * as archive from \"./archive\";\nimport * as storage from \"./storage\";\nimport * as docker from \"./docker\";\nimport * as dockerCoverage from \"./docker-coverage\";\nimport { tmpSpecFile } from \"./docker-conda\";\n\nexport class Core {\n private readonly logger: winston.Logger;\n private _entrypoints: Map<string, entrypoint.Entrypoint> | undefined;\n private _renderer: SwJsonRenderer | undefined;\n\n public readonly pkgInfo: PackageInfo;\n public targetPlatform: util.PlatformType | undefined;\n public allPlatforms: boolean = false;\n public fullDirHash: boolean;\n\n constructor(\n logger: winston.Logger,\n opts?: {\n pkgInfo?: PackageInfo;\n packageRoot?: string;\n },\n ) {\n this.logger = logger;\n this.pkgInfo = opts?.pkgInfo ?? new PackageInfo(logger, { packageRoot: opts?.packageRoot });\n\n this.fullDirHash = false;\n }\n\n public get buildMode(): util.BuildMode {\n return this.pkgInfo.buildMode;\n }\n\n public set buildMode(mode: util.BuildMode) {\n this.pkgInfo.buildMode = mode;\n }\n\n public set version(v: string | undefined) {\n this.pkgInfo.version = v;\n }\n\n public get isPrivate(): boolean {\n return this.pkgInfo.isPrivate;\n }\n\n public binArchivePath(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n os: util.OSType,\n arch: util.ArchType,\n ): string {\n const name = this.pkgInfo.artifactName(artifact);\n const version = this.pkgInfo.artifactVersion(artifact);\n return archive.getPath(this.archiveOptions(artifact, name, version, os, arch, \"tgz\"));\n }\n\n public assetArchivePath(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n os: util.OSType,\n arch: util.ArchType,\n ): string {\n const name = this.pkgInfo.artifactName(artifact);\n const version = this.pkgInfo.artifactVersion(artifact);\n return archive.getPath(this.archiveOptions(artifact, name, version, os, arch, \"zip\"));\n }\n\n public archivePath(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n os: util.OSType,\n arch: util.ArchType,\n ): string {\n if (artifact.type === \"asset\") {\n return this.assetArchivePath(artifact, os, arch);\n }\n\n return this.binArchivePath(artifact, os, arch);\n }\n\n public get entrypoints(): Map<string, entrypoint.Entrypoint> {\n if (!this._entrypoints) {\n this._entrypoints = this.pkgInfo.entrypoints;\n }\n\n return this._entrypoints;\n }\n\n public get packages(): Map<string, artifacts.withId<artifacts.anyArtifactType>> {\n const pkgs = new Map<string, artifacts.withId<artifacts.anyArtifactType>>();\n\n for (const [_, ep] of this.entrypoints.entries()) {\n if (ep.type === \"reference\") {\n // References have no pacakge definitions inside\n continue;\n }\n\n const key =\n ep.artifact.type === \"docker\" ? docker.entrypointName(ep.artifact.id) : ep.artifact.id;\n pkgs.set(key, ep.artifact);\n }\n\n return pkgs;\n }\n\n public get packageEntrypointsIndex(): Map<string, string[]> {\n const result = new Map<string, string[]>();\n\n for (const [epName, ep] of this.entrypoints) {\n if (ep.type === \"reference\") {\n // References have no pacakge definitions inside\n continue;\n }\n\n if (!result.has(ep.artifact.id)) {\n result.set(ep.artifact.id, []);\n }\n\n result.get(ep.artifact.id)!.push(epName);\n }\n\n return result;\n }\n\n public get buildablePackages(): Map<string, artifacts.withId<artifacts.anyArtifactType>> {\n return new Map(\n Array.from(this.packages.entries())\n .filter(([id, _]) => !docker.isVirtualDockerEntrypointName(id)) // do not show virtual docker entrypoints\n .filter(([, value]) => artifacts.isBuildable(value.type)),\n );\n }\n\n public get dockerPackages(): Map<string, artifacts.withId<artifacts.anyArtifactType>> {\n return new Map(\n Array.from(this.packages.entries())\n .filter(([id, _]) => docker.isVirtualDockerEntrypointName(id)) // do not show virtual docker entrypoints\n .filter(([, value]) => value.type === \"docker\"),\n );\n }\n\n /**\n * The docker artifacts a build would actually produce for this selection.\n *\n * Mirrors the resolution `buildDockerImages` performs, so callers can reason\n * about a build before running it. Note that `ids` are entrypoint names, not\n * docker package keys: `getArtifact(id, \"docker\")` resolves the `:docker`\n * virtual entrypoint, so a plain set intersection with `dockerPackages`\n * would be wrong.\n */\n public selectedDockerPackages(ids?: string[]): string[] {\n const selected = ids ?? Array.from(this.dockerPackages.keys());\n return selected.filter((id) => this.getArtifact(id, \"docker\") !== undefined);\n }\n\n public packageHasType(id: string, type: artifacts.artifactType): boolean {\n const pkg = this.packages.get(id);\n if (pkg && pkg.type === type) {\n return true;\n }\n\n // check 'magic' entrypoint name with suffix\n const dockerPkg = this.packages.get(docker.entrypointName(id));\n if (dockerPkg) {\n return true;\n }\n\n return false;\n }\n\n public getArtifact(\n id: string,\n type: \"docker\",\n ): artifacts.withId<artifacts.dockerType> | undefined;\n public getArtifact(\n id: string,\n type: \"archive\",\n ): artifacts.withId<artifacts.anyArtifactType> | undefined;\n public getArtifact(\n id: string,\n type: \"docker\" | \"archive\",\n ): artifacts.withId<artifacts.anyArtifactType> | undefined {\n const artifact = this.packages.get(id);\n\n switch (type) {\n case \"docker\": {\n if (artifact?.type === \"docker\") {\n return artifact;\n }\n // Virtual entrypoint with suffix specially for docker artifacts.\n return this.packages.get(docker.entrypointName(id));\n }\n case \"archive\": {\n if (artifact?.type === \"docker\") {\n return undefined;\n }\n return artifact;\n }\n default: {\n util.assertNever(type);\n return undefined;\n }\n }\n }\n\n /**\n * Fails a CI build that would describe software no kubernetes installation can run.\n *\n * `buildSwJsonFiles` calls this on the selection it is about to write, so no path\n * can skip it. Callers may also invoke it up front — the answer comes from the\n * package's declaration alone, so a CI run that is going to fail can fail before\n * it spends minutes building archives and images.\n *\n * Only builds that write a registry descriptor answer for coverage. A dev-local\n * build (`build:dev-local`, and the `test` script's binary-only build) describes\n * software by filesystem path: it never reaches a cluster, so a missing image\n * cannot hurt anyone there, and failing those runs would block a block's tests on\n * a release rule. Release and dev-remote builds do publish, and are checked.\n */\n public assertDockerCoverage(options?: { entrypoints?: Map<string, entrypoint.Entrypoint> }) {\n if (!util.producesRegistryDescriptor(this.buildMode)) return;\n\n dockerCoverage.assertDockerCoverage({\n softwareWithoutDocker: dockerCoverage.softwareEntrypointsWithoutDocker(\n options?.entrypoints ?? this.entrypoints,\n ),\n requirementWaived: !this.pkgInfo.requireDocker,\n });\n }\n\n // Get entrypoints defined in package.json, transform them to local or release (depending on `buildMode`)\n // sw.json entrypoint descriptors, and write them to ./dist/tengo/sw.json or as.json next to the package.json.\n public buildSwJsonFiles(options?: {\n packageIds?: string[];\n entrypoints?: string[];\n sources?: util.SoftwareSource[];\n requireAllArtifacts?: boolean;\n noSoftware?: boolean;\n skipDockerCoverage?: boolean;\n }) {\n const index = this.packageEntrypointsIndex;\n\n const entrypointNames = options?.entrypoints ?? [];\n if (options?.packageIds) {\n for (const pkgId of options.packageIds) {\n const packageEntrypoints = index.get(pkgId);\n if (!packageEntrypoints || packageEntrypoints.length === 0) {\n throw util.CLIError(\n `cannot build descriptor for package ${pkgId}: no entrypoints found for package`,\n );\n }\n\n entrypointNames.push(...packageEntrypoints);\n }\n }\n\n let entrypoints = Array.from(this.entrypoints.entries());\n if (entrypointNames.length > 0) {\n entrypoints = entrypoints.filter(([epName, _]) => entrypointNames.includes(epName));\n }\n\n // The descriptor is the contract the backend reads, so this is the last point at\n // which a software entrypoint with no docker image can still be stopped. Judged\n // over the selection being described, so a targeted build answers only for what\n // it writes. Skipped where this build produces no software of its own: the\n // placeholder path describes none, and `skipDockerCoverage` is for a caller\n // pointing the descriptor at an artifact someone else already released.\n if (!options?.noSoftware && !options?.skipDockerCoverage) {\n this.assertDockerCoverage({ entrypoints: new Map(entrypoints) });\n }\n\n const infos = options?.noSoftware\n ? this.renderer.renderPlaceholderEntrypoints(new Map(entrypoints))\n : this.renderer.renderSoftwareEntrypoints(this.buildMode, new Map(entrypoints), {\n requireAllArtifacts: options?.requireAllArtifacts,\n fullDirHash: this.fullDirHash,\n });\n\n for (const swJson of infos.values()) {\n this.renderer.writeSwJson(swJson);\n }\n\n for (const [epName, ep] of entrypoints) {\n if (ep.type === \"reference\") {\n const srcPath = this.pkgInfo.resolveReference(epName, ep);\n this.renderer.copySwJson(epName, srcPath);\n }\n }\n }\n\n // Point artifact-info at the already-published, version-derived artifact without building or\n // uploading, so buildSwJsonFiles renders a registry descriptor for it. Release mode, binary only.\n public writePublishedArtifactInfo(options?: { ids?: string[] }) {\n const platform = util.currentPlatform();\n for (const [id, artifact] of this.buildablePackages) {\n if (options?.ids && !options.ids.includes(id)) continue;\n\n // Cross-platform archives are stored under a platform-agnostic key; this is the key\n // renderBinaryInfo reads back from.\n const locationKey = artifacts.isCrossPlatform(artifact.type) ? undefined : platform;\n const registry = this.pkgInfo.artifactRegistrySettings(artifact);\n\n writeBuiltArtifactInfo(this.pkgInfo.artifactInfoLocation(id, \"archive\", locationKey), {\n type: artifact.type,\n platform,\n registryURL: registry.downloadURL,\n registryName: registry.name,\n remoteArtifactLocation: this.pkgInfo.artifactArchiveAddressPattern(artifact),\n uploadPath: this.pkgInfo.artifactArchiveFullName(artifact, platform),\n });\n }\n }\n\n public async buildSoftwareArchives(options?: {\n ids?: string[];\n forceBuild?: boolean;\n\n archivePath?: string;\n contentRoot?: string;\n skipIfEmpty?: boolean;\n\n // Automated builds settings\n condaBuild?: boolean;\n }) {\n this.logger.info(`Building package archives...`);\n\n const packagesToBuild = options?.ids ?? Array.from(this.buildablePackages.keys());\n this.logger.debug(`Selected packages:\\n ${packagesToBuild.join(\"\\n \")}`);\n this.logger.debug(`All known packages:\\n ${Array.from(this.packages.keys()).join(\"\\n \")}`);\n\n if (packagesToBuild.length > 1 && options?.archivePath && !options.forceBuild) {\n this.logger.error(\n \"Attempt to build several packages targeting single package archive. This will simply overwrite the archive several times. If you know what you are doing, add '--force' flag\",\n );\n throw util.CLIError(\n \"attempt to build several packages using the same software package archive\",\n );\n }\n\n for (const artifactID of packagesToBuild) {\n const artifact = this.getArtifact(artifactID, \"archive\");\n\n if (!artifact) {\n if (options?.ids) {\n this.logger.warn(`Package '${artifactID}' is not buildable into archive. Skipped.`);\n }\n continue;\n }\n\n if (artifacts.isCrossPlatform(artifact.type)) {\n await this.buildSoftwareArchive(artifact, util.currentPlatform(), options);\n } else if (this.targetPlatform) {\n await this.buildSoftwareArchive(artifact, this.targetPlatform, options);\n } else if (this.allPlatforms) {\n for (const platform of this.pkgInfo.artifactPlatforms(artifact)) {\n await this.buildSoftwareArchive(artifact, platform, options);\n }\n } else {\n await this.buildSoftwareArchive(artifact, util.currentPlatform(), options);\n }\n }\n }\n\n // NOTE: each artifact build consists of 2 components:\n // - built artifact in any shape (archive, docker image, etc)\n // - artifact location file, that contains address of the artifact in registry (docker tag, archive path and so on)\n //\n // artifact may be uploaded to the registry in content-addressable mode, when the artifact location\n // is derived from the actual artifact (software archive, docker image, etc) content.\n // artifact location files are used to build sw.json entrypoint descriptor with correct artifact address.\n public async buildSoftwareArchive(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n platform: util.PlatformType,\n options?: {\n archivePath?: string;\n contentRoot?: string;\n skipIfEmpty?: boolean;\n\n // Automated builds settings\n condaBuild?: boolean;\n },\n ) {\n this.logger.info(`Building software package '${artifact.id}' for platform '${platform}'...`);\n const { os, arch } = util.splitPlatform(platform);\n\n if (!artifacts.archiveArtifactTypes.includes(artifact.type)) {\n if (options?.skipIfEmpty) {\n this.logger.info(` archive build was skipped: package '${artifact.id}' is not buildable`);\n }\n this.logger.error(\n ` not buildable: artifact '${artifact.id}' archive build is impossible for configuration inside '${util.softwareConfigName}'`,\n );\n\n throw util.CLIError(\"not a buildable artifact\");\n }\n\n const contentRoot =\n options?.contentRoot ?? this.pkgInfo.artifactContentRoot(artifact, platform);\n\n if (artifact.type === \"asset\") {\n const archivePath = options?.archivePath ?? this.assetArchivePath(artifact, os, arch);\n await this.createPackageArchive(\"assets\", artifact, archivePath, contentRoot, os, arch);\n return;\n }\n\n const artType = artifact.type;\n switch (artType) {\n case \"conda\": {\n if (options?.condaBuild === undefined || options.condaBuild) {\n // build by default, skip if explicitly disabled\n await this.buildCondaPackage({ artifact, platform, contentRoot });\n } else {\n this.logger.debug(`Conda environment build was skipped.`);\n }\n break;\n }\n }\n\n if (!util.producesRegistryDescriptor(this.buildMode)) {\n this.logger.info(\n ` no need to build software archive in '${this.buildMode}' mode: archive build was skipped`,\n );\n return;\n }\n\n const archivePath = options?.archivePath ?? this.binArchivePath(artifact, os, arch);\n await this.createPackageArchive(\"software\", artifact, archivePath, contentRoot, os, arch);\n }\n\n public buildDockerImages(options?: {\n ids?: string[];\n registry?: string;\n strictPlatformMatching?: boolean; // if true, build docker images only on linux OS and only for supported architectures. Used in CI.\n }) {\n this.logger.info(`Building docker images...`);\n\n const packagesToBuild = options?.ids ?? Array.from(this.dockerPackages.keys());\n this.logger.debug(`Selected packages:\\n ${packagesToBuild.join(\"\\n \")}`);\n this.logger.debug(`All known packages:\\n ${Array.from(this.packages.keys()).join(\"\\n \")}`);\n\n for (const pkgID of packagesToBuild) {\n const artifact = this.getArtifact(pkgID, \"docker\");\n\n if (!artifact) {\n if (options?.ids) {\n this.logger.warn(`Package '${pkgID}' is not buildable into docker image. Skipped.`);\n }\n continue;\n }\n\n // Docker images are always built as linux/amd64 (Platforma's K8s target);\n // on non-x64 hosts pl-pkg cross-compiles via qemu so dev iteration on\n // Macs works. In CI, strictPlatformMatching is set on the caller side\n // and we still want exactly one matrix leg (linux/x64) to do the work —\n // otherwise every arm/windows runner duplicates the build and Windows\n // runners outright fail on 'docker build --platform linux/amd64'.\n if (options?.strictPlatformMatching) {\n if (util.currentOS() !== \"linux\" || util.currentArch() !== \"x64\") {\n this.logger.debug(\n `Docker image build skipped for '${artifact.id}': strict-platform mode requires linux/x64 host`,\n );\n continue;\n }\n }\n\n // Docker software is built as linux/amd64 only (Platforma's K8s target). An explicit\n // non-x64 target cannot be honored — fail clearly instead of silently emitting amd64.\n if (this.targetPlatform && util.splitPlatform(this.targetPlatform).arch !== \"x64\") {\n throw util.CLIError(\n `cannot build docker image '${artifact.id}' for target '${this.targetPlatform}': ` +\n `docker software is built as ${defaults.DOCKER_BUILD_PLATFORM} only`,\n );\n }\n\n this.buildDockerImage(artifact.id, artifact, options?.registry);\n }\n }\n\n // NOTE: each artifact build consists of 2 components:\n // - built artifact in any shape (archive, docker image, etc)\n // - artifact location file, that contains address of the artifact in registry (docker tag, archive path and so on)\n //\n // docker image is uploaded to the registry after build with unique tag that is derived from the actual image content.\n // artifact location files are used to build sw.json entrypoint descriptor with correct artifact address.\n private buildDockerImage(\n pkgID: string,\n artifact: artifacts.withId<artifacts.dockerType>,\n registry?: string,\n ) {\n const dockerfile = path.resolve(this.pkgInfo.packageRoot, artifact.dockerfile ?? \"Dockerfile\");\n const context = path.resolve(this.pkgInfo.packageRoot, artifact.context ?? \".\");\n registry = registry ?? artifact.registry;\n\n if (!fs.existsSync(dockerfile)) {\n throw util.CLIError(`Dockerfile '${dockerfile}' not found`);\n }\n\n if (!fs.existsSync(context)) {\n throw util.CLIError(`Context '${context}' not found`);\n }\n\n const localTag = docker.generateLocalTagName(this.pkgInfo.packageRoot, artifact);\n\n this.logger.info(`Building docker image for '${pkgID}'...`);\n this.logger.debug(` dockerfile: '${dockerfile}'\n context: '${context}'\n localTag: '${localTag}'\n `);\n\n const name = this.pkgInfo.artifactName(artifact);\n\n docker.build(context, dockerfile, localTag, name, this.pkgInfo.version);\n\n const imageHash = docker.getImageHash(localTag);\n const dstTag = docker.generateRemoteTagName(name, imageHash, registry);\n\n this.logger.debug(`Adding destination tag to docker image:\n dstTag: \"${dstTag}\"\n `);\n docker.addTag(localTag, dstTag);\n // do not remove local tag to make 'local' builds to also work with docker.\n\n // Docker images target linux/amd64 regardless of host (see docker.build).\n const artInfoPath = this.pkgInfo.artifactInfoLocation(pkgID, \"docker\", \"x64\");\n writeBuiltArtifactInfo(artInfoPath, {\n type: \"docker\",\n platform: \"linux-x64\",\n remoteArtifactLocation: dstTag,\n entrypoint: docker.getImageEntrypoint(localTag),\n });\n\n this.logger.info(`Docker image is built:\n tag: '${dstTag}'\n location file: '${artInfoPath}'`);\n\n this.logger.debug(`Clearing context directory from temporary files...`);\n if (fs.existsSync(path.join(context, tmpSpecFile))) {\n fs.unlinkSync(path.join(context, tmpSpecFile));\n }\n }\n\n private async buildCondaPackage(opts: {\n artifact: artifacts.withId<artifacts.condaType>;\n platform: util.PlatformType;\n contentRoot: string;\n }) {\n const { artifact, platform, contentRoot } = opts;\n\n if (platform !== util.currentPlatform()) {\n this.logger.warn(\n `Conda package cannot be built cross-platform:\\n` +\n ` current platform is '${util.currentPlatform()}', requested platform is '${platform}'\\n` +\n `Conda environment automatic build was skipped`,\n );\n return;\n }\n\n this.logger.info(`Building conda environment for current platform...`);\n\n const srcSpecPath = path.resolve(this.pkgInfo.packageRoot, artifact.spec);\n if (!fs.existsSync(srcSpecPath)) {\n this.logger.error(\n `Conda environment specification file '${artifact.spec}' not found at '${srcSpecPath}'`,\n );\n throw util.CLIError(\n `Cannot build conda environment '${artifact.id}': no specification file.`,\n );\n }\n\n this.logger.debug(`Validating conda spec file for forbidden channels...`);\n try {\n validateCondaSpec(this.logger, srcSpecPath);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error(errorMessage);\n throw util.CLIError(`Cannot build conda environment '${artifact.id}': ${errorMessage}`);\n }\n\n const micromambaRoot = path.join(contentRoot, defaults.CONDA_DATA_LOCATION);\n const micromambaBin = path.join(contentRoot, \"micromamba\");\n\n this.logger.debug(`Creating micromamba root directory: '${micromambaRoot}'`);\n await fsp.mkdir(micromambaRoot, { recursive: true });\n\n this.logger.debug(`Creating micromamba instance...`);\n const m = new micromamba(\n this.logger,\n micromambaRoot,\n artifact[\"micromamba-version\"],\n micromambaBin,\n );\n\n const resultSpecPath = path.join(contentRoot, defaults.CONDA_FROZEN_ENV_SPEC_FILE);\n\n await m.downloadBinary();\n m.createEnvironment({ specFile: srcSpecPath });\n m.exportEnvironment({ outputFile: resultSpecPath });\n m.deleteEnvironment({});\n\n this.logger.debug(`Conda environment was built at '${micromambaRoot}'.`);\n\n this.logger.debug(`Cutting prefix from conda environment file...`);\n\n const resultSpec = yaml.parse(await fsp.readFile(resultSpecPath, \"utf-8\")) as Record<\n string,\n unknown\n >;\n resultSpec.prefix = undefined; // cut original env location (with path from CI) from the resulting spec file\n\n // Fixup the structure: for empty lists export produces YAML that cannot be then read back on server side for restoration.\n if (!resultSpec.channels) {\n resultSpec.channels = [];\n }\n if (!resultSpec.dependencies) {\n resultSpec.dependencies = [];\n }\n await fsp.writeFile(resultSpecPath, yaml.stringify(resultSpec));\n\n this.logger.debug(`Conda environment file is ready: '${resultSpecPath}'`);\n }\n\n private async createPackageArchive(\n packageContentType: string,\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n archivePath: string,\n contentRoot: string,\n os: util.OSType,\n arch: util.ArchType,\n ) {\n this.logger.debug(` packing ${packageContentType} into a package`);\n if (artifacts.isCrossPlatform(artifact.type)) {\n this.logger.debug(` generating cross-platform package`);\n } else {\n this.logger.debug(` generating package for os='${os}', arch='${arch}'`);\n }\n this.logger.debug(` package content root: '${contentRoot}'`);\n this.logger.debug(` package destination archive: '${archivePath}'`);\n\n await archive.create(this.logger, contentRoot, archivePath);\n\n const artInfoPath = this.pkgInfo.artifactInfoLocation(\n artifact.id,\n \"archive\",\n artifacts.isCrossPlatform(artifact.type) ? undefined : util.joinPlatform(os, arch),\n );\n\n const registry = this.pkgInfo.artifactRegistrySettings(artifact);\n\n writeBuiltArtifactInfo(artInfoPath, {\n type: artifact.type,\n platform: util.joinPlatform(os, arch),\n registryURL: registry.downloadURL,\n registryName: registry.name,\n remoteArtifactLocation: this.pkgInfo.artifactArchiveAddressPattern(artifact),\n uploadPath: this.pkgInfo.artifactArchiveFullName(artifact, util.joinPlatform(os, arch)),\n });\n\n this.logger.info(`${packageContentType} archive is built:\n archive: '${archivePath}'\n location file: '${artInfoPath}'`);\n }\n\n public async publishPackages(options?: {\n ids?: string[];\n\n archivePath?: string;\n storageURL?: string;\n\n failExisting?: boolean; // do not warn if package already exists in storage, fail with error instead.\n forceReupload?: boolean; // re-upload packages even if they already exist in storage\n }) {\n this.logger.info(`Publishing packages...`);\n\n const packagesToPublish = options?.ids ?? Array.from(this.buildablePackages.keys());\n this.logger.debug(`Selected packages:\\n ${packagesToPublish.join(\"\\n \")}`);\n this.logger.debug(`All known packages:\\n ${Array.from(this.packages.keys()).join(\"\\n \")}`);\n\n const uploads: Promise<void>[] = [];\n for (const pkgID of packagesToPublish) {\n const pkg = this.getArtifact(pkgID, \"archive\");\n\n if (!pkg) {\n if (options?.ids) {\n this.logger.warn(\n `Package '${pkgID}' is not buildable into archive. Cannot publish archive artifact.`,\n );\n }\n continue;\n }\n\n if (artifacts.isCrossPlatform(pkg.type)) {\n uploads.push(this.publishPackage(pkg, util.currentPlatform(), options));\n } else if (this.targetPlatform) {\n uploads.push(this.publishPackage(pkg, this.targetPlatform, options));\n } else if (this.allPlatforms) {\n for (const platform of this.pkgInfo.artifactPlatforms(pkg)) {\n uploads.push(this.publishPackage(pkg, platform, options));\n }\n } else {\n uploads.push(this.publishPackage(pkg, util.currentPlatform(), options));\n }\n }\n\n await Promise.all(uploads);\n }\n\n private async publishPackage(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n platform: util.PlatformType,\n options?: {\n archivePath?: string;\n storageURL?: string;\n\n failExisting?: boolean;\n forceReupload?: boolean;\n },\n ) {\n if (artifact.type === \"docker\") {\n this.publishDockerImage(artifact);\n return;\n }\n\n await this.publishArchive(artifact, platform, options);\n }\n\n private async publishArchive(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n platform: util.PlatformType,\n options?: {\n archivePath?: string;\n storageURL?: string;\n failExisting?: boolean;\n forceReupload?: boolean;\n },\n ) {\n const { os, arch } = util.splitPlatform(platform);\n\n const artifactName = this.pkgInfo.artifactName(artifact);\n const registry = this.pkgInfo.artifactRegistrySettings(artifact);\n const storageURL = options?.storageURL ?? registry.storageURL;\n\n const archivePath = options?.archivePath ?? this.archivePath(artifact, os, arch);\n\n const artInfoPath = this.pkgInfo.artifactInfoLocation(\n artifact.id,\n \"archive\",\n artifacts.isCrossPlatform(artifact.type) ? undefined : util.joinPlatform(os, arch),\n );\n const artInfo = readBuiltArtifactInfo(artInfoPath);\n const dstName = artInfo.uploadPath ?? artInfo.remoteArtifactLocation;\n\n if (!storageURL) {\n const regNameUpper = registry.name.toUpperCase().replaceAll(/[^A-Z0-9_]/g, \"_\");\n this.logger.error(`no storage URL is set for registry ${registry.name}`);\n throw util.CLIError(\n `'registry.storageURL' of package '${artifact.id}' is empty. Set it as command option, in '${util.softwareConfigName}' file or via environment variable 'PL_REGISTRY_${regNameUpper}_UPLOAD_URL'`,\n );\n }\n\n this.logger.info(\n `Publishing package '${artifactName}' for platform '${platform}' into registry '${registry.name}'`,\n );\n this.logger.debug(` registry storage URL: '${storageURL}'`);\n this.logger.debug(` archive to publish: '${archivePath}'`);\n this.logger.debug(` target package name: '${dstName}'`);\n\n const s = await storage.initByUrl(storageURL, this.pkgInfo.packageRoot);\n\n const exists = await s.exists(dstName);\n if (exists && !options?.forceReupload) {\n if (options?.failExisting) {\n throw util.CLIError(\n `software package '${dstName}' already exists in registry '${registry.name}'. To re-upload it, use 'force' flag. To not fail, remove 'fail-existing-packages' flag`,\n );\n }\n\n this.logger.warn(\n `software package '${dstName}' already exists in registry '${registry.name}'. Upload was skipped.`,\n );\n return;\n }\n\n const uploads: Promise<void>[] = [];\n\n const archive = fs.createReadStream(archivePath);\n uploads.push(\n s.putFile(dstName, archive).finally(() => {\n archive.close();\n return;\n }),\n );\n\n return Promise.all(uploads).then(() => {\n this.logger.info(`Package '${artifactName}' was published to '${registry.name}:${dstName}'`);\n return;\n });\n }\n\n public publishDockerImages(options?: {\n ids?: string[];\n pushTo?: string;\n strictPlatformMatching?: boolean; // if true, publish docker images only on linux OS and only for supported architectures. Used in CI.\n }) {\n this.logger.info(`Publishing docker images...`);\n\n // Iterate only dockerPackages (matches buildDockerImages). Previously we\n // also iterated buildablePackages.keys(), but for entrypoints with a python\n // or conda binary that autogens a docker image, the binary key (e.g. \"main\")\n // and the virtual docker key (\"main:docker\") both resolve to the same\n // docker artifact via getArtifact's :docker fallback. That caused\n // publishDockerImage to run twice — first push succeeded, second saw the\n // tag in the registry and logged a misleading \"Skipping push...\" line.\n const packagesToPublish = options?.ids ?? Array.from(this.dockerPackages.keys());\n this.logger.debug(`Selected packages:\\n ${packagesToPublish.join(\"\\n \")}`);\n this.logger.debug(`All known packages:\\n ${Array.from(this.packages.keys()).join(\"\\n \")}`);\n\n for (const pkgID of packagesToPublish) {\n const pkg = this.getArtifact(pkgID, \"docker\");\n if (!pkg) {\n if (options?.ids) {\n this.logger.warn(\n `Package '${pkgID}' is not buildable into docker image. Cannot publish docker image.`,\n );\n }\n continue;\n }\n\n // Mirror the gate in buildDockerImages: in strict (CI) mode, only the\n // linux/x64 leg publishes so we don't race parallel pushes of the same\n // tag from arm and windows matrix legs. Dev (non-strict) mode pushes\n // unconditionally — the cross-compile produced a valid linux/amd64\n // image regardless of host.\n if (options?.strictPlatformMatching) {\n if (util.currentOS() !== \"linux\" || util.currentArch() !== \"x64\") {\n this.logger.debug(\n `Docker image publish skipped for '${pkg.id}': strict-platform mode requires linux/x64 host`,\n );\n continue;\n }\n }\n\n this.publishDockerImage(pkg, options?.pushTo);\n }\n }\n\n private publishDockerImage(\n artifact: artifacts.withId<artifacts.anyArtifactType>,\n pushTo?: string,\n ) {\n if (artifact.type !== \"docker\") {\n throw util.CLIError(`package '${artifact.id}' is not a docker package`);\n }\n\n // Matches the \"x64\" write in buildDockerImage — docker artifacts are always\n // cross-compiled to linux/amd64 so we look up the x64 descriptor regardless\n // of host.\n const artInfoPath = this.pkgInfo.artifactInfoLocation(artifact.id, \"docker\", \"x64\");\n const artInfo = readBuiltArtifactInfo(artInfoPath);\n const tag = artInfo.remoteArtifactLocation;\n const pushTag = pushTo ? `${pushTo}:${tag.split(\":\").slice(-1)[0]}` : tag;\n\n // Because of turbo caching, we may face situation when no real docker build was executed on CI agent,\n // but image is already in remote registry. We should not fail in such scenarios, calmly skipping docker push step.\n const remoteImageExists = docker.remoteImageExists(pushTag);\n if (remoteImageExists) {\n this.logger.info(\n `Docker image '${tag}' not exists locally but is already in remote registry. Skipping push...`,\n );\n return;\n }\n\n const localImageExists = docker.localImageExists(tag);\n if (!localImageExists) {\n throw util.CLIError(\n `Docker image '${tag}' not exists locally and is not found in remote registry. Publication failed.`,\n );\n }\n\n if (pushTo) {\n docker.addTag(tag, pushTag);\n this.logger.info(`Publishing docker image '${tag}' using alternative tag '${pushTag}'`);\n } else {\n this.logger.info(`Publishing docker image '${tag}' with tag '${pushTag}'`);\n }\n\n docker.push(pushTag);\n }\n\n private get renderer(): SwJsonRenderer {\n if (!this._renderer) {\n this._renderer = new SwJsonRenderer(this.logger, this.pkgInfo);\n }\n\n return this._renderer;\n }\n\n private archiveOptions(\n pkg: artifacts.anyArtifactType,\n name: string,\n version: string,\n os: util.OSType,\n arch: util.ArchType,\n archiveType: archive.archiveType,\n ): archive.archiveOptions {\n return {\n packageRoot: this.pkgInfo.packageRoot,\n packageName: name,\n packageVersion: version,\n\n crossplatform: artifacts.isCrossPlatform(pkg.type),\n os: os,\n arch: arch,\n ext: archiveType,\n };\n }\n}\n"],"mappings":"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"}
|
package/dist/core/core.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { ArchType, BuildMode, OSType, PlatformType, SoftwareSource } from "./util.js";
|
|
2
|
-
import { anyArtifactType, artifactType, dockerType, withId } from "./schemas/artifacts.js";
|
|
3
|
-
import { Entrypoint } from "./schemas/entrypoints.js";
|
|
1
|
+
import { ArchType, BuildMode, OSType, PlatformType, SoftwareSource, util_d_exports } from "./util.js";
|
|
2
|
+
import { anyArtifactType, artifactType, artifacts_d_exports, dockerType, withId } from "./schemas/artifacts.js";
|
|
3
|
+
import { Entrypoint, entrypoints_d_exports } from "./schemas/entrypoints.js";
|
|
4
4
|
import { PackageInfo } from "./package-info.js";
|
|
5
5
|
import winston from "winston";
|
|
6
|
-
|
|
7
6
|
//#region src/core/core.d.ts
|
|
8
|
-
declare class Core {
|
|
7
|
+
export declare class Core {
|
|
9
8
|
private readonly logger;
|
|
10
9
|
private _entrypoints;
|
|
11
10
|
private _renderer;
|
|
@@ -29,15 +28,43 @@ declare class Core {
|
|
|
29
28
|
get packageEntrypointsIndex(): Map<string, string[]>;
|
|
30
29
|
get buildablePackages(): Map<string, withId<anyArtifactType>>;
|
|
31
30
|
get dockerPackages(): Map<string, withId<anyArtifactType>>;
|
|
31
|
+
/**
|
|
32
|
+
* The docker artifacts a build would actually produce for this selection.
|
|
33
|
+
*
|
|
34
|
+
* Mirrors the resolution `buildDockerImages` performs, so callers can reason
|
|
35
|
+
* about a build before running it. Note that `ids` are entrypoint names, not
|
|
36
|
+
* docker package keys: `getArtifact(id, "docker")` resolves the `:docker`
|
|
37
|
+
* virtual entrypoint, so a plain set intersection with `dockerPackages`
|
|
38
|
+
* would be wrong.
|
|
39
|
+
*/
|
|
40
|
+
selectedDockerPackages(ids?: string[]): string[];
|
|
32
41
|
packageHasType(id: string, type: artifactType): boolean;
|
|
33
42
|
getArtifact(id: string, type: "docker"): withId<dockerType> | undefined;
|
|
34
43
|
getArtifact(id: string, type: "archive"): withId<anyArtifactType> | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Fails a CI build that would describe software no kubernetes installation can run.
|
|
46
|
+
*
|
|
47
|
+
* `buildSwJsonFiles` calls this on the selection it is about to write, so no path
|
|
48
|
+
* can skip it. Callers may also invoke it up front — the answer comes from the
|
|
49
|
+
* package's declaration alone, so a CI run that is going to fail can fail before
|
|
50
|
+
* it spends minutes building archives and images.
|
|
51
|
+
*
|
|
52
|
+
* Only builds that write a registry descriptor answer for coverage. A dev-local
|
|
53
|
+
* build (`build:dev-local`, and the `test` script's binary-only build) describes
|
|
54
|
+
* software by filesystem path: it never reaches a cluster, so a missing image
|
|
55
|
+
* cannot hurt anyone there, and failing those runs would block a block's tests on
|
|
56
|
+
* a release rule. Release and dev-remote builds do publish, and are checked.
|
|
57
|
+
*/
|
|
58
|
+
assertDockerCoverage(options?: {
|
|
59
|
+
entrypoints?: Map<string, Entrypoint>;
|
|
60
|
+
}): void;
|
|
35
61
|
buildSwJsonFiles(options?: {
|
|
36
62
|
packageIds?: string[];
|
|
37
63
|
entrypoints?: string[];
|
|
38
64
|
sources?: SoftwareSource[];
|
|
39
65
|
requireAllArtifacts?: boolean;
|
|
40
66
|
noSoftware?: boolean;
|
|
67
|
+
skipDockerCoverage?: boolean;
|
|
41
68
|
}): void;
|
|
42
69
|
writePublishedArtifactInfo(options?: {
|
|
43
70
|
ids?: string[];
|
|
@@ -83,5 +110,4 @@ declare class Core {
|
|
|
83
110
|
private archiveOptions;
|
|
84
111
|
}
|
|
85
112
|
//#endregion
|
|
86
|
-
export { Core };
|
|
87
113
|
//# sourceMappingURL=core.d.ts.map
|
package/dist/core/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","names":[],"sources":["../../src/core/core.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"core.d.ts","names":[],"sources":["../../src/core/core.ts"],"mappings":";;;;;;qBAoBa;mBACM;UACT;UACA;WAEQ,SAAS;EAClB,gBAAgB;EAChB;EACA;EAEP,YACE,QAAQ,QAAQ,QAChB;IACE,UAAU;IACV;;MASO,aAAa;MAIb,UAAU,MAAM;MAIhB,QAAQ;MAIR;EAIJ,eACL,UAAU,OAAiB,kBAC3B,IAAI,QACJ,MAAM;EAOD,iBACL,UAAU,OAAiB,kBAC3B,IAAI,QACJ,MAAM;EAOD,YACL,UAAU,OAAiB,kBAC3B,IAAI,QACJ,MAAM;MASG,eAAe,YAAY;MAQ3B,YAAY,YAAY,OAAiB;MAiBzC,2BAA2B;MAmB3B,qBAAqB,YAAY,OAAiB;MAQlD,kBAAkB,YAAY,OAAiB;;;;;;;;;;EAiBnD,uBAAuB;EAKvB,eAAe,YAAY,MAAM;EAejC,YACL,YACA,iBACC,OAAiB;EACb,YACL,YACA,kBACC,OAAiB;;;;;;;;;;;;;;;EA0Cb,qBAAqB;IAAY,cAAc,YAAY;;EAa3D,iBAAiB;IACtB;IACA;IACA,UAAU;IACV;IACA;IACA;;EAsDK,2BAA2B;IAAY;;EAqBjC,sBAAsB;IACjC;IACA;IAEA;IACA;IACA;IAGA;MACD;EA+CY,qBACX,UAAU,OAAiB,kBAC3B,UAAU,cACV;IACE;IACA;IACA;IAGA;MACD;EAiDI,kBAAkB;IACvB;IACA;IACA;;UAoDM;UAyDM;UAgFA;EAyCD,gBAAgB;IAC3B;IAEA;IACA;IAEA;IACA;MACD;UAoCa;UAmBA;EAyEP,oBAAoB;IACzB;IACA;IACA;;UA4CM;cA2CI;UAQJ"}
|
package/dist/core/core.js
CHANGED
|
@@ -6,6 +6,7 @@ import { micromamba } from "./conda/builder.js";
|
|
|
6
6
|
import { validateCondaSpec } from "./conda/validate-spec.js";
|
|
7
7
|
import { tmpSpecFile } from "./docker-conda.js";
|
|
8
8
|
import { PackageInfo } from "./package-info.js";
|
|
9
|
+
import { assertDockerCoverage, softwareEntrypointsWithoutDocker } from "./docker-coverage.js";
|
|
9
10
|
import { SwJsonRenderer, readBuiltArtifactInfo, writeBuiltArtifactInfo } from "./sw-json-render.js";
|
|
10
11
|
import { create, getPath } from "./archive.js";
|
|
11
12
|
import { initByUrl } from "./storage.js";
|
|
@@ -81,6 +82,18 @@ var Core = class {
|
|
|
81
82
|
get dockerPackages() {
|
|
82
83
|
return new Map(Array.from(this.packages.entries()).filter(([id, _]) => isVirtualDockerEntrypointName(id)).filter(([, value]) => value.type === "docker"));
|
|
83
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* The docker artifacts a build would actually produce for this selection.
|
|
87
|
+
*
|
|
88
|
+
* Mirrors the resolution `buildDockerImages` performs, so callers can reason
|
|
89
|
+
* about a build before running it. Note that `ids` are entrypoint names, not
|
|
90
|
+
* docker package keys: `getArtifact(id, "docker")` resolves the `:docker`
|
|
91
|
+
* virtual entrypoint, so a plain set intersection with `dockerPackages`
|
|
92
|
+
* would be wrong.
|
|
93
|
+
*/
|
|
94
|
+
selectedDockerPackages(ids) {
|
|
95
|
+
return (ids ?? Array.from(this.dockerPackages.keys())).filter((id) => this.getArtifact(id, "docker") !== void 0);
|
|
96
|
+
}
|
|
84
97
|
packageHasType(id, type) {
|
|
85
98
|
const pkg = this.packages.get(id);
|
|
86
99
|
if (pkg && pkg.type === type) return true;
|
|
@@ -101,6 +114,27 @@ var Core = class {
|
|
|
101
114
|
return;
|
|
102
115
|
}
|
|
103
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Fails a CI build that would describe software no kubernetes installation can run.
|
|
119
|
+
*
|
|
120
|
+
* `buildSwJsonFiles` calls this on the selection it is about to write, so no path
|
|
121
|
+
* can skip it. Callers may also invoke it up front — the answer comes from the
|
|
122
|
+
* package's declaration alone, so a CI run that is going to fail can fail before
|
|
123
|
+
* it spends minutes building archives and images.
|
|
124
|
+
*
|
|
125
|
+
* Only builds that write a registry descriptor answer for coverage. A dev-local
|
|
126
|
+
* build (`build:dev-local`, and the `test` script's binary-only build) describes
|
|
127
|
+
* software by filesystem path: it never reaches a cluster, so a missing image
|
|
128
|
+
* cannot hurt anyone there, and failing those runs would block a block's tests on
|
|
129
|
+
* a release rule. Release and dev-remote builds do publish, and are checked.
|
|
130
|
+
*/
|
|
131
|
+
assertDockerCoverage(options) {
|
|
132
|
+
if (!producesRegistryDescriptor(this.buildMode)) return;
|
|
133
|
+
assertDockerCoverage({
|
|
134
|
+
softwareWithoutDocker: softwareEntrypointsWithoutDocker(options?.entrypoints ?? this.entrypoints),
|
|
135
|
+
requirementWaived: !this.pkgInfo.requireDocker
|
|
136
|
+
});
|
|
137
|
+
}
|
|
104
138
|
buildSwJsonFiles(options) {
|
|
105
139
|
const index = this.packageEntrypointsIndex;
|
|
106
140
|
const entrypointNames = options?.entrypoints ?? [];
|
|
@@ -111,6 +145,7 @@ var Core = class {
|
|
|
111
145
|
}
|
|
112
146
|
let entrypoints = Array.from(this.entrypoints.entries());
|
|
113
147
|
if (entrypointNames.length > 0) entrypoints = entrypoints.filter(([epName, _]) => entrypointNames.includes(epName));
|
|
148
|
+
if (!options?.noSoftware && !options?.skipDockerCoverage) this.assertDockerCoverage({ entrypoints: new Map(entrypoints) });
|
|
114
149
|
const infos = options?.noSoftware ? this.renderer.renderPlaceholderEntrypoints(new Map(entrypoints)) : this.renderer.renderSoftwareEntrypoints(this.buildMode, new Map(entrypoints), {
|
|
115
150
|
requireAllArtifacts: options?.requireAllArtifacts,
|
|
116
151
|
fullDirHash: this.fullDirHash
|