@norskvideo/ctl-dev-kit 0.1.69 → 0.1.71

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.
@@ -79,20 +79,20 @@ jobs:
79
79
  # HOST's, so registration times out at 60s with nothing in the log saying
80
80
  # why. The daemon's own detection stays the default; here the probe that
81
81
  # already knows simply says so.
82
- - name: Probe runner docker topology and set NORSK_TEST_HOST + NORSK_NET_REACH
82
+ - name: Probe runner docker topology and set NORSK_TEST_HOST + NORSK_TEST_NET
83
83
  run: |
84
84
  set -uo pipefail
85
85
  echo "hostname=$(hostname)"
86
86
  if docker inspect "$(hostname)" >/dev/null 2>&1; then
87
87
  echo "TOPO: hostname resolves to a container -> runner is containerized (DooD)"
88
88
  echo "NORSK_TEST_HOST=host.docker.internal" >> "$GITHUB_ENV"
89
- echo "NORSK_NET_REACH=direct" >> "$GITHUB_ENV"
89
+ echo "NORSK_TEST_NET=direct" >> "$GITHUB_ENV"
90
90
  echo "NORSK_CTL_PRODUCT_REACH=container-address" >> "$GITHUB_ENV"
91
91
  echo "NORSK_RUNNER_OWNS_DOCKER=false" >> "$GITHUB_ENV"
92
92
  else
93
93
  echo "TOPO: hostname is not a container -> runner is host-based"
94
94
  echo "NORSK_TEST_HOST=localhost" >> "$GITHUB_ENV"
95
- echo "NORSK_NET_REACH=publish" >> "$GITHUB_ENV"
95
+ echo "NORSK_TEST_NET=publish" >> "$GITHUB_ENV"
96
96
  echo "NORSK_CTL_PRODUCT_REACH=host" >> "$GITHUB_ENV"
97
97
  echo "NORSK_RUNNER_OWNS_DOCKER=true" >> "$GITHUB_ENV"
98
98
  fi
@@ -0,0 +1,104 @@
1
+ // Lint that a product's compose actually DECLARES the product to Studio.
2
+ //
3
+ // Studio names a product to the engine at the V2 licence handshake. Given no
4
+ // NORSK_PRODUCT_NAME it falls back to its baked default, "norsk-studio", and so
5
+ // demands a Studio entitlement rather than the product's own. A repo whose
6
+ // licence is cut for its own product then launches instances that are refused:
7
+ // Studio still serves its API, but every media node is refused, so SRT
8
+ // listeners never bind and the graph produces nothing.
9
+ //
10
+ // That failure is nearly unreadable from outside. It is not a crash and not a
11
+ // timeout at launch — the instance comes up "healthy" and only the media-
12
+ // dependent assertions fail, which reads as a broken workflow rather than a
13
+ // missing declaration. funke-pegasus shipped mis-declared from the day it was
14
+ // created and only surfaced when a licence re-mint stopped carrying a
15
+ // norsk-studio entry; reuters had declared its own name since 2026-07-28.
16
+ //
17
+ // check-template.ts is this lint's other half: it asserts the repo RECORDS the
18
+ // entitlement it needs, and this asserts the repo ASKS for the one it records.
19
+ // Either alone leaves the pair free to drift, which is exactly what happened.
20
+ import { readFileSync } from "node:fs";
21
+
22
+ /** Source with comments blanked out, so a mention of the key in prose cannot
23
+ * satisfy the lint. Walks the text rather than regex-replacing, so a `//`
24
+ * inside a string literal (a URL) is not mistaken for a comment. */
25
+ export function stripComments(source: string): string {
26
+ let out = "";
27
+ let i = 0;
28
+ while (i < source.length) {
29
+ const c = source[i];
30
+ const next = source[i + 1];
31
+ if (c === "/" && next === "/") {
32
+ while (i < source.length && source[i] !== "\n") i++;
33
+ continue;
34
+ }
35
+ if (c === "/" && next === "*") {
36
+ i += 2;
37
+ while (i < source.length && !(source[i] === "*" && source[i + 1] === "/")) i++;
38
+ i += 2;
39
+ continue;
40
+ }
41
+ if (c === '"' || c === "'" || c === "`") {
42
+ const quote = c;
43
+ out += c;
44
+ i++;
45
+ while (i < source.length && source[i] !== quote) {
46
+ if (source[i] === "\\") {
47
+ out += source[i];
48
+ i++;
49
+ }
50
+ if (i < source.length) {
51
+ out += source[i];
52
+ i++;
53
+ }
54
+ }
55
+ out += quote;
56
+ i++;
57
+ continue;
58
+ }
59
+ out += c;
60
+ i++;
61
+ }
62
+ return out;
63
+ }
64
+
65
+ const DECLARATION = /NORSK_PRODUCT_NAME\s*[:=]\s*(PRODUCT_NAME\b|"([^"]*)"|'([^']*)')/;
66
+
67
+ /** `templateSource` is the repo's product-template module — the one that builds
68
+ * the studio service's environment. `product` is the repo's PRODUCT_NAME. */
69
+ export function productNameProblems(templateSource: string, product: string): string[] {
70
+ const match = DECLARATION.exec(stripComments(templateSource));
71
+ if (!match) {
72
+ return [
73
+ `the studio service does not declare NORSK_PRODUCT_NAME, so Studio will ask for "norsk-studio" at the licence handshake instead of "${product}" — set NORSK_PRODUCT_NAME: PRODUCT_NAME in its environment`,
74
+ ];
75
+ }
76
+ const declared = match[2] ?? match[3];
77
+ // The PRODUCT_NAME constant is correct by construction; only a literal can
78
+ // name the wrong thing.
79
+ if (declared !== undefined && declared !== product) {
80
+ return [`NORSK_PRODUCT_NAME is declared as "${declared}" but this repo's product is "${product}"`];
81
+ }
82
+ return [];
83
+ }
84
+
85
+ if (import.meta.main) {
86
+ const [file, product] = process.argv.slice(2);
87
+ if (!file || !product) {
88
+ console.error("usage: check-product-name.ts <product-template-source> <product-name>");
89
+ process.exit(2);
90
+ }
91
+ let contents: string;
92
+ try {
93
+ contents = readFileSync(file, "utf8");
94
+ } catch {
95
+ console.error(`product-name: cannot read ${file}`);
96
+ process.exit(1);
97
+ }
98
+ const problems = productNameProblems(contents, product);
99
+ if (problems.length) {
100
+ for (const p of problems) console.error(`product-name: ${p}`);
101
+ process.exit(1);
102
+ }
103
+ console.log(`product-name: ${file} declares ${product} to Studio`);
104
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@norskvideo/ctl-dev-kit",
3
- "version": "0.1.69",
3
+ "version": "0.1.71",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./create-product": "./create-product/create-product.ts",
@@ -13,6 +13,7 @@
13
13
  "./doc-guide/prose-bundle": "./doc-guide/prose-bundle.js",
14
14
  "./docs/path-existence": "./docs/path-existence.ts",
15
15
  "./docs/splice-generated": "./docs/splice-generated.ts",
16
+ "./licence/check-product-name": "./licence/check-product-name.ts",
16
17
  "./licence/check-template": "./licence/check-template.ts",
17
18
  "./package.json": "./package.json",
18
19
  "./testing/byte-snapshot": "./testing/byte-snapshot.ts",