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

4.2 KiB

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.pypre_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.