Skip to content

Build daily-driver OS and GCP E2E - #6

Merged
oratis merged 1 commit into
mainfrom
codex/daily-driver-e2e
Aug 1, 2026
Merged

Build daily-driver OS and GCP E2E#6
oratis merged 1 commit into
mainfrom
codex/daily-driver-e2e

Conversation

@oratis

@oratis oratis commented Jul 28, 2026

Copy link
Copy Markdown
Owner

What changed

  • expands the Fedora bootc/KDE image into a virtual-hardware Daily Driver Candidate with Flatpak/Discover, LibreOffice, Firefox, Chinese input, PipeWire, common formats, peripheral services, and gaming prerequisites
  • defaults the consumer image to no SSH service or wildcard port 22 listener, while enabling firewall, OOM protection, zram, trim, bounded journals, printing, Bluetooth, and firmware services
  • adds first-boot SELinux relabeling for installed mutable state before D-Bus and the desktop session
  • adds real Plasma Wayland, PipeWire, Office OOXML/PDF, Firefox, service, security, disk-space, and user-data persistence checks across update and rollback
  • adds a nested-KVM GCP runner with host gates and portable evidence capture
  • documents the consumer baseline, GCP evidence, hardware limits, README status, and product-plan checkpoint

Why

The installable preview proved boot and bootc lifecycle mechanics, but not the day-to-day desktop workload or user-data invariants needed for a consumer candidate. This change turns those product claims into executable checks and closes failures found during repeated GCP nested-virtualization runs.

GCP E2E evidence

A clean 32 GiB disk completed offline ISO installation, first boot, revision 2 update, and revision 1 rollback. The normalized serial sequence ended in ANDROMEDA_E2E_OK.

  • environment: GCE n2-standard-16, nested Intel KVM, L2 Q35/OVMF with 4 vCPU and 8 GiB RAM
  • run: 2026-07-28 18:58:31–19:25:22 UTC
  • ISO SHA-256: 6f8d74e5f14b7dab9c478b8fd538defbdbde717dee62bbc3c7ca5c13cc597108
  • source marker: daily-driver-final-b9150477f12f

The outer GCP collector originally returned 1 after the OS had emitted all success markers because its exact grep did not normalize serial CRLF/ANSI data. The extraction fix is included and revalidated with status 0 against the same raw evidence.

Validation

  • bash -n os/scripts/*.sh os/installer/*.sh os/files/usr/libexec/*
  • shellcheck os/scripts/*.sh os/installer/*.sh os/files/usr/libexec/*
  • git diff --check
  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets --locked -- -D warnings
  • cargo test --workspace --locked (19 tests)
  • full GCP nested-KVM ISO install / first boot / update / rollback lifecycle

Scope boundary

This is a Daily Driver Candidate on virtual hardware. It does not certify physical GPU, Wi-Fi, Bluetooth, camera, battery/suspend, firmware, Mac hardware, Steam/Proton performance, DRM, anti-cheat, Windows Workspace, or Microsoft Office itself.

@oratis
oratis marked this pull request as ready for review August 1, 2026 04:26
@oratis

oratis commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

PR #6 代码评审:Build daily-driver OS and GCP E2E

总体评价

这是一个质量相当高的 E2E 工程 PR:把"日用桌面能力"从文档口号变成了串口标记驱动的可执行验收,错误处理(set -Eeuo pipefail、带行号的 ERR trap、current_check 分段标记)和证据收集(EXIT trap 无论成败都归档)都体现了良好的工程素养,文档对证据边界的诚实程度也少见。但有两个实质问题:PR 自己宣传的安全不变量("不监听通配地址的 22 端口")在代码里只检查了 IPv4,IPv6 通配监听会漏过;且文档记录的 GCP "PASS" 是外层收集器失败(exit 1)后修复提取器、对旧日志离线重放得到的,修复后的完整链路从未一次性跑绿过。

优点

  • 标记顺序严格校验,而非仅存在性检查:os/scripts/test-install.sh 新增的 Python 块用 log.find() 对全部 10 个标记做单调递增位置校验(positions != sorted(positions) 即失败),比常见的逐个 grep 严谨得多。
  • CRLF/ANSI 假阴性的根因分析和修复到位:os/scripts/test-gcp-nested.sh:69-71LC_ALL=C grep -aoE 'ANDROMEDA_...[[:print:]]*' 从二进制串口流提取标记,正确解决了 \r 结尾和 agetty 控制序列同行导致的 grep -x 失配,且在文档中如实披露了这次假阴性。
  • 昂贵操作前置门槛:test-gcp-nested.sh:38-44 在开始约 100 分钟构建前先校验 /dev/kvm、vmx flag 数、vCPU、内存、100 GiB 磁盘余量,避免注定失败的烧钱运行。
  • 真会话检测而非进程 grep:andromeda-daily-driver-verify:39-95 同时要求 wayland socket、用户 D-Bus、kwin_wayland/plasmashell 进程、以及 loginctl 报告 Type=waylandState=active,这确实在测"真实 Plasma Wayland 会话"。
  • 用户数据持久性测试设计正确:固定内容 + 固定 SHA-256(本地复算 a76c14260fc4... 与代码一致),在 first-boot 创建、update/rollback 两个阶段复验,真正覆盖了跨 bootc 部署的 /home 不变量。
  • Office 测试是真转换而非装包即过:隔离 profile(-env:UserInstallation)、每步 timeout 120s、fodt→docx→pdf 链式往返、unzip -t 验 ZIP 结构、pdfinfo 验元数据。
  • 无凭据泄漏:diff 中没有任何 GCP 密钥、token 或 gcloud 调用;仓库脚本被刻意设计为不触碰云资源。
  • 消费镜像默认关 SSH 并在运行时断言(Containerfile systemctl disable sshd.service + verify 脚本双重检查),纵深防御思路正确。
  • andromeda-ci-verify 的 ERR trap 改为 trap 'on_error "$?" "${LINENO}"' ERR,失败标记带行号,显著改善远程排障。

问题与建议

  • 【严重】SSH 通配监听检查漏掉 IPv6(os/files/usr/libexec/andromeda-daily-driver-verify:140-144):
    if ss --listening --tcp --numeric \
        | grep -Eq '(^|[[:space:]])0\.0\.0\.0:22([[:space:]]|$)'; then
    sshd 默认同时监听 0.0.0.0:22[::]:22,而 Linux 默认 bindv6only=0[::]:22 同样接受 IPv4 连接。若因任何原因(如 sshd.socket 被 preset 激活、或配置漂移)只剩 IPv6 通配监听,此检查会静默通过,直接违背 PR/README 明确宣传的"不监听通配地址的 22 端口"。建议改为匹配任意通配地址:grep -Eq '(0\.0\.0\.0|\[::\]|\*):22\b',并在 Containerfile 中同时 systemctl disable sshd.socket(systemctl is-active sshd.service 抓不到 socket 激活的待命状态)。
  • 【中等】文档记录的 PASS 不是修复后代码的一次性绿跑(docs/development/daily-driver-e2e.md "已验证运行":原始外层状态 1 / 规范化复验 0):提取器修复只在旧的原始串口日志上重放验证过,test-gcp-nested.sh 当前版本从未端到端跑绿。披露很诚实,但合并前应该用最终代码完整重跑一次 GCP E2E,否则 README 的 "Daily Driver Candidate" 徽章建立在拼接证据上。
  • 【中等】云资源生命周期完全在仓库之外,清理与成本控制不可审计(os/scripts/test-gcp-nested.sh 全文 + docs/development/daily-driver-e2e.md:"云资源的创建、标签校验、最大运行时、证据下载与精确清理由本地 gcp-os-e2e Codex skill 管理"):该 skill 不在仓库中,意味着 (a) E2E 无法仅凭仓库复现;(b) 如果 skill 中途失败,一台 n2-standard-16(约 $0.78/小时,泄漏一个月约 $560)没有任何仓库内兜底。建议至少提交一个瘦 gcloud 包装脚本:创建实例时带 --max-run-duration--labels,用 EXIT trap 删除实例,或在文档中给出手工兜底清理命令。
  • 【中等】Firefox 检查测不到它宣称的东西(andromeda-daily-driver-verify:239-264):systemd-run --property=Type=exec 在 exec 成功即视为 active,之后仅 sleep 5 再查一次。MOZ_ENABLE_WAYLAND=1 在 Wayland 连接失败时会静默回落到 Xwayland,进程照样存活——所以 os/README 里 "a real Firefox Wayland launch" 并未被证明。建议追加证据,例如断言 firefox 进程持有 wayland socket 连接(ss -xp | grep -F "$(basename "${wayland_socket}")" 或检查 lsof -p),或至少验证 profile 目录内产生了会话文件。
  • 【中等】andromeda-first-boot-labels 在消费路径上有两个脆弱点(os/files/usr/libexec/andromeda-first-boot-labels:7,12 + os/installer/install-uefi-fallback.sh:88-90 无条件 touch marker):(a) SELinux 为 Disabled 时 test "$(getenforce)" != Disabled 使单元每次开机失败且 marker 永不删除,用户机器上会留下一个永久红色 failed unit——Disabled 情况应删 marker 并 exit 0;(b) tee /dev/ttyS0 是 CI 专属产物却进入了所有安装(包括非 CI),在无串口设备的硬件上可能使 set -e 下整个 relabel 服务失败,建议 tee /dev/ttyS0 || true 或仅在 CI 模式发标记。
  • 【轻微】GCP 收集器最终断言仍有残余脆弱性(test-gcp-nested.sh:72):grep -qx 'ANDROMEDA_E2E_OK' 在标记后同一行还有可打印垃圾(如光标控制后的残字)时会再次假阴性——这正是刚修过的坑的变体。用 grep -q '^ANDROMEDA_E2E_OK$' 之外,更稳的是锚定前缀 grep -q '^ANDROMEDA_E2E_OK' 或复用 test-install.sh 的 Python 顺序校验。
  • 【轻微】分区探测循环超时后静默放行(os/scripts/test-install.sh:126-135):30 秒内没等到 ESP GUID + andromeda-root label 时 while 循环直接落空继续执行,失败会推迟到后续步骤以更晦涩的方式爆出。循环后应显式 test/报错。
  • 【轻微】嵌套 KVM + llvmpipe 下超时余量偏紧,有 flake 风险:Plasma 会话等待 180 秒(andromeda-daily-driver-verify:39)、每个 LibreOffice 转换 120 秒(首个 headless 启动需初始化全新 profile,软件渲染下可能贴线)、Firefox 仅靠 sleep 5 判定健康。建议 Plasma/首个 LO 转换放宽到 300 秒。同理 disk-space 的固定 5 GiB 阈值(:147-148)会随镜像增长悄悄逼近失败。
  • 【轻微】E2E 用户不必要地加入 wheel 组(os/installer/andromeda-ci.ks:10:user --name=andromeda --groups=wheel --lock):自动登录的测试会话没有任何检查需要管理员身份,最小权限原则下应去掉 wheel,降低 CI 镜像被当模板复制时的暴露面。
  • 【轻微】OOXML 只验证了 ZIP 完整性,未验证内容(andromeda-daily-driver-verify:224-227):unzip -t 过不代表转换语义正确,加一行 unzip -p .../andromeda.docx word/document.xml | grep -q Andromeda 成本极低。
  • 【轻微】Containerfile 新增 9 个独立 RUN dnf install(os/Containerfile:63-163):分层利于缓存调试,但最终镜像/OCI archive 体积和层数都会膨胀;稳定后可考虑按主题合并为 2-3 层。

结论

Request changes —— 主体工程质量很好,但 IPv6 通配 SSH 检查漏洞直接击穿了 PR 自己宣传的安全不变量,且合并前应以修复后的完整代码重跑一次端到端绿跑来支撑"已验证运行"的 PASS 记录;两者修复成本都很低。


Review by Claude Code

@oratis
oratis changed the base branch from codex/installable-preview to main August 1, 2026 07:58
@oratis
oratis merged commit e4450e1 into main Aug 1, 2026
5 checks passed
oratis added a commit that referenced this pull request Aug 2, 2026
Ties the pieces together: the A/B/C/D tiering, the full input inventory
with per-input status, the re-pin runbook, and how to read the freshness
check. Records two investigations the review asked for.

ghcr.io/osbuild/image-builder-cli is NOT the next fedora-bootc. GitHub
Packages documents deletion as manual only (30-day restore window) with
no automatic expiry, the currently pinned digest still resolves while
:latest has moved on, and osbuild tags every build sha-<commit> so
historical versions never become untagged. Keeping that pin is correct;
build-iso.sh is owned by opt/e2e-p1-cache-split and stays untouched.

Fedora publishes no durable dated snapshot for a supported release, so
Tier B is documented rather than implemented. kojipkgs dated composes
exist and serve valid repodata, but the index holds only ~10 days
(F44: 20260724-20260802, measured) -- pointing the Containerfile at one
would rot faster than the quay digest that already broke the build,
trading a reproducibility problem for an availability one. The frozen GA
compose is durable but ships zero security updates. The content-
addressed payload cache from P1 #6 gets the same reproducibility with no
external endpoint to rot, and is the recommended path instead.

fedora-bootc stays tag-tracked. Re-pinning before Renovate is installed
would just re-break the build within days.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
oratis added a commit that referenced this pull request Aug 2, 2026
Ties the pieces together: the A/B/C/D tiering, the full input inventory
with per-input status, the re-pin runbook, and how to read the freshness
check. Records two investigations the review asked for.

ghcr.io/osbuild/image-builder-cli is NOT the next fedora-bootc. GitHub
Packages documents deletion as manual only (30-day restore window) with
no automatic expiry, the currently pinned digest still resolves while
:latest has moved on, and osbuild tags every build sha-<commit> so
historical versions never become untagged. Keeping that pin is correct;
build-iso.sh is owned by opt/e2e-p1-cache-split and stays untouched.

Fedora publishes no durable dated snapshot for a supported release, so
Tier B is documented rather than implemented. kojipkgs dated composes
exist and serve valid repodata, but the index holds only ~10 days
(F44: 20260724-20260802, measured) -- pointing the Containerfile at one
would rot faster than the quay digest that already broke the build,
trading a reproducibility problem for an availability one. The frozen GA
compose is durable but ships zero security updates. The content-
addressed payload cache from P1 #6 gets the same reproducibility with no
external endpoint to rot, and is the recommended path instead.

fedora-bootc stays tag-tracked. Re-pinning before Renovate is installed
would just re-break the build within days.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@oratis
oratis deleted the codex/daily-driver-e2e branch August 2, 2026 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant