@platforma-sdk/package-builder-lib 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/core.cjs +12 -0
- package/dist/core/core.cjs.map +1 -1
- package/dist/core/core.d.ts +10 -0
- package/dist/core/core.d.ts.map +1 -1
- package/dist/core/core.js +12 -0
- package/dist/core/core.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 +12 -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/index.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- 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 +14 -0
- package/src/core/push-guard.ts +42 -0
- package/src/index.ts +2 -0
package/dist/core/core.cjs
CHANGED
|
@@ -86,6 +86,18 @@ var Core = class {
|
|
|
86
86
|
get dockerPackages() {
|
|
87
87
|
return new Map(Array.from(this.packages.entries()).filter(([id, _]) => require_docker.isVirtualDockerEntrypointName(id)).filter(([, value]) => value.type === "docker"));
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* The docker artifacts a build would actually produce for this selection.
|
|
91
|
+
*
|
|
92
|
+
* Mirrors the resolution `buildDockerImages` performs, so callers can reason
|
|
93
|
+
* about a build before running it. Note that `ids` are entrypoint names, not
|
|
94
|
+
* docker package keys: `getArtifact(id, "docker")` resolves the `:docker`
|
|
95
|
+
* virtual entrypoint, so a plain set intersection with `dockerPackages`
|
|
96
|
+
* would be wrong.
|
|
97
|
+
*/
|
|
98
|
+
selectedDockerPackages(ids) {
|
|
99
|
+
return (ids ?? Array.from(this.dockerPackages.keys())).filter((id) => this.getArtifact(id, "docker") !== void 0);
|
|
100
|
+
}
|
|
89
101
|
packageHasType(id, type) {
|
|
90
102
|
const pkg = this.packages.get(id);
|
|
91
103
|
if (pkg && pkg.type === type) return true;
|
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 { 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 // 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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"}
|
package/dist/core/core.d.ts
CHANGED
|
@@ -29,6 +29,16 @@ declare class Core {
|
|
|
29
29
|
get packageEntrypointsIndex(): Map<string, string[]>;
|
|
30
30
|
get buildablePackages(): Map<string, withId<anyArtifactType>>;
|
|
31
31
|
get dockerPackages(): Map<string, withId<anyArtifactType>>;
|
|
32
|
+
/**
|
|
33
|
+
* The docker artifacts a build would actually produce for this selection.
|
|
34
|
+
*
|
|
35
|
+
* Mirrors the resolution `buildDockerImages` performs, so callers can reason
|
|
36
|
+
* about a build before running it. Note that `ids` are entrypoint names, not
|
|
37
|
+
* docker package keys: `getArtifact(id, "docker")` resolves the `:docker`
|
|
38
|
+
* virtual entrypoint, so a plain set intersection with `dockerPackages`
|
|
39
|
+
* would be wrong.
|
|
40
|
+
*/
|
|
41
|
+
selectedDockerPackages(ids?: string[]): string[];
|
|
32
42
|
packageHasType(id: string, type: artifactType): boolean;
|
|
33
43
|
getArtifact(id: string, type: "docker"): withId<dockerType> | undefined;
|
|
34
44
|
getArtifact(id: string, type: "archive"): withId<anyArtifactType> | undefined;
|
package/dist/core/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","names":[],"sources":["../../src/core/core.ts"],"mappings":";;;;;;;cAmBa,IAAA;EAAA,iBACM,MAAA;EAAA,QACT,YAAA;EAAA,QACA,SAAA;EAAA,SAEQ,OAAA,EAAS,WAAA;EAClB,cAAA,EAAgB,YAAA;EAChB,YAAA;EACA,WAAA;cAGL,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAChB,IAAA;IACE,OAAA,GAAU,WAAA;IACV,WAAA;EAAA;EAAA,IASO,SAAA,IAAa,SAAA;EAAA,IAIb,SAAA,CAAU,IAAA,EAAM,SAAA;EAAA,IAIhB,OAAA,CAAQ,CAAA;EAAA,IAIR,SAAA;EAIJ,cAAA,CACL,QAAA,EAAU,MAAA,CAAiB,eAAA,GAC3B,EAAA,EAAI,MAAA,EACJ,IAAA,EAAM,QAAA;EAOD,gBAAA,CACL,QAAA,EAAU,MAAA,CAAiB,eAAA,GAC3B,EAAA,EAAI,MAAA,EACJ,IAAA,EAAM,QAAA;EAOD,WAAA,CACL,QAAA,EAAU,MAAA,CAAiB,eAAA,GAC3B,EAAA,EAAI,MAAA,EACJ,IAAA,EAAM,QAAA;EAAA,IASG,WAAA,IAAe,GAAA,SAAY,UAAA;EAAA,IAQ3B,QAAA,IAAY,GAAA,SAAY,MAAA,CAAiB,eAAA;EAAA,IAiBzC,uBAAA,IAA2B,GAAA;EAAA,IAmB3B,iBAAA,IAAqB,GAAA,SAAY,MAAA,CAAiB,eAAA;EAAA,IAQlD,cAAA,IAAkB,GAAA,SAAY,MAAA,CAAiB,eAAA;
|
|
1
|
+
{"version":3,"file":"core.d.ts","names":[],"sources":["../../src/core/core.ts"],"mappings":";;;;;;;cAmBa,IAAA;EAAA,iBACM,MAAA;EAAA,QACT,YAAA;EAAA,QACA,SAAA;EAAA,SAEQ,OAAA,EAAS,WAAA;EAClB,cAAA,EAAgB,YAAA;EAChB,YAAA;EACA,WAAA;cAGL,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAChB,IAAA;IACE,OAAA,GAAU,WAAA;IACV,WAAA;EAAA;EAAA,IASO,SAAA,IAAa,SAAA;EAAA,IAIb,SAAA,CAAU,IAAA,EAAM,SAAA;EAAA,IAIhB,OAAA,CAAQ,CAAA;EAAA,IAIR,SAAA;EAIJ,cAAA,CACL,QAAA,EAAU,MAAA,CAAiB,eAAA,GAC3B,EAAA,EAAI,MAAA,EACJ,IAAA,EAAM,QAAA;EAOD,gBAAA,CACL,QAAA,EAAU,MAAA,CAAiB,eAAA,GAC3B,EAAA,EAAI,MAAA,EACJ,IAAA,EAAM,QAAA;EAOD,WAAA,CACL,QAAA,EAAU,MAAA,CAAiB,eAAA,GAC3B,EAAA,EAAI,MAAA,EACJ,IAAA,EAAM,QAAA;EAAA,IASG,WAAA,IAAe,GAAA,SAAY,UAAA;EAAA,IAQ3B,QAAA,IAAY,GAAA,SAAY,MAAA,CAAiB,eAAA;EAAA,IAiBzC,uBAAA,IAA2B,GAAA;EAAA,IAmB3B,iBAAA,IAAqB,GAAA,SAAY,MAAA,CAAiB,eAAA;EAAA,IAQlD,cAAA,IAAkB,GAAA,SAAY,MAAA,CAAiB,eAAA;EApDhC;;;;;;;;;EAqEnB,sBAAA,CAAuB,GAAA;EAKvB,cAAA,CAAe,EAAA,UAAY,IAAA,EAAM,YAAA;EAejC,WAAA,CACL,EAAA,UACA,IAAA,aACC,MAAA,CAAiB,UAAA;EACb,WAAA,CACL,EAAA,UACA,IAAA,cACC,MAAA,CAAiB,eAAA;EA8Bb,gBAAA,CAAiB,OAAA;IACtB,UAAA;IACA,WAAA;IACA,OAAA,GAAU,cAAA;IACV,mBAAA;IACA,UAAA;EAAA;EA4CK,0BAAA,CAA2B,OAAA;IAAY,GAAA;EAAA;EAqBjC,qBAAA,CAAsB,OAAA;IACjC,GAAA;IACA,UAAA;IAEA,WAAA;IACA,WAAA;IACA,WAAA;IAGA,UAAA;EAAA,IACD,OAAA;EA+CY,oBAAA,CACX,QAAA,EAAU,MAAA,CAAiB,eAAA,GAC3B,QAAA,EAAU,YAAA,EACV,OAAA;IACE,WAAA;IACA,WAAA;IACA,WAAA;IAGA,UAAA;EAAA,IACD,OAAA;EAiDI,iBAAA,CAAkB,OAAA;IACvB,GAAA;IACA,QAAA;IACA,sBAAA;EAAA;EAAA,QAoDM,gBAAA;EAAA,QAyDM,iBAAA;EAAA,QAgFA,oBAAA;EAyCD,eAAA,CAAgB,OAAA;IAC3B,GAAA;IAEA,WAAA;IACA,UAAA;IAEA,YAAA;IACA,aAAA;EAAA,IACD,OAAA;EAAA,QAoCa,cAAA;EAAA,QAmBA,cAAA;EAyEP,mBAAA,CAAoB,OAAA;IACzB,GAAA;IACA,MAAA;IACA,sBAAA;EAAA;EAAA,QA4CM,kBAAA;EAAA,YA2CI,QAAA;EAAA,QAQJ,cAAA;AAAA"}
|
package/dist/core/core.js
CHANGED
|
@@ -81,6 +81,18 @@ var Core = class {
|
|
|
81
81
|
get dockerPackages() {
|
|
82
82
|
return new Map(Array.from(this.packages.entries()).filter(([id, _]) => isVirtualDockerEntrypointName(id)).filter(([, value]) => value.type === "docker"));
|
|
83
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* The docker artifacts a build would actually produce for this selection.
|
|
86
|
+
*
|
|
87
|
+
* Mirrors the resolution `buildDockerImages` performs, so callers can reason
|
|
88
|
+
* about a build before running it. Note that `ids` are entrypoint names, not
|
|
89
|
+
* docker package keys: `getArtifact(id, "docker")` resolves the `:docker`
|
|
90
|
+
* virtual entrypoint, so a plain set intersection with `dockerPackages`
|
|
91
|
+
* would be wrong.
|
|
92
|
+
*/
|
|
93
|
+
selectedDockerPackages(ids) {
|
|
94
|
+
return (ids ?? Array.from(this.dockerPackages.keys())).filter((id) => this.getArtifact(id, "docker") !== void 0);
|
|
95
|
+
}
|
|
84
96
|
packageHasType(id, type) {
|
|
85
97
|
const pkg = this.packages.get(id);
|
|
86
98
|
if (pkg && pkg.type === type) return true;
|
package/dist/core/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","names":["archive.getPath","docker.entrypointName","docker.isVirtualDockerEntrypointName","artifacts.isBuildable","util.CLIError","util.currentPlatform","artifacts.isCrossPlatform","util.splitPlatform","util.softwareConfigName","util.producesRegistryDescriptor","util.currentOS","util.currentArch","defaults.DOCKER_BUILD_PLATFORM","docker.generateLocalTagName","docker.getImageHash","docker.generateRemoteTagName","docker.getImageEntrypoint","defaults.CONDA_DATA_LOCATION","defaults.CONDA_FROZEN_ENV_SPEC_FILE","archive.create","util.joinPlatform","storage.initByUrl","docker.remoteImageExists","docker.localImageExists"],"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.js","names":["archive.getPath","docker.entrypointName","docker.isVirtualDockerEntrypointName","artifacts.isBuildable","util.CLIError","util.currentPlatform","artifacts.isCrossPlatform","util.splitPlatform","util.softwareConfigName","util.producesRegistryDescriptor","util.currentOS","util.currentArch","defaults.DOCKER_BUILD_PLATFORM","docker.generateLocalTagName","docker.getImageHash","docker.generateRemoteTagName","docker.getImageEntrypoint","defaults.CONDA_DATA_LOCATION","defaults.CONDA_FROZEN_ENV_SPEC_FILE","archive.create","util.joinPlatform","storage.initByUrl","docker.remoteImageExists","docker.localImageExists"],"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 /**\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 // 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":";;;;;;;;;;;;;;;;AAmBA,IAAa,OAAb,MAAkB;CAChB;CACA;CACA;CAEA;CACA;CACA,eAA+B;CAC/B;CAEA,YACE,QACA,MAIA;EACA,KAAK,SAAS;EACd,KAAK,UAAU,MAAM,WAAW,IAAI,YAAY,QAAQ,EAAE,aAAa,MAAM,YAAY,CAAC;EAE1F,KAAK,cAAc;CACrB;CAEA,IAAW,YAA4B;EACrC,OAAO,KAAK,QAAQ;CACtB;CAEA,IAAW,UAAU,MAAsB;EACzC,KAAK,QAAQ,YAAY;CAC3B;CAEA,IAAW,QAAQ,GAAuB;EACxC,KAAK,QAAQ,UAAU;CACzB;CAEA,IAAW,YAAqB;EAC9B,OAAO,KAAK,QAAQ;CACtB;CAEA,eACE,UACA,IACA,MACQ;EACR,MAAM,OAAO,KAAK,QAAQ,aAAa,QAAQ;EAC/C,MAAM,UAAU,KAAK,QAAQ,gBAAgB,QAAQ;EACrD,OAAOA,QAAgB,KAAK,eAAe,UAAU,MAAM,SAAS,IAAI,MAAM,KAAK,CAAC;CACtF;CAEA,iBACE,UACA,IACA,MACQ;EACR,MAAM,OAAO,KAAK,QAAQ,aAAa,QAAQ;EAC/C,MAAM,UAAU,KAAK,QAAQ,gBAAgB,QAAQ;EACrD,OAAOA,QAAgB,KAAK,eAAe,UAAU,MAAM,SAAS,IAAI,MAAM,KAAK,CAAC;CACtF;CAEA,YACE,UACA,IACA,MACQ;EACR,IAAI,SAAS,SAAS,SACpB,OAAO,KAAK,iBAAiB,UAAU,IAAI,IAAI;EAGjD,OAAO,KAAK,eAAe,UAAU,IAAI,IAAI;CAC/C;CAEA,IAAW,cAAkD;EAC3D,IAAI,CAAC,KAAK,cACR,KAAK,eAAe,KAAK,QAAQ;EAGnC,OAAO,KAAK;CACd;CAEA,IAAW,WAAqE;EAC9E,MAAM,uBAAO,IAAI,IAAyD;EAE1E,KAAK,MAAM,CAAC,GAAG,OAAO,KAAK,YAAY,QAAQ,GAAG;GAChD,IAAI,GAAG,SAAS,aAEd;GAGF,MAAM,MACJ,GAAG,SAAS,SAAS,WAAWC,eAAsB,GAAG,SAAS,EAAE,IAAI,GAAG,SAAS;GACtF,KAAK,IAAI,KAAK,GAAG,QAAQ;EAC3B;EAEA,OAAO;CACT;CAEA,IAAW,0BAAiD;EAC1D,MAAM,yBAAS,IAAI,IAAsB;EAEzC,KAAK,MAAM,CAAC,QAAQ,OAAO,KAAK,aAAa;GAC3C,IAAI,GAAG,SAAS,aAEd;GAGF,IAAI,CAAC,OAAO,IAAI,GAAG,SAAS,EAAE,GAC5B,OAAO,IAAI,GAAG,SAAS,IAAI,CAAC,CAAC;GAG/B,OAAO,IAAI,GAAG,SAAS,EAAE,CAAC,CAAE,KAAK,MAAM;EACzC;EAEA,OAAO;CACT;CAEA,IAAW,oBAA8E;EACvF,OAAO,IAAI,IACT,MAAM,KAAK,KAAK,SAAS,QAAQ,CAAC,CAAC,CAChC,QAAQ,CAAC,IAAI,OAAO,CAACC,8BAAqC,EAAE,CAAC,CAAC,CAC9D,QAAQ,GAAG,WAAWC,YAAsB,MAAM,IAAI,CAAC,CAC5D;CACF;CAEA,IAAW,iBAA2E;EACpF,OAAO,IAAI,IACT,MAAM,KAAK,KAAK,SAAS,QAAQ,CAAC,CAAC,CAChC,QAAQ,CAAC,IAAI,OAAOD,8BAAqC,EAAE,CAAC,CAAC,CAC7D,QAAQ,GAAG,WAAW,MAAM,SAAS,QAAQ,CAClD;CACF;;;;;;;;;;CAWA,uBAA8B,KAA0B;EAEtD,QADiB,OAAO,MAAM,KAAK,KAAK,eAAe,KAAK,CAAC,EAAA,CAC7C,QAAQ,OAAO,KAAK,YAAY,IAAI,QAAQ,MAAM,KAAA,CAAS;CAC7E;CAEA,eAAsB,IAAY,MAAuC;EACvE,MAAM,MAAM,KAAK,SAAS,IAAI,EAAE;EAChC,IAAI,OAAO,IAAI,SAAS,MACtB,OAAO;EAKT,IADkB,KAAK,SAAS,IAAID,eAAsB,EAAE,CAChD,GACV,OAAO;EAGT,OAAO;CACT;CAUA,YACE,IACA,MACyD;EACzD,MAAM,WAAW,KAAK,SAAS,IAAI,EAAE;EAErC,QAAQ,MAAR;GACE,KAAK;IACH,IAAI,UAAU,SAAS,UACrB,OAAO;IAGT,OAAO,KAAK,SAAS,IAAIA,eAAsB,EAAE,CAAC;GAEpD,KAAK;IACH,IAAI,UAAU,SAAS,UACrB;IAEF,OAAO;GAET;IACE,YAAiB,IAAI;IACrB;EAEJ;CACF;CAIA,iBAAwB,SAMrB;EACD,MAAM,QAAQ,KAAK;EAEnB,MAAM,kBAAkB,SAAS,eAAe,CAAC;EACjD,IAAI,SAAS,YACX,KAAK,MAAM,SAAS,QAAQ,YAAY;GACtC,MAAM,qBAAqB,MAAM,IAAI,KAAK;GAC1C,IAAI,CAAC,sBAAsB,mBAAmB,WAAW,GACvD,MAAMG,SACJ,uCAAuC,MAAM,mCAC/C;GAGF,gBAAgB,KAAK,GAAG,kBAAkB;EAC5C;EAGF,IAAI,cAAc,MAAM,KAAK,KAAK,YAAY,QAAQ,CAAC;EACvD,IAAI,gBAAgB,SAAS,GAC3B,cAAc,YAAY,QAAQ,CAAC,QAAQ,OAAO,gBAAgB,SAAS,MAAM,CAAC;EAGpF,MAAM,QAAQ,SAAS,aACnB,KAAK,SAAS,6BAA6B,IAAI,IAAI,WAAW,CAAC,IAC/D,KAAK,SAAS,0BAA0B,KAAK,WAAW,IAAI,IAAI,WAAW,GAAG;GAC5E,qBAAqB,SAAS;GAC9B,aAAa,KAAK;EACpB,CAAC;EAEL,KAAK,MAAM,UAAU,MAAM,OAAO,GAChC,KAAK,SAAS,YAAY,MAAM;EAGlC,KAAK,MAAM,CAAC,QAAQ,OAAO,aACzB,IAAI,GAAG,SAAS,aAAa;GAC3B,MAAM,UAAU,KAAK,QAAQ,iBAAiB,QAAQ,EAAE;GACxD,KAAK,SAAS,WAAW,QAAQ,OAAO;EAC1C;CAEJ;CAIA,2BAAkC,SAA8B;EAC9D,MAAM,WAAWC,gBAAqB;EACtC,KAAK,MAAM,CAAC,IAAI,aAAa,KAAK,mBAAmB;GACnD,IAAI,SAAS,OAAO,CAAC,QAAQ,IAAI,SAAS,EAAE,GAAG;GAI/C,MAAM,cAAcC,gBAA0B,SAAS,IAAI,IAAI,KAAA,IAAY;GAC3E,MAAM,WAAW,KAAK,QAAQ,yBAAyB,QAAQ;GAE/D,uBAAuB,KAAK,QAAQ,qBAAqB,IAAI,WAAW,WAAW,GAAG;IACpF,MAAM,SAAS;IACf;IACA,aAAa,SAAS;IACtB,cAAc,SAAS;IACvB,wBAAwB,KAAK,QAAQ,8BAA8B,QAAQ;IAC3E,YAAY,KAAK,QAAQ,wBAAwB,UAAU,QAAQ;GACrE,CAAC;EACH;CACF;CAEA,MAAa,sBAAsB,SAUhC;EACD,KAAK,OAAO,KAAK,8BAA8B;EAE/C,MAAM,kBAAkB,SAAS,OAAO,MAAM,KAAK,KAAK,kBAAkB,KAAK,CAAC;EAChF,KAAK,OAAO,MAAM,yBAAyB,gBAAgB,KAAK,MAAM,GAAG;EACzE,KAAK,OAAO,MAAM,0BAA0B,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG;EAE3F,IAAI,gBAAgB,SAAS,KAAK,SAAS,eAAe,CAAC,QAAQ,YAAY;GAC7E,KAAK,OAAO,MACV,8KACF;GACA,MAAMF,SACJ,2EACF;EACF;EAEA,KAAK,MAAM,cAAc,iBAAiB;GACxC,MAAM,WAAW,KAAK,YAAY,YAAY,SAAS;GAEvD,IAAI,CAAC,UAAU;IACb,IAAI,SAAS,KACX,KAAK,OAAO,KAAK,YAAY,WAAW,0CAA0C;IAEpF;GACF;GAEA,IAAIE,gBAA0B,SAAS,IAAI,GACzC,MAAM,KAAK,qBAAqB,UAAUD,gBAAqB,GAAG,OAAO;QACpE,IAAI,KAAK,gBACd,MAAM,KAAK,qBAAqB,UAAU,KAAK,gBAAgB,OAAO;QACjE,IAAI,KAAK,cACd,KAAK,MAAM,YAAY,KAAK,QAAQ,kBAAkB,QAAQ,GAC5D,MAAM,KAAK,qBAAqB,UAAU,UAAU,OAAO;QAG7D,MAAM,KAAK,qBAAqB,UAAUA,gBAAqB,GAAG,OAAO;EAE7E;CACF;CASA,MAAa,qBACX,UACA,UACA,SAQA;EACA,KAAK,OAAO,KAAK,8BAA8B,SAAS,GAAG,kBAAkB,SAAS,KAAK;EAC3F,MAAM,EAAE,IAAI,SAASE,cAAmB,QAAQ;EAEhD,IAAI,CAAA,qBAAgC,SAAS,SAAS,IAAI,GAAG;GAC3D,IAAI,SAAS,aACX,KAAK,OAAO,KAAK,yCAAyC,SAAS,GAAG,mBAAmB;GAE3F,KAAK,OAAO,MACV,8BAA8B,SAAS,GAAG,0DAA0DC,mBAAwB,EAC9H;GAEA,MAAMJ,SAAc,0BAA0B;EAChD;EAEA,MAAM,cACJ,SAAS,eAAe,KAAK,QAAQ,oBAAoB,UAAU,QAAQ;EAE7E,IAAI,SAAS,SAAS,SAAS;GAC7B,MAAM,cAAc,SAAS,eAAe,KAAK,iBAAiB,UAAU,IAAI,IAAI;GACpF,MAAM,KAAK,qBAAqB,UAAU,UAAU,aAAa,aAAa,IAAI,IAAI;GACtF;EACF;EAGA,QADgB,SAAS,MACzB;GACE,KAAK;IACH,IAAI,SAAS,eAAe,KAAA,KAAa,QAAQ,YAE/C,MAAM,KAAK,kBAAkB;KAAE;KAAU;KAAU;IAAY,CAAC;SAEhE,KAAK,OAAO,MAAM,sCAAsC;IAE1D;EAEJ;EAEA,IAAI,CAACK,2BAAgC,KAAK,SAAS,GAAG;GACpD,KAAK,OAAO,KACV,2CAA2C,KAAK,UAAU,kCAC5D;GACA;EACF;EAEA,MAAM,cAAc,SAAS,eAAe,KAAK,eAAe,UAAU,IAAI,IAAI;EAClF,MAAM,KAAK,qBAAqB,YAAY,UAAU,aAAa,aAAa,IAAI,IAAI;CAC1F;CAEA,kBAAyB,SAItB;EACD,KAAK,OAAO,KAAK,2BAA2B;EAE5C,MAAM,kBAAkB,SAAS,OAAO,MAAM,KAAK,KAAK,eAAe,KAAK,CAAC;EAC7E,KAAK,OAAO,MAAM,yBAAyB,gBAAgB,KAAK,MAAM,GAAG;EACzE,KAAK,OAAO,MAAM,0BAA0B,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG;EAE3F,KAAK,MAAM,SAAS,iBAAiB;GACnC,MAAM,WAAW,KAAK,YAAY,OAAO,QAAQ;GAEjD,IAAI,CAAC,UAAU;IACb,IAAI,SAAS,KACX,KAAK,OAAO,KAAK,YAAY,MAAM,+CAA+C;IAEpF;GACF;GAQA,IAAI,SAAS;QACPC,UAAe,MAAM,WAAWC,YAAiB,MAAM,OAAO;KAChE,KAAK,OAAO,MACV,mCAAmC,SAAS,GAAG,gDACjD;KACA;IACF;;GAKF,IAAI,KAAK,kBAAkBJ,cAAmB,KAAK,cAAc,CAAC,CAAC,SAAS,OAC1E,MAAMH,SACJ,8BAA8B,SAAS,GAAG,gBAAgB,KAAK,eAAe,iCAC7CQ,sBAA+B,MAClE;GAGF,KAAK,iBAAiB,SAAS,IAAI,UAAU,SAAS,QAAQ;EAChE;CACF;CAQA,iBACE,OACA,UACA,UACA;EACA,MAAM,aAAa,KAAK,QAAQ,KAAK,QAAQ,aAAa,SAAS,cAAc,YAAY;EAC7F,MAAM,UAAU,KAAK,QAAQ,KAAK,QAAQ,aAAa,SAAS,WAAW,GAAG;EAC9E,WAAW,YAAY,SAAS;EAEhC,IAAI,CAAC,GAAG,WAAW,UAAU,GAC3B,MAAMR,SAAc,eAAe,WAAW,YAAY;EAG5D,IAAI,CAAC,GAAG,WAAW,OAAO,GACxB,MAAMA,SAAc,YAAY,QAAQ,YAAY;EAGtD,MAAM,WAAWS,qBAA4B,KAAK,QAAQ,aAAa,QAAQ;EAE/E,KAAK,OAAO,KAAK,8BAA8B,MAAM,KAAK;EAC1D,KAAK,OAAO,MAAM,kBAAkB,WAAW;cACrC,QAAQ;eACP,SAAS;KACnB;EAED,MAAM,OAAO,KAAK,QAAQ,aAAa,QAAQ;EAE/C,MAAa,SAAS,YAAY,UAAU,MAAM,KAAK,QAAQ,OAAO;EAGtE,MAAM,SAASE,sBAA6B,MAD1BD,aAAoB,QACY,GAAW,QAAQ;EAErE,KAAK,OAAO,MAAM;iBACL,OAAO;KACnB;EACD,OAAc,UAAU,MAAM;EAI9B,MAAM,cAAc,KAAK,QAAQ,qBAAqB,OAAO,UAAU,KAAK;EAC5E,uBAAuB,aAAa;GAClC,MAAM;GACN,UAAU;GACV,wBAAwB;GACxB,YAAYE,mBAA0B,QAAQ;EAChD,CAAC;EAED,KAAK,OAAO,KAAK;UACX,OAAO;oBACG,YAAY,EAAE;EAE9B,KAAK,OAAO,MAAM,oDAAoD;EACtE,IAAI,GAAG,WAAW,KAAK,KAAK,SAAA,oCAAoB,CAAC,GAC/C,GAAG,WAAW,KAAK,KAAK,SAAS,WAAW,CAAC;CAEjD;CAEA,MAAc,kBAAkB,MAI7B;EACD,MAAM,EAAE,UAAU,UAAU,gBAAgB;EAE5C,IAAI,aAAaX,gBAAqB,GAAG;GACvC,KAAK,OAAO,KACV,yEAC4BA,gBAAqB,EAAE,4BAA4B,SAAS,iDAE1F;GACA;EACF;EAEA,KAAK,OAAO,KAAK,oDAAoD;EAErE,MAAM,cAAc,KAAK,QAAQ,KAAK,QAAQ,aAAa,SAAS,IAAI;EACxE,IAAI,CAAC,GAAG,WAAW,WAAW,GAAG;GAC/B,KAAK,OAAO,MACV,yCAAyC,SAAS,KAAK,kBAAkB,YAAY,EACvF;GACA,MAAMD,SACJ,mCAAmC,SAAS,GAAG,0BACjD;EACF;EAEA,KAAK,OAAO,MAAM,sDAAsD;EACxE,IAAI;GACF,kBAAkB,KAAK,QAAQ,WAAW;EAC5C,SAAS,OAAO;GACd,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAC1E,KAAK,OAAO,MAAM,YAAY;GAC9B,MAAMA,SAAc,mCAAmC,SAAS,GAAG,KAAK,cAAc;EACxF;EAEA,MAAM,iBAAiB,KAAK,KAAK,aAAaa,mBAA4B;EAC1E,MAAM,gBAAgB,KAAK,KAAK,aAAa,YAAY;EAEzD,KAAK,OAAO,MAAM,wCAAwC,eAAe,EAAE;EAC3E,MAAM,IAAI,MAAM,gBAAgB,EAAE,WAAW,KAAK,CAAC;EAEnD,KAAK,OAAO,MAAM,iCAAiC;EACnD,MAAM,IAAI,IAAI,WACZ,KAAK,QACL,gBACA,SAAS,uBACT,aACF;EAEA,MAAM,iBAAiB,KAAK,KAAK,aAAaC,0BAAmC;EAEjF,MAAM,EAAE,eAAe;EACvB,EAAE,kBAAkB,EAAE,UAAU,YAAY,CAAC;EAC7C,EAAE,kBAAkB,EAAE,YAAY,eAAe,CAAC;EAClD,EAAE,kBAAkB,CAAC,CAAC;EAEtB,KAAK,OAAO,MAAM,mCAAmC,eAAe,GAAG;EAEvE,KAAK,OAAO,MAAM,+CAA+C;EAEjE,MAAM,aAAa,KAAK,MAAM,MAAM,IAAI,SAAS,gBAAgB,OAAO,CAAC;EAIzE,WAAW,SAAS,KAAA;EAGpB,IAAI,CAAC,WAAW,UACd,WAAW,WAAW,CAAC;EAEzB,IAAI,CAAC,WAAW,cACd,WAAW,eAAe,CAAC;EAE7B,MAAM,IAAI,UAAU,gBAAgB,KAAK,UAAU,UAAU,CAAC;EAE9D,KAAK,OAAO,MAAM,qCAAqC,eAAe,EAAE;CAC1E;CAEA,MAAc,qBACZ,oBACA,UACA,aACA,aACA,IACA,MACA;EACA,KAAK,OAAO,MAAM,aAAa,mBAAmB,gBAAgB;EAClE,IAAIZ,gBAA0B,SAAS,IAAI,GACzC,KAAK,OAAO,MAAM,uCAAuC;OAEzD,KAAK,OAAO,MAAM,kCAAkC,GAAG,WAAW,KAAK,EAAE;EAE3E,KAAK,OAAO,MAAM,8BAA8B,YAAY,EAAE;EAC9D,KAAK,OAAO,MAAM,qCAAqC,YAAY,EAAE;EAErE,MAAMa,OAAe,KAAK,QAAQ,aAAa,WAAW;EAE1D,MAAM,cAAc,KAAK,QAAQ,qBAC/B,SAAS,IACT,WACAb,gBAA0B,SAAS,IAAI,IAAI,KAAA,IAAYc,aAAkB,IAAI,IAAI,CACnF;EAEA,MAAM,WAAW,KAAK,QAAQ,yBAAyB,QAAQ;EAE/D,uBAAuB,aAAa;GAClC,MAAM,SAAS;GACf,UAAUA,aAAkB,IAAI,IAAI;GACpC,aAAa,SAAS;GACtB,cAAc,SAAS;GACvB,wBAAwB,KAAK,QAAQ,8BAA8B,QAAQ;GAC3E,YAAY,KAAK,QAAQ,wBAAwB,UAAUA,aAAkB,IAAI,IAAI,CAAC;EACxF,CAAC;EAED,KAAK,OAAO,KAAK,GAAG,mBAAmB;cAC7B,YAAY;oBACN,YAAY,EAAE;CAChC;CAEA,MAAa,gBAAgB,SAQ1B;EACD,KAAK,OAAO,KAAK,wBAAwB;EAEzC,MAAM,oBAAoB,SAAS,OAAO,MAAM,KAAK,KAAK,kBAAkB,KAAK,CAAC;EAClF,KAAK,OAAO,MAAM,yBAAyB,kBAAkB,KAAK,MAAM,GAAG;EAC3E,KAAK,OAAO,MAAM,0BAA0B,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG;EAE3F,MAAM,UAA2B,CAAC;EAClC,KAAK,MAAM,SAAS,mBAAmB;GACrC,MAAM,MAAM,KAAK,YAAY,OAAO,SAAS;GAE7C,IAAI,CAAC,KAAK;IACR,IAAI,SAAS,KACX,KAAK,OAAO,KACV,YAAY,MAAM,kEACpB;IAEF;GACF;GAEA,IAAId,gBAA0B,IAAI,IAAI,GACpC,QAAQ,KAAK,KAAK,eAAe,KAAKD,gBAAqB,GAAG,OAAO,CAAC;QACjE,IAAI,KAAK,gBACd,QAAQ,KAAK,KAAK,eAAe,KAAK,KAAK,gBAAgB,OAAO,CAAC;QAC9D,IAAI,KAAK,cACd,KAAK,MAAM,YAAY,KAAK,QAAQ,kBAAkB,GAAG,GACvD,QAAQ,KAAK,KAAK,eAAe,KAAK,UAAU,OAAO,CAAC;QAG1D,QAAQ,KAAK,KAAK,eAAe,KAAKA,gBAAqB,GAAG,OAAO,CAAC;EAE1E;EAEA,MAAM,QAAQ,IAAI,OAAO;CAC3B;CAEA,MAAc,eACZ,UACA,UACA,SAOA;EACA,IAAI,SAAS,SAAS,UAAU;GAC9B,KAAK,mBAAmB,QAAQ;GAChC;EACF;EAEA,MAAM,KAAK,eAAe,UAAU,UAAU,OAAO;CACvD;CAEA,MAAc,eACZ,UACA,UACA,SAMA;EACA,MAAM,EAAE,IAAI,SAASE,cAAmB,QAAQ;EAEhD,MAAM,eAAe,KAAK,QAAQ,aAAa,QAAQ;EACvD,MAAM,WAAW,KAAK,QAAQ,yBAAyB,QAAQ;EAC/D,MAAM,aAAa,SAAS,cAAc,SAAS;EAEnD,MAAM,cAAc,SAAS,eAAe,KAAK,YAAY,UAAU,IAAI,IAAI;EAO/E,MAAM,UAAU,sBALI,KAAK,QAAQ,qBAC/B,SAAS,IACT,WACAD,gBAA0B,SAAS,IAAI,IAAI,KAAA,IAAYc,aAAkB,IAAI,IAAI,CAEnC,CAAC;EACjD,MAAM,UAAU,QAAQ,cAAc,QAAQ;EAE9C,IAAI,CAAC,YAAY;GACf,MAAM,eAAe,SAAS,KAAK,YAAY,CAAC,CAAC,WAAW,eAAe,GAAG;GAC9E,KAAK,OAAO,MAAM,sCAAsC,SAAS,MAAM;GACvE,MAAMhB,SACJ,qCAAqC,SAAS,GAAG,4CAA4CI,mBAAwB,kDAAkD,aAAa,aACtL;EACF;EAEA,KAAK,OAAO,KACV,uBAAuB,aAAa,kBAAkB,SAAS,mBAAmB,SAAS,KAAK,EAClG;EACA,KAAK,OAAO,MAAM,4BAA4B,WAAW,EAAE;EAC3D,KAAK,OAAO,MAAM,0BAA0B,YAAY,EAAE;EAC1D,KAAK,OAAO,MAAM,2BAA2B,QAAQ,EAAE;EAEvD,MAAM,IAAI,MAAMa,UAAkB,YAAY,KAAK,QAAQ,WAAW;EAGtE,IAAI,MADiB,EAAE,OAAO,OAAO,KACvB,CAAC,SAAS,eAAe;GACrC,IAAI,SAAS,cACX,MAAMjB,SACJ,qBAAqB,QAAQ,gCAAgC,SAAS,KAAK,wFAC7E;GAGF,KAAK,OAAO,KACV,qBAAqB,QAAQ,gCAAgC,SAAS,KAAK,uBAC7E;GACA;EACF;EAEA,MAAM,UAA2B,CAAC;EAElC,MAAM,UAAU,GAAG,iBAAiB,WAAW;EAC/C,QAAQ,KACN,EAAE,QAAQ,SAAS,OAAO,CAAC,CAAC,cAAc;GACxC,QAAQ,MAAM;EAEhB,CAAC,CACH;EAEA,OAAO,QAAQ,IAAI,OAAO,CAAC,CAAC,WAAW;GACrC,KAAK,OAAO,KAAK,YAAY,aAAa,sBAAsB,SAAS,KAAK,GAAG,QAAQ,EAAE;EAE7F,CAAC;CACH;CAEA,oBAA2B,SAIxB;EACD,KAAK,OAAO,KAAK,6BAA6B;EAS9C,MAAM,oBAAoB,SAAS,OAAO,MAAM,KAAK,KAAK,eAAe,KAAK,CAAC;EAC/E,KAAK,OAAO,MAAM,yBAAyB,kBAAkB,KAAK,MAAM,GAAG;EAC3E,KAAK,OAAO,MAAM,0BAA0B,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG;EAE3F,KAAK,MAAM,SAAS,mBAAmB;GACrC,MAAM,MAAM,KAAK,YAAY,OAAO,QAAQ;GAC5C,IAAI,CAAC,KAAK;IACR,IAAI,SAAS,KACX,KAAK,OAAO,KACV,YAAY,MAAM,mEACpB;IAEF;GACF;GAOA,IAAI,SAAS;QACPM,UAAe,MAAM,WAAWC,YAAiB,MAAM,OAAO;KAChE,KAAK,OAAO,MACV,qCAAqC,IAAI,GAAG,gDAC9C;KACA;IACF;;GAGF,KAAK,mBAAmB,KAAK,SAAS,MAAM;EAC9C;CACF;CAEA,mBACE,UACA,QACA;EACA,IAAI,SAAS,SAAS,UACpB,MAAMP,SAAc,YAAY,SAAS,GAAG,0BAA0B;EAQxE,MAAM,MADU,sBADI,KAAK,QAAQ,qBAAqB,SAAS,IAAI,UAAU,KAC7B,CAC9B,CAAC,CAAC;EACpB,MAAM,UAAU,SAAS,GAAG,OAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO;EAKtE,IAD0BkB,kBAAyB,OAC/B,GAAG;GACrB,KAAK,OAAO,KACV,iBAAiB,IAAI,yEACvB;GACA;EACF;EAGA,IAAI,CADqBC,iBAAwB,GAC7B,GAClB,MAAMnB,SACJ,iBAAiB,IAAI,8EACvB;EAGF,IAAI,QAAQ;GACV,OAAc,KAAK,OAAO;GAC1B,KAAK,OAAO,KAAK,4BAA4B,IAAI,2BAA2B,QAAQ,EAAE;EACxF,OACE,KAAK,OAAO,KAAK,4BAA4B,IAAI,cAAc,QAAQ,EAAE;EAG3E,KAAY,OAAO;CACrB;CAEA,IAAY,WAA2B;EACrC,IAAI,CAAC,KAAK,WACR,KAAK,YAAY,IAAI,eAAe,KAAK,QAAQ,KAAK,OAAO;EAG/D,OAAO,KAAK;CACd;CAEA,eACE,KACA,MACA,SACA,IACA,MACA,aACwB;EACxB,OAAO;GACL,aAAa,KAAK,QAAQ;GAC1B,aAAa;GACb,gBAAgB;GAEhB,eAAeE,gBAA0B,IAAI,IAAI;GAC7C;GACE;GACN,KAAK;EACP;CACF;AACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const require_envs = require("./envs.cjs");
|
|
2
|
+
const require_util = require("./util.cjs");
|
|
3
|
+
//#region src/core/push-guard.ts
|
|
4
|
+
/** Throws when a CI run is about to reference docker images it never pushed. */
|
|
5
|
+
function assertDockerPushIntent(intent) {
|
|
6
|
+
if (!require_envs.isCI()) return;
|
|
7
|
+
if (!intent.buildDocker || intent.pushDocker) return;
|
|
8
|
+
if (intent.dockerPackageCount === 0) return;
|
|
9
|
+
if (intent.pushDisabledExplicitly) return;
|
|
10
|
+
throw require_util.CLIError(`This CI run would build docker images without pushing them, while still writing entrypoint descriptors that reference them. Consumers would fail to pull the images.
|
|
11
|
+
The usual cause is "private": true in package.json: auto-push is gated on !isPrivate, and software packages must never be private.
|
|
12
|
+
If this package really must build images without publishing them, say so with --docker-no-autopush (or ${require_envs.PL_DOCKER_NO_AUTOPUSH}=1).`);
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
exports.assertDockerPushIntent = assertDockerPushIntent;
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=push-guard.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-guard.cjs","names":[],"sources":["../../src/core/push-guard.ts"],"sourcesContent":["// Guard against the silent \"image built, never pushed\" outcome.\n//\n// Docker auto-push defaults to `isCI() && !isPrivate`, but the entrypoint\n// descriptor is written with the image tag either way. A stray\n// `\"private\": true` on a software package therefore yields a green CI run and\n// a published block that 404s pulling its image at runtime — the failure only\n// surfaces when a user runs the block (MILAB-6714).\n//\n// So: in CI, building docker images without pushing them is an error unless\n// the caller says it meant to, via `--docker-no-autopush` /\n// `PL_DOCKER_NO_AUTOPUSH=1`.\n\nimport * as envs from \"./envs\";\nimport * as util from \"./util\";\n\nexport type PushIntent = {\n /** Docker images were built in this run. */\n buildDocker: boolean;\n /** Resolved auto-push decision. */\n pushDocker: boolean;\n /** Caller passed `--docker-no-autopush` / `PL_DOCKER_NO_AUTOPUSH=1`. */\n pushDisabledExplicitly: boolean;\n /** How many entrypoints produce a docker image. */\n dockerPackageCount: number;\n};\n\n/** Throws when a CI run is about to reference docker images it never pushed. */\nexport function assertDockerPushIntent(intent: PushIntent): void {\n if (!envs.isCI()) return;\n if (!intent.buildDocker || intent.pushDocker) return;\n if (intent.dockerPackageCount === 0) return;\n if (intent.pushDisabledExplicitly) return;\n\n throw util.CLIError(\n `This CI run would build docker images without pushing them, while still writing ` +\n `entrypoint descriptors that reference them. Consumers would fail to pull the images.\\n` +\n ` The usual cause is \"private\": true in package.json: auto-push is gated on ` +\n `!isPrivate, and software packages must never be private.\\n` +\n ` If this package really must build images without publishing them, say so with ` +\n `--docker-no-autopush (or ${envs.PL_DOCKER_NO_AUTOPUSH}=1).`,\n );\n}\n"],"mappings":";;;;AA2BA,SAAgB,uBAAuB,QAA0B;CAC/D,IAAI,CAAA,aAAA,KAAW,GAAG;CAClB,IAAI,CAAC,OAAO,eAAe,OAAO,YAAY;CAC9C,IAAI,OAAO,uBAAuB,GAAG;CACrC,IAAI,OAAO,wBAAwB;CAEnC,MAAA,aAAA,SACE;;8IAKyD,KAC3D;AACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/core/push-guard.d.ts
|
|
2
|
+
type PushIntent = {
|
|
3
|
+
/** Docker images were built in this run. */buildDocker: boolean; /** Resolved auto-push decision. */
|
|
4
|
+
pushDocker: boolean; /** Caller passed `--docker-no-autopush` / `PL_DOCKER_NO_AUTOPUSH=1`. */
|
|
5
|
+
pushDisabledExplicitly: boolean; /** How many entrypoints produce a docker image. */
|
|
6
|
+
dockerPackageCount: number;
|
|
7
|
+
};
|
|
8
|
+
/** Throws when a CI run is about to reference docker images it never pushed. */
|
|
9
|
+
declare function assertDockerPushIntent(intent: PushIntent): void;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { PushIntent, assertDockerPushIntent };
|
|
12
|
+
//# sourceMappingURL=push-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-guard.d.ts","names":[],"sources":["../../src/core/push-guard.ts"],"mappings":";KAeY,UAAA;EAAA,4CAEV,WAAA;EAEA,UAAA,WAFA;EAIA,sBAAA;EAEA,kBAAA;AAAA;AAAkB;AAAA,iBAIJ,sBAAA,CAAuB,MAAkB,EAAV,UAAU"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PL_DOCKER_NO_AUTOPUSH, isCI } from "./envs.js";
|
|
2
|
+
import { CLIError } from "./util.js";
|
|
3
|
+
//#region src/core/push-guard.ts
|
|
4
|
+
/** Throws when a CI run is about to reference docker images it never pushed. */
|
|
5
|
+
function assertDockerPushIntent(intent) {
|
|
6
|
+
if (!isCI()) return;
|
|
7
|
+
if (!intent.buildDocker || intent.pushDocker) return;
|
|
8
|
+
if (intent.dockerPackageCount === 0) return;
|
|
9
|
+
if (intent.pushDisabledExplicitly) return;
|
|
10
|
+
throw CLIError(`This CI run would build docker images without pushing them, while still writing entrypoint descriptors that reference them. Consumers would fail to pull the images.
|
|
11
|
+
The usual cause is "private": true in package.json: auto-push is gated on !isPrivate, and software packages must never be private.
|
|
12
|
+
If this package really must build images without publishing them, say so with --docker-no-autopush (or ${PL_DOCKER_NO_AUTOPUSH}=1).`);
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { assertDockerPushIntent };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=push-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-guard.js","names":["envs.isCI","util.CLIError","envs.PL_DOCKER_NO_AUTOPUSH"],"sources":["../../src/core/push-guard.ts"],"sourcesContent":["// Guard against the silent \"image built, never pushed\" outcome.\n//\n// Docker auto-push defaults to `isCI() && !isPrivate`, but the entrypoint\n// descriptor is written with the image tag either way. A stray\n// `\"private\": true` on a software package therefore yields a green CI run and\n// a published block that 404s pulling its image at runtime — the failure only\n// surfaces when a user runs the block (MILAB-6714).\n//\n// So: in CI, building docker images without pushing them is an error unless\n// the caller says it meant to, via `--docker-no-autopush` /\n// `PL_DOCKER_NO_AUTOPUSH=1`.\n\nimport * as envs from \"./envs\";\nimport * as util from \"./util\";\n\nexport type PushIntent = {\n /** Docker images were built in this run. */\n buildDocker: boolean;\n /** Resolved auto-push decision. */\n pushDocker: boolean;\n /** Caller passed `--docker-no-autopush` / `PL_DOCKER_NO_AUTOPUSH=1`. */\n pushDisabledExplicitly: boolean;\n /** How many entrypoints produce a docker image. */\n dockerPackageCount: number;\n};\n\n/** Throws when a CI run is about to reference docker images it never pushed. */\nexport function assertDockerPushIntent(intent: PushIntent): void {\n if (!envs.isCI()) return;\n if (!intent.buildDocker || intent.pushDocker) return;\n if (intent.dockerPackageCount === 0) return;\n if (intent.pushDisabledExplicitly) return;\n\n throw util.CLIError(\n `This CI run would build docker images without pushing them, while still writing ` +\n `entrypoint descriptors that reference them. Consumers would fail to pull the images.\\n` +\n ` The usual cause is \"private\": true in package.json: auto-push is gated on ` +\n `!isPrivate, and software packages must never be private.\\n` +\n ` If this package really must build images without publishing them, say so with ` +\n `--docker-no-autopush (or ${envs.PL_DOCKER_NO_AUTOPUSH}=1).`,\n );\n}\n"],"mappings":";;;;AA2BA,SAAgB,uBAAuB,QAA0B;CAC/D,IAAI,CAACA,KAAU,GAAG;CAClB,IAAI,CAAC,OAAO,eAAe,OAAO,YAAY;CAC9C,IAAI,OAAO,uBAAuB,GAAG;CACrC,IAAI,OAAO,wBAAwB;CAEnC,MAAMC,SACJ;;2GAK8BC,sBAA2B,KAC3D;AACF"}
|
package/dist/index.cjs
CHANGED
|
@@ -3,11 +3,13 @@ const require_defaults = require("./defaults.cjs");
|
|
|
3
3
|
const require_envs = require("./core/envs.cjs");
|
|
4
4
|
const require_util = require("./core/util.cjs");
|
|
5
5
|
const require_core = require("./core/core.cjs");
|
|
6
|
+
const require_push_guard = require("./core/push-guard.cjs");
|
|
6
7
|
//#region src/index.ts
|
|
7
8
|
function createBuilder(logger, opts) {
|
|
8
9
|
return new require_core.Core(logger, opts);
|
|
9
10
|
}
|
|
10
11
|
//#endregion
|
|
12
|
+
exports.assertDockerPushIntent = require_push_guard.assertDockerPushIntent;
|
|
11
13
|
exports.createBuilder = createBuilder;
|
|
12
14
|
Object.defineProperty(exports, "defaults", {
|
|
13
15
|
enumerable: true,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["Core"],"sources":["../src/index.ts"],"sourcesContent":["import type winston from \"winston\";\nimport { Core } from \"./core/core\";\n\nexport * as util from \"./core/util\";\nexport * as envs from \"./core/envs\";\nexport * as defaults from \"./defaults\";\n\n/** The logger the engine and its callers pass around. */\nexport type Logger = winston.Logger;\n\n/**\n * Public surface of the build engine. Derived from `Core` so signatures never\n * drift, while the `Core` class itself stays internal (per A-0023: the engine is\n * a library, not a half-binary with an exported orchestrator class). Consumers\n * (`pl-pkg`, and later `block-tools software`) wrap this, they do not subclass it.\n */\nexport type Builder = Pick<\n Core,\n | \"buildMode\"\n | \"targetPlatform\"\n | \"allPlatforms\"\n | \"fullDirHash\"\n | \"version\"\n | \"isPrivate\"\n | \"buildDockerImages\"\n | \"buildSoftwareArchives\"\n | \"buildSwJsonFiles\"\n | \"writePublishedArtifactInfo\"\n | \"publishPackages\"\n | \"publishDockerImages\"\n>;\n\nexport function createBuilder(logger: winston.Logger, opts?: { packageRoot?: string }): Builder {\n return new Core(logger, opts);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["Core"],"sources":["../src/index.ts"],"sourcesContent":["import type winston from \"winston\";\nimport { Core } from \"./core/core\";\n\nexport * as util from \"./core/util\";\nexport * as envs from \"./core/envs\";\nexport * as defaults from \"./defaults\";\nexport { assertDockerPushIntent, type PushIntent } from \"./core/push-guard\";\n\n/** The logger the engine and its callers pass around. */\nexport type Logger = winston.Logger;\n\n/**\n * Public surface of the build engine. Derived from `Core` so signatures never\n * drift, while the `Core` class itself stays internal (per A-0023: the engine is\n * a library, not a half-binary with an exported orchestrator class). Consumers\n * (`pl-pkg`, and later `block-tools software`) wrap this, they do not subclass it.\n */\nexport type Builder = Pick<\n Core,\n | \"buildMode\"\n | \"targetPlatform\"\n | \"allPlatforms\"\n | \"fullDirHash\"\n | \"version\"\n | \"isPrivate\"\n | \"selectedDockerPackages\"\n | \"buildDockerImages\"\n | \"buildSoftwareArchives\"\n | \"buildSwJsonFiles\"\n | \"writePublishedArtifactInfo\"\n | \"publishPackages\"\n | \"publishDockerImages\"\n>;\n\nexport function createBuilder(logger: winston.Logger, opts?: { packageRoot?: string }): Builder {\n return new Core(logger, opts);\n}\n"],"mappings":";;;;;;;AAkCA,SAAgB,cAAc,QAAwB,MAA0C;CAC9F,OAAO,IAAIA,aAAAA,KAAK,QAAQ,IAAI;AAC9B"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { util_d_exports } from "./core/util.js";
|
|
|
2
2
|
import { Core } from "./core/core.js";
|
|
3
3
|
import { envs_d_exports } from "./core/envs.js";
|
|
4
4
|
import { defaults_d_exports } from "./defaults.js";
|
|
5
|
+
import { PushIntent, assertDockerPushIntent } from "./core/push-guard.js";
|
|
5
6
|
import winston from "winston";
|
|
6
7
|
|
|
7
8
|
//#region src/index.d.ts
|
|
@@ -13,10 +14,10 @@ type Logger = winston.Logger;
|
|
|
13
14
|
* a library, not a half-binary with an exported orchestrator class). Consumers
|
|
14
15
|
* (`pl-pkg`, and later `block-tools software`) wrap this, they do not subclass it.
|
|
15
16
|
*/
|
|
16
|
-
type Builder = Pick<Core, "buildMode" | "targetPlatform" | "allPlatforms" | "fullDirHash" | "version" | "isPrivate" | "buildDockerImages" | "buildSoftwareArchives" | "buildSwJsonFiles" | "writePublishedArtifactInfo" | "publishPackages" | "publishDockerImages">;
|
|
17
|
+
type Builder = Pick<Core, "buildMode" | "targetPlatform" | "allPlatforms" | "fullDirHash" | "version" | "isPrivate" | "selectedDockerPackages" | "buildDockerImages" | "buildSoftwareArchives" | "buildSwJsonFiles" | "writePublishedArtifactInfo" | "publishPackages" | "publishDockerImages">;
|
|
17
18
|
declare function createBuilder(logger: winston.Logger, opts?: {
|
|
18
19
|
packageRoot?: string;
|
|
19
20
|
}): Builder;
|
|
20
21
|
//#endregion
|
|
21
|
-
export { Builder, Logger, createBuilder, defaults_d_exports as defaults, envs_d_exports as envs, util_d_exports as util };
|
|
22
|
+
export { Builder, Logger, type PushIntent, assertDockerPushIntent, createBuilder, defaults_d_exports as defaults, envs_d_exports as envs, util_d_exports as util };
|
|
22
23
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;KASY,MAAA,GAAS,OAAA,CAAQ,MAAM;AAAnC;;;;AAAmC;AAQnC;AARA,KAQY,OAAA,GAAU,IAAI,CACxB,IAAA;AAAA,iBAgBc,aAAA,CAAc,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAQ,IAAA;EAAS,WAAA;AAAA,IAAyB,OAAO"}
|
package/dist/index.js
CHANGED
|
@@ -2,11 +2,12 @@ import { defaults_exports } from "./defaults.js";
|
|
|
2
2
|
import { envs_exports } from "./core/envs.js";
|
|
3
3
|
import { util_exports } from "./core/util.js";
|
|
4
4
|
import { Core } from "./core/core.js";
|
|
5
|
+
import { assertDockerPushIntent } from "./core/push-guard.js";
|
|
5
6
|
//#region src/index.ts
|
|
6
7
|
function createBuilder(logger, opts) {
|
|
7
8
|
return new Core(logger, opts);
|
|
8
9
|
}
|
|
9
10
|
//#endregion
|
|
10
|
-
export { createBuilder, defaults_exports as defaults, envs_exports as envs, util_exports as util };
|
|
11
|
+
export { assertDockerPushIntent, createBuilder, defaults_exports as defaults, envs_exports as envs, util_exports as util };
|
|
11
12
|
|
|
12
13
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type winston from \"winston\";\nimport { Core } from \"./core/core\";\n\nexport * as util from \"./core/util\";\nexport * as envs from \"./core/envs\";\nexport * as defaults from \"./defaults\";\n\n/** The logger the engine and its callers pass around. */\nexport type Logger = winston.Logger;\n\n/**\n * Public surface of the build engine. Derived from `Core` so signatures never\n * drift, while the `Core` class itself stays internal (per A-0023: the engine is\n * a library, not a half-binary with an exported orchestrator class). Consumers\n * (`pl-pkg`, and later `block-tools software`) wrap this, they do not subclass it.\n */\nexport type Builder = Pick<\n Core,\n | \"buildMode\"\n | \"targetPlatform\"\n | \"allPlatforms\"\n | \"fullDirHash\"\n | \"version\"\n | \"isPrivate\"\n | \"buildDockerImages\"\n | \"buildSoftwareArchives\"\n | \"buildSwJsonFiles\"\n | \"writePublishedArtifactInfo\"\n | \"publishPackages\"\n | \"publishDockerImages\"\n>;\n\nexport function createBuilder(logger: winston.Logger, opts?: { packageRoot?: string }): Builder {\n return new Core(logger, opts);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type winston from \"winston\";\nimport { Core } from \"./core/core\";\n\nexport * as util from \"./core/util\";\nexport * as envs from \"./core/envs\";\nexport * as defaults from \"./defaults\";\nexport { assertDockerPushIntent, type PushIntent } from \"./core/push-guard\";\n\n/** The logger the engine and its callers pass around. */\nexport type Logger = winston.Logger;\n\n/**\n * Public surface of the build engine. Derived from `Core` so signatures never\n * drift, while the `Core` class itself stays internal (per A-0023: the engine is\n * a library, not a half-binary with an exported orchestrator class). Consumers\n * (`pl-pkg`, and later `block-tools software`) wrap this, they do not subclass it.\n */\nexport type Builder = Pick<\n Core,\n | \"buildMode\"\n | \"targetPlatform\"\n | \"allPlatforms\"\n | \"fullDirHash\"\n | \"version\"\n | \"isPrivate\"\n | \"selectedDockerPackages\"\n | \"buildDockerImages\"\n | \"buildSoftwareArchives\"\n | \"buildSwJsonFiles\"\n | \"writePublishedArtifactInfo\"\n | \"publishPackages\"\n | \"publishDockerImages\"\n>;\n\nexport function createBuilder(logger: winston.Logger, opts?: { packageRoot?: string }): Builder {\n return new Core(logger, opts);\n}\n"],"mappings":";;;;;;AAkCA,SAAgB,cAAc,QAAwB,MAA0C;CAC9F,OAAO,IAAI,KAAK,QAAQ,IAAI;AAC9B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-sdk/package-builder-lib",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "MiLaboratories Platforma Package builder engine (library)",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -31,16 +31,16 @@
|
|
|
31
31
|
"@milaboratories/resolve-helper": "1.1.3"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@platforma-open/milaboratories.runenv-python-3": "1.11.
|
|
34
|
+
"@platforma-open/milaboratories.runenv-python-3": "1.11.4",
|
|
35
35
|
"@types/archiver": "^6.0.3",
|
|
36
36
|
"@types/node": "~24.5.2",
|
|
37
37
|
"@vitest/coverage-istanbul": "^4.1.3",
|
|
38
38
|
"typescript": "~5.9.3",
|
|
39
39
|
"vite": "^8.0.6",
|
|
40
40
|
"vitest": "^4.1.3",
|
|
41
|
-
"@milaboratories/
|
|
42
|
-
"@milaboratories/ts-configs": "1.
|
|
43
|
-
"@milaboratories/
|
|
41
|
+
"@milaboratories/ts-builder": "1.6.2",
|
|
42
|
+
"@milaboratories/ts-configs": "1.4.0",
|
|
43
|
+
"@milaboratories/build-configs": "2.0.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "ts-builder build --target node",
|
|
@@ -307,3 +307,66 @@ describe("Core.buildDockerImages + publishDockerImages", () => {
|
|
|
307
307
|
}
|
|
308
308
|
});
|
|
309
309
|
});
|
|
310
|
+
|
|
311
|
+
// selectedDockerPackages answers "what docker images would this build produce?"
|
|
312
|
+
// for a given --package-id selection. Callers use it to reason about a build
|
|
313
|
+
// before running it, so it must mirror buildDockerImages' own id resolution:
|
|
314
|
+
// a plain intersection with dockerPackages would miss the `:docker` virtual
|
|
315
|
+
// entrypoint that python autogen produces.
|
|
316
|
+
describe("Core.selectedDockerPackages", () => {
|
|
317
|
+
let tempDir: string;
|
|
318
|
+
|
|
319
|
+
beforeEach(() => {
|
|
320
|
+
vi.clearAllMocks();
|
|
321
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "selected-docker-test-"));
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
afterEach(() => {
|
|
325
|
+
try {
|
|
326
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
327
|
+
} catch {
|
|
328
|
+
// ignore
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
function mixedPackageRoot(): string {
|
|
333
|
+
return makePackageRoot(
|
|
334
|
+
tempDir,
|
|
335
|
+
{
|
|
336
|
+
name: "@test/mixed",
|
|
337
|
+
version: "1.0.0",
|
|
338
|
+
"block-software": {
|
|
339
|
+
entrypoints: { pyep: pythonEntrypoint, javaep: javaEntrypoint },
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
{ requirementsTxt: true, runenv: { ref: RUNENV_REF, pythonVersion: "3.12.10" } },
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
it("counts every docker artifact when nothing is selected", () => {
|
|
347
|
+
const core = new Core(mockLogger, { packageRoot: mixedPackageRoot() });
|
|
348
|
+
expect(core.selectedDockerPackages()).toHaveLength(1);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it("returns none when the selection has no docker artifact", () => {
|
|
352
|
+
const core = new Core(mockLogger, { packageRoot: mixedPackageRoot() });
|
|
353
|
+
expect(core.selectedDockerPackages(["javaep"])).toHaveLength(0);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it("resolves the virtual :docker entrypoint for a selected python entrypoint", () => {
|
|
357
|
+
const core = new Core(mockLogger, { packageRoot: mixedPackageRoot() });
|
|
358
|
+
expect(core.selectedDockerPackages(["pyep"])).toHaveLength(1);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it("returns none for a package with no docker artifacts at all", () => {
|
|
362
|
+
const root = makePackageRoot(tempDir, {
|
|
363
|
+
name: "@test/java-only-selection",
|
|
364
|
+
version: "1.0.0",
|
|
365
|
+
"block-software": { entrypoints: { main: javaEntrypoint } },
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
const core = new Core(mockLogger, { packageRoot: root });
|
|
369
|
+
expect(core.selectedDockerPackages()).toHaveLength(0);
|
|
370
|
+
expect(core.selectedDockerPackages(["main"])).toHaveLength(0);
|
|
371
|
+
});
|
|
372
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Regression tests for the "built but never pushed" guard (MILAB-6714).
|
|
2
|
+
//
|
|
3
|
+
// The trap: `"private": true` on a software package flips the auto-push default
|
|
4
|
+
// off, the descriptor is still written with the image tag, CI goes green, and
|
|
5
|
+
// the block 404s pulling the image at runtime.
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
8
|
+
import { assertDockerPushIntent, type PushIntent } from "../push-guard";
|
|
9
|
+
|
|
10
|
+
const PUSH_SUPPRESSED: PushIntent = {
|
|
11
|
+
buildDocker: true,
|
|
12
|
+
pushDocker: false,
|
|
13
|
+
pushDisabledExplicitly: false,
|
|
14
|
+
dockerPackageCount: 1,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
describe("assertDockerPushIntent", () => {
|
|
18
|
+
let ci: string | undefined;
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
ci = process.env.CI;
|
|
22
|
+
process.env.CI = "true";
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
if (ci === undefined) delete process.env.CI;
|
|
27
|
+
else process.env.CI = ci;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("throws when CI builds docker images it will not push", () => {
|
|
31
|
+
expect(() => assertDockerPushIntent(PUSH_SUPPRESSED)).toThrow(/without pushing them/);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("names private as the likely cause", () => {
|
|
35
|
+
expect(() => assertDockerPushIntent(PUSH_SUPPRESSED)).toThrow(/"private": true/);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("accepts an explicit --docker-no-autopush", () => {
|
|
39
|
+
expect(() =>
|
|
40
|
+
assertDockerPushIntent({ ...PUSH_SUPPRESSED, pushDisabledExplicitly: true }),
|
|
41
|
+
).not.toThrow();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("accepts a run that does push", () => {
|
|
45
|
+
expect(() => assertDockerPushIntent({ ...PUSH_SUPPRESSED, pushDocker: true })).not.toThrow();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("accepts a run that builds no docker images", () => {
|
|
49
|
+
expect(() => assertDockerPushIntent({ ...PUSH_SUPPRESSED, buildDocker: false })).not.toThrow();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("accepts a package with no docker entrypoints", () => {
|
|
53
|
+
expect(() =>
|
|
54
|
+
assertDockerPushIntent({ ...PUSH_SUPPRESSED, dockerPackageCount: 0 }),
|
|
55
|
+
).not.toThrow();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("stays out of the way outside CI, where dev iteration never pushes", () => {
|
|
59
|
+
delete process.env.CI;
|
|
60
|
+
expect(() => assertDockerPushIntent(PUSH_SUPPRESSED)).not.toThrow();
|
|
61
|
+
});
|
|
62
|
+
});
|
package/src/core/core.ts
CHANGED
|
@@ -148,6 +148,20 @@ export class Core {
|
|
|
148
148
|
);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
/**
|
|
152
|
+
* The docker artifacts a build would actually produce for this selection.
|
|
153
|
+
*
|
|
154
|
+
* Mirrors the resolution `buildDockerImages` performs, so callers can reason
|
|
155
|
+
* about a build before running it. Note that `ids` are entrypoint names, not
|
|
156
|
+
* docker package keys: `getArtifact(id, "docker")` resolves the `:docker`
|
|
157
|
+
* virtual entrypoint, so a plain set intersection with `dockerPackages`
|
|
158
|
+
* would be wrong.
|
|
159
|
+
*/
|
|
160
|
+
public selectedDockerPackages(ids?: string[]): string[] {
|
|
161
|
+
const selected = ids ?? Array.from(this.dockerPackages.keys());
|
|
162
|
+
return selected.filter((id) => this.getArtifact(id, "docker") !== undefined);
|
|
163
|
+
}
|
|
164
|
+
|
|
151
165
|
public packageHasType(id: string, type: artifacts.artifactType): boolean {
|
|
152
166
|
const pkg = this.packages.get(id);
|
|
153
167
|
if (pkg && pkg.type === type) {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Guard against the silent "image built, never pushed" outcome.
|
|
2
|
+
//
|
|
3
|
+
// Docker auto-push defaults to `isCI() && !isPrivate`, but the entrypoint
|
|
4
|
+
// descriptor is written with the image tag either way. A stray
|
|
5
|
+
// `"private": true` on a software package therefore yields a green CI run and
|
|
6
|
+
// a published block that 404s pulling its image at runtime — the failure only
|
|
7
|
+
// surfaces when a user runs the block (MILAB-6714).
|
|
8
|
+
//
|
|
9
|
+
// So: in CI, building docker images without pushing them is an error unless
|
|
10
|
+
// the caller says it meant to, via `--docker-no-autopush` /
|
|
11
|
+
// `PL_DOCKER_NO_AUTOPUSH=1`.
|
|
12
|
+
|
|
13
|
+
import * as envs from "./envs";
|
|
14
|
+
import * as util from "./util";
|
|
15
|
+
|
|
16
|
+
export type PushIntent = {
|
|
17
|
+
/** Docker images were built in this run. */
|
|
18
|
+
buildDocker: boolean;
|
|
19
|
+
/** Resolved auto-push decision. */
|
|
20
|
+
pushDocker: boolean;
|
|
21
|
+
/** Caller passed `--docker-no-autopush` / `PL_DOCKER_NO_AUTOPUSH=1`. */
|
|
22
|
+
pushDisabledExplicitly: boolean;
|
|
23
|
+
/** How many entrypoints produce a docker image. */
|
|
24
|
+
dockerPackageCount: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Throws when a CI run is about to reference docker images it never pushed. */
|
|
28
|
+
export function assertDockerPushIntent(intent: PushIntent): void {
|
|
29
|
+
if (!envs.isCI()) return;
|
|
30
|
+
if (!intent.buildDocker || intent.pushDocker) return;
|
|
31
|
+
if (intent.dockerPackageCount === 0) return;
|
|
32
|
+
if (intent.pushDisabledExplicitly) return;
|
|
33
|
+
|
|
34
|
+
throw util.CLIError(
|
|
35
|
+
`This CI run would build docker images without pushing them, while still writing ` +
|
|
36
|
+
`entrypoint descriptors that reference them. Consumers would fail to pull the images.\n` +
|
|
37
|
+
` The usual cause is "private": true in package.json: auto-push is gated on ` +
|
|
38
|
+
`!isPrivate, and software packages must never be private.\n` +
|
|
39
|
+
` If this package really must build images without publishing them, say so with ` +
|
|
40
|
+
`--docker-no-autopush (or ${envs.PL_DOCKER_NO_AUTOPUSH}=1).`,
|
|
41
|
+
);
|
|
42
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { Core } from "./core/core";
|
|
|
4
4
|
export * as util from "./core/util";
|
|
5
5
|
export * as envs from "./core/envs";
|
|
6
6
|
export * as defaults from "./defaults";
|
|
7
|
+
export { assertDockerPushIntent, type PushIntent } from "./core/push-guard";
|
|
7
8
|
|
|
8
9
|
/** The logger the engine and its callers pass around. */
|
|
9
10
|
export type Logger = winston.Logger;
|
|
@@ -22,6 +23,7 @@ export type Builder = Pick<
|
|
|
22
23
|
| "fullDirHash"
|
|
23
24
|
| "version"
|
|
24
25
|
| "isPrivate"
|
|
26
|
+
| "selectedDockerPackages"
|
|
25
27
|
| "buildDockerImages"
|
|
26
28
|
| "buildSoftwareArchives"
|
|
27
29
|
| "buildSwJsonFiles"
|