@specific.dev/spectest 0.120.1 → 0.122.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/README.md +19 -0
- package/dist/components/k3s-nodes.d.ts +5 -0
- package/dist/components/k3s-nodes.js +37 -0
- package/dist/components/k3s.d.ts +7 -41
- package/dist/components/k3s.js +260 -215
- package/dist/components/supabase-coverage.d.ts +7 -0
- package/dist/components/supabase-coverage.js +375 -0
- package/dist/components/supabase.js +30 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -3
- package/package.json +1 -1
- package/src/components/internal-fetch.test.ts +68 -0
- package/src/components/k3s-concurrency.test.ts +76 -3
- package/src/components/k3s-docker.test.ts +140 -0
- package/src/components/k3s-nodes.test.ts +73 -0
- package/src/components/k3s-nodes.ts +35 -0
- package/src/components/k3s-registry.test.ts +13 -8
- package/src/components/k3s.ts +268 -223
- package/src/components/supabase-coverage.test.ts +261 -0
- package/src/components/supabase-coverage.ts +373 -0
- package/src/components/supabase.ts +30 -7
- package/src/index.ts +11 -4
package/README.md
CHANGED
|
@@ -20,6 +20,25 @@ Pub/Sub integrations are project-owned as of SDK 0.98.0. The former
|
|
|
20
20
|
Use a local service definition or `serviceGroup()` wrapper; the repository’s
|
|
21
21
|
`examples/google-pubsub` demonstrates this using public SDK APIs.
|
|
22
22
|
|
|
23
|
+
## Supabase function coverage (0.122.0)
|
|
24
|
+
|
|
25
|
+
`supabase({ dir: "supabase" })` automatically collects coverage for its edge
|
|
26
|
+
functions, including local shared modules outside that directory. No application
|
|
27
|
+
instrumentation or coverage option is needed. Custom component names and folder
|
|
28
|
+
layouts work the same way. Stacks without functions have no extra collector.
|
|
29
|
+
|
|
30
|
+
Coverage starts before user code in both shared and per-function isolates. Setup
|
|
31
|
+
and individual test captures are separate, with source maps checked against the
|
|
32
|
+
uploaded TypeScript/JavaScript. Generated startup gates let functions warm
|
|
33
|
+
concurrently while preserving their Deno configuration and import maps.
|
|
34
|
+
Isolate captures, source metadata reads, and report writes run concurrently.
|
|
35
|
+
Lost workers or unusable source metadata fail
|
|
36
|
+
collection rather than silently reporting no execution. Changes to the function
|
|
37
|
+
catalogue or runtime configuration conservatively invalidate subset selection,
|
|
38
|
+
including newly added functions. This collects edge function code only: SQL and
|
|
39
|
+
application frontend coverage are separate, and subset enforcement remains a
|
|
40
|
+
project setting.
|
|
41
|
+
|
|
23
42
|
## Interactive entrypoints (0.114.0)
|
|
24
43
|
|
|
25
44
|
Choose the links shown in the interactive dashboard and PR preview comment:
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SpectestContext } from "../index.js";
|
|
2
|
+
/** /readyz only checks the API server. Check the expected identities, not just
|
|
3
|
+
* a count: an unregistered agent must not be hidden by an unrelated node.
|
|
4
|
+
* This runs alongside image imports and infrastructure rollouts. */
|
|
5
|
+
export declare function waitForK3sNodes(server: string, names: readonly string[], exec: SpectestContext["exec"], timeoutMs: number): Promise<void>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** /readyz only checks the API server. Check the expected identities, not just
|
|
2
|
+
* a count: an unregistered agent must not be hidden by an unrelated node.
|
|
3
|
+
* This runs alongside image imports and infrastructure rollouts. */
|
|
4
|
+
export async function waitForK3sNodes(server, names, exec, timeoutMs) {
|
|
5
|
+
const deadline = Date.now() + timeoutMs;
|
|
6
|
+
let detail = "no nodes registered";
|
|
7
|
+
for (;;) {
|
|
8
|
+
const result = await exec(server, ["kubectl", "get", "nodes", "-o", "json", "--request-timeout=5s"], { timeoutMs: 10_000 });
|
|
9
|
+
if (result.exitCode === 0) {
|
|
10
|
+
const nodes = JSON.parse(result.stdout).items;
|
|
11
|
+
const pending = names.flatMap(name => {
|
|
12
|
+
const node = nodes.find(node => node.metadata?.name === name);
|
|
13
|
+
const ready = node?.status?.conditions?.find(condition => condition.type === "Ready");
|
|
14
|
+
return ready?.status === "True" ? [] : [`${name}: ${node ? ready?.message || `Ready=${ready?.status ?? "Unknown"}` : "not registered"}`];
|
|
15
|
+
});
|
|
16
|
+
if (!pending.length)
|
|
17
|
+
return;
|
|
18
|
+
detail = pending.join("; ");
|
|
19
|
+
}
|
|
20
|
+
else
|
|
21
|
+
detail = result.stderr || result.stdout;
|
|
22
|
+
if (Date.now() >= deadline) {
|
|
23
|
+
// Agent startup errors otherwise look like a missing Kubernetes Node.
|
|
24
|
+
const diagnostics = await Promise.all(names.map(async (name) => {
|
|
25
|
+
try {
|
|
26
|
+
const result = await exec(name, ["sh", "-c", "test -S /run/k3s/containerd/containerd.sock"], { timeoutMs: 5_000 });
|
|
27
|
+
return `${name}: ${result.exitCode === 0 ? "containerd socket present" : result.stderr || "containerd socket missing"}`;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
return `${name}: ${String(error)}`;
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
33
|
+
throw new Error(`k3s(${server}): nodes did not become Ready within ${timeoutMs / 1000}s: ${detail}\n${diagnostics.join("\n")}`);
|
|
34
|
+
}
|
|
35
|
+
await new Promise(resolve => setTimeout(resolve, 250));
|
|
36
|
+
}
|
|
37
|
+
}
|
package/dist/components/k3s.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AppsV1Api, BatchV1Api, CoreV1Api, KubeConfig, PatchStrategy, type KubernetesListObject, type KubernetesObject, type V1DeleteOptions, type V1Job, type V1Status } from "@kubernetes/client-node";
|
|
2
|
-
import type {
|
|
2
|
+
import type { ServiceConfig } from "../index.js";
|
|
3
3
|
import { type KubernetesImage } from "../harness/component-images.js";
|
|
4
4
|
export type { KubernetesImage } from "../harness/component-images.js";
|
|
5
5
|
import type { Wrapped } from "../inspect.js";
|
|
@@ -15,6 +15,9 @@ export interface K3sRegistryOptions {
|
|
|
15
15
|
/** Kubernetes pods receive read-only environment CA mounts during admission.
|
|
16
16
|
* Image bytes and digests stay unchanged; explicit pod trust settings win. */
|
|
17
17
|
export interface K3sOptions {
|
|
18
|
+
/** Total schedulable nodes, including the server node. Defaults to 1.
|
|
19
|
+
* Additional nodes run k3s agents in separate containers inside the same VM. */
|
|
20
|
+
nodes?: number;
|
|
18
21
|
/** Images available to kubelet before project setup. Use registry strings,
|
|
19
22
|
* or Dockerfile builds with a full `reference` matching your manifests. Builds
|
|
20
23
|
* support path/content, context, exclude, target and buildArgs, and run in
|
|
@@ -248,6 +251,8 @@ export interface LogsOptions {
|
|
|
248
251
|
}
|
|
249
252
|
/** Helpers a `k3s(...)` service exposes on `ctx.svc.<name>`. */
|
|
250
253
|
export interface K3sHelpers {
|
|
254
|
+
/** Kubernetes node names, also their Spectest container/service names. */
|
|
255
|
+
nodes: readonly string[];
|
|
251
256
|
/**
|
|
252
257
|
* Fully-loaded `KubeConfig`. The cluster server URL is rewritten to
|
|
253
258
|
* `https://<service-name>.internal:6443`, the auto-assigned DNS name
|
|
@@ -343,43 +348,4 @@ export interface K3sHelpers {
|
|
|
343
348
|
}
|
|
344
349
|
/** @internal Exported for regression tests; not part of the components API. */
|
|
345
350
|
export declare function isTransientApplyError(err: unknown): boolean;
|
|
346
|
-
export declare function k3s(opts?: K3sOptions):
|
|
347
|
-
image: {
|
|
348
|
-
type: "registry";
|
|
349
|
-
reference: string;
|
|
350
|
-
};
|
|
351
|
-
imageBuilds: import("../index.js").ComponentImageBuild[];
|
|
352
|
-
tls: {
|
|
353
|
-
hostname: string;
|
|
354
|
-
port: number;
|
|
355
|
-
}[];
|
|
356
|
-
command: string;
|
|
357
|
-
privileged: true;
|
|
358
|
-
tmpfs: string[];
|
|
359
|
-
cgroupns: string;
|
|
360
|
-
ports: number[];
|
|
361
|
-
volumes: ({
|
|
362
|
-
source: string;
|
|
363
|
-
target: string;
|
|
364
|
-
readOnly?: undefined;
|
|
365
|
-
} | {
|
|
366
|
-
target: string;
|
|
367
|
-
source?: undefined;
|
|
368
|
-
readOnly?: undefined;
|
|
369
|
-
} | {
|
|
370
|
-
source: string;
|
|
371
|
-
target: string;
|
|
372
|
-
readOnly: boolean;
|
|
373
|
-
})[];
|
|
374
|
-
files: {
|
|
375
|
-
path: string;
|
|
376
|
-
content: string;
|
|
377
|
-
}[];
|
|
378
|
-
readyCheck: {
|
|
379
|
-
type: "exec";
|
|
380
|
-
command: string;
|
|
381
|
-
timeoutSecs: number;
|
|
382
|
-
};
|
|
383
|
-
setup: (ctx: ServiceSetupContext<K3sHelpers>) => Promise<void>;
|
|
384
|
-
helpers: ({ name, exec, poll }: ServiceHelpersContext) => Promise<K3sHelpers>;
|
|
385
|
-
};
|
|
351
|
+
export declare function k3s(opts?: K3sOptions): import("../index.js").ServiceGroup<Record<string, ServiceConfig>, K3sHelpers, "server">;
|