@norskvideo/ctl-dev-kit 0.2.72 → 0.2.74
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/create-product/canon.ts
CHANGED
|
@@ -26,6 +26,7 @@ export interface Canon {
|
|
|
26
26
|
dprint: string;
|
|
27
27
|
buildImageBootstrap: string;
|
|
28
28
|
buildImage: string;
|
|
29
|
+
smoke: string;
|
|
29
30
|
/** conventions/build-docs.yml — the embedded docs workflow a turnkey carries. */
|
|
30
31
|
buildDocs: string;
|
|
31
32
|
gitignoreCore: string;
|
|
@@ -53,6 +54,7 @@ export function loadCanon(): Canon {
|
|
|
53
54
|
dprint: readFileSync(join(conventionsDir, "dprint.base.jsonc"), "utf8"),
|
|
54
55
|
buildImageBootstrap: readFileSync(join(buildDir, "build-image.bootstrap.sh"), "utf8"),
|
|
55
56
|
buildImage: readFileSync(join(conventionsDir, "build-image.yml"), "utf8"),
|
|
57
|
+
smoke: readFileSync(join(conventionsDir, "smoke.yml"), "utf8"),
|
|
56
58
|
gitignoreCore: readFileSync(join(conventionsDir, "gitignore.core"), "utf8"),
|
|
57
59
|
invariantsTemplate: readFileSync(join(import.meta.dir, "..", "testing", "INVARIANTS.template.md"), "utf8"),
|
|
58
60
|
demoShim: readFileSync(join(conventionsDir, "demo.sh"), "utf8"),
|
|
@@ -223,6 +223,7 @@ function conventionFiles(ctx: ShapeContext, shape: ShapeModule): GeneratedFile[]
|
|
|
223
223
|
{ path: ".github/workflows/bump.yml", content: fillProduct(canon.bump) },
|
|
224
224
|
{ path: ".github/workflows/bot-prs.yml", content: canon.botPrs },
|
|
225
225
|
{ path: ".github/workflows/build-image.yml", content: fillProduct(canon.buildImage) },
|
|
226
|
+
{ path: ".github/workflows/smoke.yml", content: fillProduct(canon.smoke) },
|
|
226
227
|
{ path: ".github/actions/ci-status-dispatch/action.yml", content: loadAsset("ci-status-dispatch.yml") },
|
|
227
228
|
{ path: "manifest.seed.json", content: seedJson(ctx) },
|
|
228
229
|
{ path: "licenseTemplate.json", content: licenseTemplateJson(ctx) },
|
|
@@ -257,9 +257,15 @@ refreshed \`~/.norsk-ctl/product-templates/<name>/compose.yml\` carries the pins
|
|
|
257
257
|
so table and tests cannot drift apart.
|
|
258
258
|
- **Layer 4 — studio-load round-trip** (\`tests/unit/loads-in-studio.test.ts\`):
|
|
259
259
|
emitted YAML through Studio's real \`document.load()\`.
|
|
260
|
-
- **Layer 5 — integration**:
|
|
261
|
-
|
|
260
|
+
- **Layer 5 — integration**: the smoke tier (\`tests/smoke.spec.ts\`, run by
|
|
261
|
+
the convention \`smoke.yml\` on PRs, main and the nightly bump). It launches
|
|
262
|
+
the built image, sends the camera1 sample to the SRT ingest and checks the
|
|
263
|
+
graph is up and the ingest connected. Grow its observations as the product
|
|
264
|
+
takes shape; add an \`integration.yml\` when a regression needs more than
|
|
265
|
+
one journey (see
|
|
262
266
|
\`node_modules/@norskvideo/ctl-dev-kit/conventions/integration-testing.md\`).
|
|
267
|
+
Locally: \`bun run build:image && bun run test:smoke\` with
|
|
268
|
+
\`NORSK_LICENSE_FILE\` set.
|
|
263
269
|
|
|
264
270
|
Byte-snapshots (\`tests/unit/workflow-snapshot.test.ts\`) pin the emitted wire
|
|
265
271
|
bytes; \`UPDATE_SNAPSHOTS=1\` refreshes deliberately.
|
|
@@ -303,6 +309,7 @@ function rootPackageJson(ctx: ShapeContext): string {
|
|
|
303
309
|
test: "bun run test:unit",
|
|
304
310
|
"test:unit": `bun test shared/src/ backend/src/ ${hasComponents ? "components/src/ " : ""}tests/unit/`,
|
|
305
311
|
"test:image": "bun test tests/image/",
|
|
312
|
+
"test:smoke": "NORSK_CTL_ENV=test bun test tests/smoke.spec.ts",
|
|
306
313
|
"check:drift": "bun run node_modules/@norskvideo/ctl-dev-kit/conventions/check-drift.ts",
|
|
307
314
|
"docs:check":
|
|
308
315
|
"bun run node_modules/@norskvideo/ctl-dev-kit/docs/path-existence.ts && bun run node_modules/@norskvideo/ctl-dev-kit/docs/light-pages.ts && bun run node_modules/@norskvideo/ctl-dev-kit/docs/journeys.ts",
|
|
@@ -1210,9 +1217,10 @@ ${studioLibraries}
|
|
|
1210
1217
|
// SRT-listener ingests bind inside the media engine and must be published as
|
|
1211
1218
|
// UDP (without /udp docker publishes TCP and the host can't reach Norsk's
|
|
1212
1219
|
// listener). srt-caller ingests dial out — no published port.
|
|
1220
|
+
// INGEST_PORT is the host side only: the listener inside the engine binds the
|
|
1221
|
+
// configured port whatever INGEST_PORT says.
|
|
1213
1222
|
if (config.input.transport === "srt-listener") {
|
|
1214
|
-
|
|
1215
|
-
mediaPorts.push("\${INGEST_PORT}:\${INGEST_PORT}/udp");
|
|
1223
|
+
mediaPorts.push(\`\\\${INGEST_PORT}:\${config.input.port}/udp\`);
|
|
1216
1224
|
}
|
|
1217
1225
|
|
|
1218
1226
|
const compose = {
|
|
@@ -1824,6 +1832,49 @@ exec bun run demo -- up --mode image --daemon reuse
|
|
|
1824
1832
|
`;
|
|
1825
1833
|
}
|
|
1826
1834
|
|
|
1835
|
+
function smokeSpecTs(ctx: ShapeContext): string {
|
|
1836
|
+
return `// The smoke tier: one journey through the built image, run by
|
|
1837
|
+
// @norskvideo/ctl-test-harness/smoke on PRs, main and the nightly bump.
|
|
1838
|
+
// smoke.yml builds the image and sets SMOKE_IMAGE_TAG; locally,
|
|
1839
|
+
// \`bun run build:image && bun run test:smoke\` with NORSK_LICENSE_FILE set.
|
|
1840
|
+
// The tag must be one the licence names (licenseTemplate.json).
|
|
1841
|
+
//
|
|
1842
|
+
// The camera1 sample goes to the SRT ingest. What it proves: the graph is up
|
|
1843
|
+
// and the ingest takes the feed. Grow the observations as the product takes
|
|
1844
|
+
// shape: they are what an unattended nightly bump is trusted on.
|
|
1845
|
+
import { test } from "bun:test";
|
|
1846
|
+
import { hashSlot } from "@norskvideo/ctl-test-harness/harness-config";
|
|
1847
|
+
import { runProductSmoke } from "@norskvideo/ctl-test-harness/smoke";
|
|
1848
|
+
|
|
1849
|
+
// The listener inside the media container (the configured default), which the
|
|
1850
|
+
// pump dials on the docker network.
|
|
1851
|
+
const LISTENER_PORT = 5001;
|
|
1852
|
+
// The host side of that publish, moved off 5001: other products' smokes (and a
|
|
1853
|
+
// running demo) hold it on a shared runner.
|
|
1854
|
+
const INGEST_HOST_PORT = 27001 + hashSlot("${ctx.name}", 40) * 4;
|
|
1855
|
+
|
|
1856
|
+
test(
|
|
1857
|
+
"${ctx.name}: the graph comes up and takes the SRT feed",
|
|
1858
|
+
() =>
|
|
1859
|
+
runProductSmoke("${ctx.name}", {
|
|
1860
|
+
product: {
|
|
1861
|
+
name: "${ctx.name}",
|
|
1862
|
+
register: { image: process.env.SMOKE_IMAGE_TAG ?? "${ctx.name}:dev" },
|
|
1863
|
+
},
|
|
1864
|
+
template: { name: "default" },
|
|
1865
|
+
params: [\`INGEST_PORT=\${INGEST_HOST_PORT}\`],
|
|
1866
|
+
hardware: "none",
|
|
1867
|
+
sources: [{ port: LISTENER_PORT, name: "input", streamId: "input", preset: "camera1" }],
|
|
1868
|
+
observe: [
|
|
1869
|
+
{ kind: "components", ids: ["ingest", "egest"] },
|
|
1870
|
+
{ kind: "srt-connected", componentId: "ingest" },
|
|
1871
|
+
],
|
|
1872
|
+
}),
|
|
1873
|
+
600_000,
|
|
1874
|
+
);
|
|
1875
|
+
`;
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1827
1878
|
function demoSpecTs(ctx: ShapeContext): string {
|
|
1828
1879
|
return `// The ${ctx.name} demo (fleet review 05-demo): the manifest's default
|
|
1829
1880
|
// template with the daemon's camera1 sample pumped into the SRT ingest. Run by
|
|
@@ -2221,6 +2272,7 @@ export const turnkey: ShapeModule = {
|
|
|
2221
2272
|
{ path: "scripts/with-display.sh", content: ctx.canon.withDisplay, executable: true },
|
|
2222
2273
|
{ path: "scripts/docs-handover.sh", content: DOCS_HANDOVER_SH, executable: true },
|
|
2223
2274
|
{ path: "tests/demo.spec.ts", content: demoSpecTs(ctx) },
|
|
2275
|
+
{ path: "tests/smoke.spec.ts", content: smokeSpecTs(ctx) },
|
|
2224
2276
|
{ path: "tests/unit/demo-spec.test.ts", content: DEMO_SPEC_TEST_TS },
|
|
2225
2277
|
{ path: "shared/package.json", content: sharedPackageJson(ctx) },
|
|
2226
2278
|
{ path: "shared/tsconfig.json", content: WORKSPACE_TSCONFIG },
|