@norskvideo/ctl-test-harness 0.1.20 → 0.1.22

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/demo/spec.d.ts CHANGED
@@ -30,14 +30,26 @@ export interface DemoSource {
30
30
  ingest: DemoIngest;
31
31
  streamId?: string;
32
32
  }
33
- export interface DemoContext {
33
+ /** How the product is registered: `dev` runs `dev.command` from source and
34
+ * adds it by URL; `image` adds the built `image` (the customer path). */
35
+ export type DemoMode = "dev" | "image";
36
+ /** Whose daemon: a `private` one on a throwaway store (the default; what
37
+ * `check` always uses), or `reuse` the developer's listening daemon and its
38
+ * real store — where `product add` refuses an existing name and stored
39
+ * templates are immutable, so the driver deletes/removes/re-adds first. */
40
+ export type DemoDaemonPolicy = "private" | "reuse";
41
+ /** What `beforeLaunch` sees: the template is stored, nothing is launched. */
42
+ export interface DemoLaunchContext {
34
43
  action: "up" | "check";
44
+ mode: DemoMode;
45
+ daemon: DemoDaemonPolicy;
35
46
  product: string;
36
47
  instanceId: string;
37
48
  daemonPort: number;
38
49
  storeDir: string;
39
- /** Resolve a spec URL against this run's ports. */
40
- url(ref: DemoUrl): string;
50
+ templateName: string;
51
+ /** The stored template's directory (`compose.yml`, `workflow.yml`, ...). */
52
+ templateDir: string;
41
53
  cli(argv: string[], opts?: {
42
54
  output?: "json" | "yaml";
43
55
  }): Promise<{
@@ -45,9 +57,13 @@ export interface DemoContext {
45
57
  stderr: string;
46
58
  exitCode: number;
47
59
  }>;
48
- fetch(url: string, init?: RequestInit): Promise<Response>;
49
60
  log(line: string): void;
50
61
  }
62
+ export interface DemoContext extends DemoLaunchContext {
63
+ /** Resolve a spec URL against this run's ports. */
64
+ url(ref: DemoUrl): string;
65
+ fetch(url: string, init?: RequestInit): Promise<Response>;
66
+ }
51
67
  export type DemoReady = {
52
68
  http: DemoUrl;
53
69
  status?: number;
@@ -75,9 +91,21 @@ export type DemoTemplate = {
75
91
  input: string | Record<string, unknown>;
76
92
  };
77
93
  };
94
+ /** A sidecar container the demo needs beside the instance (funke's ad-push
95
+ * capture origin): `docker run -d --name <name> --network norsk-net <args>
96
+ * <image> <command>`, started before the launch, removed at teardown. */
97
+ export interface DemoExtra {
98
+ name: string;
99
+ image: string;
100
+ /** Extra `docker run` flags (`-p`, `-v`, `--entrypoint`, ...). */
101
+ args?: string[];
102
+ command?: string[];
103
+ }
78
104
  export interface DemoSpec {
79
105
  /** Manifest name, e.g. "norsk-playout". The registration must report it. */
80
106
  product: string;
107
+ /** The default `--mode`; `dev` when omitted. */
108
+ mode?: DemoMode;
81
109
  /** Started with PORT=<driver-chosen> in the environment; the driver polls
82
110
  * `readyPath` (default `/manifest.json`, what `product add` fetches). */
83
111
  dev: {
@@ -99,6 +127,10 @@ export interface DemoSpec {
99
127
  path: string;
100
128
  hint: string;
101
129
  }>;
130
+ extras?: DemoExtra[];
131
+ /** Runs once the template is stored and pin-checked, before the launch —
132
+ * the place for a product-only patch to the stored template. */
133
+ beforeLaunch?: (ctx: DemoLaunchContext) => Promise<void>;
102
134
  sources?: DemoSource[];
103
135
  /** Gates polled in order once the instance runs and the sources pump — so a
104
136
  * gate may demand what only a source produces (composing, analysing). */
@@ -106,12 +138,22 @@ export interface DemoSpec {
106
138
  /** Runs once every gate holds. */
107
139
  after?: (ctx: DemoContext) => Promise<void>;
108
140
  open?: DemoOpen[];
109
- /** The standalone tier's live-source links, for `--mode standalone`. Paths
110
- * are relative to the repo root. */
141
+ /** The standalone tier (`dev-loop`, `check --mode standalone --export-only`):
142
+ * the live-source links (paths relative to the repo root) and, for the full
143
+ * tier, where the engine and Studio checkouts and the exported workdir live
144
+ * (absolute or `~`-rooted; NORSK_DIR / STUDIO_DIR / TO in the environment
145
+ * override them, the conventional `~/dev/...` paths apply when neither says). */
111
146
  standalone?: {
112
147
  links?: Record<string, string>;
113
148
  dashboards?: string;
114
149
  params?: Record<string, string | number>;
150
+ norskDir?: string;
151
+ studioDir?: string;
152
+ workdir?: string;
153
+ /** The template the dev-loop builds when it is not the demo's (probe:
154
+ * the standalone form assumes the box's side-loads, the demo form is
155
+ * portable). The export gate keeps the demo's, CI-portable. */
156
+ template?: DemoTemplate;
115
157
  };
116
158
  }
117
159
  export declare const DemoSpecSchema: z.ZodType<DemoSpec>;
package/demo/spec.js CHANGED
@@ -38,25 +38,31 @@ const relativePath = z
38
38
  .string()
39
39
  .min(1)
40
40
  .refine((p) => !isAbsolute(p) && !p.startsWith("~"), { message: "must be a relative path inside the repo" });
41
+ const homePath = z
42
+ .string()
43
+ .min(1)
44
+ .refine((p) => isAbsolute(p) || p === "~" || p.startsWith("~/"), {
45
+ message: "must be an absolute or ~-rooted path (a checkout outside the repo)",
46
+ });
47
+ const Template = z.union([
48
+ z.strictObject({ name: z.string().min(1) }),
49
+ z.strictObject({
50
+ build: z.strictObject({
51
+ name: z.string().min(1).optional(),
52
+ input: z.union([z.string().min(1), z.record(z.string(), z.unknown())]),
53
+ }),
54
+ }),
55
+ ]);
41
56
  export const DemoSpecSchema = z
42
57
  .strictObject({
43
58
  product: z.string().min(1),
59
+ mode: z.enum(["dev", "image"]).optional(),
44
60
  dev: z.strictObject({
45
61
  command: z.array(z.string().min(1)).min(1),
46
62
  readyPath: z.string().startsWith("/").optional(),
47
63
  }),
48
64
  image: z.string().min(1).optional(),
49
- template: z
50
- .union([
51
- z.strictObject({ name: z.string().min(1) }),
52
- z.strictObject({
53
- build: z.strictObject({
54
- name: z.string().min(1).optional(),
55
- input: z.union([z.string().min(1), z.record(z.string(), z.unknown())]),
56
- }),
57
- }),
58
- ])
59
- .optional(),
65
+ template: Template.optional(),
60
66
  launch: z
61
67
  .strictObject({
62
68
  hardware: z.enum(["nvidia", "none"]).optional(),
@@ -65,6 +71,15 @@ export const DemoSpecSchema = z
65
71
  })
66
72
  .optional(),
67
73
  prerequisites: z.array(z.strictObject({ path: z.string().min(1), hint: z.string().min(1) })).optional(),
74
+ extras: z
75
+ .array(z.strictObject({
76
+ name: z.string().min(1),
77
+ image: z.string().min(1),
78
+ args: z.array(z.string()).optional(),
79
+ command: z.array(z.string().min(1)).optional(),
80
+ }))
81
+ .optional(),
82
+ beforeLaunch: fn().optional(),
68
83
  sources: z
69
84
  .array(z.strictObject({
70
85
  name: z.string().min(1),
@@ -95,6 +110,10 @@ export const DemoSpecSchema = z
95
110
  links: z.record(z.string().min(1), relativePath).optional(),
96
111
  dashboards: relativePath.optional(),
97
112
  params: Params.optional(),
113
+ norskDir: homePath.optional(),
114
+ studioDir: homePath.optional(),
115
+ workdir: homePath.optional(),
116
+ template: Template.optional(),
98
117
  })
99
118
  .optional(),
100
119
  })
@@ -106,6 +125,13 @@ export const DemoSpecSchema = z
106
125
  }
107
126
  seen.add(s.name);
108
127
  });
128
+ const extras = new Set();
129
+ (spec.extras ?? []).forEach((e, i) => {
130
+ if (extras.has(e.name)) {
131
+ ctx.addIssue({ code: "custom", path: ["extras", i, "name"], message: `duplicate extra name '${e.name}'` });
132
+ }
133
+ extras.add(e.name);
134
+ });
109
135
  });
110
136
  /** Format zod's issue list as one line per problem, path first. A union's
111
137
  * failure would otherwise arrive as every branch's complaint; the rule the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@norskvideo/ctl-test-harness",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -46,12 +46,21 @@
46
46
  "./demo": {
47
47
  "types": "./demo/index.d.ts",
48
48
  "default": "./demo/index.js"
49
+ },
50
+ "./container-logs": {
51
+ "types": "./container-logs.d.ts",
52
+ "default": "./container-logs.js"
53
+ },
54
+ "./compose-advancing": {
55
+ "types": "./compose-advancing.d.ts",
56
+ "default": "./compose-advancing.js"
49
57
  }
50
58
  },
51
59
  "main": "./index.js",
52
60
  "types": "./index.d.ts",
53
61
  "bin": {
54
- "ctl-demo": "./demo/cli.js"
62
+ "ctl-demo": "./demo/cli.js",
63
+ "ctl-dev-loop": "./demo/dev-loop-cli.js"
55
64
  },
56
65
  "dependencies": {
57
66
  "@norskvideo/ctl-sdk": "^0.1.0",