Style the engine's own logs, notice enrolment while serving, say more in status
Docs / docs (push) Successful in 21s
Playwright Tests / test-playwright (1, 2) (push) Failing after 4m24s
Playwright Tests / test-playwright (2, 2) (push) Failing after 1m37s
pre-commit / pre-commit (push) Failing after 3m14s
Test Backend / test-backend (push) Successful in 2m15s
Compose Smoke Test / test-compose (push) Successful in 34s
Playwright Tests / merge-reports (push) Failing after 1m3s

Four things from a testing pass.

`fluksio serve` printed its own lines through the root logger, which has no
handler and falls back to `INFO:fluksio.cloud.connector:...` — beside uvicorn's
aligned output it reads like something went wrong. The engine's loggers and
alembic's now use uvicorn's own handler. Named rather than configuring the
root: httpx logs every portal call at INFO and none of that is printed today.

`fluksio enroll` writes its config from another process, so an engine already
serving never learned it had been paired. It now looks for one every few
seconds and dials when it appears. `load()` rather than `exists()`, or a file
that does not parse would be restarted forever.

`fluksio status` says where the installation stands with its portal — never
paired, linked, or paired and unreachable, which is the one worth acting on.

`--seed` and `--timeout` had no help text at all. Both say what they are for
now, and the docs say what a seed is actually for: recorded on the run, part of
its input digest, and passed to an input named `seed` when the flow declares
one, so the number a run is labelled with is the one the code drew from.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019V5bsYGNxcgPs4xXmTPx69
This commit is contained in:
2026-08-25 09:29:22 +02:00
co-authored by Claude Opus 5
parent 7c5b212f43
commit 60757fa7fa
8 changed files with 231 additions and 29 deletions
+48
View File
@@ -9,6 +9,7 @@ nothing, which is what makes deleting that local account a revocation.
from __future__ import annotations
import asyncio
import uuid
from dataclasses import replace
from unittest.mock import Mock, patch
@@ -358,3 +359,50 @@ def test_the_owner_is_adopted_when_the_enrolling_row_is_gone(
healed = cloud_config.load()
assert healed is not None
assert healed.local_user_id == str(enrolled.id)
# -----------------------------------------------------------------------------
# Enrolling an engine that is already running
#
# `fluksio enroll` writes the config against the database from another process
# entirely, with no idea whether an engine is up. Noticing that is what saves a
# restart.
# -----------------------------------------------------------------------------
@pytest.mark.anyio
async def test_a_config_that_appears_while_running_is_dialled(monkeypatch) -> None:
from fluksio.cloud import connector
app = Mock()
app.state = Mock(cloud_task=None, cloud_connector=None)
started: list[object] = []
monkeypatch.setattr(connector, "ENROL_POLL_S", 0.01)
monkeypatch.setattr(connector, "start", lambda one: started.append(one))
monkeypatch.setattr(cloud_config, "load", lambda: object())
watcher = asyncio.create_task(connector.watch_enrolment(app))
await asyncio.sleep(0.05)
watcher.cancel()
assert started
@pytest.mark.anyio
async def test_a_config_that_cannot_be_read_is_not_dialled(monkeypatch) -> None:
"""Otherwise the connector gives up at once and this restarts it forever."""
from fluksio.cloud import connector
app = Mock()
app.state = Mock(cloud_task=None, cloud_connector=None)
started: list[object] = []
monkeypatch.setattr(connector, "ENROL_POLL_S", 0.01)
monkeypatch.setattr(connector, "start", lambda one: started.append(one))
# The file is there; it just does not parse, which `load` reports as None.
monkeypatch.setattr(cloud_config, "load", lambda: None)
watcher = asyncio.create_task(connector.watch_enrolment(app))
await asyncio.sleep(0.05)
watcher.cancel()
assert not started