@norskvideo/ctl-dev-kit 0.2.51 → 0.2.53

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.
@@ -20,7 +20,7 @@
20
20
  // workspace-symlinked and installed from the published tarball.
21
21
 
22
22
  import { execFileSync } from "node:child_process";
23
- import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
23
+ import { existsSync, lstatSync, readdirSync, readFileSync, statSync } from "node:fs";
24
24
  import { join } from "node:path";
25
25
  import { parseManifestSeed } from "@norskvideo/ctl-sdk/manifest-seed";
26
26
  import { checkTheme } from "../docs-theme/sync.ts";
@@ -369,16 +369,21 @@ const CHECKS_LOGS = /\bproductTemplateLogsProblems\b/;
369
369
  const SKIP_DIRS = new Set(["node_modules", ".git", "dist", "build", "lib", "coverage", ".wireit"]);
370
370
 
371
371
  function sourceFiles(dir: string, out: string[] = []): string[] {
372
- let names: string[];
373
- try {
374
- names = readdirSync(dir);
375
- } catch {
376
- return out;
377
- }
378
- for (const name of names) {
372
+ // `dir` is the repo root or an entry just stat'd as a directory: one the walk
373
+ // cannot list is a real failure, never an empty directory
374
+ for (const name of readdirSync(dir)) {
379
375
  if (SKIP_DIRS.has(name)) continue;
380
376
  const path = join(dir, name);
381
- const st = statSync(path);
377
+ let st: ReturnType<typeof statSync>;
378
+ try {
379
+ st = statSync(path);
380
+ } catch (e) {
381
+ // Only a symlink whose target is absent is skipped: a docs site's link to
382
+ // a doc-guide capture not generated yet (a fresh checkout). Anything else
383
+ // that stops the walk reading an entry is a real failure.
384
+ if ((e as NodeJS.ErrnoException).code === "ENOENT" && lstatSync(path).isSymbolicLink()) continue;
385
+ throw e;
386
+ }
382
387
  if (st.isDirectory()) sourceFiles(path, out);
383
388
  else if (/\.(ts|tsx)$/.test(name)) out.push(path);
384
389
  }
@@ -187,29 +187,52 @@ jobs:
187
187
  # their logs. The same host took four of that night's norsk image jobs down
188
188
  # the same way. Nothing said "this machine's docker is broken".
189
189
  #
190
+ # A containerised (DooD) runner must also be able to JOIN a new network:
191
+ # the harness attaches it to each instance's network to reach the media
192
+ # container. On 2026-10-07/08 ashton-nuc's runner container had lost its
193
+ # network sandbox files (it lived through a dockerd restart), so every
194
+ # `docker network connect` failed with "open .../resolv.conf: no such file
195
+ # or directory" while create still worked: commentary saw "Unable to
196
+ # connect" in every scenario, playout "could not join <instance>'s
197
+ # network", and probe -- which never joins -- passed on the same host.
198
+ #
190
199
  # The chain is not readable without root on these runners, so this asserts
191
- # the capability instead: create a throwaway network, remove it. One step,
192
- # its own name, so the jobs API attributes the failure to it rather than to
193
- # whatever composite step happened to be running.
194
- - name: Check this host's docker can still create a network
200
+ # the capabilities instead: create a throwaway network, join it when
201
+ # containerised, leave, remove it. One step, its own name, so the jobs API
202
+ # attributes the failure to it rather than to whatever composite step
203
+ # happened to be running.
204
+ - name: Check this host's docker can still create a network and attach the runner to it
195
205
  run: |
196
206
  set -uo pipefail
197
207
  net="preflight-${{ github.run_id }}-${{ github.run_attempt }}-$RANDOM"
198
- if err=$(docker network create "$net" 2>&1); then
199
- docker network rm "$net" >/dev/null 2>&1 || true
200
- echo "docker can create networks on $(hostname) -- ok"
201
- exit 0
208
+ if ! err=$(docker network create "$net" 2>&1); then
209
+ echo "::error::docker on this runner cannot create a network, so every container this suite starts would silently not exist -- the tests would fail for a reason that is not theirs. Host: $(hostname). Fix: \`sudo systemctl restart docker\` on that machine (it rebuilds the DOCKER/DOCKER-ISOLATION iptables chains), then re-run."
210
+ echo "$err"
211
+ echo "--- docker0 (a subnet other than 172.17.0.1/16 means it was re-addressed) ---"
212
+ ip -br addr show docker0 2>/dev/null || true
213
+ echo "--- networks and their subnets ---"
214
+ for n in $(docker network ls --format '{{.Name}}' 2>/dev/null); do
215
+ printf '%-28s ' "$n"
216
+ docker network inspect "$n" --format '{{range .IPAM.Config}}{{.Subnet}} {{end}}' 2>/dev/null || echo
217
+ done
218
+ exit 1
202
219
  fi
203
- echo "::error::docker on this runner cannot create a network, so every container this suite starts would silently not exist -- the tests would fail for a reason that is not theirs. Host: $(hostname). Fix: \`sudo systemctl restart docker\` on that machine (it rebuilds the DOCKER/DOCKER-ISOLATION iptables chains), then re-run."
204
- echo "$err"
205
- echo "--- docker0 (a subnet other than 172.17.0.1/16 means it was re-addressed) ---"
206
- ip -br addr show docker0 2>/dev/null || true
207
- echo "--- networks and their subnets ---"
208
- for n in $(docker network ls --format '{{.Name}}' 2>/dev/null); do
209
- printf '%-28s ' "$n"
210
- docker network inspect "$n" --format '{{range .IPAM.Config}}{{.Subnet}} {{end}}' 2>/dev/null || echo
211
- done
212
- exit 1
220
+ me="$(hostname)"
221
+ if docker inspect "$me" >/dev/null 2>&1; then
222
+ # Containerised: join the network exactly as the harness will.
223
+ if ! err=$(docker network connect "$net" "$me" 2>&1); then
224
+ docker network disconnect -f "$net" "$me" >/dev/null 2>&1 || true
225
+ docker network rm "$net" >/dev/null 2>&1 || true
226
+ name="$(docker inspect -f '{{.Name}}' "$me" 2>/dev/null | sed 's|^/||')"
227
+ echo "::error::this runner's container cannot join a new docker network, so the harness cannot reach any instance it starts -- the tests would fail as 'Unable to connect' / 'could not join', for a reason that is not theirs. Host: $(hostname) (container ${name:-$me}). Fix: on the docker host, \`docker restart ${name:-$me}\` once it is idle (it rebuilds the container's network sandbox), then re-run. ashton-nuc does this itself every 15 min (~steve/bin/runner-netcheck.sh, user timer runner-netcheck.timer)."
228
+ echo "$err"
229
+ exit 1
230
+ fi
231
+ docker network disconnect "$net" "$me" >/dev/null 2>&1 || true
232
+ echo "the runner container ($me) can join a new network -- ok"
233
+ fi
234
+ docker network rm "$net" >/dev/null 2>&1 || true
235
+ echo "docker can create networks on $(hostname) -- ok"
213
236
 
214
237
  # `product add --image` publishes the control plane on 127.0.0.1:14321. The
215
238
  # daemon means to reap it on shutdown (daemon.ts, model B) but only does so
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@norskvideo/ctl-dev-kit",
3
- "version": "0.2.51",
3
+ "version": "0.2.53",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./create-product": "./create-product/create-product.ts",