Files
cc-ci/tests/mailu/PARITY.md
autonomic-bot 44e02425ab
Some checks failed
continuous-integration/drone/push Build is failing
feat(cfold): canonicalize custom test layout
2026-06-12 16:08:18 +00:00

60 lines
4.2 KiB
Markdown

# mailu — recipe-maintainer → cc-ci parity (Phase 2 P2)
**P2 is VACUOUS for mailu:** there is no `recipe-info/mailu/tests/` corpus in the recipe-maintainer
workspace (`/srv/recipe-maintainer`), so there are no recipe-maintainer tests to port. Coverage is
therefore health + recipe-specific functional tests (P3), authored from what mailu *is* (a full
email stack: nginx front + admin + postfix/smtp + dovecot/imap + rspamd/antispam + webmail + redis).
## cc-ci deployment notes
- `COMPOSE_FILE=compose.yml` (base). recipe_meta.EXTRA_ENV(domain) pins `MAIL_DOMAIN`/`HOSTNAMES` to
the per-run domain, `TRAEFIK_STACK_NAME=traefik_ci_commoninternet_net` (so the external
`*_letsencrypt` volume the certdumper mounts resolves), and **`TLS_FLAVOR=notls`** — mailu's
mail-port TLS normally comes from `certdumper` dumping traefik's ACME `acme.json`, but cc-ci uses a
file-provider wildcard cert (no ACME), so there is no acme.json; `notls` removes that dependency.
(certdumper still runs idle; harmless — it converges 1/1.) Web/admin is served over the real
wildcard TLS via Traefik. Mail ports 25/465/587/110/143/993/995 are published mode:host → on-host
(cc-ci-run) tests reach SMTP/IMAP at 127.0.0.1.
## Recipe-specific functional tests (P3 — ≥2)
1. `custom/test_mailbox.py` — §4.3 create-an-object + read-back: create a mailbox via the admin
container's `flask mailu user` CLI, then read it back from `flask mailu config-export --json` and
assert the address is present (admin-DB provisioning round-trip).
2. `custom/test_mail_flow.py` — the characteristic end-to-end mail flow: INJECT a uniquely-marked
message to the mailbox via the postfix container's local `sendmail` (locally-originated → not
greylisted), then VERIFY delivery+storage via dovecot's `doveadm search` in the imap container —
a real postfix → rspamd → dovecot deliver/store/fetch round-trip. We use the in-container mail
tools (not the host network ports) because TLS_FLAVOR=notls makes dovecot refuse plaintext auth
over the network (143); the in-container path exercises the same delivery/storage stack. (A
network IMAP-auth test was dropped: under notls dovecot disallows plaintext network auth, so a
host-side login is not a meaningful signal here.)
## Backup data-integrity (P4) — COVERED (phase-mailu, 2026-06-11)
P4 is now **earned** via recipe-mirror PR#3 (`add-backupbot-labels`) on
`git.autonomic.zone/recipe-maintainers/mailu`. That PR adds backupbot v2 labels to the `admin`
service (`/data` — sqlite DB) and `imap` service (`/mail` — Maildir), making `backup_capable=True`
at the PR head.
cc-ci tests (all in `tests/mailu/`):
- `ops.py``pre_backup`: seeds `citest@<domain>` via `flask mailu user` + injects a uniquely-tagged
message (`ccci-backup-probe`) into the INBOX via `sendmail` in the smtp container → verified with
`doveadm search` in the imap container. `pre_restore`: (1) deletes the account from sqlite via
Python; (2) `rm -rf /mail/<domain>/citest` in the imap container to wipe the Maildir — both
volumes are wiped independently so each must be restored to pass.
- `test_backup.py` — two tests: `test_backup_captures_mailbox` asserts `citest@<domain>` is in
`config-export` at backup time (SQLite `/data`); `test_backup_captures_mail_message` asserts the
`ccci-backup-probe` message is in INBOX (Maildir `/mail`).
- `test_restore.py` — two tests: `test_restore_returns_mailbox` asserts the account is back in
`config-export` after restore (SQLite `/data`); `test_restore_returns_mail_message` asserts the
`ccci-backup-probe` message is back in INBOX (Maildir `/mail`).
Both volumes (`/data` SQLite + `/mail` Maildir) are specifically seeded, independently wiped, and
verified restored — proven in drone build #477 (all four backup/restore tests PASS, L5).
Auto-detected: `generic.backup_capable()` scans the compose.yml for `backupbot.backup.*true` and
returns `True` at the PR head — no `BACKUP_CAPABLE` override needed in `recipe_meta.py`.
## Browser flow (P6)
Not added: mailu's user-facing UX (webmail/admin) is a standard web UI; the characteristic behaviour
(mail send/receive, account auth) is covered functionally above. No Playwright flow owed.