Skip to content

Fix SQLite source-tree migration discovery#129

Open
neubig wants to merge 2 commits into
mainfrom
openhands/fix-sqlite-migration-discovery
Open

Fix SQLite source-tree migration discovery#129
neubig wants to merge 2 commits into
mainfrom
openhands/fix-sqlite-migration-discovery

Conversation

@neubig
Copy link
Copy Markdown
Member

@neubig neubig commented May 19, 2026

Summary

  • Extract SQLite migration path discovery into a helper.
  • Preserve packaged migration discovery while checking the source checkout repo-root migrations/ path via package_dir.parent.parent / "migrations".
  • Retain the previous package_dir.parent / "migrations" path as a legacy fallback.
  • Add tests covering packaged, source checkout, legacy fallback, and missing-path behavior.

Fixes #128.

Tests

  • uv run pytest tests/test_app_migrations.py -v
  • uv run ruff check openhands/automation/app.py tests/test_app_migrations.py
  • uv run ruff format --check openhands/automation/app.py tests/test_app_migrations.py
  • uv run pre-commit run --files openhands/automation/app.py tests/test_app_migrations.py --show-diff-on-failure
  • Attempted uv run pytest tests/ -v --ignore=tests/integration, but the full suite could not complete because this environment does not have a Docker daemon available for testcontainers.

This PR was created by an AI agent (OpenHands) on behalf of the user.

@neubig can click here to continue refining the PR

Co-authored-by: openhands <openhands@all-hands.dev>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 19, 2026

🚀 Deploy Preview PR Created/Updated

A deploy preview has been created/updated for this PR.

Deploy PR: https://github.com/OpenHands/deploy/pull/4348
Automation SHA: 010b40af90dc09d7d8b0c65413d3f8b6716c7230
Last updated: May 19, 2026, 11:26:15 PM ET

Once the deploy PR's CI passes, the automation service will be deployed to the feature environment.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 19, 2026

Coverage

Coverage Report
FileStmtsMissCoverMissing
__init__.py10100% 
app.py1537650%59, 62, 65, 71, 73, 76, 79–82, 85, 90–92, 94, 96, 98–99, 101–102, 105–111, 114–115, 118, 125–126, 129–130, 134, 142–143, 146, 153–154, 156, 159–160, 163, 168–176, 178–180, 286–288, 293–294, 296–297, 299, 302–304, 306–307, 309–310, 315–316, 320, 323, 325
auth.py146795%82, 110, 119, 156, 376, 384–385
config.py1580100% 
constants.py170100% 
db.py672956%60, 74–75, 78–80, 82, 89, 92–93, 96, 104, 111, 144, 147–148, 152–153, 161, 169, 174, 201, 204–210
dispatcher.py1864575%70, 82, 84–85, 137, 199–202, 237, 240, 255–256, 262–264, 281–282, 288–292, 295–297, 307, 373–374, 399–406, 426, 441–442, 456–457, 466–467, 469
event_router.py591967%83, 88, 119–121, 137–138, 156, 158, 160–161, 163, 173, 179–181, 184, 186, 188
exceptions.py40100% 
execution.py22013339%39–41, 76–79, 87–91, 93, 101–103, 108–112, 114, 128–131, 133, 135, 137–140, 142–147, 149, 151–158, 160–161, 163, 199–201, 207–209, 220–223, 229–231, 271–275, 284, 292, 296, 298–299, 304–305, 310, 388–389, 473–475, 477–483, 486–487, 489, 491–493, 496, 499, 502–505, 507, 510–511, 514–516, 520–521, 525–528, 530, 538–539, 543–545, 547–553, 557, 559, 568–570, 572–574
filter_eval.py50296%161–162
logger.py551769%37, 50–51, 53–59, 74, 77, 101, 103–106
models.py810100% 
preset_router.py1905670%143–145, 255–256, 261–268, 273, 276, 278–279, 291–294, 296–300, 305, 314, 386–388, 501–502, 507–514, 519, 522, 524–525, 537–540, 542–546, 551, 561
router.py1176544%80–81, 101, 103, 106, 108, 122, 135, 137–138, 140–141, 143–144, 147–149, 160–162, 180–183, 202, 205, 208, 215, 217, 251–253, 256–258, 262–263, 268, 272–275, 277, 285, 287–288, 293–294, 297, 299, 301–303, 306–309, 314, 316–317, 326, 347–349, 353
scheduler.py60985%134–135, 172–173, 188–189, 199–200, 202
schemas.py2701793%32, 166, 172–174, 233–235, 237, 342–343, 346, 351, 356, 500, 508, 515
trigger_matcher.py28389%72–74
uploads.py1075944%142–145, 153–155, 161–162, 165, 174–175, 178–179, 187–188, 190–193, 196–199, 201, 203–205, 207–210, 212–213, 215, 230, 236–237, 240, 243, 246, 249, 251, 264–265, 279, 282–284, 286–287, 289, 295–296, 309, 317–319, 323
watchdog.py984554%55–57, 69–70, 162–163, 204–205, 207, 209, 218, 220–222, 224, 231–233, 235–237, 239–240, 242, 257, 259, 264–267, 269–274, 276–282, 284
webhook_router.py804840%57, 82–83, 107–108, 110, 113–114, 116, 126, 128–132, 137, 139, 151, 154, 157, 164–165, 167, 180, 182–183, 188, 204, 206–207, 213–215, 217–218, 220, 235, 237–238, 243–244, 261, 263–264, 270–271, 273, 275
backends
   __init__.py130100% 
   base.py290100% 
   cloud.py1306252%43–45, 50–52, 103, 116–118, 131–135, 142–143, 145, 147, 159–160, 229–230, 232–233, 235–238, 240–245, 247–255, 257–258, 260, 267–269, 272–273, 275, 282–284, 289–293, 295
   local.py430100% 
event_schemas
   __init__.py29196%53
   custom.py33584%52–53, 64–66
   detection.py320100% 
   github.py125496%306, 311, 456, 483
presets
   __init__.py00100% 
storage
   __init__.py60100% 
   factory.py15193%36
   file_store.py22577%21, 30, 35, 40, 64
   google_cloud.py721184%49, 97–102, 136–137, 190, 192
   local.py680100% 
   s3.py1121586%56, 100, 102–103, 107, 109, 190, 213–215, 269–270, 275, 337–338
utils
   __init__.py50100% 
   agent_server.py530100% 
   api_key.py322425%40–41, 46–48, 50, 55, 60, 62–65, 67–68, 70–71, 73, 79, 81–82, 89, 91–92, 98
   cron.py45686%39, 45, 74, 80, 123, 140
   log_context.py100100% 
   model_profiles.py110100% 
   run.py841483%74–76, 183–184, 200–202, 207–209, 256, 262–263
   sandbox.py716114%49–50, 55–58, 60–62, 64–70, 80–81, 86–92, 115–116, 118–122, 124–128, 159–160, 162, 164–167, 172–173, 176, 180–181, 187–189, 194–196, 201–202, 210–212, 214
   tarball_validation.py480100% 
   time.py30100% 
   webhook.py57984%47, 52, 120, 130–132, 138, 201–202
TOTAL329584874% 

@neubig neubig marked this pull request as ready for review May 20, 2026 03:24
Copy link
Copy Markdown

@all-hands-bot all-hands-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Good taste - Clean refactoring that extracts migration path discovery into a testable helper while maintaining backward compatibility through a prioritized fallback chain.

[RISK ASSESSMENT]

  • [Overall PR] ⚠️ Risk Assessment: 🟢 LOW
    Backward-compatible refactoring with comprehensive test coverage. All previous migration paths are preserved as fallbacks, ensuring no breaking changes for packaged installs, source checkouts, or legacy layouts.

VERDICT:
Worth merging: Solid engineering that fixes issue #128 with well-tested code.

KEY INSIGHT:
The three-candidate fallback approach elegantly handles multiple deployment contexts (packaged wheel, source checkout, legacy) without special-case logic, making the code both maintainable and robust.


Was this automated review useful? React with 👍 or 👎 to this review to help us measure review quality.
Workflow run: https://github.com/OpenHands/automation/actions/runs/26139299198

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.

SQLite migration discovery fallback points to wrong source-tree path

3 participants