Skip to content

Clean up unused projects when migration setup is cancelled - #3201

Open
HarshMN2345 wants to merge 18 commits into
mainfrom
codex/fix-7685-migration-project-cleanup
Open

HarshMN2345 wants to merge 18 commits into
mainfrom
codex/fix-7685-migration-project-cleanup

Conversation

@HarshMN2345

@HarshMN2345 HarshMN2345 commented Sep 15, 2026

Copy link
Copy Markdown
Member

Cancelling migration setup after creating a destination project left the project behind. Going back to edit the setup and continuing also created another project each time.

Track the project created by the wizard, reuse it while its settings match, and delete an unused destination before confirming exit or replacing it. Wait for in-flight creation and deletion, use the returned project region and ID, and keep the wizard open when cleanup fails so the user can retry. Once an import request is attempted, retain the destination even if the response fails because data may already be importing.

Route browser Back and internal links through the same exit confirmation and cleanup. Resume an internal link after successful cleanup; successful migration submission closes the wizard before navigating to its destination. Only wizards with an exit cleanup callback register the navigation handler.

Closes appwrite/appwrite#7685.

Validation:

  • The cancellation regression fails on the original source and passes with the fix.
  • 26 migration component regressions and 4 wizard ownership tests cover existing destinations, reuse/replacement, creation and deletion races, cleanup failures, missing projects, import retention, prepared destination selection, keyboard exits and navigation through the mounted shell.
  • All 321 unit/component tests pass locally and in GitHub CI. Formatting, dependency audit, Svelte check, lint and the production build pass with existing warnings.
  • Isolated headless Chromium passes six cancellation, keyboard, cleanup retry and navigation scenarios through the actual shell navigation hook, with no page errors or external requests.
  • The E2E workflow succeeds: 1 staging journey passes on the first attempt and 2 pass on retry. The console-stage deployment check passes. Staging journeys were not executed locally.

Cleanup covers confirmed wizard exits and internal navigation. Tab close, reload and external page unload cannot await asynchronous cleanup.

@appwrite

appwrite Bot commented Sep 15, 2026

Copy link
Copy Markdown

Console (appwrite/console)

Project ID: 688b7bf400350cbd60e9

Sites (1)
Site Status Logs Preview QR
 console-stage
688b7cf6003b1842c9dc
Ready Ready View Logs Preview URL QR Code

Tip

Git integration provides automatic deployments with optional PR comments

@HarshMN2345
HarshMN2345 marked this pull request as ready for review September 15, 2026 07:54
@greptile-apps

greptile-apps Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 3/5

The PR is not yet safe to merge because confirmed browser Back navigation still closes the wizard without completing the canceled history traversal.

Fix All in Claude CodeFindings

  1. P1 Back Navigation Is Lost
  2. P2 Tests Mirror Private State
Fix with agent prompt
### Issue 1
src/lib/layout/shell.svelte:114-118
When the user presses browser Back, this code cancels the navigation and passes `null` to the exit handler. After cleanup succeeds, the wizard closes, but no destination exists to resume the canceled history traversal. The user therefore remains on the same route and must press Back again.

### Issue 2
src/lib/stores/wizard.test.ts:12-47
These tests directly inspect the private `exitHandler` store field and mirror its registration and replacement logic instead of testing observable wizard behavior. The migration suite repeats this problem by invoking `get(wizard).exitHandler(...)` and asserting private store state. This violates the repository directive to test observable behavior rather than source implementation, so the tests must be rewritten before merging to exercise navigation through a mounted wizard.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

This PR adds lifecycle management for migration-created destination projects and routes wizard exits through asynchronous cleanup.

  • Reuses or replaces wizard-created projects as destination settings change.
  • Deletes unused destinations after confirmed cancellation and retains them once migration submission is attempted.
  • Intercepts internal navigation while cleanup runs and resumes link navigation after successful cleanup.
  • Adds migration cancellation, cleanup-race, retry, and navigation coverage.

Reviews (2) · Last reviewed commit: "test(migrations): exercise exits through..."

Comment on lines +114 to +118
if ($wizard.exitHandler) {
navigation.cancel();
}
if (navigation.type !== 'leave') {
wizard.hide();
$wizard.exitHandler(
navigation.type === 'popstate' ? null : (navigation.to?.url.href ?? null)
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Back Navigation Is Lost

When the user presses browser Back, this code cancels the navigation and passes null to the exit handler. After cleanup succeeds, the wizard closes, but no destination exists to resume the canceled history traversal. The user therefore remains on the same route and must press Back again.

Knowledge Base Used: Console application shell

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/layout/shell.svelte
Line: 114-118

Comment:
**Back Navigation Is Lost**

When the user presses browser Back, this code cancels the navigation and passes `null` to the exit handler. After cleanup succeeds, the wizard closes, but no destination exists to resume the canceled history traversal. The user therefore remains on the same route and must press Back again.

**Knowledge Base Used:** [Console application shell](https://app.greptile.com/appwrite/-/custom-context/knowledge-base/appwrite/console/-/docs/console-application-shell.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Codex

Comment on lines +12 to +47
const unregister = wizard.setExitHandler(handler);

expect(get(wizard).exitHandler).toBe(handler);
unregister();

expect(get(wizard).exitHandler).toBeNull();
});

it('does not unregister a replacement component handler', () => {
const unregister = wizard.setExitHandler(vi.fn());
const replacement = vi.fn();
wizard.setExitHandler(replacement);

unregister();

expect(get(wizard).exitHandler).toBe(replacement);
});

it('clears the previous handler when another wizard starts', () => {
const unregister = wizard.setExitHandler(vi.fn());

wizard.start(() => ({}));
expect(get(wizard).exitHandler).toBeNull();

const replacement = vi.fn();
wizard.setExitHandler(replacement);
unregister();
expect(get(wizard).exitHandler).toBe(replacement);
});

it('clears navigation interception when the wizard is hidden', () => {
wizard.start(() => ({}));
wizard.setExitHandler(vi.fn());

wizard.hide();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Tests Mirror Private State

These tests directly inspect the private exitHandler store field and mirror its registration and replacement logic instead of testing observable wizard behavior. The migration suite repeats this problem by invoking get(wizard).exitHandler(...) and asserting private store state. This violates the repository directive to test observable behavior rather than source implementation, so the tests must be rewritten before merging to exercise navigation through a mounted wizard.

Context Used: Call out and harshly judge implementation-coupled tests. We don't mirror source code, configuration, or version pins in assertions. We test observable behavior; use linters for syntax and schema checks. (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/stores/wizard.test.ts
Line: 12-47

Comment:
**Tests Mirror Private State**

These tests directly inspect the private `exitHandler` store field and mirror its registration and replacement logic instead of testing observable wizard behavior. The migration suite repeats this problem by invoking `get(wizard).exitHandler(...)` and asserting private store state. This violates the repository directive to test observable behavior rather than source implementation, so the tests must be rewritten before merging to exercise navigation through a mounted wizard.

**Context Used:** Call out and harshly judge implementation-coupled tests. We don't mirror source code, configuration, or version pins in assertions. We test observable behavior; use linters for syntax and schema checks. ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code Fix in Codex

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.

🐛 Bug Report: Cancelling Initial Migration Creates a Pseudo Project

1 participant