/** * `@intentius/chant/testing` (#1224) — the live-stack test harness. * * A vitest suite deploys a real instance of its project once, asserts against * it, and tears it down — emulator-locally on a dev machine, real-cloud in CI, * with the same suite text. One call composes machinery that already exists: * * - **build** — the same programmatic path `chant build` takes: config * resolution (`buildParams` + the ownership marker) mirrored from the CLI, * then `build()` over the project's own serializers. * - **apply** — an additive `nativeApply` per built lexicon output, run * in-process through the local Op executor (`runOpLocally`). `deleteMode` * is `"never"`: a test deploy creates and updates, nothing else. * - **destroy** — #1222's marker-scoped teardown (`executeTeardown`), called * in-process for exactly this suite's environment. Stateless by design: * a crashed suite's environment is recovered by calling destroy again (or * `chant lifecycle teardown --yes`). * * ## Isolation * * Every deploy targets its own environment: `test--` by default * ({@link testEnvName}), so parallel CI jobs never collide. The environment * is the teardown key — everything the deploy stamps carries the ownership * marker `{ stack, env }`, and `destroy()` selects on that identity and * nothing else. A project that declares `environments` must legalize the * dynamic names with a pattern entry (#1221): * * ```ts * environments: ["dev", "prod", { name: "test-*", endpoint: "http://localhost:4566" }] * ``` * * ## Emulators * * The harness is emulator-aware the same way `--live` reads are (#1166): the * target environment's declared `endpoint` is injected into each lexicon's * ambient endpoint variable (`AWS_ENDPOINT_URL`, …) for the apply and the * teardown — unless the variable is already set. Ambient always wins, so the * env vars `chant emulator up --json` reports (#920) take precedence when * exported, and a CI job pointing the identical suite at a real account just * leaves both unset. */ import type { Declarable } from "./declarable.js"; import type { SerializerResult } from "./serializer.js"; import { type BuildParamValue } from "./build-params.js"; import type { LexiconPlugin } from "./lexicon.js"; import { type ActivityFn, type ActivityProfile } from "./op/activity-registry.js"; import { type TeardownReport } from "./lifecycle/teardown.js"; export interface DeployStackOptions { /** The chant project directory (where the infra source lives). */ dir: string; /** * Explicit environment name. Overrides the default `test--` * derivation — for a shared long-lived test environment, or a test that * needs a deterministic name. Must be legal for the project's declared * `environments`, exactly as `--env` would be. */ env?: string; /** * Suite name folded into the default environment name. Defaults to the * project directory's basename. */ suite?: string; /** Build parameters, exactly as `--param name=value` flags would supply them. */ params?: Record; /** * Loaded lexicon plugins. Defaults to loading the project's own declared/ * detected lexicons — pass this only to substitute test doubles. */ plugins?: LexiconPlugin[]; /** Activity implementations for the apply. Defaults to the real registry. */ activities?: Map; /** Activity profiles (timeouts/retries). Defaults to the lexicon-declared table. */ profiles?: Record; /** * Extra lexicon-name → `nativeApply` target entries, merged over the * built-in map (aws → cloudformation, k8s → kubectl, azure → arm, * gcp → gcp, fly → fly). A seam for tests and out-of-tree lexicons. */ applyTargets?: Record; } /** The handle a suite holds between `beforeAll` and `afterAll`. */ export interface DeployedStack { /** The built outputs, keyed by lexicon — what was deployed. */ outputs: Map; /** The discovered entities, keyed by name. */ entities: Map; /** The environment this deploy targeted — the teardown key. */ env: string; /** * Tear down everything carrying this suite's marker `{ stack, env }`. * Throws {@link TeardownIncompleteError} when any candidate failed to * delete or the plan had holes — an environment that cannot be called * clean is a test failure, never a silent leak. Safe to call again: * teardown is stateless, and a second call over a clean environment * plans nothing. */ destroy(): Promise; } /** * Thrown by {@link DeployedStack.destroy} when the environment cannot be * called clean: candidates still `failed` after the retry pass, or the plan * had holes (#1089 — parts of the estate could not be read, so "nothing * left" would be a claim about what was readable, not about the environment). * Carries the full report for diagnosis. */ export declare class TeardownIncompleteError extends Error { readonly report: TeardownReport; constructor(report: TeardownReport); } /** * The default environment name for one suite run: `test--`. * The `test-` prefix is what a project's `"test-*"` pattern entry (#1221) * legalizes; the nonce keeps parallel CI jobs of the same suite apart. */ export declare function testEnvName(suite: string): string; /** * Deploy a live instance of the project in `dir` for one test suite. * * Build (the CLI's own config resolution: `buildParams`, ownership marker, * build roots) + additive apply (one `nativeApply` per built output with a * native mechanism, via the local Op executor). Returns the handle the suite * holds: outputs, entities, the environment name, and `destroy`. * * The ownership marker stamped on every resource is `{ stack: ownership.stack, * env: }` — the marker env always follows the * suite environment, whatever `ownership.env` in config says, because the * marker is the only thing `destroy()` selects on. A project with no * `ownership.stack` is refused up front: a deploy that stamps nothing is a * deploy nothing can sweep. * * Failures are thrown, never returned: build errors, unresolved parameters, * an illegal environment name, and a failed apply (the local executor's * `OpRunFailure`) all reject the returned promise. */ export declare function deployStack(options: DeployStackOptions): Promise; //# sourceMappingURL=testing.d.ts.map