/** * Bundle helpers for sibling-package sources a Dockerfile has to COPY. * * Why this exists: Dockerfile.registry COPYs from a `registry-server/` * directory in its build context. When cele2e runs from inside the * monorepo, that path is found via `..` (= packages/registry-server). * When cele2e is npm-installed at lunacycle/node_modules/@celilo/e2e, * `..` resolves to node_modules/@celilo/ which has no sibling * registry-server — the build fails with "registry-server: not found". * * Fix: always bundle a copy of registry-server INSIDE the e2e package * (at /registry-server). The build context is the package dir * itself, so the COPY succeeds whether we're in the monorepo (where * the bundle is regenerated from the sibling source on every build) * or installed from npm (where the bundle is shipped in the tarball). * * The bundled directory is .gitignored — it's a build artifact, not * canonical source. The canonical source remains packages/registry-server. * * The same reasoning applies to @celilo/terraform-fake, which * Dockerfile.proxmox-sim needs, with one addition that is not merely * convenience: the simulator MUST run the workspace copy, not the published * one. Installing it from npm inside the image would mean a PR that changes the * fake is tested against whatever was last released — the "modules run their * bundled copy" trap (celilo#173) in a new place, and silent. It also cannot * work before the first release: `bun install` in the image resolved * `@celilo/terraform-fake@*` against registry.npmjs.org and got a 404. */ import { cpSync, existsSync, rmSync } from 'node:fs'; import { basename, join } from 'node:path'; // @psbanka - 2026-09: Test files are excluded from the bundle (ce-62u1). A // bundled test copy is one directory deeper than its source, so // workspace-relative imports like '../../../apps/...' resolve one level short // and fail. The bundle exists to serve the sim image, which runs no tests, so // the tests belong to the source package only. function isTestFile(path: string): boolean { return /\.test\.tsx?$/.test(basename(path)); } /** * Ensure /registry-server/ contains a fresh copy of the * upstream packages/registry-server source files Dockerfile.registry * needs (package.json, tsconfig.json, src/). * * - In the monorepo (sibling `packages/registry-server` exists), wipe * the bundle and recopy from the sibling. Cheap and idempotent. * - When npm-installed (no sibling), the bundle is expected to already * be in place from publish-time. If it isn't, throw — the package was * published incorrectly. */ export function ensureRegistryServerBundle(pkgDir: string): void { ensureSiblingBundle(pkgDir, 'registry-server', ['package.json', 'tsconfig.json', 'src']); } /** * Ensure /terraform-fake/ holds the source Dockerfile.proxmox-sim * COPYs, so the simulator runs the fake from THIS checkout. */ export function ensureTerraformFakeBundle(pkgDir: string): void { ensureSiblingBundle(pkgDir, 'terraform-fake', ['package.json', 'src']); } /** * Copy `entries` from the sibling package `name` into `/`. * * In the monorepo the bundle is wiped and recopied every time — cheap, and it * means the image can never build from a stale copy. When npm-installed there * is no sibling and the bundle must already have shipped in the tarball; a * missing one is a publish defect, not something to paper over. */ function ensureSiblingBundle(pkgDir: string, name: string, entries: string[]): void { const bundle = join(pkgDir, name); const upstream = join(pkgDir, '..', name); if (!existsSync(upstream)) { if (!existsSync(bundle)) { throw new Error( `cele2e: ${bundle} is missing and ../${name} doesn't exist either.\nThe @celilo/e2e package was published without its ${name} bundle. Re-publish from infra/scripts/publish.ts so the bundle is recreated.`, ); } return; // npm-installed; bundle ships in tarball } rmSync(bundle, { recursive: true, force: true }); for (const entry of entries) { cpSync(join(upstream, entry), join(bundle, entry), { recursive: true, filter: (src) => !isTestFile(src), }); } }