feat: add opencode.db cleanup and migration failure auto-recovery#200
Conversation
Implements issue #198 — prevent and recover from stale SQLite database issues on self-hosted runners. Scheme A (preventive cleanup): - New shared/cleanup-db.sh checks opencode.db size before each run - Deletes db if it exceeds configurable threshold (default 50MB) - New github-run-opencode input 'cleanup-db' (default: true) Scheme C (migration failure auto-recovery): - run-opencode/run-opencode.sh now detects 'duplicate column name' errors - Auto-deletes the stale db and retries once Files changed: - shared/cleanup-db.sh: new standalone cleanup script - github-run-opencode/action.yml: add cleanup-db input + step - run-opencode/run-opencode.sh: add migration error recovery - READMEs updated for both actions + shared/
分析过程已读取 PR 全部 6 个变更文件: Scheme A — 预防性清理(运行前)
Scheme C — 迁移失败自动恢复(运行时)
文档
所有规格要求均被完整实现,未发现遗漏。 无遗漏 |
最终决策:有条件合并 / CONDITIONAL MERGE本 PR 引入数据库自动清理和迁移恢复机制,架构合理、纵深防御设计良好。但存在一个需要修复的阻塞问题。 阻塞项 / Blocking Issues
建议项 / Suggestions
📋 各 Reviewer 详细审查结果quality有条件合并 / CONDITIONAL MERGE 此 PR 主要新增了两个功能:1) 在运行前自动清理过大的 阻塞项:
建议项:
security存在风险 / AT RISK 安全分析摘要本 PR 引入了两个安全机制:SQLite 数据库大小阈值清理和迁移失败自动恢复。整体设计合理,输入验证较好,但存在若干可被恶意工作流利用的风险点。 阻塞项:无未发现必须阻止合并的严重漏洞。 建议项
performance性能有疑虑 / CONCERNS 本次 PR 新增了 阻塞项:无 建议项:
architecture架构合理 / SOUND 该 PR 的变更遵循了项目已有的架构模式,没有引入架构层面的问题。 分析摘要:
阻塞项:无 建议项:无 |
Svitter
left a comment
There was a problem hiding this comment.
Review: P2 — needs maintainer call
This PR adds a two-pronged DB cleanup feature (preventive size-threshold deletion + reactive migration-error recovery) targeting stale opencode.db on self-hosted runners. The approach is sound and the implementation is small and focused (6 files, 78 lines). Ranked P2 because cleanup-db defaults to "true", changing default behavior — conventions require explicit maintainer sign-off.
Findings summary:
- No tests for
cleanup-db.shor therun-opencode.shmigration recovery block. The existing test suite has zero coverage for these paths. - Redundant false guard in
github-run-opencode/action.yml:252— the inlineif [[ "$cleanup_val" == "false" ]]is dead code since the step'sif:already gates on!= 'false'. - Linux suboptimal stat order in
shared/cleanup-db.sh:23—stat -f%z(macOS) runs and fails on every Linux invocation before falling through tostat -c%s. Swap them since Linux is the only supported runner. OPENCODE_DB_PATHnot plumbed — neither the cleanup step nor the run step passes a custom DB path. Both scripts hardcode the default~/.local/share/opencode/opencode.db. Users with non-default paths need to setOPENCODE_DB_PATHin their workflowenv:, but this isn't documented.
None of these are blocking correctness issues. The stat fallback works despite the order; the recovery continue correctly avoids double-counting the attempt. Docs are updated across all three READMEs.
Thanks for the clean, focused PR.
| run: | | ||
| set -euo pipefail | ||
| cleanup_val="$INPUT_CLEANUP_DB" | ||
| if [[ "$cleanup_val" == "false" ]]; then exit 0; fi |
There was a problem hiding this comment.
should-fix: This false check is dead code. The step's if: guard on line 245 already ensures inputs.cleanup-db != 'false', so $cleanup_val can never be "false" when this inline script executes. Removing it avoids misleading future readers.
| exit 0 | ||
| fi | ||
|
|
||
| size_bytes="$(stat -f%z "$db_path" 2>/dev/null || stat -c%s "$db_path" 2>/dev/null || echo 0)" |
There was a problem hiding this comment.
should-fix: stat -f%z (BSD/macOS) runs first, fails on Linux (exit 1, verified), then stat -c%s (GNU/Linux) succeeds via ||. The action only supports Linux (runner.os != 'Linux' exits early at action.yml:168). Swapping to stat -c%s first eliminates an unnecessary failing subprocess on every invocation. The macOS fallback can remain as-is after the ||.
| @@ -0,0 +1,32 @@ | |||
| #!/usr/bin/env bash | |||
There was a problem hiding this comment.
should-fix: Neither cleanup-db.sh nor the migration recovery block in run-opencode.sh (line 148) has test coverage. The existing test suite (tests/test_all.py) has no references to cleanup-db, OPENCODE_DB_PATH, or duplicate column name. At minimum, cleanup-db.sh should have a test that verifies it deletes a file exceeding the threshold and leaves a file under the threshold alone.
|
|
||
| # Auto-recover from SQLite migration failures: delete the stale db and retry once. | ||
| if [[ "$migration_recovery_done" == "false" ]] && grep -qi "duplicate column name" "$log_file"; then | ||
| db_path="${OPENCODE_DB_PATH:-$HOME/.local/share/opencode/opencode.db}" |
There was a problem hiding this comment.
should-fix: OPENCODE_DB_PATH is never set by github-run-opencode/action.yml for either the cleanup-db step or the run-opencode step. If a user configures opencode with a non-default database path, neither the preventive cleanup (cleanup-db.sh) nor the reactive recovery (this line) will find it — both hardcode ~/.local/share/opencode/opencode.db. Consider adding an optional db-path input to github-run-opencode/action.yml that flows OPENCODE_DB_PATH to both steps, or document that users must set OPENCODE_DB_PATH in their workflow env: for custom paths.

Summary
Closes #198
Prevents and recovers from stale
opencode.dbSQLite database issues on self-hosted runners, where the database can grow to 160MB+ and causeduplicate column namemigration errors when opencode upgrades.Changes
Scheme A — Preventive cleanup (before run)
shared/cleanup-db.sh: standalone script that checksopencode.dbsize and deletes it if it exceeds a configurable threshold (default 50MB)github-run-opencodeinputcleanup-db:"true"(default, 50MB threshold), a number like"100"for custom MB threshold, or"false"to disablegithub-run-opencode/action.ymlbetween install and runScheme C — Migration failure auto-recovery (during run)
run-opencode/run-opencode.sh: detectsduplicate column nameerrors in opencode output, auto-deletes the stale database, and retries onceDocs
github-run-opencode/README.mdwith new input and feature descriptionrun-opencode/README.mdwith migration recovery descriptionshared/README.mdwith cleanup-db.sh documentationTesting
All pre-existing tests pass identically on this branch (21 failures + 4 errors are pre-existing on main due to Python 3.14 type union syntax and missing dogfood workflow file — not introduced by this PR).
Files changed
shared/cleanup-db.shgithub-run-opencode/action.ymlcleanup-dbinput + cleanup steprun-opencode/run-opencode.shgithub-run-opencode/README.mdrun-opencode/README.mdshared/README.md