Skip to content

Add JSON import/export endpoints for migrations#11646

Open
premtsd-code wants to merge 14 commits into1.9.xfrom
feat/import-export-json
Open

Add JSON import/export endpoints for migrations#11646
premtsd-code wants to merge 14 commits into1.9.xfrom
feat/import-export-json

Conversation

@premtsd-code
Copy link
Copy Markdown
Contributor

Summary

  • Add POST /v1/migrations/json/imports — import documents from a JSON file
  • Add POST /v1/migrations/json/exports — export documents to a JSON file
  • Works for all database types (tablesdb, documentsdb, vectorsdb)
  • Uses existing migration worker pipeline (queue, file storage, email notifications)
  • JSON format preserves nested objects (metadata) unlike CSV

Cherry-picked from import-export-json branch (1.8.x) and adapted for 1.9.x:

  • Updated App:: to Http:: routing
  • Removed stale spec files (specs dir removed in 1.9.x)
  • Fixed duplicate setProject call in import endpoint

Depends on: utopia-php/migration PR #141 (already merged)

Test plan

  • JSON export creates downloadable file with correct document data
  • JSON import creates documents from uploaded JSON file
  • Works with documentsdb collections (nested metadata)
  • Works with vectorsdb collections (embeddings arrays)
  • Error handling for malformed JSON, wrong schema
  • Email notification on export completion

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds two ADMIN-only JSON migration API endpoints: POST /v1/migrations/json/imports and POST /v1/migrations/json/exports. The imports handler validates bucket/file presence, inspects file attributes for OpenSSL/ZSTD/GZIP processing, writes or transfers a JSON payload to the migrations device, computes size, creates a migrations document (source=JSON, destination=Appwrite) and enqueues processing. The exports handler validates queries, resolves and authorizes database/collection and ID types, creates a migrations document (source=Appwrite, destination=JSON) with export options and enqueues processing. Migration worker updated to support JSON source/destination and generalized export completion handling. Multiple JSON test fixtures added and utopia-php/migration bumped to 1.9.*.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and clearly describes the main addition: JSON import/export endpoints for migrations, which matches the primary change in the changeset.
Description check ✅ Passed The description is directly related to the changeset, providing a comprehensive summary of the new JSON import/export endpoints, their purpose, and implementation details.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/import-export-json

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 26, 2026

Greptile Summary

This PR adds POST /v1/migrations/json/imports and POST /v1/migrations/json/exports endpoints, mirroring the existing CSV migration pair, and ships four JSON test fixtures and a minor doc tweak.

The routing and request-handling logic is structurally sound, but the implementation is incomplete in two critical ways that will cause every call to the new endpoints to fail at runtime:

  • Missing JSON class import in the controller — Both new endpoints call JSON::getName(), but no use Utopia\Migration\Sources\JSON (or destination equivalent) is present. PHP will throw a fatal error on first invocation.
  • Migrations worker not updatedprocessSource and processDestination only recognise the existing source/destination types. Any migration queued via the new endpoints will immediately fail in the worker with "Invalid source/destination type". Additionally, there is no handleJSONExportComplete path, so successful JSON exports will never store the output file or dispatch the notification email.

Until these gaps are filled the feature is non-functional end-to-end. The test fixtures and queue-trigger plumbing are otherwise well-structured.

Confidence Score: 1/5

Not safe to merge — both new endpoints will throw fatal errors at runtime due to missing class imports and unimplemented worker handlers.

Three independent P0 blockers exist: (1) JSON class is never imported in the controller, causing a PHP fatal on every call; (2) the worker's processSource/processDestination match statements have no JSON case, so queued migrations immediately throw an exception; (3) there is no JSON export completion handler, so exports would never write the output file or send notifications. The feature is entirely non-functional end-to-end until these gaps are closed.

app/controllers/api/migrations.php and src/Appwrite/Platform/Workers/Migrations.php both require significant additions before the feature can work.

Important Files Changed

Filename Overview
app/controllers/api/migrations.php Adds JSON import and export endpoints, but JSON::getName() references an unimported class, causing a fatal error on both routes; also missing ->setPlatform($platform) in the import trigger.
src/Appwrite/Platform/Workers/Migrations.php Only adds 'type' => $this->dataExportType to email template data, but critically omits JSON cases in processSource/processDestination match statements and a JSON export completion handler — all migrations queued via the new endpoints will fail in the worker.
tests/e2e/Services/Migrations/MigrationsBase.php Refactors test helpers to use @depends chains instead of static cache; changes $this->webEndpoint to $this->endpoint; removes assertEventually timeout args in one place and large migration-fixture tests.
tests/resources/json/documents.json New JSON test fixture for document import; format looks correct.
docs/references/health/get-queue-audits.md Minor wording fix: 'audit logs' → 'audits'; no functional impact.

Comments Outside Diff (2)

  1. src/Appwrite/Platform/Workers/Migrations.php, line 215-254 (link)

    P0 processSource and processDestination don't handle JSON

    The worker's processSource match at line 215 only recognises Firebase, Supabase, NHost, SourceAppwrite, and CSV. When the migration worker picks up a JSON-import migration (whose source is JSON::getName()), it will hit the default case and throw new \Exception('Invalid source type'), silently failing the migration.

    Similarly, processDestination (around line 265–291) only handles DestinationAppwrite and DestinationCSV. A JSON-export migration (destination = JSON::getName()) will throw 'Invalid destination type'.

    Both match statements need new cases — for example in processSource:

    JSON::getName() => new JSON(
        $resourceId,
        $migrationOptions['path'],
        $this->deviceForMigrations,
        $this->dbForProject,
        $getDatabasesDB
    ),

    And in processDestination:

    DestinationJSON::getName() => new DestinationJSON(
        $this->deviceForFiles,
        $migration->getAttribute('resourceId'),
        $options['bucketId'],
        $options['filename'],
        $options['columns'],
        $options['queries'],
    ),

    (Adjust constructor arguments to match the actual utopia-php/migration API.)

  2. src/Appwrite/Platform/Workers/Migrations.php, line 553-555 (link)

    P0 Missing JSON export completion handler

    The post-migration block only calls handleCSVExportComplete when the destination is CSV. The JSON export endpoint stores 'notify' => $notify and 'userInternalId' in its options (mirroring the CSV export), but there's no corresponding handleJSONExportComplete (or equivalent) called here.

    As written, a completed JSON export will never:

    1. Move/register the output file in the storage bucket.
    2. Send the user an email notification (even when notify = true).

    A guard analogous to the CSV one is needed:

    if ($migration->getAttribute('destination') === DestinationJSON::getName()) {
        $this->handleJSONExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform, $authorization);
    }

Reviews (1): Last reviewed commit: "cleanup: remove duplicate setProject, re..." | Re-trigger Greptile

@github-actions
Copy link
Copy Markdown

🔄 PHP-Retry Summary

Flaky tests detected across commits:

Commit 30907d7 - 1 flaky test
Test Retries Total Time Details
UsageTest::testVectorsDBStats 1 10.39s Logs

'$id' => $migrationId,
'status' => 'pending',
'stage' => 'init',
'source' => JSON::getName(),
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.

P0 JSON class is not imported

Both JSON::getName() calls (here and at line 864) reference a class that is never imported in this file. The existing pattern for CSV is:

use Utopia\Migration\Sources\CSV;

Without the corresponding use statements for the JSON source and destination classes, PHP will throw a fatal Class 'JSON' not found error whenever either endpoint is called.

The required imports likely look like:

use Utopia\Migration\Sources\JSON;
use Utopia\Migration\Destinations\JSON as DestinationJSON;

(Verify the exact namespace against the utopia-php/migration package once it lands in the vendor directory.)

Comment on lines +759 to +763
$queueForEvents->setParam('migrationId', $migration->getId());

$queueForMigrations
->setMigration($migration)
->setProject($project)
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 Missing ->setPlatform($platform) on the JSON import trigger

Every other migration endpoint (Appwrite, Firebase, Supabase, NHost, and CSV export) calls ->setPlatform($platform) before ->trigger(). The JSON import omits it. While the worker falls back to Config::getParam('platform', []), the missing call is inconsistent and may cause subtle differences in platform-specific behaviour.

Suggested change
$queueForEvents->setParam('migrationId', $migration->getId());
$queueForMigrations
->setMigration($migration)
->setProject($project)
$queueForMigrations
->setMigration($migration)
->setProject($project)
->setPlatform($platform)
->trigger();

@github-actions
Copy link
Copy Markdown

✨ Benchmark results

  • Requests per second: 1,477
  • Requests with 200 status code: 265,936
  • P99 latency: 0.121549769

⚡ Benchmark Comparison

Metric This PR Latest version
RPS 1,477 1,074
200 265,936 193,443
P99 0.121549769 0.208707759

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/controllers/api/migrations.php`:
- Around line 741-757: The migration documents are being created with
source/destination set to JSON via JSON::getName() and export options
(options.path/options.size) are stored, but
src/Appwrite/Platform/Workers/Migrations.php still only recognizes
Appwrite/Firebase/Supabase/NHost/CSV and only handles CSV export completion;
update the worker to accept the JSON source and JSON destination (add
JSON::getName() to the source/destination match/switches in the Migrations
worker), add a JSON-aware export completion path that consumes the options.path
and options.size from the migration document and routes them into the existing
file-finalization/notification logic (so exports do not fail with "Invalid
source/destination" and export options reach finalization), and ensure errors
for unknown types are only raised after these JSON branches are covered.
- Around line 745-746: The code references JSON::getName() which doesn't
exist/wasn't imported and will cause a fatal error; replace JSON::getName() with
the correct migration source (e.g., CSV::getName(), Firebase::getName(),
NHost::getName(), or Supabase::getName() depending on the intended source) and
add the corresponding import from Utopia\Migration\Sources (for example import
Utopia\Migration\Sources\CSV) or, if JSON was intended, add/implement the JSON
source class and import it; update both occurrences of JSON::getName() and
ensure the matching class name is used consistently alongside
Appwrite::getName().

In `@src/Appwrite/Platform/Workers/Migrations.php`:
- Line 792: The code reads an undefined property $this->dataExportType when
calling sendCSVEmail; fix by changing the call site to pass the export type
explicitly (e.g., CSV::getName() as the default) into sendCSVEmail so the
template 'type' receives a value. Locate the sendCSVEmail invocation that
currently builds the payload with 'type' => $this->dataExportType and replace it
to pass a concrete string or CSV::getName() as the third/appropriate argument
(or add an explicit $type parameter to the method call), ensuring sendCSVEmail
and any callers accept/forward this type value instead of relying on the
non-existent dataExportType property.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 70ed7ea5-3c21-4f04-be78-719196cdc260

📥 Commits

Reviewing files that changed from the base of the PR and between 1ab05ac and 30907d7.

⛔ Files ignored due to path filters (1)
  • docs/references/health/get-queue-audits.md is excluded by !docs/references/**
📒 Files selected for processing (7)
  • app/controllers/api/migrations.php
  • src/Appwrite/Platform/Workers/Migrations.php
  • tests/e2e/Services/Migrations/MigrationsBase.php
  • tests/resources/json/documents-internals.json
  • tests/resources/json/documents.json
  • tests/resources/json/irrelevant-column.json
  • tests/resources/json/missing-column.json

Comment on lines +745 to +746
'source' => JSON::getName(),
'destination' => Appwrite::getName(),
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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "JSON::getName() call sites:"
rg -n '\bJSON::getName\s*\(' app/controllers/api/migrations.php

echo
echo "JSON imports in this file:"
rg -n '^\s*use\s+.+\\JSON\s*;' app/controllers/api/migrations.php || true

Repository: appwrite/appwrite

Length of output: 211


🏁 Script executed:

# Check the imports section at the top of the file
head -50 app/controllers/api/migrations.php

Repository: appwrite/appwrite

Length of output: 1719


🏁 Script executed:

# Check context around line 745-746
sed -n '740,750p' app/controllers/api/migrations.php

Repository: appwrite/appwrite

Length of output: 506


🏁 Script executed:

# Check context around line 863-864
sed -n '858,868p' app/controllers/api/migrations.php

Repository: appwrite/appwrite

Length of output: 550


🏁 Script executed:

# Search for JSON class definition in the codebase
rg -l 'class JSON' --type php

Repository: appwrite/appwrite

Length of output: 43


🏁 Script executed:

# Search for JSON migration source class
rg -l 'Utopia.Migration.Sources.JSON' --type php

Repository: appwrite/appwrite

Length of output: 43


🏁 Script executed:

# Look for JSON source class definition in Utopia
rg 'class JSON' --type php -A 3

Repository: appwrite/appwrite

Length of output: 43


🏁 Script executed:

# Search for references to JSON class in migration-related contexts
rg '\bJSON::\w+' --type php | head -20

Repository: appwrite/appwrite

Length of output: 517


🏁 Script executed:

# Check vendor directory for Utopia\Migration\Sources
find . -path '*/Utopia/Migration/Sources*' -name '*.php' 2>/dev/null | head -20

Repository: appwrite/appwrite

Length of output: 43


🏁 Script executed:

# Find all available migration sources
find . -path '*/Migration/Sources/*.php' -type f 2>/dev/null

Repository: appwrite/appwrite

Length of output: 43


🏁 Script executed:

# Check git history or comments for JSON migration source
rg -B5 -A5 'source.*JSON::getName' app/controllers/api/migrations.php

Repository: appwrite/appwrite

Length of output: 506


🏁 Script executed:

# Look for any mention of CSV or other sources to understand the pattern
rg 'CSV::getName|Firebase::getName|Supabase::getName' --type php

Repository: appwrite/appwrite

Length of output: 1122


Resolve JSON::getName() before calling it.

These lines reference JSON::getName() without importing a JSON class. There is no JSON migration source class in the Utopia\Migration\Sources namespace—the available sources are Appwrite, CSV, Firebase, NHost, and Supabase. This will cause a fatal error at runtime. Add the correct migration source class import and replace JSON::getName() with the appropriate source.

Affected lines: 745–746, 863–864.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/controllers/api/migrations.php` around lines 745 - 746, The code
references JSON::getName() which doesn't exist/wasn't imported and will cause a
fatal error; replace JSON::getName() with the correct migration source (e.g.,
CSV::getName(), Firebase::getName(), NHost::getName(), or Supabase::getName()
depending on the intended source) and add the corresponding import from
Utopia\Migration\Sources (for example import Utopia\Migration\Sources\CSV) or,
if JSON was intended, add/implement the JSON source class and import it; update
both occurrences of JSON::getName() and ensure the matching class name is used
consistently alongside Appwrite::getName().

@blacksmith-sh
Copy link
Copy Markdown

blacksmith-sh bot commented Mar 26, 2026

Found 1 test error and 2 test failures on Blacksmith runners:

Error

Test View Logs
› Tests\E2E\Services\Databases\DocumentsDBConsoleClientTest/testTimeout View Logs

Failures

Test View Logs
› Tests\E2E\Services\TablesDB\TablesDBConsoleClientTest/testNotBetween View Logs
› Tests\E2E\Services\TablesDB\Transactions\TablesDBTransactionsConsoleClientTest/
testUpdateDocument
View Logs

Fix in Cursor

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
app/controllers/api/migrations.php (2)

742-758: ⚠️ Potential issue | 🔴 Critical

Worker cannot process JSON imports — will fail with "Invalid source type".

The migration document sets source to JSON::getName(), but src/Appwrite/Platform/Workers/Migrations.php::processSource() (around line 215) only handles Firebase, Supabase, NHost, Appwrite, and CSV sources. This migration will fail immediately when the worker processes it.

The worker's processSource method needs a JSON::getName() case that instantiates the JSON source class.

#!/bin/bash
# Check processSource match statement in worker
rg -A 50 "protected function processSource" src/Appwrite/Platform/Workers/Migrations.php | head -70
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/controllers/api/migrations.php` around lines 742 - 758, The migration
sets source to JSON::getName(), but the worker's processSource() (in
Migrations.php) lacks a case for JSON::getName(), causing "Invalid source type";
update processSource() to add a branch for JSON::getName() that instantiates and
returns the JSON source class (the same class referenced by JSON::getName()) so
the worker can process JSON imports, mirroring how existing cases (Firebase,
Supabase, NHost, Appwrite, CSV) construct their source handler.

860-880: ⚠️ Potential issue | 🔴 Critical

Worker cannot process JSON exports — missing destination handler and export completion logic.

Two issues prevent JSON exports from working:

  1. processDestination() in the worker (around line 271) only matches Appwrite and CSV destinations — JSON::getName() will throw "Invalid destination type".

  2. Export completion handling (line 553 in worker) only triggers for DestinationCSV::getName():

    if ($migration->getAttribute('destination') === DestinationCSV::getName()) {
        $this->handleCSVExportComplete(...);
    }

    JSON exports won't trigger file finalization or email notifications.

The worker needs:

  • A DestinationJSON case in processDestination()
  • Either extend handleCSVExportComplete or add handleJSONExportComplete for JSON destination
#!/bin/bash
# Check processDestination and export completion handling in worker
echo "=== processDestination match ==="
rg -A 15 "protected function processDestination" src/Appwrite/Platform/Workers/Migrations.php

echo -e "\n=== Export completion handling ==="
rg -B2 -A5 "handleCSVExportComplete" src/Appwrite/Platform/Workers/Migrations.php
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/controllers/api/migrations.php` around lines 860 - 880,
processDestination() currently only handles Appwrite and CSV destinations and
will throw for JSON exports; add a case for DestinationJSON::getName() in
processDestination() that mirrors the CSV flow (serialize resources to JSON into
the internal bucket and return the same structure used for CSV). Also ensure
export completion logic that currently calls handleCSVExportComplete(...) when
$migration->getAttribute('destination') === DestinationCSV::getName() is
extended to handle DestinationJSON::getName()—either by reusing/abstracting the
CSV finalization into a common method or by adding a new
handleJSONExportComplete(...) that performs file finalization, updates migration
status, and sends notifications using the same patterns as
handleCSVExportComplete; update references to DestinationJSON::getName(),
processDestination(), handleCSVExportComplete(), and optionally
handleJSONExportComplete() so JSON exports complete and notify correctly.
🧹 Nitpick comments (1)
app/controllers/api/migrations.php (1)

762-765: Missing setPlatform($platform) for consistency with export endpoints.

Both CSV and JSON export endpoints call setPlatform($platform) on the queue, but this JSON import endpoint does not. While imports may not trigger email notifications, including it maintains consistency and future-proofs the code.

♻️ Suggested change
 $queueForMigrations
     ->setMigration($migration)
     ->setProject($project)
+    ->setPlatform($platform)
     ->trigger();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/controllers/api/migrations.php` around lines 762 - 765, Add a call to
setPlatform($platform) on the same queue instance to match the CSV/JSON export
endpoints: update the chain where
$queueForMigrations->setMigration($migration)->setProject($project)->trigger()
is invoked so it also calls ->setPlatform($platform) before ->trigger(); this
keeps behavior consistent and future-proofs imports for any platform-dependent
logic tied to setPlatform.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Appwrite/Platform/Workers/Migrations.php`:
- Line 792: The variable $migration is undefined inside sendCSVEmail; update the
sendCSVEmail method signature to accept a new parameter (e.g., $type) and use
that instead of referencing $migration inside the method, then update all call
sites in handleCSVExportComplete to pass $migration->getAttribute('destination',
'CSV') into sendCSVEmail; ensure references in sendCSVEmail that previously used
$migration->getAttribute('destination', 'CSV') are replaced with the new $type
parameter.

---

Duplicate comments:
In `@app/controllers/api/migrations.php`:
- Around line 742-758: The migration sets source to JSON::getName(), but the
worker's processSource() (in Migrations.php) lacks a case for JSON::getName(),
causing "Invalid source type"; update processSource() to add a branch for
JSON::getName() that instantiates and returns the JSON source class (the same
class referenced by JSON::getName()) so the worker can process JSON imports,
mirroring how existing cases (Firebase, Supabase, NHost, Appwrite, CSV)
construct their source handler.
- Around line 860-880: processDestination() currently only handles Appwrite and
CSV destinations and will throw for JSON exports; add a case for
DestinationJSON::getName() in processDestination() that mirrors the CSV flow
(serialize resources to JSON into the internal bucket and return the same
structure used for CSV). Also ensure export completion logic that currently
calls handleCSVExportComplete(...) when $migration->getAttribute('destination')
=== DestinationCSV::getName() is extended to handle
DestinationJSON::getName()—either by reusing/abstracting the CSV finalization
into a common method or by adding a new handleJSONExportComplete(...) that
performs file finalization, updates migration status, and sends notifications
using the same patterns as handleCSVExportComplete; update references to
DestinationJSON::getName(), processDestination(), handleCSVExportComplete(), and
optionally handleJSONExportComplete() so JSON exports complete and notify
correctly.

---

Nitpick comments:
In `@app/controllers/api/migrations.php`:
- Around line 762-765: Add a call to setPlatform($platform) on the same queue
instance to match the CSV/JSON export endpoints: update the chain where
$queueForMigrations->setMigration($migration)->setProject($project)->trigger()
is invoked so it also calls ->setPlatform($platform) before ->trigger(); this
keeps behavior consistent and future-proofs imports for any platform-dependent
logic tied to setPlatform.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1a214281-7691-469c-be3a-336e65a02b4d

📥 Commits

Reviewing files that changed from the base of the PR and between 30907d7 and 8f09e74.

📒 Files selected for processing (3)
  • app/controllers/api/migrations.php
  • composer.json
  • src/Appwrite/Platform/Workers/Migrations.php
✅ Files skipped from review due to trivial changes (1)
  • composer.json

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/Appwrite/Platform/Workers/Migrations.php (1)

807-807: ⚠️ Potential issue | 🔴 Critical

Undefined variable in email variables payload (runtime error).

Line 807 reads $migration inside sendCSVEmail(), but that variable is not in scope in this method, which will fail when email notification is sent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Appwrite/Platform/Workers/Migrations.php` at line 807, sendCSVEmail uses
an undefined $migration variable (line with 'type' =>
$migration->getAttribute('destination', 'CSV')), which will cause a runtime
error; fix by using the correct in-scope migration object or value (e.g.,
$this->migration or the migration variable passed into the caller) or by adding
a migration parameter to sendCSVEmail and wiring it from the caller, then call
getAttribute('destination','CSV') on that valid object (and add a null
check/default if needed) so the 'type' entry uses an existing variable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Appwrite/Platform/Workers/Migrations.php`:
- Around line 299-305: The JSON destination was added but the export completion
flow only checks for CSV, so DestinationJSON exports never run the post-export
completion (download-link/email) logic; update the completion gating in the
worker (the block that currently checks DestinationCSV at the export completion
step) to also recognize DestinationJSON (or better, check a common
interface/base like DestinationInterface or a trait such as isDownloadable())
and invoke the same completion steps using the migration options (notify,
filename, bucketId, columns) so JSON exports trigger the download-link/email
pipeline just like CSV exports.

---

Duplicate comments:
In `@src/Appwrite/Platform/Workers/Migrations.php`:
- Line 807: sendCSVEmail uses an undefined $migration variable (line with 'type'
=> $migration->getAttribute('destination', 'CSV')), which will cause a runtime
error; fix by using the correct in-scope migration object or value (e.g.,
$this->migration or the migration variable passed into the caller) or by adding
a migration parameter to sendCSVEmail and wiring it from the caller, then call
getAttribute('destination','CSV') on that valid object (and add a null
check/default if needed) so the 'type' entry uses an existing variable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 19a63d7e-344f-465e-bd63-0c5d8f593dec

📥 Commits

Reviewing files that changed from the base of the PR and between 8f09e74 and 52ae8b3.

📒 Files selected for processing (2)
  • app/controllers/api/migrations.php
  • src/Appwrite/Platform/Workers/Migrations.php
✅ Files skipped from review due to trivial changes (1)
  • app/controllers/api/migrations.php

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/Appwrite/Platform/Workers/Migrations.php (1)

652-660: ⚠️ Potential issue | 🔴 Critical

Fix undefined $migration in sendExportEmail() (runtime error).

Line 809 reads $migration inside sendExportEmail(), but that variable is not in scope in this method. This will fail when building email variables.

Suggested fix
     protected function sendExportEmail(
         bool $success,
         Document $project,
         Document $user,
         array $options,
         Mail $queueForMails,
         array $platform,
+        string $type = 'CSV',
         string $downloadUrl = '',
         float $sizeMB = 0.0,
     ): void {
@@
-            'type' => $migration->getAttribute('destination', 'CSV'),
+            'type' => $type,
         ];
                 $this->sendExportEmail(
                     success: false,
                     project: $project,
                     user: $user,
                     options: $options,
                     queueForMails: $queueForMails,
                     platform: $platform,
+                    type: $migration->getAttribute('destination', 'CSV'),
                     sizeMB: $sizeMB
                 );
         $this->sendExportEmail(
             success: true,
             project: $project,
             user: $user,
             options: $options,
             queueForMails: $queueForMails,
             platform: $platform,
+            type: $migration->getAttribute('destination', 'CSV'),
             downloadUrl: $downloadUrl
         );
#!/bin/bash
set -euo pipefail

FILE="src/Appwrite/Platform/Workers/Migrations.php"

echo "Method signature and in-method type assignment:"
rg -n -C3 "function sendExportEmail|['\"]type['\"]\s*=>" "$FILE"

echo
echo "Call sites:"
rg -n -C2 "sendExportEmail\(" "$FILE"

Also applies to: 714-722, 739-748, 809-809

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Appwrite/Platform/Workers/Migrations.php` around lines 652 - 660, The
sendExportEmail method references $migration which is not in scope; fix by
adding an optional parameter to sendExportEmail (e.g., ?array $migration = null)
and updating its implementation to handle a null $migration when building email
variables, then update every sendExportEmail(...) call site (calls in this file)
to pass the local $migration where it exists or pass null otherwise so the
method never reads an undefined variable; reference the sendExportEmail function
and the $migration usages inside it when making the changes.
🧹 Nitpick comments (1)
src/Appwrite/Platform/Workers/Migrations.php (1)

739-773: Update export-email docs/text to reflect generic export, not CSV-only.

sendExportEmail() now serves CSV and JSON, but doc/comments and localization key namespace remain CSV-specific, which is misleading for maintenance and future template evolution.
As per coding guidelines, "Include comprehensive PHPDoc comments".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Appwrite/Platform/Workers/Migrations.php` around lines 739 - 773,
sendExportEmail currently uses CSV-specific docs and localization keys
(emails.csvExport.*) while handling CSV and JSON exports; update the PHPDoc for
sendExportEmail to describe generic export notifications (CSV/JSON/other), and
replace all Locale key lookups ("emails.csvExport.{$emailType}.*") with a
generic namespace such as "emails.export.{$emailType}.*" (and adjust the
$buttonText logic accordingly), making sure to also update any related template
identifiers and variable names that reference CSV to use export; preserve
backward-compatibility by falling back to the old keys if the new keys are
missing or update templates and localization files to include the new keys.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Appwrite/Platform/Workers/Migrations.php`:
- Around line 568-570: The post-processing call to handleDataExportComplete is
currently executed for any export destination even when the migration failed;
update the condition that checks $migration->getAttribute('destination') (the
block using DestinationCSV::getName() and DestinationJSON::getName()) to also
verify the migration status is completed (e.g.
$migration->getAttribute('status') === MigrationStatus::STATUS_COMPLETED or
equivalent constant/method on the Migration object) before invoking
handleDataExportComplete($project, $migration, $queueForMails,
$queueForRealtime, $platform, $authorization), so export file/path operations
and notifications only run for successful migrations.

---

Duplicate comments:
In `@src/Appwrite/Platform/Workers/Migrations.php`:
- Around line 652-660: The sendExportEmail method references $migration which is
not in scope; fix by adding an optional parameter to sendExportEmail (e.g.,
?array $migration = null) and updating its implementation to handle a null
$migration when building email variables, then update every sendExportEmail(...)
call site (calls in this file) to pass the local $migration where it exists or
pass null otherwise so the method never reads an undefined variable; reference
the sendExportEmail function and the $migration usages inside it when making the
changes.

---

Nitpick comments:
In `@src/Appwrite/Platform/Workers/Migrations.php`:
- Around line 739-773: sendExportEmail currently uses CSV-specific docs and
localization keys (emails.csvExport.*) while handling CSV and JSON exports;
update the PHPDoc for sendExportEmail to describe generic export notifications
(CSV/JSON/other), and replace all Locale key lookups
("emails.csvExport.{$emailType}.*") with a generic namespace such as
"emails.export.{$emailType}.*" (and adjust the $buttonText logic accordingly),
making sure to also update any related template identifiers and variable names
that reference CSV to use export; preserve backward-compatibility by falling
back to the old keys if the new keys are missing or update templates and
localization files to include the new keys.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b4f2c0ca-a4c3-4fad-8c86-d341b3fad7ae

📥 Commits

Reviewing files that changed from the base of the PR and between b36472f and e850804.

📒 Files selected for processing (2)
  • src/Appwrite/Platform/Workers/Migrations.php
  • tests/e2e/Services/Migrations/MigrationsBase.php

Comment on lines +568 to +570
$destination_type = $migration->getAttribute('destination');
if ($destination_type === DestinationCSV::getName() || $destination_type === DestinationJSON::getName()) {
$this->handleDataExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform, $authorization);
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.

⚠️ Potential issue | 🟠 Major

Gate export post-processing to completed migrations only.

handleDataExportComplete() is invoked even when migration status is failed. This can trigger file/path operations and notifications in error paths.

Suggested fix
-                $destination_type = $migration->getAttribute('destination');
-                if ($destination_type === DestinationCSV::getName() || $destination_type === DestinationJSON::getName()) {
-                    $this->handleDataExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform, $authorization);
-                }
+                if ($migration->getAttribute('status', '') === 'completed') {
+                    $destinationType = $migration->getAttribute('destination');
+                    if (\in_array($destinationType, [DestinationCSV::getName(), DestinationJSON::getName()], true)) {
+                        $this->handleDataExportComplete($project, $migration, $queueForMails, $queueForRealtime, $platform, $authorization);
+                    }
+                }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Appwrite/Platform/Workers/Migrations.php` around lines 568 - 570, The
post-processing call to handleDataExportComplete is currently executed for any
export destination even when the migration failed; update the condition that
checks $migration->getAttribute('destination') (the block using
DestinationCSV::getName() and DestinationJSON::getName()) to also verify the
migration status is completed (e.g. $migration->getAttribute('status') ===
MigrationStatus::STATUS_COMPLETED or equivalent constant/method on the Migration
object) before invoking handleDataExportComplete($project, $migration,
$queueForMails, $queueForRealtime, $platform, $authorization), so export
file/path operations and notifications only run for successful migrations.

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