@norskvideo/ctl-dev-kit 0.1.71 → 0.1.73
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/conventions/checks.yml
CHANGED
|
@@ -78,16 +78,27 @@ jobs:
|
|
|
78
78
|
bun run docs:check
|
|
79
79
|
'
|
|
80
80
|
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
81
|
+
# The two halves of one licence guarantee, run together because they only
|
|
82
|
+
# work as a pair: check-template asserts this repo RECORDS the entitlement
|
|
83
|
+
# it needs, and check-product-name asserts it ASKS for the one it records.
|
|
84
|
+
#
|
|
85
|
+
# Either alone leaves them free to drift. funke-pegasus recorded
|
|
86
|
+
# funke-pegasus and asked for "norsk-studio" -- Studio's baked default,
|
|
87
|
+
# used whenever NORSK_PRODUCT_NAME is unset -- for its entire life. The
|
|
88
|
+
# template check was green throughout, because the template was never the
|
|
89
|
+
# wrong half. What that cost: the handshake was refused, so every media
|
|
90
|
+
# node was refused, so no SRT listener bound, while the instance reported
|
|
91
|
+
# healthy and Studio served its API. It reads as a broken workflow, and it
|
|
92
|
+
# took most of a day to find.
|
|
93
|
+
#
|
|
94
|
+
# PRODUCT_NAME is read ONCE and handed to both: two readings could
|
|
95
|
+
# disagree, and a lint that passes while naming the wrong product is worse
|
|
96
|
+
# than no lint. Cheap, no secrets, every PR.
|
|
86
97
|
#
|
|
87
98
|
# The image name is CI's own rule: PUBLISH_IMAGE when set, else the build
|
|
88
99
|
# script's IMAGE_TAG default, tag stripped -- a licence matches the repo
|
|
89
100
|
# part alone, never the tag.
|
|
90
|
-
- name: Check
|
|
101
|
+
- name: Check this repo records, and asks for, its own licence
|
|
91
102
|
run: |
|
|
92
103
|
set -euo pipefail
|
|
93
104
|
product="$(sed -nE 's/.*PRODUCT_NAME[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/p' shared/src/version.ts | head -1)"
|
|
@@ -102,6 +113,13 @@ jobs:
|
|
|
102
113
|
nix develop .#build --command bun \
|
|
103
114
|
node_modules/@norskvideo/ctl-dev-kit/licence/check-template.ts \
|
|
104
115
|
licenseTemplate.json "$product" "$image"
|
|
116
|
+
# The compose the product renders is where the declaration has to be;
|
|
117
|
+
# the check exits 1 on an unreadable file rather than passing quietly,
|
|
118
|
+
# so a repo that moves this module fails here instead of silently
|
|
119
|
+
# dropping the gate.
|
|
120
|
+
nix develop .#build --command bun \
|
|
121
|
+
node_modules/@norskvideo/ctl-dev-kit/licence/check-product-name.ts \
|
|
122
|
+
shared/src/product-template.ts "$product"
|
|
105
123
|
|
|
106
124
|
# Report this pipeline's result to the aggregated product CI dashboard
|
|
107
125
|
# (id3as/ci-workflows) instead of posting its own pony — the dashboard renders
|
|
@@ -114,8 +114,11 @@ jobs:
|
|
|
114
114
|
- name: Open (or update) the pin-freshness PR
|
|
115
115
|
if: steps.bump.outputs.changed == '1'
|
|
116
116
|
env:
|
|
117
|
-
|
|
117
|
+
API_TOKEN: ${{ secrets.CI_DISPATCH_TOKEN }}
|
|
118
118
|
GATE: ${{ steps.gate.outcome }}
|
|
119
|
+
# Through the env, never interpolated into the script below: see the
|
|
120
|
+
# heredoc comment for what happens when it is.
|
|
121
|
+
MOVED: ${{ steps.bump.outputs.moved }}
|
|
119
122
|
run: |
|
|
120
123
|
set -euo pipefail
|
|
121
124
|
branch="chore/sync-ctl-packages"
|
|
@@ -130,18 +133,24 @@ jobs:
|
|
|
130
133
|
|
|
131
134
|
if [ "$GATE" = "success" ]; then
|
|
132
135
|
verdict="Gate green: check:drift, lint, typecheck and unit tests all pass on the new pins."
|
|
133
|
-
draft=
|
|
136
|
+
draft=false
|
|
134
137
|
else
|
|
135
138
|
verdict="**Gate red** — the new pins do not fit this product as-is. Adopting them is real engineering, not a merge."
|
|
136
|
-
draft=
|
|
139
|
+
draft=true
|
|
137
140
|
fi
|
|
138
141
|
|
|
142
|
+
# $MOVED, not the expression that produced it. This heredoc is unquoted
|
|
143
|
+
# so $verdict expands, which means its literal text is scanned for
|
|
144
|
+
# command substitution too -- and the moved-pin list names every package
|
|
145
|
+
# in backticks. Pasted in directly, each name RAN (exit 127, no PR,
|
|
146
|
+
# every morning since this workflow shipped). Bash does not rescan an
|
|
147
|
+
# expansion's result, so through the env the same backticks are inert.
|
|
139
148
|
body="$(cat <<EOF
|
|
140
149
|
Automated by \`sync-ctl-packages\`.
|
|
141
150
|
|
|
142
151
|
## Pins moved
|
|
143
152
|
|
|
144
|
-
$
|
|
153
|
+
$MOVED
|
|
145
154
|
|
|
146
155
|
## What the gate proved
|
|
147
156
|
|
|
@@ -153,10 +162,24 @@ jobs:
|
|
|
153
162
|
EOF
|
|
154
163
|
)"
|
|
155
164
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
165
|
+
# gh is not on the self-hosted runner PATH -- it lives only inside
|
|
166
|
+
# `nix develop`, and this step runs outside it -- so create/update the
|
|
167
|
+
# PR straight against the REST API with the same PAT that pushed the
|
|
168
|
+
# branch. This is the identical fix sync-dev-kit already carries and
|
|
169
|
+
# documents; it was applied to one sibling convention and not its twin,
|
|
170
|
+
# so this step failed with exit 127 in every product repo. curl and jq
|
|
171
|
+
# ARE on the host PATH (the pin-resolve step above uses them).
|
|
172
|
+
title="chore: sync the ctl-* pins to their newest published versions"
|
|
173
|
+
repo="${{ github.repository }}"; owner="${repo%%/*}"
|
|
174
|
+
api="https://api.github.com/repos/$repo/pulls"
|
|
175
|
+
curl_api=(--fail-with-body -sS -H "Authorization: Bearer $API_TOKEN" -H "Accept: application/vnd.github+json")
|
|
176
|
+
existing="$(curl "${curl_api[@]}" "$api?head=$owner:$branch&state=open" | jq -r '.[0].number // empty')"
|
|
177
|
+
if [ -n "$existing" ]; then
|
|
178
|
+
# draft is not settable by PATCH; the standing PR keeps whichever
|
|
179
|
+
# state it opened in and the refreshed body carries the verdict.
|
|
180
|
+
curl "${curl_api[@]}" -X PATCH "$api/$existing" \
|
|
181
|
+
--data "$(jq -nc --arg t "$title" --arg b "$body" '{title:$t, body:$b}')" >/dev/null
|
|
160
182
|
else
|
|
161
|
-
|
|
183
|
+
curl "${curl_api[@]}" -X POST "$api" \
|
|
184
|
+
--data "$(jq -nc --arg t "$title" --arg b "$body" --arg h "$branch" --argjson d "$draft" '{title:$t, body:$b, head:$h, base:"main", draft:$d}')" >/dev/null
|
|
162
185
|
fi
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Convention workflows carry real shell scripts inside YAML, and the two live in
|
|
2
|
+
// different worlds: the runner's bare PATH outside `nix develop`, a single-quoted
|
|
3
|
+
// word inside `bash -c '...'`. The guards over those hazards all need the same
|
|
4
|
+
// question answered first — is this line inside a quoted block or not — so it is
|
|
5
|
+
// asked in one place.
|
|
6
|
+
|
|
7
|
+
/** 1-indexed line numbers inside a multi-line `bash -c '` block, which ends at a
|
|
8
|
+
* line that is just `'`. A one-liner closing its own quote (`bash -c 'a; b'`)
|
|
9
|
+
* opens no block — it is already balanced. */
|
|
10
|
+
export function bashBlockLines(yaml: string): Set<number> {
|
|
11
|
+
const OPEN = "bash -c '";
|
|
12
|
+
const inside = new Set<number>();
|
|
13
|
+
let open = false;
|
|
14
|
+
yaml.split("\n").forEach((text, i) => {
|
|
15
|
+
if (!open) {
|
|
16
|
+
const at = text.indexOf(OPEN);
|
|
17
|
+
if (at >= 0 && !text.slice(at + OPEN.length).includes("'")) open = true;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (text.trim() === "'") {
|
|
21
|
+
open = false;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
inside.add(i + 1);
|
|
25
|
+
});
|
|
26
|
+
return inside;
|
|
27
|
+
}
|