unoverse 0.1.33 → 0.1.35
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/lib/create.mjs +12 -1
- package/operator/lib/init.sh +67 -12
- package/package.json +1 -1
package/lib/create.mjs
CHANGED
|
@@ -31,6 +31,17 @@ async function ask(rl, q) {
|
|
|
31
31
|
* pre-encoded base64 `user:token` blob that docker config (and the starter's own
|
|
32
32
|
* `docr` setting) uses. Wrapping the second shape in base64 AGAIN is how a valid
|
|
33
33
|
* credential gets refused, so detect it and pass it through untouched. */
|
|
34
|
+
/** The raw dop_v1 token, whichever shape was pasted. docker login needs the raw form,
|
|
35
|
+
* so the base64 user:token blob is decoded before anything downstream sees it. */
|
|
36
|
+
function rawToken(token) {
|
|
37
|
+
if (/^[A-Za-z0-9+/]+=*$/.test(token) && !token.startsWith("dop_v1_")) {
|
|
38
|
+
const decoded = Buffer.from(token, "base64").toString("utf8");
|
|
39
|
+
const m = /^([\x20-\x7e]+):[\x20-\x7e]+$/.exec(decoded);
|
|
40
|
+
if (m) return m[1];
|
|
41
|
+
}
|
|
42
|
+
return token;
|
|
43
|
+
}
|
|
44
|
+
|
|
34
45
|
function registryAuth(token) {
|
|
35
46
|
if (/^[A-Za-z0-9+/]+=*$/.test(token)) {
|
|
36
47
|
const decoded = Buffer.from(token, "base64").toString("utf8");
|
|
@@ -280,7 +291,7 @@ export async function create(nameArg) {
|
|
|
280
291
|
const r = spawnSync("bash", [operatorScript, "init"], {
|
|
281
292
|
stdio: "inherit",
|
|
282
293
|
cwd: name,
|
|
283
|
-
env: { ...process.env, UNOVERSE_DOCR_TOKEN: token },
|
|
294
|
+
env: { ...process.env, UNOVERSE_DOCR_TOKEN: rawToken(token) },
|
|
284
295
|
});
|
|
285
296
|
if (r.status !== 0) {
|
|
286
297
|
fail(`setup did not finish. Run 'unoverse start'${name === "." ? "" : ` in ./${name}`} to pick it back up`);
|
package/operator/lib/init.sh
CHANGED
|
@@ -5,6 +5,49 @@
|
|
|
5
5
|
# (`npm i -g unoverse`); symlinking a per-project bash script into /usr/local/bin was the
|
|
6
6
|
# second CLI we set out to delete.
|
|
7
7
|
|
|
8
|
+
# ── The image download, as an experience ─────────────────────────────────────
|
|
9
|
+
#
|
|
10
|
+
# The pull starts the moment the token is accepted, so the minute spent answering
|
|
11
|
+
# questions is also the minute the images arrive. NOTHING writes to the terminal
|
|
12
|
+
# asynchronously — a progress bar racing a readline prompt corrupts what the developer
|
|
13
|
+
# is typing. The background half writes one line of STATE to a temp file; the wizard
|
|
14
|
+
# prints a status line synchronously between question groups, where output composes
|
|
15
|
+
# with input; the end of setup attaches with docker's own bars for whatever remains.
|
|
16
|
+
PULL_STATE=""
|
|
17
|
+
start_background_pull() {
|
|
18
|
+
PULL_STATE=$(mktemp)
|
|
19
|
+
(
|
|
20
|
+
imgs=$(docker compose -f "$ROOT/docker-compose.yml" config --images 2>/dev/null | sort -u)
|
|
21
|
+
total=$(printf '%s\n' "$imgs" | grep -c .)
|
|
22
|
+
n=0
|
|
23
|
+
for img in $imgs; do
|
|
24
|
+
short="${img##*/}"; short="${short%%:*}"
|
|
25
|
+
if docker image inspect "$img" >/dev/null 2>&1; then
|
|
26
|
+
n=$((n+1)); echo "$n $total ready $short" > "$PULL_STATE"; continue
|
|
27
|
+
fi
|
|
28
|
+
echo "$n $total pulling $short" > "$PULL_STATE"
|
|
29
|
+
docker pull "$img" >/dev/null 2>&1
|
|
30
|
+
n=$((n+1)); echo "$n $total pulled $short" > "$PULL_STATE"
|
|
31
|
+
done
|
|
32
|
+
echo "$total $total done -" > "$PULL_STATE"
|
|
33
|
+
) &
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# One dim line, printed only when the wizard is printing anyway. Never a redraw.
|
|
37
|
+
pull_status_line() {
|
|
38
|
+
[ -n "$PULL_STATE" ] && [ -s "$PULL_STATE" ] || return 0
|
|
39
|
+
local n total verb what
|
|
40
|
+
read -r n total verb what < "$PULL_STATE" 2>/dev/null || return 0
|
|
41
|
+
if [ "$verb" = "done" ]; then
|
|
42
|
+
echo -e " ${GREEN}⬇${NC} ${DIM}platform images: all $total downloaded${NC}"
|
|
43
|
+
elif [ "$verb" = "pulling" ]; then
|
|
44
|
+
echo -e " ${CYAN}⬇${NC} ${DIM}platform images: $n of $total · pulling $what…${NC}"
|
|
45
|
+
else
|
|
46
|
+
echo -e " ${CYAN}⬇${NC} ${DIM}platform images: $n of $total${NC}"
|
|
47
|
+
fi
|
|
48
|
+
echo ""
|
|
49
|
+
}
|
|
50
|
+
|
|
8
51
|
# First-run detection
|
|
9
52
|
check_first_run() {
|
|
10
53
|
if [ ! -f "$ROOT/.env" ]; then
|
|
@@ -115,6 +158,22 @@ cmd_init() {
|
|
|
115
158
|
done
|
|
116
159
|
fi
|
|
117
160
|
|
|
161
|
+
# THE DOWNLOAD STARTS NOW (see the block at the top of this file).
|
|
162
|
+
if [ "$DOCKER_OK" = "1" ]; then
|
|
163
|
+
local login_err
|
|
164
|
+
if login_err=$(echo "$DOCR_TOKEN" | docker login "$DOCR_REGISTRY" -u "$DOCR_TOKEN" --password-stdin 2>&1 >/dev/null); then
|
|
165
|
+
start_background_pull
|
|
166
|
+
echo ""
|
|
167
|
+
echo -e " ${CYAN}⬇${NC} ${DIM}Platform images are downloading in the background while you configure${NC}"
|
|
168
|
+
echo ""
|
|
169
|
+
else
|
|
170
|
+
# The REASON, not just the fact: a swallowed docker error left "login failed"
|
|
171
|
+
# undiagnosable when create had just validated the same credential.
|
|
172
|
+
warn "Registry login failed. Images will not pull until it is fixed"
|
|
173
|
+
echo "$login_err" | grep -vi "warning" | head -3 | sed 's/^/ /'
|
|
174
|
+
fi
|
|
175
|
+
fi
|
|
176
|
+
|
|
118
177
|
# A DEFAULT, because "from your admin" is meaningless when you are the admin. The
|
|
119
178
|
# platform ships no database (docker-compose has no postgres), so this points at one
|
|
120
179
|
# you run. Enter takes the conventional local one.
|
|
@@ -144,6 +203,7 @@ cmd_init() {
|
|
|
144
203
|
fi
|
|
145
204
|
fi
|
|
146
205
|
|
|
206
|
+
pull_status_line
|
|
147
207
|
# Redis, current values as defaults
|
|
148
208
|
local rd
|
|
149
209
|
rd=$(_env_cur REDIS_HOST); rd="${rd:-host.docker.internal}"
|
|
@@ -174,7 +234,7 @@ cmd_init() {
|
|
|
174
234
|
# a deployed universe ("there is no auth-off deployment"), and the platform enforces it
|
|
175
235
|
# rather than trusting this wizard: authConfig.ts refuses to start with auth off when
|
|
176
236
|
# NODE_ENV=production. So answering "no" here cannot produce an unprotected deployment.
|
|
177
|
-
|
|
237
|
+
pull_status_line
|
|
178
238
|
local cur_auth idp_prompt
|
|
179
239
|
cur_auth=$(_env_cur AUTH_ENABLED)
|
|
180
240
|
idp_prompt="[y/N]"
|
|
@@ -243,6 +303,7 @@ cmd_init() {
|
|
|
243
303
|
ok "Redis namespace: ${BOLD}${REDIS_NAMESPACE}${NC}"
|
|
244
304
|
|
|
245
305
|
# OpenAI (for Memory Server)
|
|
306
|
+
pull_status_line
|
|
246
307
|
local cur_oai
|
|
247
308
|
cur_oai=$(_env_cur OPENAI_API_KEY)
|
|
248
309
|
# NOT just the memory server: compose hands this to the unoverse service itself —
|
|
@@ -297,21 +358,15 @@ ENVEOF
|
|
|
297
358
|
|
|
298
359
|
ok ".env created"
|
|
299
360
|
|
|
300
|
-
#
|
|
301
|
-
#
|
|
361
|
+
# Attach to the background pull started when the token was accepted: layers already
|
|
362
|
+
# down show as complete, the rest stream docker's progress bars. Without a daemon the
|
|
363
|
+
# token is in .env, and `unoverse start` pulls on its first run.
|
|
302
364
|
if [ "$DOCKER_OK" = "1" ]; then
|
|
303
|
-
echo ""
|
|
304
|
-
echo -e " Logging in to DigitalOcean Container Registry..."
|
|
305
|
-
if echo "$DOCR_TOKEN" | docker login "$DOCR_REGISTRY" -u "$DOCR_TOKEN" --password-stdin &>/dev/null; then
|
|
306
|
-
ok "Logged in to DOCR"
|
|
307
|
-
else
|
|
308
|
-
fail "DOCR login failed. Check your token"
|
|
309
|
-
exit 1
|
|
310
|
-
fi
|
|
311
365
|
pull_missing_images
|
|
366
|
+
[ -n "$PULL_STATE" ] && rm -f "$PULL_STATE"
|
|
312
367
|
else
|
|
313
368
|
echo ""
|
|
314
|
-
info "Skipped the
|
|
369
|
+
info "Skipped the image download. ${BOLD}unoverse start${NC} does it once Docker is up"
|
|
315
370
|
fi
|
|
316
371
|
|
|
317
372
|
# Install to PATH
|
package/package.json
CHANGED