Skip to content

Fix 3.0 migration to read from NSUserDefaults instead of Core Data#5

Merged
kern merged 5 commits into
masterfrom
claude/fix-ditto-migration-2R46G
May 17, 2026
Merged

Fix 3.0 migration to read from NSUserDefaults instead of Core Data#5
kern merged 5 commits into
masterfrom
claude/fix-ditto-migration-2R46G

Conversation

@kern
Copy link
Copy Markdown
Owner

@kern kern commented May 17, 2026

LegacyDataMigrator was scanning for a Core Data SQLite store that
pre-3.0 installs never had — the v1/v2 app persisted user content
in NSUserDefaults under "categories" ([String]) and "dittos"
([String: [String]]). On upgrade the migration silently no-op'd
and DittoStore filled the new SwiftData container with presets,
which is why users saw their dittos disappear.

  • Rewrite migrator to read the legacy NSUserDefaults keys from
    both the App Group suite and UserDefaults.standard, merging by
    title when both are populated.
  • Reuse any existing Profile (e.g. one already filled with presets
    by a broken 3.0 launch) and merge legacy categories/dittos into
    it by title/text, so affected users recover their data without
    duplicates on the next launch.
  • Do NOT delete the legacy keys from NSUserDefaults; the source
    data stays intact so users can roll back or re-run if needed.
  • Switch the completion flag key so installs that were marked
    complete by the broken Core Data migrator will run the new
    NSUserDefaults migration once.
  • Update tests to cover detection, order preservation, the
    no-delete invariant, and the standard-defaults fallback path.

claude added 5 commits May 17, 2026 15:24
LegacyDataMigrator was scanning for a Core Data SQLite store that
pre-3.0 installs never had — the v1/v2 app persisted user content
in NSUserDefaults under "categories" ([String]) and "dittos"
([String: [String]]). On upgrade the migration silently no-op'd
and DittoStore filled the new SwiftData container with presets,
which is why users saw their dittos disappear.

- Rewrite migrator to read the legacy NSUserDefaults keys from
  both the App Group suite and UserDefaults.standard, merging by
  title when both are populated.
- Reuse any existing Profile (e.g. one already filled with presets
  by a broken 3.0 launch) and merge legacy categories/dittos into
  it by title/text, so affected users recover their data without
  duplicates on the next launch.
- Do NOT delete the legacy keys from NSUserDefaults; the source
  data stays intact so users can roll back or re-run if needed.
- Switch the completion flag key so installs that were marked
  complete by the broken Core Data migrator will run the new
  NSUserDefaults migration once.
- Update tests to cover detection, order preservation, the
  no-delete invariant, and the standard-defaults fallback path.
- LegacyDataMigratorTests: replace the 5-element tuple with a private
  DefaultsSnapshot struct so SwiftLint's large_tuple rule passes.
- LegacyDataMigrator: drop the indented `///   - ` bullets in the
  doc comment so the consecutiveSpaces rule no longer flags them.
- ScreenshotTests: mark the XCTestCase subclass @mainactor so calls
  to the @MainActor-isolated setupSnapshot / snapshot helpers compile
  under stricter actor isolation checking (pre-existing on master).
- SnapshotHelper: collapse the double space after `?` on the landscape
  ternary so consecutiveSpaces no longer fails the SwiftFormat job
  (pre-existing on master).
Swift Testing creates a fresh struct instance per @test method, so
the prior static helpers couldn't be reached from instance methods
without a Self. prefix and the compiler rejected the bare references.
Demote the helpers and constants to instance members so the @test
methods can call them directly.
The Tests and UI Tests step timeouts (10 min) tripped on this branch
after the @mainactor fix unblocked the build. Worse, the trailing
`| tail -30` buffered xcodebuild's output until the pipeline finished,
so when the step timed out there was no useful progress to diagnose.

- Bump Run unit tests step timeout 10 → 15 min and the job to 25 min.
- Bump Run UI tests step timeout 10 → 15 min and the job to 30 min.
- Drop the trailing tail so xcodebuild output streams as it runs, and
  add a Show-test-errors step that prints the last 200 lines on failure
  so a hang or slow test is visible in the action log.
Tests still timed out at the 15-min step budget. Adding xcodebuild's
per-test timeout (60s default, 180s max) so a single hung test gets
killed and reported by xcresult instead of consuming the whole step
budget, and so we can identify which test stalls.
@kern kern merged commit c8ffeb8 into master May 17, 2026
5 checks passed
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.

2 participants