fix: package the qualified UI in release ISOs

This commit is contained in:
archipelago
2026-10-05 16:02:48 -04:00
parent 69857c4ace
commit 415826f0a6
5 changed files with 99 additions and 1 deletions
+42
View File
@@ -717,3 +717,45 @@ track AIUI changes and pass the checkout revision. Actual image qualification
and public demo deployment remain pending. The demo/release VPS currently has
under1GiB free disk; capacity must be resolved before image/artifact publication.
No running container, volume, release or repository was deleted.
### Authorized release-storage cleanup — 2026-10-05
Operator approved removing only the old v1.8.13-alpha and v1.8.15-alpha ISO
attachments, then clarified that broader retention changes should be dropped if
that suffices. Both local ISO archives were independently hashed against their
published checksum files before removal. Gitea API deletion removed attachment
IDs219 and226 only; all other assets in both releases were verified unchanged.
Public server free space increased from887MiB to5.9GiB. Remaining historical
releases, OTA files, registry packages and application data were preserved.
Gitea's prior read-only storage doctor found no orphaned archives, attachments or
package blobs. No storage-doctor fix or package garbage collection was run.
Further removals are not planned; check exact final upload/image sizes first.
### Corrected binary deployed and restart verified
Final security backend SHA256
`560aa6006cd9ef8be95b1f7831cf3b53854e911622b50022bb4402ce0f8b010a`
built from e0b2181a after the complete1,681-test isolated pass. Deployed dev,
yaya and Shorty: health200, both embedded helper files match reviewed source,
active HTTP/HTTPS defaults are guarded, and all existing container IDs/start
times are unchanged. Backup per node: `support/190-guard-560aa6006cd9`.
The first dev check incorrectly inspected sites-available rather than the actual
regular sites-enabled file; automatic backend rollback ran. Corrected check
uses the helper's active-dashboard resolution, and the second deployment passes.
This was a qualification-script path error; retain the first failed log.
Shorty's final backend manager restart passed302 continuous public HTTP/HTTPS
RPC denial probes, followed by healthy management. Existing public32-case and
read-only Angor acceptance are rerunning against this exact deployed binary.
Logs: `/tmp/archy-190-guard-dev-deploy-2.log`,
`/tmp/archy-190-guard-yaya-deploy.log`, `/tmp/archy-190-guard-shorty-deploy.log`,
`/tmp/archy-190-final-shorty-restart-security.log`.
ISO release packaging now explicitly selects the qualified dashboard/AIUI
payload rather than capturing a live node's cached runtime files or choosing
AIUI by timestamp. Three executable builder-branch fixtures pass qualified,
missing and partial payloads; missing inputs fail without a live-node fallback.
The release wrapper sets this path and the release harness includes the test.
Accepted companion54 APK/metadata replace the stale copies in the packaging
staging directory; exact SHA remains ceb58a7d…fab1a1. Final ISO and OTA package
acceptance/signatures remain pending.
@@ -1448,7 +1448,19 @@ mkdir -p "$ARCH_DIR/web-ui"
# Try to get from live server first (unless BUILD_FROM_SOURCE=1)
WEBUI_CAPTURED=0
if [ "$BUILD_FROM_SOURCE" != "1" ]; then
if [ -n "${ARCHIPELAGO_WEB_UI:-}" ]; then
# Release builds supply the qualified payload explicitly. Never substitute
# a running node's cached runtime files or an older installed dashboard.
if [ ! -f "$ARCHIPELAGO_WEB_UI/index.html" ] || \
[ ! -f "$ARCHIPELAGO_WEB_UI/aiui/index.html" ] || \
[ ! -f "$ARCHIPELAGO_WEB_UI/aiui/BUILD-INFO" ]; then
echo "ERROR: ARCHIPELAGO_WEB_UI must contain the qualified dashboard and AIUI"
exit 1
fi
cp -r "$ARCHIPELAGO_WEB_UI/." "$ARCH_DIR/web-ui/"
WEBUI_CAPTURED=1
fi
if [ "$WEBUI_CAPTURED" = "0" ] && [ "$BUILD_FROM_SOURCE" != "1" ]; then
# Direct copy from local filesystem (when running on target with sudo)
if [ -d "/opt/archipelago/web-ui" ] && [ "$(ls -A /opt/archipelago/web-ui 2>/dev/null)" ]; then
cp -r /opt/archipelago/web-ui/* "$ARCH_DIR/web-ui/"
@@ -1504,6 +1516,9 @@ AIUI_INCLUDED=0
# or yesterday's hashed assets linger next to today's forever.
AIUI_SRC=""
AIUI_NEWEST=0
if [ -n "${ARCHIPELAGO_WEB_UI:-}" ]; then
AIUI_SRC="$ARCHIPELAGO_WEB_UI/aiui"
else
for AIUI_DIR in \
"$SCRIPT_DIR/../../aiui/packages/app/dist" \
"$SCRIPT_DIR/../../AIUI/packages/app/dist" \
@@ -1520,6 +1535,7 @@ for AIUI_DIR in \
fi
fi
done
fi
if [ -n "$AIUI_SRC" ]; then
echo " Including AIUI from $AIUI_SRC (newest of the candidates)..."
mkdir -p "$ARCH_DIR/web-ui/aiui"
+1
View File
@@ -147,6 +147,7 @@ build_iso() {
BUILD_FROM_SOURCE=0
DEV_SERVER=localhost
ARCHIPELAGO_BIN="$REPO/core/target/release/archipelago"
ARCHIPELAGO_WEB_UI="$REPO/web/dist/neode-ui"
)
[ -n "$RC_OVERRIDE" ] && env_args+=(RC="$RC_OVERRIDE")
sudo -E env "${env_args[@]}" nice -n 5 bash image-recipe/build-debian-iso.sh
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
"""Exercise the ISO builder's actual payload-selection branches, without a build."""
import os
import pathlib
import subprocess
import tempfile
ROOT = pathlib.Path(__file__).resolve().parents[2]
source = (ROOT / 'image-recipe/_archived/build-auto-installer-iso.sh').read_text()
capture = source.split('WEBUI_CAPTURED=0', 1)[1].split('# Include AIUI web app', 1)[0]
select = source.split('AIUI_SRC=""', 1)[1].split('if [ -n "$AIUI_SRC" ]; then', 1)[0]
program = 'set -eu\nWEBUI_CAPTURED=0\n' + capture + '\nAIUI_SRC=""\n' + select + '\nprintf "%s\\n" "$AIUI_SRC"\n'
with tempfile.TemporaryDirectory(prefix='archy-iso-qualified-ui-') as tmp:
base = pathlib.Path(tmp)
qualified = base / 'qualified'
(qualified / 'aiui').mkdir(parents=True)
(qualified / 'index.html').write_text('qualified-dashboard')
(qualified / 'aiui/index.html').write_text('qualified-aiui')
(qualified / 'aiui/BUILD-INFO').write_text('commit=fixture')
for label, path, success in [('qualified', qualified, True), ('missing', base / 'absent', False), ('partial', base / 'partial', False)]:
out = base / 'outputs' / label / 'installer'
(out / 'web-ui').mkdir(parents=True)
if label == 'partial':
path.mkdir(exist_ok=True)
(path / 'index.html').write_text('incomplete')
result = subprocess.run(['bash', '-c', program], env=os.environ | {
'ARCHIPELAGO_WEB_UI': str(path), 'ARCH_DIR': str(out),
'BUILD_FROM_SOURCE': '0', 'DEV_SERVER': 'localhost', 'SCRIPT_DIR': str(base),
}, capture_output=True, text=True)
assert (result.returncode == 0) == success, (label, result.stdout, result.stderr)
if success:
assert (out / 'web-ui/index.html').read_text() == 'qualified-dashboard'
assert (out / 'web-ui/aiui/index.html').read_text() == 'qualified-aiui'
assert result.stdout.strip().splitlines()[-1] == str(qualified / 'aiui')
assert not (out / 'web-ui/archipelago-runtime').exists()
else:
assert not list((out / 'web-ui').iterdir()), 'invalid payload silently fell back to a live node'
print('PASS ISO payload selection:', label)
+1
View File
@@ -72,6 +72,7 @@ summary() {
stage "git-diff-check" git diff --check
stage "mirror-gate-regression" python3 scripts/tests/test_git_mirrors.py
stage "iso-boot-runner-regression" python3 scripts/tests/test_iso_qemu_runner.py
stage "iso-qualified-web-ui" python3 tests/regression/iso-qualified-web-ui.py
stage "demo-rpc-parity" timeout 120 node neode-ui/scripts/mock-rpc-parity.mjs
stage "demo-resumable-uploads" timeout 120 node --test neode-ui/scripts/demo-upload-test.mjs
stage "companion-signature-regression" python3 scripts/tests/test_companion_apk_verification.py