ryugi-artifacts 1.7.0 → 1.7.2
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/dist/start-server.sh +89 -9
- package/dist/viewer/index.js +7 -7
- package/package.json +1 -1
package/dist/start-server.sh
CHANGED
|
@@ -92,11 +92,59 @@ PID_FILE="$STATE_DIR/server.pid"
|
|
|
92
92
|
LOG_FILE="$STATE_DIR/server.log"
|
|
93
93
|
SERVER_ID_FILE="$STATE_DIR/server-instance-id"
|
|
94
94
|
INFO_FILE="$STATE_DIR/server-info"
|
|
95
|
+
VERSION_FILE="$STATE_DIR/server-version"
|
|
95
96
|
OWNERS_FILE="$STATE_DIR/owners"
|
|
96
97
|
mkdir -p "$STATE_DIR"
|
|
97
98
|
[[ -f "$STATE_DIR/.gitignore" ]] || printf '*\n' > "$STATE_DIR/.gitignore"
|
|
98
99
|
|
|
99
|
-
|
|
100
|
+
RELEASES_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/ryugi/artifacts"
|
|
101
|
+
LATEST_CHECK_MS=$((24 * 60 * 60 * 1000))
|
|
102
|
+
RETRY_CHECK_MS=$((60 * 60 * 1000))
|
|
103
|
+
SERVER_VERSION=""
|
|
104
|
+
|
|
105
|
+
# Modes: "cached" prints the release npm named within the last day; "checked <version>" records
|
|
106
|
+
# what npm just said. When npm or the install fails, "installed" falls back to the newest release
|
|
107
|
+
# already installed and records it so npm is asked again in an hour, not on every start.
|
|
108
|
+
latest_version() {
|
|
109
|
+
node -e '(() => {
|
|
110
|
+
const fs = require("node:fs");
|
|
111
|
+
const path = require("node:path");
|
|
112
|
+
const [releases, maxAge, retryAfter, mode, fresh] = process.argv.slice(1);
|
|
113
|
+
const file = path.join(releases, "latest.json");
|
|
114
|
+
const valid = (v) => /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(v || "");
|
|
115
|
+
const record = (version, checkedAt) => {
|
|
116
|
+
fs.mkdirSync(releases, { recursive: true });
|
|
117
|
+
fs.writeFileSync(`${file}.${process.pid}`, JSON.stringify({ version, checkedAt }));
|
|
118
|
+
fs.renameSync(`${file}.${process.pid}`, file);
|
|
119
|
+
};
|
|
120
|
+
if (mode === "cached") {
|
|
121
|
+
try {
|
|
122
|
+
const { version, checkedAt } = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
123
|
+
if (valid(version) && Date.now() - checkedAt < Number(maxAge)) console.log(version);
|
|
124
|
+
} catch {}
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (mode === "checked" && valid(fresh)) {
|
|
128
|
+
record(fresh, Date.now());
|
|
129
|
+
return console.log(fresh);
|
|
130
|
+
}
|
|
131
|
+
const parts = (v) => v.split(/[-+]/)[0].split(".").map(Number);
|
|
132
|
+
const newer = (a, b) => { const x = parts(a), y = parts(b); for (let i = 0; i < 3; i++) if (x[i] !== y[i]) return x[i] - y[i]; return 0; };
|
|
133
|
+
let installed = [];
|
|
134
|
+
try { installed = fs.readdirSync(releases).filter((v) => valid(v) && fs.existsSync(path.join(releases, v, "node_modules/ryugi-artifacts/dist/server.cjs"))); } catch {}
|
|
135
|
+
const newest = installed.sort(newer).pop();
|
|
136
|
+
if (!newest) return;
|
|
137
|
+
record(newest, Date.now() - Number(maxAge) + Number(retryAfter));
|
|
138
|
+
console.log(newest);
|
|
139
|
+
})()' "$RELEASES_DIR" "$LATEST_CHECK_MS" "$RETRY_CHECK_MS" "$@"
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
use_release() {
|
|
143
|
+
SERVER_VERSION="$1"
|
|
144
|
+
SERVER="$RELEASES_DIR/$1/node_modules/ryugi-artifacts/dist/server.cjs"
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
# A local build (pnpm build:server) wins; otherwise run the newest ryugi-artifacts release,
|
|
100
148
|
# installed once per version. Runs before the project lock: a slow install must not outlive
|
|
101
149
|
# the lock's stale threshold. npm installs into a staging dir that is renamed into place;
|
|
102
150
|
# rename(2) refuses a non-empty target, so a concurrent start that finished first keeps its install.
|
|
@@ -105,16 +153,27 @@ resolve_server() {
|
|
|
105
153
|
SERVER="$SCRIPT_DIR/server.cjs"
|
|
106
154
|
return 0
|
|
107
155
|
fi
|
|
108
|
-
local version cache staging
|
|
109
|
-
version="$(
|
|
110
|
-
|
|
111
|
-
|
|
156
|
+
local version cache staging fallback
|
|
157
|
+
version="$(latest_version cached)"
|
|
158
|
+
[[ -n "$version" ]] || version="$(latest_version checked "$(npm view ryugi-artifacts version --prefer-online --fetch-retries=0 --fetch-timeout=10000 2>/dev/null | tail -1 | tr -d '[:space:]')")"
|
|
159
|
+
if [[ -z "$version" ]]; then
|
|
160
|
+
node -e 'console.log(JSON.stringify({ error: `Could not reach npm for the latest ryugi-artifacts; the first start needs network access and a writable ${process.argv[1]}, so rerun outside the sandbox.` }))' "$RELEASES_DIR"
|
|
161
|
+
return 1
|
|
162
|
+
fi
|
|
163
|
+
use_release "$version"
|
|
164
|
+
cache="$RELEASES_DIR/$version"
|
|
112
165
|
[[ -f "$SERVER" ]] && return 0
|
|
113
166
|
staging="$cache.install.$$"
|
|
114
167
|
rm -rf "$staging"
|
|
115
168
|
mkdir -p "$staging"
|
|
116
169
|
if ! npm install --prefix "$staging" --no-save --no-package-lock --no-audit --no-fund --loglevel=error \
|
|
117
170
|
"ryugi-artifacts@$version" > "$staging.log" 2>&1 || [[ ! -f "$staging/node_modules/ryugi-artifacts/dist/server.cjs" ]]; then
|
|
171
|
+
fallback="$(latest_version installed)"
|
|
172
|
+
if [[ -n "$fallback" ]]; then
|
|
173
|
+
rm -rf "$staging" "$staging.log"
|
|
174
|
+
use_release "$fallback"
|
|
175
|
+
return 0
|
|
176
|
+
fi
|
|
118
177
|
node -e 'console.log(JSON.stringify({ error: `Could not install ${process.argv[1]} from npm; the first start of each version needs network access and a writable ${process.argv[2]}, so rerun outside the sandbox. npm: ${process.argv[3].trim().split("\n").pop() || "failed"}` }))' \
|
|
119
178
|
"ryugi-artifacts@$version" "$(dirname "$cache")" "$(cat "$staging.log")"
|
|
120
179
|
rm -rf "$staging" "$staging.log"
|
|
@@ -216,10 +275,29 @@ emit_info() {
|
|
|
216
275
|
' "$1" "$2" "$ARTIFACT"
|
|
217
276
|
}
|
|
218
277
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
278
|
+
# A server from an older release is replaced; the new one keeps its port and key, so open tabs reconnect.
|
|
279
|
+
if RUNNING_PID="$(running_server_pid)" && [[ -f "$INFO_FILE" ]]; then
|
|
280
|
+
if [[ -z "$SERVER_VERSION" || "$(cat "$VERSION_FILE" 2>/dev/null)" == "$SERVER_VERSION" ]]; then
|
|
281
|
+
register_owner
|
|
282
|
+
emit_info "$(cat "$INFO_FILE")" true
|
|
283
|
+
exit 0
|
|
284
|
+
fi
|
|
285
|
+
kill -TERM "$RUNNING_PID" 2>/dev/null
|
|
286
|
+
for _ in {1..50}; do
|
|
287
|
+
kill -0 "$RUNNING_PID" 2>/dev/null || break
|
|
288
|
+
sleep 0.1
|
|
289
|
+
done
|
|
290
|
+
if kill -0 "$RUNNING_PID" 2>/dev/null; then
|
|
291
|
+
kill -KILL "$RUNNING_PID" 2>/dev/null
|
|
292
|
+
for _ in {1..20}; do
|
|
293
|
+
kill -0 "$RUNNING_PID" 2>/dev/null || break
|
|
294
|
+
sleep 0.1
|
|
295
|
+
done
|
|
296
|
+
fi
|
|
297
|
+
if kill -0 "$RUNNING_PID" 2>/dev/null; then
|
|
298
|
+
echo "{\"error\": \"The running server (pid $RUNNING_PID) is on an older release and did not stop; stop it with stop-server.sh and retry\"}"
|
|
299
|
+
exit 1
|
|
300
|
+
fi
|
|
223
301
|
fi
|
|
224
302
|
|
|
225
303
|
register_owner
|
|
@@ -233,6 +311,7 @@ if ! [[ "$SERVER_ID" =~ ^[A-Za-z0-9_-]{32,64}$ ]]; then
|
|
|
233
311
|
SERVER_ID="$(printf '%08x%08x%08x%08x' "$$" "$(date +%s)" "${RANDOM:-0}" "${RANDOM:-0}")"
|
|
234
312
|
fi
|
|
235
313
|
printf '%s\n' "$SERVER_ID" > "$SERVER_ID_FILE"
|
|
314
|
+
printf '%s\n' "$SERVER_VERSION" > "$VERSION_FILE"
|
|
236
315
|
|
|
237
316
|
SERVER_ENV=(ARTIFACTS_ROOT="$ROOT_DIR" ARTIFACTS_HOST="$BIND_HOST" ARTIFACTS_URL_HOST="$URL_HOST" ARTIFACTS_OPEN="$OPEN")
|
|
238
317
|
[[ -n "$ARTIFACT" ]] && SERVER_ENV+=(ARTIFACTS_OPEN_ARTIFACT="$ARTIFACT")
|
|
@@ -247,6 +326,7 @@ if [[ "$FOREGROUND" == "true" ]]; then
|
|
|
247
326
|
sleep 0.1
|
|
248
327
|
done
|
|
249
328
|
release_lock
|
|
329
|
+
trap - EXIT
|
|
250
330
|
wait "$SERVER_PID"
|
|
251
331
|
exit $?
|
|
252
332
|
fi
|