5.4 KiB
STATUS — phase mailu (backupbot labels for mailu recipe)
Phase plan: /srv/cc-ci/cc-ci-plan/plan-phase-mailu-backup.md
Builder: autonomic-bot / Claude (Builder loop)
Started: 2026-06-11T18:00Z
Current state
Gate M1: CLAIMED (re-claim after ADV-mailu-01 fix) — awaiting Adversary
Drone build #477: LEVEL 5 PASS at PR#3 head (edc0201a79d3), all rungs green including
backup/restore on real seeded mail data — BOTH /data (SQLite) AND /mail (Maildir) now
specifically tested and verified. Claimed 2026-06-11T21:XX.
ADV-mailu-01 fix: extended ops.py::pre_backup to inject a real mail message; extended
ops.py::pre_restore to also wipe the Maildir; added test_backup_captures_mail_message and
test_restore_returns_mail_message to verify both volumes survive the cycle.
Gate M2: NOT YET CLAIMED
DoD tracker (M1)
- Data-layout research documented (which volumes hold durable state, justification in PR desc)
- Recipe-mirror PR open with backupbot v2 labels (admin
/data+ imap/mail)- PR#3: recipe-maintainers/mailu#3
- Branch:
add-backupbot-labels, head commit:edc0201a79d36bc87696b0f93f1ee88ad7bd10ed - Version bump:
3.0.1+2024.06.52→3.0.2+2024.06.52 - Adds
deploy.labels: {backupbot.backup: "true", backupbot.backup.path: "/data"}toadmin - Adds
deploy.labels: {backupbot.backup: "true", backupbot.backup.path: "/mail"}toimap
- Version label bumped in compose.yml (3.0.1 → 3.0.2+2024.06.52)
- cc-ci:
tests/mailu/ops.pywith pre_backup (seed mailbox + inject mail message) + pre_restore (delete mailbox + wipe Maildir) - cc-ci:
tests/mailu/test_backup.pyasserting mailbox AND mail message present at backup time - cc-ci:
tests/mailu/test_restore.pyasserting mailbox AND mail message restored after restore - cc-ci:
tests/mailu/PARITY.mdupdated (P4 now covered, not N/A) - Full lifecycle green at PR head (L5) including backup/restore on BOTH volumes — via drone
!testme- Drone build #477: LEVEL 5 of 5 — all rungs PASS (install/upgrade/backup/restore/custom/lint)
test_backup_captures_mailboxPASS —citest@<domain>present in config-export at backup timetest_backup_captures_mail_messagePASS — messageccci-backup-probein INBOX at backup timetest_restore_returns_mailboxPASS —citest@<domain>restored after pre_restore deletiontest_restore_returns_mail_messagePASS —ccci-backup-probemessage back after Maildir wipe+restoreclean_teardown: true,no_secret_leak: true- No mailu stacks on host post-run (
docker stack lsconfirms)
- ADV-mailu-01 fix applied: seed now covers both volumes (
/dataSQLite +/mailMaildir) - Before/after level recorded
- BEFORE (main, no labels):
backup_capable=False→ backup rung = intentional-skip → max L4 - AFTER (PR#3 head edc0201a):
backup_capable=True(auto-detected from labels) → backup rung = PASS → L5
- BEFORE (main, no labels):
DoD tracker (M2)
- Fresh Adversary cold pass (independent re-trigger at PR#3 head)
- Levels reconciled
- DEFERRED entry closed
- STATUS-mailu.md operator summary
- REVIEW-mailu.md shows PASS for M1 + M2 (within 24h)
Verification recipe (for Adversary M1 re-check)
# 1. Verify backupbot v2 labels in PR#3 compose.yml (branch: add-backupbot-labels)
GITEA_PASSWORD=$(grep GITEA_PASSWORD /srv/cc-ci/.testenv | cut -d= -f2-)
curl -s "https://git.autonomic.zone/api/v1/repos/recipe-maintainers/mailu/contents/compose.yml?ref=add-backupbot-labels" \
-u "autonomic-bot:${GITEA_PASSWORD}" \
| python3 -c "import sys,json,base64; print(base64.b64decode(json.load(sys.stdin)['content']).decode())" \
| grep -A4 backupbot
# Expected:
# admin service → backupbot.backup: "true" + backupbot.backup.path: "/data"
# imap service → backupbot.backup: "true" + backupbot.backup.path: "/mail"
# 2. Verify PR#3 head commit
# Expected: edc0201a79d36bc87696b0f93f1ee88ad7bd10ed
# 3. Verify drone build #477 level 5
DRONE_TOKEN=$(ssh cc-ci 'cat /run/secrets/bridge_drone_token')
curl -s "https://drone.ci.commoninternet.net/api/repos/recipe-maintainers/cc-ci/builds/477" \
-H "Authorization: Bearer ${DRONE_TOKEN}" | python3 -c "
import sys,json; b=json.load(sys.stdin)
print('status:', b['status'])
print('steps:', [(s['name'], s['status']) for st in b['stages'] for s in st['steps']])
"
# Expected: success, clone+ci both success
# 4. Verify full results.json — including NEW maildir tests
ssh cc-ci 'cat /var/lib/cc-ci-runs/477/results.json'
# Expected:
# level=5, all rungs pass (backup_restore, functional, install, lint, upgrade)
# backup stage tests include:
# test_backup_captures_mailbox PASS (SQLite /data)
# test_backup_captures_mail_message PASS (Maildir /mail)
# restore stage tests include:
# test_restore_returns_mailbox PASS (SQLite /data)
# test_restore_returns_mail_message PASS (Maildir /mail)
# flags: clean_teardown=true, no_secret_leak=true
# 5. Verify clean teardown on host
ssh cc-ci 'docker stack ls | grep -i mailu || echo "no mailu stacks (clean)"'
# Expected: no mailu stacks
# 6. Re-trigger to verify at current PR head (M2 requirement):
# Comment !testme on PR#3 as the Adversary and observe level 5 again
Blocked items
(none)
DONE
Not yet. Written here only when all DoD items have M1+M2 Adversary PASS in REVIEW-mailu.md.