/** * Derivation for the buildx registry-cache ECR repository that sits beside an * app's image repository. Both the `fjall build` provisioner * (`@fjall/cli` EcrBuildOrchestrator) and the deploy-path provisioner * (`@fjall/deploy-core` dockerBuildHelper) address the SAME physical repo, so * the name derivation and the lifecycle retention live here — a re-implemented * `\`${name}-cache\`` at either site is silent drift against a shared AWS * resource (see code-quality.md § "Runtime resource names must match the CDK * construct's derivation" — same rule, orchestrator↔orchestrator seam). */ import { type Result } from "./result.js"; /** `-cache`; `repositoryName` is the kebab-case app repo name. */ export declare function buildCacheRepositoryName(repositoryName: string): string; export declare const BUILD_CACHE_MODE_ENV_VAR = "FJALL_BUILD_CACHE_MODE"; export declare const BUILD_CACHE_MODES: readonly ["max", "min", "off"]; export type BuildCacheMode = (typeof BUILD_CACHE_MODES)[number]; /** * Resolve the registry cache-export mode from the environment. `max` * (default) exports every intermediate layer — the cross-machine win for * multi-stage npm Dockerfiles, whose valuable cache entries are the * dependency-stage layers that `min` would drop. `min` exports final-stage * layers only; `off` skips `--cache-to` entirely (`--cache-from` still * reads any existing cache). Escape hatch for slow uplinks where the * dep-bump double upload (image push + mode=max export) is not worth the * cross-machine reuse — trade-off recorded in * the 2026-07-17 decision: buildx cache export mode. * * Fails (rather than falling back) on an empty or unrecognised value. */ export declare function resolveBuildCacheMode(env: NodeJS.ProcessEnv): Result; export interface RegistryCacheRefsInput { /** * Full URI of the app's `-cache` sibling ECR repository, or undefined * when the caller has no cache repo provisioned (refs are skipped entirely). */ readonly cacheRepoUri: string | undefined; readonly appName: string; /** Per-service cache tag within a shared app cache repo, when building one service of many. */ readonly serviceName?: string | undefined; readonly mode: BuildCacheMode; } export interface RegistryCacheRefs { readonly cacheFrom: string[]; readonly cacheTo?: string[]; } /** * Build the buildx `--cache-from`/`--cache-to` registry refs for an app * service. The CLI provider (`@fjall/cli` CliDockerProvider) and the deploy * worker (webapp `workerDockerProvider`) build against the SAME physical * cache repo and tags — a cache exported by one machine must be importable * by the other, so the tag derivation and ref syntax are a cross-repo * coupled value (code-quality.md § "Coupled values") and live here only. * * The tag is `(serviceName ?? appName).toLowerCase()` — existing cache tags * are already in this form, so changing the derivation would orphan every * cache pushed to date. * * `off` drops `--cache-to` but keeps `--cache-from`: reading an existing * cache costs nothing and only speeds the build up. */ export declare function buildRegistryCacheRefs(input: RegistryCacheRefsInput): RegistryCacheRefs | undefined; /** * Days before untagged cache layers expire. Buildx registry-cache writes leave * untagged image layers behind on every push; both provisioners apply the same * lifecycle policy idempotently, so a differing value would flip-flop between * `fjall build` and `fjall deploy` runs (last writer wins). */ export declare const CACHE_REPO_UNTAGGED_RETENTION_DAYS = 14; /** * The exact lifecycle-policy document both provisioners PUT on the cache * repo. Shared so the stored policy text is byte-identical regardless of * which path wrote last — a structurally-equal-but-differently-worded * document would rewrite the policy on every alternating build/deploy run. */ export declare function untaggedLifecyclePolicyText(daysUntilExpiry: number): string;