fix: add missing ai_providers columns and fix linux-amd64 build #41
No reviewers
Labels
No Label
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: sarman/tftsr-devops_investigation#41
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "fix/ai-provider-migration-issue"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
🤖 Automated PR Review:\n\n### 1. Summary
This PR addresses two main issues:
use_datastore_upload,created_at) to theai_providerstable via a new migration (015_add_ai_provider_missing_columns), with robust error handling for idempotency.fuseand installslinuxdeploy(required for Tauri 2.x AppImage bundling) to thelinux-amd64Dockerfile.The changes are generally well-structured, with thoughtful error handling and a comprehensive test. However, there are several critical and high-priority issues that must be addressed before merging.
2. Bugs / Errors
🔴 Critical: Incorrect
linuxdeployinstallation in Dockerfile➡️ Problem: This line only makes an already-installed
linuxdeployexecutable — but nocurlorwgetcommand downloads it.linuxdeployis not part of the base image or any priorapt-get install. This will cause the build to fail with:✅ Fix:
🟠 High: Migration SQL syntax error
➡️ Problem: SQLite does not support multiple
ALTER TABLEstatements in a singleALTER TABLEcommand — eachALTER TABLEmust be executed separately. The current code passes the entire string toconn.execute_batch(sql), which will fail with:✅ Fix:
Split the migration into two separate entries in the
migrationsarray:Or, if you want to keep a single migration name (e.g.,
015_add_ai_provider_missing_columns), use twoexecutecalls in the migration runner — but the currentmigrationsloop expects one SQL string per migration.🟠 High: Test uses
i64forINTEGERcolumn, but SQLite stores booleans as0/1➡️ Problem:
use_datastore_uploadis declared asINTEGER(noPRIMARY KEY, noCHECK, noBOOLEANtype). SQLite has noBOOLEANtype — it stores0/1as integers. Usingi64is technically correct, but semantically misleading.✅ Fix: Either:
bool(rusqlite supportsboolmapping to0/1):i64, but add a comment:// SQLite INTEGER used for boolean (0/1)Also, consider adding a
CHECK (use_datastore_upload IN (0, 1))constraint in the migration.🟡 Medium: Test doesn’t verify idempotency (skipping on duplicate columns)
The migration has logic to handle
duplicate column name, but the test only verifies the success path. The error-handling branch is untested.✅ Fix: Add a test case:
3. Security Issues
🟢 No direct security issues found, but:
use_datastore_uploadis anINTEGER— ensure it’s used as a boolean (0/1) in application logic. If misused (e.g., as a count), it could lead to logic bugs (e.g., uploading unintended data). Recommend adding:created_atisTEXT NOT NULL DEFAULT (datetime('now')). Ensure all consumers parse it consistently (e.g., ISO 8601). SQLite’sdatetime('now')returnsYYYY-MM-DD HH:MM:SS, which is safe and standard.4. Best Practices
✅ Good practices present:
🟡 Improvements recommended:
Migration naming convention
Current:
015_add_ai_provider_missing_columnsBetter:
015_add_missing_columns_to_ai_providers→ Avoids ambiguity (e.g., "missing" could refer to many columns).
Use
TIMESTAMPtype forcreated_at?TEXTwith ISO 8601 is fine, but considerINTEGER(Unix epoch) for easier sorting/comparisons.→ If keeping
TEXT, ensure all app code useschrono::DateTime<Utc>or equivalent.Add migration version to schema
Consider adding a
schema_versiontable to track applied migrations explicitly (though rusqlite/migrations pattern likely handles this internally).Dockerfile: Use multi-stage for final image
The current Dockerfile installs Rust toolchain and build deps but doesn’t show the final image. Ensure
linuxdeployis not included in the final runtime image (only needed for bundling).→ Add comment:
# linuxdeploy only needed during bundling, not runtimeAdd
updated_atto migration?The table definition in tests already has
updated_at, but the migration SQL doesn’t mention it. Ensure it’s not accidentally dropped or duplicated.Final Recommendation
Do not merge as-is. Fix the following before merging:
linuxdeploydownload step (critical).ALTER TABLEstatements (critical).After fixes, this is a solid, production-ready PR.\n\n---\nthis is an automated review from Ollama
🤖 Automated PR Review:\n\n### 1) Summary
This PR addresses two issues:
use_datastore_uploadandcreated_atcolumns to theai_providerstable, with idempotent handling for partial/multiple migration runs.fuseandlinuxdeployto support AppImage bundling for Tauri 2.x.The migration logic now gracefully handles column-already-exists errors, and includes comprehensive unit tests for idempotency and data integrity.
2) Bugs / Errors
❌ Critical:
linuxdeployinstallation is incomplete and brokenIn the Dockerfile,
linuxdeployis referenced but never actually downloaded or installed:➡️ Problem:
chmodis executed on a non-existent file (/usr/local/bin/linuxdeploy), which will cause the Docker build to fail withchmod: cannot access '/usr/local/bin/linuxdeploy': No such file or directory.✅ Fix (recommended approach):
But that’s overly complex and fragile. A more robust, maintainable solution:
⚠️ Migration SQL:
created_atcolumn usesdatetime('now')but type isTEXT— could cause issues➡️ Problem:
datetime('now')returns a string like"2024-06-15 14:30:22"— acceptable forTEXT, but:datetime()function compatibility unless explicitly cast.CURRENT_TIMESTAMP(which isTEXTin SQLite), it’s still inconsistent.✅ Fix: Explicitly document the format and ensure consistency across the codebase.
Better yet: use
TIMESTAMP(SQLite treats it asTEXTanyway) but add a comment:→
strftimegives more control and avoids ambiguousdatetime()behavior.Also: consider using
created_at TEXT NOT NULL DEFAULT (datetime('now', 'utc'))if UTC is required.⚠️ Migration error handling is overly broad
➡️ Problem:
"has no column named"is a runtime query error, not a DDL error — it may appear in unrelated contexts (e.g.,SELECTon a malformed table)."duplicate column name"is correct forALTER TABLE ADD COLUMN, but"has no column named"is misleading here — SQLite returns"duplicate column name"for duplicateADD COLUMN, but"has no column named"is for invalid column references inSELECT,UPDATE, etc.✅ Fix: Use precise error codes or strings. SQLite error codes:
SQLITE_ERROR(1) with"duplicate column name"→err_str.contains("duplicate column name")✅"has no column named"is not expected inALTER TABLE ADD COLUMN, so it should be treated as a real error.→ Only check for
"duplicate column name":3) Security Issues
✅ No critical security issues found.
execute()/execute_batch()— safe.linuxdeployinstallation (if fixed) uses HTTPS from GitHub releases — secure if checksums or signatures are verified (but that’s out of scope for this PR; assume trusted source for now).4) Best Practices
✅ Strong migration idempotency testing
The added unit tests (
test_add_missing_columns_to_existing_table,test_idempotent_add_missing_columns) are excellent:✅ Clear separation of
executevsexecute_batchCorrectly uses
execute()for singleALTER TABLE(SQLite limitation) andexecute_batch()for multi-statement migrations (e.g., FTS5). This avoids subtle bugs.⚠️ Migration names should be deterministic and versioned
➡️ Risk: If multiple PRs add migrations, naming collisions can occur (e.g., two
015_...files).✅ Best practice: Use timestamps or UUIDs for uniqueness:
Or adopt a migration framework (e.g.,
migrate-rs) that handles ordering.⚠️ Missing rollback plan
SQLite
ALTER TABLEhas limited rollback (only via transaction, but noDROP COLUMNin older SQLite versions).➡️ If migration 015/016 fails partway, the table may be left in an inconsistent state (e.g.,
use_datastore_uploadadded butcreated_atnot).✅ Recommendation:
⚠️ Dockerfile comment is outdated
➡️
linuxdeployis now always needed for Tauri 2.x AppImage builds — update comment to reflect that.✅ Final Recommendations
linuxdeploynot installed"has no column named"error check too broaddatetime('now')vsstrftime(..., 'utc')conn.transaction()linuxdeployrequirementLet me know if you'd like a corrected Dockerfile snippet or migration code patch!\n\n---\nthis is an automated review from Ollama
🤖 Automated PR Review:\n\n### 1. Summary
This PR addresses two key issues:
use_datastore_upload,created_at) to theai_providerstable with idempotent handling for re-runs.linuxdeploy(required for Tauri 2.x AppImage bundling) and updates documentation comments.The changes are well-structured, include thorough tests, and follow common Rust/SQLite patterns. However, there are critical correctness issues in the migration logic and a security concern in the Dockerfile.
2. Bugs / Errors
🔴 Critical: Incorrect error handling for
ALTER TABLEmigrationsIn
migrations.rs, the logic for handling015_add_use_datastore_uploadand016_add_created_atis flawed:Problem:
conn.execute(sql, [])is used forALTER TABLE, but SQLite’sexecute()only supports one statement per call, andALTER TABLEis a single statement — ✅ correct in principle.e.to_string()may not always contain"duplicate column name"verbatim. SQLite error messages can vary by version, locale, or build (e.g.,"duplicate column name: use_datastore_upload"vs"duplicate column name"), and rusqlite wraps errors (e.g.,rusqlite::Error::SqliteFailure), so.to_string()may include extra context.Worse: If the error message format changes (e.g., due to SQLite upgrade), the migration could silently fail to add the column on re-run, or panic on unexpected error.
✅ Suggested fix: Use
rusqlite::ErrorCodeto check for the exact error code:🟡 Minor: Inconsistent use of
execute()vsexecute_batch()The refactored logic now uses
execute()forALTER TABLEandexecute_batch()for others — good. But the comment says:This is true, but the previous code used
execute_batch()for all non-FTS migrations, which would have failed forALTER TABLE(sinceALTER TABLE ...; ALTER TABLE ...is invalid). So the fix is correct only because each migration SQL string is a singleALTER TABLEstatement.✅ But: Ensure future migrations don’t accidentally add multi-statement SQL (e.g.,
ALTER TABLE ...; CREATE INDEX ...) — consider adding a linter or comment warning.3. Security Issues
🔴 Dockerfile: Insecure
linuxdeploydownload and extractionProblem:
linuxdeploy.AppImage.The full Dockerfile likely has:
But without a checksum, this is vulnerable to:
linuxdeploychanges behavior between versions✅ Suggested fix:
linuxdeploy 1.0.1).aptorsnap), though AppImage is common forlinuxdeploy.4. Best Practices
✅ Good: Comprehensive tests
test_idempotent_add_missing_columns) is well-tested.✅ Good: Graceful handling of FTS5
⚠️ Improve: Migration naming & ordering
015_add_use_datastore_upload,016_add_created_at.created_atshould ideally be added beforeuse_datastore_uploadif there are dependencies (thoughALTER TABLEis independent here).20240615120000_add_use_datastore_upload) to avoid ordering issues across branches.⚠️ Improve: Default value consistency
use_datastore_uploadisINTEGER DEFAULT 0, but the test usesbool: SQLite storesINTEGERforbool, and rusqlite maps0/1toboolautomatically — ✅ works, but clarify in comments or useBOOLEAN(SQLite treatsBOOLEANasINTEGERanyway).✅ Good: Documentation updates
linuxdeployneed.Final Recommendations
rusqlite::ErrorCodeinstead of string matchingBefore merging, ensure:
rusqlite::ErrorCode::ConstraintViolation.Let me know if you’d like a patch for the corrected migration logic!\n\n---\nthis is an automated review from Ollama