fix(installer): put the 'pull the USB stick' step before the restart button

The hint lived on the rebooting page and in a confirm() popup — i.e. after
the click, with the machine restarting 3 s later. On the first hardware
bench the box promptly booted the stick again. The done state now shows a
two-step list (pull the stick → restart) above the button, and the button
says what it assumes: 'USB stick is out — restart now'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MScAinbyMdeNc7H2BZdnnG
This commit is contained in:
Daniel Maksymilian Syrnicki 2026-08-25 16:24:59 +02:00
parent 5ddda5302a
commit 60404ae643
4 changed files with 52 additions and 3 deletions

View file

@ -195,3 +195,34 @@ def test_build_archinstall_creds_uses_archinstall_sentinel_keys():
"groups": [], "groups": [],
} }
] ]
def test_log_page_done_state_shows_usb_step_before_restart(monkeypatch, tmp_path):
"""The 'pull the USB stick' step must be visible *before* the restart
button after the click the box reboots within seconds (first hardware
bench booted the stick again)."""
import app as app_module
log_path = tmp_path / "install.log"
log_path.write_text("Installation completed without any errors.\n")
monkeypatch.setattr(app_module, "INSTALL_LOG", log_path)
app_module.settings["hostname"] = "bench"
html = app_module.app.test_client().get("/install/log").get_data(as_text=True)
assert '<ol class="next-steps">' in html
assert "http://bench.local" in html
assert "USB stick is out" in html
assert html.index("next-steps") < html.index("USB stick is out")
def test_log_page_running_state_has_no_restart_button(monkeypatch, tmp_path):
import app as app_module
log_path = tmp_path / "install.log"
log_path.write_text("Creating partitions: /dev/sda\n")
monkeypatch.setattr(app_module, "INSTALL_LOG", log_path)
html = app_module.app.test_client().get("/install/log").get_data(as_text=True)
assert "next-steps" not in html
assert "install_reboot" not in html and "restart now" not in html

View file

@ -642,6 +642,7 @@ def install_log_view():
"install/log.html", "install/log.html",
log=log, log=log,
progress=parse_install_progress(log), progress=parse_install_progress(log),
hostname=settings["hostname"],
) )

View file

@ -421,3 +421,11 @@ select:focus {
outline-offset: 3px; outline-offset: 3px;
border-radius: 2px; border-radius: 2px;
} }
/* "Furtka is ready" — the two steps before the restart button (log.html). */
.next-steps {
margin: 1.5rem 0 1rem;
padding-left: 1.4rem;
line-height: 1.5;
}
.next-steps li { margin-bottom: 0.6rem; }

View file

@ -17,16 +17,25 @@
{% else %}Installing Furtka{% endif %} {% else %}Installing Furtka{% endif %}
</h1> </h1>
<p class="lede" id="install-lede"> <p class="lede" id="install-lede">
{% if progress.status == "done" %}Installation finished. <strong>Remove the installer USB / eject the ISO</strong>, then click Reboot. {% if progress.status == "done" %}Installation finished. Two more steps and Furtka is running from its own disk.
{% elif progress.status == "error" %}Something went wrong. Open the details below and share them so we can help. {% elif progress.status == "error" %}Something went wrong. Open the details below and share them so we can help.
{% else %}This takes a few minutes. Don't close this page or power off the machine.{% endif %} {% else %}This takes a few minutes. Don't close this page or power off the machine.{% endif %}
</p> </p>
{% if progress.status == "done" %} {% if progress.status == "done" %}
{# The USB-stick step has to be read *before* the click: the machine reboots
3 s after it, and most BIOSes boot the stick before the disk — so the
installer would just come back. Seen on the first hardware bench. #}
<ol class="next-steps">
<li><strong>Pull out the USB stick</strong> (or eject the installer ISO in your VM).
If it stays in, the computer will start this installer again instead of Furtka.</li>
<li>Click the button below. The computer restarts and comes back as
<strong>http://{{ hostname }}.local</strong> in about a minute.</li>
</ol>
<form method="post" action="{{ url_for('install_reboot') }}" <form method="post" action="{{ url_for('install_reboot') }}"
onsubmit="return confirm('Have you removed the installer USB / ejected the ISO? Click OK to reboot.');"> onsubmit="return confirm('USB stick removed? Click OK to restart the computer.');">
<div class="actions"> <div class="actions">
<button type="submit" class="btn btn-primary">Reboot now</button> <button type="submit" class="btn btn-primary">USB stick is out — restart now</button>
</div> </div>
</form> </form>
{% endif %} {% endif %}