@norskvideo/ctl-dev-kit 0.1.1 → 0.1.3
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/build/flake.nix +71 -16
- package/build/refresh-ctl-pin.sh +39 -0
- package/local-dev/README.md +99 -4
- package/package.json +1 -1
package/build/flake.nix
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
# Product build shell — single-sourced in @norskvideo/ctl-dev-kit and
|
|
2
|
-
# verbatim into each split product repo (nix needs a flake.nix at the repo
|
|
3
|
-
# for `nix develop`; it can't pull one from an npm package at CI bootstrap).
|
|
4
|
-
# copy is drift-gated (Workstream I), same model as the fenced CLAUDE.md core.
|
|
1
|
+
# Product build + dev shell — single-sourced in @norskvideo/ctl-dev-kit and
|
|
2
|
+
# copied verbatim into each split product repo (nix needs a flake.nix at the repo
|
|
3
|
+
# root for `nix develop`; it can't pull one from an npm package at CI bootstrap).
|
|
4
|
+
# The copy is drift-gated (Workstream I), same model as the fenced CLAUDE.md core.
|
|
5
5
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
6
|
+
# Two shells:
|
|
7
|
+
# nix develop -> build tools only (bun, cargo/rustc, git). This is what
|
|
8
|
+
# CI (build-image) uses; it must stay lean and must NOT
|
|
9
|
+
# depend on fetching the ctl binary.
|
|
10
|
+
# nix develop .#dev -> the above PLUS the pinned `norsk-ctl` daemon on PATH,
|
|
11
|
+
# for the local product dev loop (serve + product add).
|
|
12
|
+
#
|
|
13
|
+
# `norsk-ctl` is the released daemon binary pulled from the S3 channel and pinned
|
|
14
|
+
# by version+hash (reproducible). It is NOT built from source here — a product
|
|
15
|
+
# dev consumes the shipped ctl exactly as a customer does. Bump with:
|
|
16
|
+
# packages/dev-kit/build/refresh-ctl-pin.sh (writes ctlVersion + hashes)
|
|
10
17
|
{
|
|
11
|
-
description = "norsk-ctl product build shell";
|
|
18
|
+
description = "norsk-ctl product build + dev shell";
|
|
12
19
|
|
|
13
20
|
inputs = {
|
|
14
21
|
nixpkgs.url = "github:NixOS/nixpkgs/d233902339c02a9c334e7e593de68855ad26c4cb"; # nixpkgs-unstable 2026-05-15, bun 1.3.13
|
|
@@ -18,17 +25,65 @@
|
|
|
18
25
|
let
|
|
19
26
|
systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
|
|
20
27
|
forAllSystems = f: builtins.listToAttrs (map (s: { name = s; value = f s; }) systems);
|
|
28
|
+
|
|
29
|
+
# --- norsk-ctl channel pin -------------------------------------------
|
|
30
|
+
# The released daemon, one build per platform. Bump these together.
|
|
31
|
+
ctlVersion = "0.1.0-2026-07-27-3165484";
|
|
32
|
+
ctlBase = "https://s3.eu-west-1.amazonaws.com/norsk.video/norsk-ctl";
|
|
33
|
+
ctlAsset = {
|
|
34
|
+
"x86_64-linux" = { plat = "linux-x64"; hash = "sha256-11vl/SsWlQnxt+yNl9lCcbOI/uJh1fcbKKnHSYHt2PY="; };
|
|
35
|
+
"aarch64-linux" = { plat = "linux-arm64"; hash = "sha256-AhrpIdXsw6cTzobfECfirKAIDnx01k0PQeylTfwIUJg="; };
|
|
36
|
+
"aarch64-darwin" = { plat = "darwin-arm64"; hash = "sha256-l17fqyicZa3SZLkmUpisZIJ3xWf94JOeuXDZrpoRGic="; };
|
|
37
|
+
"x86_64-darwin" = { plat = "darwin-x64"; hash = "sha256-wYEKu0ITDpBONMnig4aqzEQ1ZgPG17JnhJZoGiA5MKc="; };
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
mkCtl = system:
|
|
41
|
+
let
|
|
42
|
+
pkgs = import nixpkgs { inherit system; };
|
|
43
|
+
asset = ctlAsset.${system};
|
|
44
|
+
in
|
|
45
|
+
pkgs.stdenv.mkDerivation {
|
|
46
|
+
pname = "norsk-ctl";
|
|
47
|
+
version = ctlVersion;
|
|
48
|
+
src = pkgs.fetchurl {
|
|
49
|
+
url = "${ctlBase}/${ctlVersion}/norsk-ctl-${ctlVersion}-${asset.plat}";
|
|
50
|
+
hash = asset.hash;
|
|
51
|
+
};
|
|
52
|
+
dontUnpack = true;
|
|
53
|
+
# bun single-file executables embed a trailing payload; stripping
|
|
54
|
+
# corrupts them, and on Linux the raw binary needs its interpreter +
|
|
55
|
+
# libstdc++ rpath patched to the nix store.
|
|
56
|
+
dontStrip = true;
|
|
57
|
+
nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.autoPatchelfHook ];
|
|
58
|
+
buildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.stdenv.cc.cc.lib ];
|
|
59
|
+
installPhase = ''
|
|
60
|
+
runHook preInstall
|
|
61
|
+
install -Dm755 "$src" "$out/bin/norsk-ctl"
|
|
62
|
+
runHook postInstall
|
|
63
|
+
'';
|
|
64
|
+
};
|
|
21
65
|
in {
|
|
66
|
+
packages = forAllSystems (system: {
|
|
67
|
+
norsk-ctl = mkCtl system;
|
|
68
|
+
});
|
|
69
|
+
|
|
22
70
|
devShells = forAllSystems (system:
|
|
23
|
-
let
|
|
71
|
+
let
|
|
72
|
+
pkgs = import nixpkgs { inherit system; };
|
|
73
|
+
buildTools = [
|
|
74
|
+
pkgs.bun
|
|
75
|
+
pkgs.cargo # builds the native product-signer addon (probe/native)
|
|
76
|
+
pkgs.rustc
|
|
77
|
+
pkgs.git
|
|
78
|
+
];
|
|
24
79
|
in {
|
|
80
|
+
# CI (build-image) uses this — lean, no ctl fetch.
|
|
25
81
|
default = pkgs.mkShell {
|
|
26
|
-
buildInputs =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
];
|
|
82
|
+
buildInputs = buildTools;
|
|
83
|
+
};
|
|
84
|
+
# Local product dev loop — build tools + the pinned daemon on PATH.
|
|
85
|
+
dev = pkgs.mkShell {
|
|
86
|
+
buildInputs = buildTools ++ [ (mkCtl system) ];
|
|
32
87
|
};
|
|
33
88
|
});
|
|
34
89
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Repin the norsk-ctl daemon in flake.nix to a channel version. Resolves the
|
|
3
|
+
# version (default: the `latest` channel), fetches each platform's sha256
|
|
4
|
+
# sidecar, converts to SRI, and rewrites `ctlVersion` + the four `hash =` lines
|
|
5
|
+
# in flake.nix in place. Run from anywhere; targets the flake.nix beside it.
|
|
6
|
+
#
|
|
7
|
+
# refresh-ctl-pin.sh # pin to the current `latest`
|
|
8
|
+
# refresh-ctl-pin.sh 0.1.0-2026-07-27-... # pin to an explicit version
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
|
+
flake="$here/flake.nix"
|
|
13
|
+
base="https://s3.eu-west-1.amazonaws.com/norsk.video/norsk-ctl"
|
|
14
|
+
|
|
15
|
+
ver="${1:-$(curl -fsSL "$base/latest")}"
|
|
16
|
+
echo "pinning norsk-ctl -> $ver"
|
|
17
|
+
|
|
18
|
+
declare -A plat=(
|
|
19
|
+
[x86_64-linux]=linux-x64
|
|
20
|
+
[aarch64-linux]=linux-arm64
|
|
21
|
+
[aarch64-darwin]=darwin-arm64
|
|
22
|
+
[x86_64-darwin]=darwin-x64
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# nix keys the ctlAsset attrset by system; rewrite each system's hash line. The
|
|
26
|
+
# hash lines live in the `ctlAsset = { ... }` block, one per platform string.
|
|
27
|
+
for sys in "${!plat[@]}"; do
|
|
28
|
+
p="${plat[$sys]}"
|
|
29
|
+
hex="$(curl -fsSL "$base/$ver/norsk-ctl-$ver-$p.sha256" | awk '{print $1}')"
|
|
30
|
+
[ -n "$hex" ] || { echo "no sha256 sidecar for $p" >&2; exit 1; }
|
|
31
|
+
sri="$(nix hash convert --hash-algo sha256 --to sri "$hex")"
|
|
32
|
+
# Replace the hash on the line that mentions this platform's plat string.
|
|
33
|
+
perl -0pi -e "s{(plat = \"$p\";\\s*hash = \")[^\"]*(\")}{\${1}$sri\${2}}" "$flake"
|
|
34
|
+
echo " $sys ($p): $sri"
|
|
35
|
+
done
|
|
36
|
+
|
|
37
|
+
perl -0pi -e "s{(ctlVersion = \")[^\"]*(\")}{\${1}$ver\${2}}" "$flake"
|
|
38
|
+
echo "updated $flake"
|
|
39
|
+
echo "next: copy this flake.nix into each split product repo root (or re-run the split)"
|
package/local-dev/README.md
CHANGED
|
@@ -1,9 +1,62 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Developing a split product repo
|
|
2
|
+
|
|
3
|
+
A product repo (funke-pegasus, playout, probe, commentary, studio) is
|
|
4
|
+
self-contained: it consumes ctl and the Norsk runtime as **published
|
|
5
|
+
packages/images**, and needs no norsk-ctl source checkout to build, launch, or
|
|
6
|
+
test. This is the whole point of the split — you clone the product and go.
|
|
7
|
+
|
|
8
|
+
## Running ctl — the daemon
|
|
9
|
+
|
|
10
|
+
`norsk-ctl` (the daemon + CLI that launches product instances) is **not** an npm
|
|
11
|
+
dependency; it is the released binary, pinned by version+hash in the repo's
|
|
12
|
+
`flake.nix` (single-sourced from `@norskvideo/ctl-dev-kit`). The dev shell puts
|
|
13
|
+
it on `PATH`:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
nix develop .#dev # build tools (bun, cargo/rustc, git) + the pinned norsk-ctl
|
|
17
|
+
# nix develop # build-only shell — no ctl (this is what CI build-image uses)
|
|
18
|
+
|
|
19
|
+
norsk-ctl serve # daemon on :8333, oauth2 proxy on :9443
|
|
20
|
+
norsk-ctl --version # confirm the pinned build
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The binary is fetched from the S3 channel and patched for the local system
|
|
24
|
+
(`autoPatchelfHook` on Linux/NixOS, plain install on macOS). To move the pin,
|
|
25
|
+
bump `ctlVersion` + the four platform hashes in `flake.nix` (or run
|
|
26
|
+
`packages/dev-kit/build/refresh-ctl-pin.sh` in the monorepo).
|
|
27
|
+
|
|
28
|
+
## The two dev loops
|
|
29
|
+
|
|
30
|
+
**Inner loop (fast, no image build)** — run the backend from source and register
|
|
31
|
+
it as a `kind: dev` product, so edits to the backend / workflow / components land
|
|
32
|
+
without building a container:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
bun install
|
|
36
|
+
bun run dev # backend + frontend (Vite)
|
|
37
|
+
norsk-ctl product add --dev-url http://localhost:<backendPort>
|
|
38
|
+
norsk-ctl instance launch-template <id> --template <t> --hardware none
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Outer loop (real container)** — rebuild the product image and reload it into
|
|
42
|
+
the live daemon, with pin + segfault guards. This is `deployment/iterate.sh`:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
NORSK_LICENSE_FILE=/path/to/license.json bun run iterate # needs a running daemon + GPU
|
|
46
|
+
HARDWARE=none NORSK_LICENSE_FILE=... bun run iterate # no GPU reservation
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`test:integration` uses the same daemon path but against the **released** ctl
|
|
50
|
+
(via `NORSK_CTL_BINARY`), exactly as CI does — see `.github/workflows/integration.yml`.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
# Advanced overrides
|
|
2
55
|
|
|
3
|
-
A product repo consumes ctl and the Norsk runtime as published packages/images.
|
|
4
56
|
To develop a product against **un-published** ctl code or a **locally-built**
|
|
5
|
-
media server, there are
|
|
6
|
-
leaves the default (registry/pinned) path untouched when unset.
|
|
57
|
+
media server, there are three independent override layers. Each is opt-in and
|
|
58
|
+
leaves the default (registry/pinned) path untouched when unset. They compose:
|
|
59
|
+
changing the daemon *and* a ctl library it exposes means layers 1 + 3 together.
|
|
7
60
|
|
|
8
61
|
## 1. The npm layer — local `@norskvideo/ctl-*` checkouts
|
|
9
62
|
|
|
@@ -43,3 +96,45 @@ bun run --cwd . iterate # or the product's launch/iterate entry
|
|
|
43
96
|
```
|
|
44
97
|
|
|
45
98
|
Leave the hooks unset to launch the pinned tags the product declares.
|
|
99
|
+
|
|
100
|
+
## 3. The daemon layer — run ctl from a source checkout (`../norsk-ctl`)
|
|
101
|
+
|
|
102
|
+
Use this when you are changing the **daemon itself** (packages/norsk-ctl) and
|
|
103
|
+
want the product to launch through your build instead of the pinned binary. The
|
|
104
|
+
daemon is a single process on `:8333` — where you start it from is irrelevant, so
|
|
105
|
+
just run it out of your checkout and drive it with the same checkout's CLI. Skip
|
|
106
|
+
`nix develop .#dev` (its pinned `norsk-ctl` would shadow yours); the plain
|
|
107
|
+
`nix develop` shell is enough on the product side.
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
# 1. daemon, from your ctl checkout (root `cli` script -> packages/norsk-ctl cli)
|
|
111
|
+
( cd ../norsk-ctl && bun run cli serve )
|
|
112
|
+
|
|
113
|
+
# 2. product backend, from the product repo
|
|
114
|
+
bun run dev
|
|
115
|
+
|
|
116
|
+
# 3. register + launch, using the SOURCE cli against the SOURCE daemon
|
|
117
|
+
bun run --cwd ../norsk-ctl cli product add --dev-url http://localhost:<backendPort>
|
|
118
|
+
bun run --cwd ../norsk-ctl cli instance launch-template demo --template <t> --hardware none
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
No linking is needed for this — you are running the daemon *code* directly. Pair
|
|
122
|
+
with layer 1 (`dev-link.sh`) only if you also changed a `@norskvideo/ctl-*`
|
|
123
|
+
library the product *compiles* against.
|
|
124
|
+
|
|
125
|
+
### Integration tests against source ctl
|
|
126
|
+
|
|
127
|
+
The harness spawns the daemon from `NORSK_CTL_BINARY` as `<that> serve …`. A split
|
|
128
|
+
repo has no in-workspace ctl source for it to auto-discover, so point that env at
|
|
129
|
+
a one-line wrapper that forwards to your checkout's CLI:
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
printf '#!/usr/bin/env bash\nexec bun run --cwd %s cli "$@"\n' "$(cd ../norsk-ctl && pwd)" > /tmp/norsk-ctl-src
|
|
133
|
+
chmod +x /tmp/norsk-ctl-src
|
|
134
|
+
NORSK_CTL_BINARY=/tmp/norsk-ctl-src NORSK_LICENSE_FILE=/path/to/license.json bun run test:integration
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The wrapper forwards `serve` / `product add` / everything, so the whole slow tier
|
|
138
|
+
runs against `../norsk-ctl`. (`NORSK_CTL_BINARY` resolution lives in
|
|
139
|
+
`@norskvideo/ctl-test-harness`'s `cli-command.ts`: explicit path → in-workspace
|
|
140
|
+
source → `norsk-ctl` on PATH.)
|