MCPcopy Index your code
hub / github.com/CopilotKit/CopilotKit / assertImageConsumersValid

Function assertImageConsumersValid

showcase/scripts/railway-envs.ts:2319–2388  ·  view source on GitHub ↗
(
  services: Record<
    string,
    {
      ciBuilt: boolean;
      imageOf?: string;
      environments?: Record<string, unknown>;
    }
  > = SERVICES,
)

Source from the content-addressed store, hash-verified

2317 * Accepts an injected map for testing; defaults to the real SERVICES map.
2318 */
2319export function assertImageConsumersValid(
2320 services: Record<
2321 string,
2322 {
2323 ciBuilt: boolean;
2324 imageOf?: string;
2325 environments?: Record<string, unknown>;
2326 }
2327 > = SERVICES,
2328): void {
2329 const problems: string[] = [];
2330 for (const [key, entry] of Object.entries(services)) {
2331 const target = entry.imageOf;
2332 if (target === undefined) continue;
2333 if (entry.ciBuilt) {
2334 problems.push(
2335 ` - "${key}" is ciBuilt but declares imageOf "${target}" — a build slot is its own image producer; drop one of the two`,
2336 );
2337 continue;
2338 }
2339 // Own-property lookup: a bare `services[target]` truthiness check
2340 // would resolve inherited Object.prototype keys (e.g. imageOf:
2341 // "toString") to a truthy non-entry and misreport the dangling target.
2342 if (!Object.hasOwn(services, target)) {
2343 problems.push(
2344 ` - imageOf "${target}" on "${key}" is not an SSOT key in SERVICES`,
2345 );
2346 continue;
2347 }
2348 const targetEntry = services[target];
2349 if (!targetEntry.ciBuilt) {
2350 problems.push(
2351 ` - imageOf "${target}" on "${key}" points at a service that is not ciBuilt — only showcase_build.yml build slots can have image consumers`,
2352 );
2353 continue;
2354 }
2355 // A consumer with ZERO declared environments passes the env-subset
2356 // check below vacuously — but a consumer that exists in no env is a
2357 // service the redeploy expansion can never reach (expandImageConsumers
2358 // filters on `environments[env]`), i.e. a silently never-redeployed
2359 // service. Reject it loudly.
2360 const consumerEnvs = Object.keys(entry.environments ?? {});
2361 if (consumerEnvs.length === 0) {
2362 problems.push(
2363 ` - "${key}" declares imageOf "${target}" but ZERO environments — the env-subset check passes vacuously and the consumer would never be redeployed in any env`,
2364 );
2365 continue;
2366 }
2367 // Env overlap: every env the consumer declares must also be one the
2368 // producer builds for. A consumer-only env would run an image that no
2369 // CI build ever refreshes there — a silently never-updating service,
2370 // the exact stale-image failure this invariant exists to prevent.
2371 const producerEnvs = targetEntry.environments ?? {};
2372 for (const env of consumerEnvs) {
2373 if (!Object.hasOwn(producerEnvs, env)) {
2374 problems.push(
2375 ` - "${key}" declares env "${env}" but its imageOf "${target}" has no "${env}" environment — "${key}" would run a never-rebuilt image there`,
2376 );

Callers 2

railway-envs.tsFile · 0.85

Calls 4

entriesMethod · 0.80
keysMethod · 0.80
pushMethod · 0.65
joinMethod · 0.65

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…