From 0467ebc1ffc3b2a23acc2703b8e5a4b318d67ab9 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 1 Jun 2025 12:07:46 +0530 Subject: [PATCH 01/15] add: `error` attribute to migrations. --- app/config/collections/projects.php | 17 +++++++++++++ src/Appwrite/Platform/Workers/Migrations.php | 25 ++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php index 48a0938a1c..bdf44e2470 100644 --- a/app/config/collections/projects.php +++ b/app/config/collections/projects.php @@ -2341,6 +2341,23 @@ return [ 'array' => true, 'filters' => [], ], + [ + /** + * A short, human-readable error message (no stacktrace), + * unlike `errors` which contains detailed entries with full trace. + * + * This is mainly used used for csv imports as its failure need to be shown on frontend. + */ + '$id' => ID::custom('error'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], [ '$id' => ID::custom('search'), 'type' => Database::VAR_STRING, diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 395ec1351e..1f094f4dd2 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -365,6 +365,7 @@ class Migrations extends Action $migration->setAttribute('errors', $errorMessages); } } finally { + $this->setMigrationError($migration, $source, $destination); $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); if ($migration->getAttribute('status', '') === 'failed') { @@ -407,4 +408,28 @@ class Migrations extends Action } } } + + /** + * Stores a human-readable error message for migration. + * + * Only applies to migrations where the source is CSV. + */ + private function setMigrationError(Document $migration, ?Source $source, ?Destination $destination): void + { + if ($migration->isEmpty() || $source === null || $destination === null) { + return; + } + + $sourceErrors = $source->getErrors(); + $destinationErrors = $destination->getErrors(); + $migrationSource = $migration->getAttribute('source'); + + if ($migrationSource === CSV::getName()) { + if (! empty($sourceErrors)) { + $migration->setAttribute('error', $sourceErrors[0]->getMessage()); + } elseif (! empty($destinationErrors)) { + $migration->setAttribute('error', $destinationErrors[0]->getMessage()); + } + } + } } From 48d5ae0bca52f4aeacd45db1745f24340551bcbd Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 1 Jun 2025 12:49:42 +0530 Subject: [PATCH 02/15] add: `1.8.x` migrations for adding `error` attribute. --- app/config/collections/projects.php | 1 + src/Appwrite/Migration/Migration.php | 1 + src/Appwrite/Migration/Version/V23.php | 76 ++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 src/Appwrite/Migration/Version/V23.php diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php index bdf44e2470..6fe6dff0ba 100644 --- a/app/config/collections/projects.php +++ b/app/config/collections/projects.php @@ -1286,6 +1286,7 @@ return [ ] ], ], + 'deployments' => [ '$collection' => ID::custom(Database::METADATA), '$id' => ID::custom('deployments'), diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 9071e0cabe..026ce1eb2e 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -89,6 +89,7 @@ abstract class Migration '1.7.2' => 'V22', '1.7.3' => 'V22', '1.7.4' => 'V22', + '1.8.0' => 'V23', ]; /** diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php new file mode 100644 index 0000000000..89ce938657 --- /dev/null +++ b/src/Appwrite/Migration/Version/V23.php @@ -0,0 +1,76 @@ + null, + fn () => [] + ); + } + + Console::info('Migrating collections'); + $this->migrateCollections(); + } + + /** + * Migrate Collections. + * + * @return void + * @throws Exception|Throwable + */ + private function migrateCollections(): void + { + $this->migrateMigrationsCollections(); + } + + /** + * Add `error` attribute on `migrations` collection. + */ + private function migrateMigrationsCollections(): void + { + $projectInternalId = $this->project->getSequence(); + + if ($projectInternalId !== 'projects') { + return; + } + + Console::info(" └── Migrating `migrations` collections."); + + if (empty($projectInternalId)) { + throw new Exception('Project ID is null'); + } + + /** + * direct access.\ + * same as `$this->collections['projects']['migrations']['$id']`. + */ + $migrationCollectionId = 'migrations'; + + try { + $attributes = ['error']; + $this->createAttributesFromCollection($this->dbForProject, $migrationCollectionId, $attributes); + } catch (\Throwable $th) { + Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$migrationCollectionId}: {$th->getMessage()}"); + } + + $this->dbForProject->purgeCachedCollection($migrationCollectionId); + } +} From 66194722a95a49f585bb7401e80a44f6fd6ce1b1 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 1 Jun 2025 12:56:59 +0530 Subject: [PATCH 03/15] add: `error` to response model. --- src/Appwrite/Utopia/Response/Model/Migration.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Appwrite/Utopia/Response/Model/Migration.php b/src/Appwrite/Utopia/Response/Model/Migration.php index 3be1d519a6..75aebfbc66 100644 --- a/src/Appwrite/Utopia/Response/Model/Migration.php +++ b/src/Appwrite/Utopia/Response/Model/Migration.php @@ -85,6 +85,13 @@ class Migration extends Model 'default' => [], 'example' => [], ]) + ->addRule('error', [ + 'type' => self::TYPE_STRING, + 'description' => 'A readable error message that occurred during the CSV migration process.', + 'array' => false, + 'default' => null, + 'example' => '', + ]) ; } From cdd047b459ecbae7db0ae98161c1dc149db6a7bf Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 1 Jun 2025 13:00:44 +0530 Subject: [PATCH 04/15] bump: lockfile. --- composer.lock | 162 +++++++++++++++++++++++--------------------------- 1 file changed, 75 insertions(+), 87 deletions(-) diff --git a/composer.lock b/composer.lock index a16ee400fd..959bcee74c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "34142c56876c7ee1e2a798616b8ff114", + "content-hash": "6c2dda1189f3de260f4b6cc9ce9a428f", "packages": [ { "name": "adhocore/jwt", @@ -283,16 +283,16 @@ }, { "name": "brick/math", - "version": "0.12.3", + "version": "0.13.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba" + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba", + "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", "shasum": "" }, "require": { @@ -331,7 +331,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.12.3" + "source": "https://github.com/brick/math/tree/0.13.1" }, "funding": [ { @@ -339,7 +339,7 @@ "type": "github" } ], - "time": "2025-02-28T13:11:00+00:00" + "time": "2025-03-29T13:50:30+00:00" }, { "name": "chillerlan/php-qrcode", @@ -2323,20 +2323,20 @@ }, { "name": "ramsey/uuid", - "version": "4.7.6", + "version": "4.8.1", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" @@ -2345,26 +2345,23 @@ "rhumsaa/uuid": "self.version" }, "require-dev": { - "captainhook/captainhook": "^5.10", + "captainhook/captainhook": "^5.25", "captainhook/plugin-composer": "^5.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "doctrine/annotations": "^1.8", - "ergebnis/composer-normalize": "^2.15", - "mockery/mockery": "^1.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", "paragonie/random-lib": "^2", - "php-mock/php-mock": "^2.2", - "php-mock/php-mock-mockery": "^1.3", - "php-parallel-lint/php-parallel-lint": "^1.1", - "phpbench/phpbench": "^1.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^8.5 || ^9", - "ramsey/composer-repl": "^1.4", - "slevomat/coding-standard": "^8.4", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.9" + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" }, "suggest": { "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", @@ -2399,19 +2396,9 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.7.6" + "source": "https://github.com/ramsey/uuid/tree/4.8.1" }, - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", - "type": "tidelift" - } - ], - "time": "2024-04-27T21:32:50+00:00" + "time": "2025-06-01T06:28:46+00:00" }, { "name": "spomky-labs/otphp", @@ -2557,16 +2544,16 @@ }, { "name": "symfony/http-client", - "version": "v7.2.4", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6" + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", - "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", + "url": "https://api.github.com/repos/symfony/http-client/zipball/57e4fb86314015a695a750ace358d07a7e37b8a9", + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9", "shasum": "" }, "require": { @@ -2632,7 +2619,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.4" + "source": "https://github.com/symfony/http-client/tree/v7.3.0" }, "funding": [ { @@ -2648,7 +2635,7 @@ "type": "tidelift" } ], - "time": "2025-02-13T10:27:23+00:00" + "time": "2025-05-02T08:23:16+00:00" }, { "name": "symfony/http-client-contracts", @@ -5344,16 +5331,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.4.0", + "version": "v5.5.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", "shasum": "" }, "require": { @@ -5396,9 +5383,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" }, - "time": "2024-12-30T11:07:19+00:00" + "time": "2025-05-31T08:24:38+00:00" }, { "name": "phar-io/manifest", @@ -7266,23 +7253,24 @@ }, { "name": "symfony/console", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218" + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0e2e3f38c192e93e622e41ec37f4ca70cfedf218", - "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218", + "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0" + "symfony/string": "^7.2" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -7339,7 +7327,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.6" + "source": "https://github.com/symfony/console/tree/v7.3.0" }, "funding": [ { @@ -7355,11 +7343,11 @@ "type": "tidelift" } ], - "time": "2025-04-07T19:09:28+00:00" + "time": "2025-05-24T10:34:04+00:00" }, { "name": "symfony/filesystem", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", @@ -7405,7 +7393,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.2.0" + "source": "https://github.com/symfony/filesystem/tree/v7.3.0" }, "funding": [ { @@ -7425,16 +7413,16 @@ }, { "name": "symfony/finder", - "version": "v7.2.2", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d", "shasum": "" }, "require": { @@ -7469,7 +7457,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.2" + "source": "https://github.com/symfony/finder/tree/v7.3.0" }, "funding": [ { @@ -7485,20 +7473,20 @@ "type": "tidelift" } ], - "time": "2024-12-30T19:00:17+00:00" + "time": "2024-12-30T19:00:26+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca", + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca", "shasum": "" }, "require": { @@ -7536,7 +7524,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" + "source": "https://github.com/symfony/options-resolver/tree/v7.3.0" }, "funding": [ { @@ -7552,7 +7540,7 @@ "type": "tidelift" } ], - "time": "2024-11-20T11:17:29+00:00" + "time": "2025-04-04T13:12:05+00:00" }, { "name": "symfony/polyfill-ctype", @@ -7870,16 +7858,16 @@ }, { "name": "symfony/process", - "version": "v7.2.5", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", + "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", "shasum": "" }, "require": { @@ -7911,7 +7899,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.2.5" + "source": "https://github.com/symfony/process/tree/v7.3.0" }, "funding": [ { @@ -7927,20 +7915,20 @@ "type": "tidelift" } ], - "time": "2025-03-13T12:21:46+00:00" + "time": "2025-04-17T09:11:12+00:00" }, { "name": "symfony/string", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931" + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931", - "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931", + "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", "shasum": "" }, "require": { @@ -7998,7 +7986,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.2.6" + "source": "https://github.com/symfony/string/tree/v7.3.0" }, "funding": [ { @@ -8014,7 +8002,7 @@ "type": "tidelift" } ], - "time": "2025-04-20T20:18:16+00:00" + "time": "2025-04-20T20:19:01+00:00" }, { "name": "textalk/websocket", From 683eecfd2d1f20d2d86d7e8dc628da3d76cc90a0 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 1 Jun 2025 13:03:00 +0530 Subject: [PATCH 05/15] update: flip check order. --- src/Appwrite/Migration/Version/V23.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 89ce938657..2b07a6584e 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -48,16 +48,17 @@ class V23 extends Migration { $projectInternalId = $this->project->getSequence(); + if (empty($projectInternalId)) { + throw new Exception('Project ID is null'); + } + + // not needed for `console` project. if ($projectInternalId !== 'projects') { return; } Console::info(" └── Migrating `migrations` collections."); - if (empty($projectInternalId)) { - throw new Exception('Project ID is null'); - } - /** * direct access.\ * same as `$this->collections['projects']['migrations']['$id']`. From c57967c3b85c67fc678d00d3f7076279f400207f Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 1 Jun 2025 13:04:25 +0530 Subject: [PATCH 06/15] update: nitpick comment. --- src/Appwrite/Migration/Version/V23.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 2b07a6584e..0b879a73e1 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -60,8 +60,9 @@ class V23 extends Migration Console::info(" └── Migrating `migrations` collections."); /** - * direct access.\ - * same as `$this->collections['projects']['migrations']['$id']`. + * Specifying the ID for direct access. + * + * This is same as `$this->collections['projects']['migrations']['$id']`. */ $migrationCollectionId = 'migrations'; From e48e4537def467ec49848af45c02c579e61bac59 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 1 Jun 2025 13:59:43 +0530 Subject: [PATCH 07/15] fix: leftovers, `getInternalId` > `getSequence`. --- .../Modules/Functions/Http/Functions/Deployment/Update.php | 2 +- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 6 +++--- .../Platform/Modules/Sites/Http/Sites/Deployment/Update.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index f91c8b88e1..5595a69617 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -109,7 +109,7 @@ class Update extends Base Query::equal("deploymentResourceType", ["function"]), Query::equal("deploymentResourceInternalId", [$function->getSequence()]), Query::equal("deploymentVcsProviderBranch", [""]), - Query::equal("projectInternalId", [$project->getInternalId()]) + Query::equal("projectInternalId", [$project->getSequence()]) ]; Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 0cfaf096ab..fa7cfab138 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1087,7 +1087,7 @@ class Builds extends Action Query::equal('deploymentResourceType', ['function']), Query::equal('trigger', ['manual']), Query::equal('deploymentVcsProviderBranch', ['']), - Query::equal("projectInternalId", [$project->getInternalId()]) + Query::equal("projectInternalId", [$project->getSequence()]) ]; $rulesUpdated = false; @@ -1113,7 +1113,7 @@ class Builds extends Action Query::equal('deploymentResourceType', ['site']), Query::equal('trigger', ['manual']), Query::equal('deploymentVcsProviderBranch', ['']), - Query::equal("projectInternalId", [$project->getInternalId()]) + Query::equal("projectInternalId", [$project->getSequence()]) ]; $dbForPlatform->forEach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { @@ -1170,7 +1170,7 @@ class Builds extends Action } $queries = [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::equal('type', ['deployment']), Query::equal('deploymentResourceInternalId', [$resource->getSequence()]), Query::equal('deploymentResourceType', ['site']), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index e71e23fa59..9fa62c2adf 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -101,7 +101,7 @@ class Update extends Base Query::equal("deploymentResourceType", ["site"]), Query::equal("deploymentResourceInternalId", [$site->getSequence()]), Query::equal("deploymentVcsProviderBranch", [""]), - Query::equal("projectInternalId", [$project->getInternalId()]) + Query::equal("projectInternalId", [$project->getSequence()]) ]; Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { From 2df28bdf19851b5642c7c30dd21128ca8d3a9dc3 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 10 Jun 2025 12:07:58 +0530 Subject: [PATCH 08/15] remove: migrations, simplify error recording for frontend. --- app/config/collections/projects.php | 17 ---- src/Appwrite/Migration/Migration.php | 1 - src/Appwrite/Migration/Version/V23.php | 78 ------------------- src/Appwrite/Platform/Workers/Migrations.php | 47 +---------- .../Utopia/Response/Model/Migration.php | 7 -- 5 files changed, 4 insertions(+), 146 deletions(-) delete mode 100644 src/Appwrite/Migration/Version/V23.php diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php index 6fe6dff0ba..ac14421382 100644 --- a/app/config/collections/projects.php +++ b/app/config/collections/projects.php @@ -2342,23 +2342,6 @@ return [ 'array' => true, 'filters' => [], ], - [ - /** - * A short, human-readable error message (no stacktrace), - * unlike `errors` which contains detailed entries with full trace. - * - * This is mainly used used for csv imports as its failure need to be shown on frontend. - */ - '$id' => ID::custom('error'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 256, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], [ '$id' => ID::custom('search'), 'type' => Database::VAR_STRING, diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 026ce1eb2e..9071e0cabe 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -89,7 +89,6 @@ abstract class Migration '1.7.2' => 'V22', '1.7.3' => 'V22', '1.7.4' => 'V22', - '1.8.0' => 'V23', ]; /** diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php deleted file mode 100644 index 0b879a73e1..0000000000 --- a/src/Appwrite/Migration/Version/V23.php +++ /dev/null @@ -1,78 +0,0 @@ - null, - fn () => [] - ); - } - - Console::info('Migrating collections'); - $this->migrateCollections(); - } - - /** - * Migrate Collections. - * - * @return void - * @throws Exception|Throwable - */ - private function migrateCollections(): void - { - $this->migrateMigrationsCollections(); - } - - /** - * Add `error` attribute on `migrations` collection. - */ - private function migrateMigrationsCollections(): void - { - $projectInternalId = $this->project->getSequence(); - - if (empty($projectInternalId)) { - throw new Exception('Project ID is null'); - } - - // not needed for `console` project. - if ($projectInternalId !== 'projects') { - return; - } - - Console::info(" └── Migrating `migrations` collections."); - - /** - * Specifying the ID for direct access. - * - * This is same as `$this->collections['projects']['migrations']['$id']`. - */ - $migrationCollectionId = 'migrations'; - - try { - $attributes = ['error']; - $this->createAttributesFromCollection($this->dbForProject, $migrationCollectionId, $attributes); - } catch (\Throwable $th) { - Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$migrationCollectionId}: {$th->getMessage()}"); - } - - $this->dbForProject->purgeCachedCollection($migrationCollectionId); - } -} diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 1f094f4dd2..7623b6ebfb 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -305,22 +305,10 @@ class Migrations extends Action $errorMessages = []; foreach ($sourceErrors as $error) { - $message = "Error occurred while fetching '{$error->getResourceName()}:{$error->getResourceId()}' from source with message: '{$error->getMessage()}'"; - if ($error->getPrevious()) { - $message .= " Message: ".$error->getPrevious()->getMessage() . " File: ".$error->getPrevious()->getFile() . " Line: ".$error->getPrevious()->getLine(); - } - - $errorMessages[] = $message; + $errorMessages[] = $error->jsonSerialize(); } foreach ($destinationErrors as $error) { - $message = "Error occurred while pushing '{$error->getResourceName()}:{$error->getResourceId()}' to destination with message: '{$error->getMessage()}'"; - - if ($error->getPrevious()) { - $message .= " Message: ".$error->getPrevious()->getMessage() . " File: ".$error->getPrevious()->getFile() . " Line: ".$error->getPrevious()->getLine(); - } - - /** @var MigrationException $error */ - $errorMessages[] = $message; + $errorMessages[] = $error->jsonSerialize(); } $migration->setAttribute('errors', $errorMessages); @@ -354,18 +342,15 @@ class Migrations extends Action $errorMessages = []; foreach ($sourceErrors as $error) { - /** @var MigrationException $error */ - $errorMessages[] = "Error occurred while fetching '{$error->getResourceName()}:{$error->getResourceId()}' from source with message '{$error->getMessage()}'"; + $errorMessages[] = $error->jsonSerialize(); } foreach ($destinationErrors as $error) { - /** @var MigrationException $error */ - $errorMessages[] = "Error occurred while pushing '{$error->getResourceName()}:{$error->getResourceId()}' to destination with message '{$error->getMessage()}'"; + $errorMessages[] = $error->jsonSerialize(); } $migration->setAttribute('errors', $errorMessages); } } finally { - $this->setMigrationError($migration, $source, $destination); $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); if ($migration->getAttribute('status', '') === 'failed') { @@ -408,28 +393,4 @@ class Migrations extends Action } } } - - /** - * Stores a human-readable error message for migration. - * - * Only applies to migrations where the source is CSV. - */ - private function setMigrationError(Document $migration, ?Source $source, ?Destination $destination): void - { - if ($migration->isEmpty() || $source === null || $destination === null) { - return; - } - - $sourceErrors = $source->getErrors(); - $destinationErrors = $destination->getErrors(); - $migrationSource = $migration->getAttribute('source'); - - if ($migrationSource === CSV::getName()) { - if (! empty($sourceErrors)) { - $migration->setAttribute('error', $sourceErrors[0]->getMessage()); - } elseif (! empty($destinationErrors)) { - $migration->setAttribute('error', $destinationErrors[0]->getMessage()); - } - } - } } diff --git a/src/Appwrite/Utopia/Response/Model/Migration.php b/src/Appwrite/Utopia/Response/Model/Migration.php index 75aebfbc66..3be1d519a6 100644 --- a/src/Appwrite/Utopia/Response/Model/Migration.php +++ b/src/Appwrite/Utopia/Response/Model/Migration.php @@ -85,13 +85,6 @@ class Migration extends Model 'default' => [], 'example' => [], ]) - ->addRule('error', [ - 'type' => self::TYPE_STRING, - 'description' => 'A readable error message that occurred during the CSV migration process.', - 'array' => false, - 'default' => null, - 'example' => '', - ]) ; } From c06ff42f61f3f5bb25681ca3732802871a8baff5 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 12 Jun 2025 10:43:35 +0530 Subject: [PATCH 09/15] fix: attribute types; update: remove sensitive information from realtime payload. --- src/Appwrite/Platform/Workers/Migrations.php | 31 ++++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 7623b6ebfb..a59668d60a 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -185,13 +185,33 @@ class Migrations extends Action */ protected function updateMigrationDocument(Document $migration, Document $project, Realtime $queueForRealtime): Document { + $errorMessages = []; + $clonedMigrationDocument = clone $migration; + + // we cannot use #sensitive because + // `errors` is nested which requires an override. + $errors = $clonedMigrationDocument->getAttribute('errors', []); + + foreach ($errors as $error) { + $decoded = json_decode($error, true); + + if (is_array($decoded) && isset($decoded['trace'])) { + unset($decoded['trace']); + $errorMessages[] = json_encode($decoded); + } + } + + // set the errors back without trace + $clonedMigrationDocument->setAttribute('errors', $errorMessages); + + /** Trigger Realtime Events */ $queueForRealtime ->setProject($project) ->setSubscribers(['console', $project->getId()]) ->setEvent('migrations.[migrationId].update') ->setParam('migrationId', $migration->getId()) - ->setPayload($migration->getArrayCopy()) + ->setPayload($clonedMigrationDocument->getArrayCopy(), ['options', 'credentials']) ->trigger(); return $this->dbForProject->updateDocument('migrations', $migration->getId(), $migration); @@ -305,14 +325,13 @@ class Migrations extends Action $errorMessages = []; foreach ($sourceErrors as $error) { - $errorMessages[] = $error->jsonSerialize(); + $errorMessages[] = json_encode($error); } foreach ($destinationErrors as $error) { - $errorMessages[] = $error->jsonSerialize(); + $errorMessages[] = json_encode($error); } $migration->setAttribute('errors', $errorMessages); - $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); return; } @@ -342,10 +361,10 @@ class Migrations extends Action $errorMessages = []; foreach ($sourceErrors as $error) { - $errorMessages[] = $error->jsonSerialize(); + $errorMessages[] = json_encode($error); } foreach ($destinationErrors as $error) { - $errorMessages[] = $error->jsonSerialize(); + $errorMessages[] = json_encode($error); } $migration->setAttribute('errors', $errorMessages); From 176c0850681789a97aac6d05d0dce8ce7c141f70 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Thu, 12 Jun 2025 11:43:11 +0530 Subject: [PATCH 10/15] Fix all vcs urls missing region --- app/controllers/api/vcs.php | 25 +++++++++++-------- app/controllers/general.php | 11 ++++---- .../Modules/Functions/Workers/Builds.php | 5 ++-- src/Appwrite/Platform/Workers/Webhooks.php | 3 ++- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index c8a0a36a85..79050c2913 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -363,6 +363,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId if (!empty($providerCommitHash) && $resource->getAttribute('providerSilentMode', false) === false) { $resourceName = $resource->getAttribute('name'); $projectName = $project->getAttribute('name'); + $region = $project->getAttribute('region', 'default'); $name = "{$resourceName} ({$projectName})"; $message = 'Starting...'; @@ -377,7 +378,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId } $owner = $github->getOwnerName($providerInstallationId); - $providerTargetUrl = $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$projectId/$resourceCollection/$resourceType-$resourceId"; + $providerTargetUrl = $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$region-$projectId/$resourceCollection/$resourceType-$resourceId"; $github->updateCommitStatus($repositoryName, $providerCommitHash, $owner, 'pending', $message, $providerTargetUrl, $name); } @@ -476,16 +477,6 @@ App::get('/v1/vcs/github/callback') $state = \json_decode($state, true); $projectId = $state['projectId'] ?? ''; - $defaultState = [ - 'success' => $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$projectId/settings/git-installations", - 'failure' => $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$projectId/settings/git-installations", - ]; - - $state = \array_merge($defaultState, $state ?? []); - - $redirectSuccess = $state['success'] ?? ''; - $redirectFailure = $state['failure'] ?? ''; - $project = $dbForPlatform->getDocument('projects', $projectId); if ($project->isEmpty()) { @@ -502,6 +493,18 @@ App::get('/v1/vcs/github/callback') throw new Exception(Exception::PROJECT_NOT_FOUND, $error); } + $region = $project->getAttribute('region', 'default'); + + $defaultState = [ + 'success' => $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$region-$projectId/settings/git-installations", + 'failure' => $request->getProtocol() . '://' . $request->getHostname() . "/console/project-$region-$projectId/settings/git-installations", + ]; + + $state = \array_merge($defaultState, $state ?? []); + + $redirectSuccess = $state['success'] ?? ''; + $redirectFailure = $state['failure'] ?? ''; + // Create / Update installation if (!empty($providerInstallationId)) { $privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY'); diff --git a/app/controllers/general.php b/app/controllers/general.php index 5beac9e1e8..14ff1aae1d 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -186,7 +186,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $resourceId = $rule->getAttribute('deploymentResourceId', ''); $type = ($resourceType === 'site') ? 'sites' : 'functions'; $exception = new AppwriteException(AppwriteException::DEPLOYMENT_NOT_FOUND, view: $errorView); - $exception->addCTA('View deployments', $url . '/console/project-' . $projectId . '/' . $type . '/' . $resourceType . '-' . $resourceId); + $exception->addCTA('View deployments', $url . '/console/project-' . $project->getAttribute('region', 'default') . '-' . $projectId . '/' . $type . '/' . $resourceType . '-' . $resourceId); throw $exception; } @@ -319,21 +319,22 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $allowAnyStatus = !\is_null($apiKey) && $apiKey->isDeploymentStatusIgnored(); if (!$allowAnyStatus && $deployment->getAttribute('status') !== 'ready') { $status = $deployment->getAttribute('status'); + $region = $project->getAttribute('region', 'default'); switch ($status) { case 'failed': $exception = new AppwriteException(AppwriteException::BUILD_FAILED, view: $errorView); - $ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments/deployment-' . $deployment->getId(); + $ctaUrl = '/console/project-' . $region . '-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments/deployment-' . $deployment->getId(); $exception->addCTA('View logs', $url . $ctaUrl); break; case 'canceled': $exception = new AppwriteException(AppwriteException::BUILD_CANCELED, view: $errorView); - $ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments'; + $ctaUrl = '/console/project-' . $region . '-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments'; $exception->addCTA('View deployments', $url . $ctaUrl); break; default: $exception = new AppwriteException(AppwriteException::BUILD_NOT_READY, view: $errorView); - $ctaUrl = '/console/project-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments/deployment-' . $deployment->getId(); + $ctaUrl = '/console/project-' . $region . '-' . $project->getId() . '/sites/site-' . $resource->getId() . '/deployments/deployment-' . $deployment->getId(); $exception->addCTA('Reload', '/'); $exception->addCTA('View logs', $url . $ctaUrl); break; @@ -345,7 +346,7 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $permissions = $resource->getAttribute('execute'); if (!(\in_array('any', $permissions)) && !(\in_array('guests', $permissions))) { $exception = new AppwriteException(AppwriteException::FUNCTION_EXECUTE_PERMISSION_MISSING, view: $errorView); - $exception->addCTA('View settings', $url . '/console/project-' . $project->getId() . '/functions/function-' . $resource->getId() . '/settings'); + $exception->addCTA('View settings', $url . '/console/project-' . $project->getAttribute('region', 'default') . '-' . $project->getId() . '/functions/function-' . $resource->getId() . '/settings'); throw $exception; } } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 399a4d5c44..a207845733 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1444,10 +1444,11 @@ class Builds extends Action $hostname = System::getEnv('_APP_DOMAIN'); $projectId = $project->getId(); + $region = $project->getAttribute('region', 'default'); $resourceId = $resource->getId(); $providerTargetUrl = match ($resource->getCollection()) { - 'functions' => "{$protocol}://{$hostname}/console/project-{$projectId}/functions/function-{$resourceId}", - 'sites' => "{$protocol}://{$hostname}/console/project-{$projectId}/sites/site-{$resourceId}", + 'functions' => "{$protocol}://{$hostname}/console/project-{$region}-{$projectId}/functions/function-{$resourceId}", + 'sites' => "{$protocol}://{$hostname}/console/project-{$region}-{$projectId}/sites/site-{$resourceId}", default => throw new \Exception('Invalid resource type') }; diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index ada4d6faaa..82dfe0f1a8 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -219,6 +219,7 @@ class Webhooks extends Action ]); $projectId = $project->getId(); + $region = $project->getAttribute('region', 'default'); $webhookId = $webhook->getId(); $template = Template::fromFile(__DIR__ . '/../../../../app/config/locale/templates/email-webhook-failed.tpl'); @@ -227,7 +228,7 @@ class Webhooks extends Action $template->setParam('{{project}}', $project->getAttribute('name')); $template->setParam('{{url}}', $webhook->getAttribute('url')); $template->setParam('{{error}}', $curlError ?? 'The server returned ' . $statusCode . ' status code'); - $template->setParam('{{path}}', "/console/project-$projectId/settings/webhooks/$webhookId"); + $template->setParam('{{path}}', "/console/project-$region-$projectId/settings/webhooks/$webhookId"); $template->setParam('{{attempts}}', $attempts); $template->setParam('{{logoUrl}}', $plan['logoUrl'] ?? APP_EMAIL_LOGO_URL); From d01f1c1a7c1d6d084fcc817cea6697dbed493c51 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 13 Jun 2025 16:20:07 +0530 Subject: [PATCH 11/15] remove: trace from `errors`. --- .../Utopia/Response/Model/Migration.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Appwrite/Utopia/Response/Model/Migration.php b/src/Appwrite/Utopia/Response/Model/Migration.php index 3be1d519a6..c74e2fb2aa 100644 --- a/src/Appwrite/Utopia/Response/Model/Migration.php +++ b/src/Appwrite/Utopia/Response/Model/Migration.php @@ -4,6 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; +use Utopia\Database\Document; class Migration extends Model { @@ -107,4 +108,25 @@ class Migration extends Model { return Response::MODEL_MIGRATION; } + + public function filter(Document $document): Document + { + $errors = $document->getAttribute('errors', []); + if (empty($errors)) { + return $document; + } + + foreach ($errors as $error) { + $decoded = json_decode($error, true); + + if (is_array($decoded) && isset($decoded['trace'])) { + unset($decoded['trace']); + $errors[] = json_encode($decoded); + } + } + + $document->setAttribute('errors', $errors); + + return $document; + } } From c4e78613588b9a6b8f2716d90868099a87d87e01 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 17 Jun 2025 09:25:58 +0530 Subject: [PATCH 12/15] update: send only the relevant errors info to frontend. --- src/Appwrite/Utopia/Response/Model/Migration.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Utopia/Response/Model/Migration.php b/src/Appwrite/Utopia/Response/Model/Migration.php index c74e2fb2aa..508eab92a3 100644 --- a/src/Appwrite/Utopia/Response/Model/Migration.php +++ b/src/Appwrite/Utopia/Response/Model/Migration.php @@ -119,12 +119,19 @@ class Migration extends Model foreach ($errors as $error) { $decoded = json_decode($error, true); + // frontend doesn't need too many details. if (is_array($decoded) && isset($decoded['trace'])) { - unset($decoded['trace']); + unset( + $decoded['trace'], + $decoded['resourceId'], + $decoded['resourceName'], + $decoded['resourceGroup'] + ); $errors[] = json_encode($decoded); } } + // errors now only have code and message. $document->setAttribute('errors', $errors); return $document; From f31a7c007e1cae2132e5888b98d9e888510fb699 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 17 Jun 2025 09:47:58 +0530 Subject: [PATCH 13/15] fix: errors not being replaced but appended. --- src/Appwrite/Utopia/Response/Model/Migration.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Utopia/Response/Model/Migration.php b/src/Appwrite/Utopia/Response/Model/Migration.php index 508eab92a3..9027d55980 100644 --- a/src/Appwrite/Utopia/Response/Model/Migration.php +++ b/src/Appwrite/Utopia/Response/Model/Migration.php @@ -116,18 +116,19 @@ class Migration extends Model return $document; } - foreach ($errors as $error) { + foreach ($errors as $index => $error) { $decoded = json_decode($error, true); // frontend doesn't need too many details. - if (is_array($decoded) && isset($decoded['trace'])) { + if (is_array($decoded)) { unset( $decoded['trace'], $decoded['resourceId'], $decoded['resourceName'], $decoded['resourceGroup'] ); - $errors[] = json_encode($decoded); + + $errors[$index] = json_encode($decoded); } } From 149ad1a0f38560f0476c87c02b73bb3c94114002 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 17 Jun 2025 10:11:23 +0530 Subject: [PATCH 14/15] update: simplify filtering. --- src/Appwrite/Utopia/Response/Model/Migration.php | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Appwrite/Utopia/Response/Model/Migration.php b/src/Appwrite/Utopia/Response/Model/Migration.php index 9027d55980..76e00b3097 100644 --- a/src/Appwrite/Utopia/Response/Model/Migration.php +++ b/src/Appwrite/Utopia/Response/Model/Migration.php @@ -121,14 +121,10 @@ class Migration extends Model // frontend doesn't need too many details. if (is_array($decoded)) { - unset( - $decoded['trace'], - $decoded['resourceId'], - $decoded['resourceName'], - $decoded['resourceGroup'] - ); - - $errors[$index] = json_encode($decoded); + $errors[$index] = json_encode([ + 'code' => $decoded['code'] ?? 0, + 'message' => $decoded['message'] ?? null, + ]); } } From cc0dfd9e699b71f98d7f032add84985a72ca5d8b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 17 Jun 2025 15:20:53 -0400 Subject: [PATCH 15/15] Revert "Update delete project scope" --- src/Appwrite/Platform/Workers/Deletes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 4e7fa1885a..43bc55583d 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -495,7 +495,7 @@ class Deletes extends Action * @throws Authorization * @throws DatabaseException */ - protected function deleteProject(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Document $document): void + private function deleteProject(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Document $document): void { $projectInternalId = $document->getInternalId(); $projectId = $document->getId();