Add Custom Domains migration

This commit is contained in:
Prem Palanisamy
2026-05-21 11:26:20 +01:00
parent e33daecfc7
commit bb1f2d4998
5 changed files with 82 additions and 9 deletions
+1 -1
View File
@@ -75,7 +75,7 @@
"utopia-php/lock": "0.2.*",
"utopia-php/logger": "0.8.*",
"utopia-php/messaging": "0.22.*",
"utopia-php/migration": "dev-add-smtp-migration as 1.12.0",
"utopia-php/migration": "dev-add-custom-domains-migration as 1.12.0",
"utopia-php/platform": "1.0.0-rc2",
"utopia-php/pools": "1.*",
"utopia-php/span": "1.1.*",
Generated
+8 -8
View File
@@ -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": "5f35f305036e8fc0a208c3adf4c7c16b",
"content-hash": "4d93c3da3ef7aa9fe898f609a6524431",
"packages": [
{
"name": "adhocore/jwt",
@@ -4675,16 +4675,16 @@
},
{
"name": "utopia-php/migration",
"version": "dev-add-smtp-migration",
"version": "dev-add-custom-domains-migration",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/migration.git",
"reference": "e5dc08619aae087c6d45768225ea8d1e55eff63e"
"reference": "7af2ef5b766d3eb34fa8f83f2c43c84c853f499a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/e5dc08619aae087c6d45768225ea8d1e55eff63e",
"reference": "e5dc08619aae087c6d45768225ea8d1e55eff63e",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/7af2ef5b766d3eb34fa8f83f2c43c84c853f499a",
"reference": "7af2ef5b766d3eb34fa8f83f2c43c84c853f499a",
"shasum": ""
},
"require": {
@@ -4741,10 +4741,10 @@
"utopia"
],
"support": {
"source": "https://github.com/utopia-php/migration/tree/add-smtp-migration",
"source": "https://github.com/utopia-php/migration/tree/add-custom-domains-migration",
"issues": "https://github.com/utopia-php/migration/issues"
},
"time": "2026-05-20T13:27:52+00:00"
"time": "2026-05-21T10:22:19+00:00"
},
{
"name": "utopia-php/mongo",
@@ -8593,7 +8593,7 @@
},
{
"package": "utopia-php/migration",
"version": "dev-add-smtp-migration",
"version": "dev-add-custom-domains-migration",
"alias": "1.12.0",
"alias_normalized": "1.12.0.0"
}
@@ -389,6 +389,8 @@ class Migrations extends Action
'targets.write',
'webhooks.read',
'webhooks.write',
'rules.read',
'rules.write',
'project.read',
'project.write',
'keys.read',
@@ -113,6 +113,12 @@ class MigrationReport extends Model
'default' => 0,
'example' => 1,
])
->addRule(Resource::TYPE_RULE, [
'type' => self::TYPE_INTEGER,
'description' => 'Number of custom-domain proxy rules to be migrated. Auto-generated `.appwrite.network` rules are skipped — they are recreated by parent Function/Site migration.',
'default' => 0,
'example' => 5,
])
->addRule(Resource::TYPE_SITE, [
'type' => self::TYPE_INTEGER,
'description' => 'Number of sites to be migrated.',
@@ -3044,6 +3044,71 @@ trait MigrationsBase
$this->client->call(Client::METHOD_PATCH, '/projects/' . $destinationProjectId . '/smtp', $consoleHeaders, $reset);
}
public function testAppwriteMigrationCustomDomains(): void
{
$sourceHeaders = [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
];
$destinationHeaders = [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getDestinationProject()['$id'],
'x-appwrite-key' => $this->getDestinationProject()['apiKey'],
];
// Unique domain so re-runs and parallel suites can't collide on the
// global domain uniqueness check.
$domain = \uniqid() . '-migration-api.myapp.com';
$createResp = $this->client->call(Client::METHOD_POST, '/proxy/rules/api', $sourceHeaders, [
'domain' => $domain,
]);
$this->assertEquals(201, $createResp['headers']['status-code']);
$sourceRule = $createResp['body'];
$result = $this->performMigrationSync([
'resources' => [
Resource::TYPE_RULE,
],
'endpoint' => $this->webEndpoint,
'projectId' => $this->getProject()['$id'],
'apiKey' => $this->getProject()['apiKey'],
]);
$this->assertEquals('completed', $result['status']);
$this->assertEquals([Resource::TYPE_RULE], $result['resources']);
$this->assertArrayHasKey(Resource::TYPE_RULE, $result['statusCounters']);
$this->assertEquals(0, $result['statusCounters'][Resource::TYPE_RULE]['error']);
$this->assertEquals(0, $result['statusCounters'][Resource::TYPE_RULE]['pending']);
$this->assertGreaterThanOrEqual(1, $result['statusCounters'][Resource::TYPE_RULE]['success']);
$this->assertEquals(0, $result['statusCounters'][Resource::TYPE_RULE]['processing']);
$this->assertEquals(0, $result['statusCounters'][Resource::TYPE_RULE]['warning']);
$listResp = $this->client->call(Client::METHOD_GET, '/proxy/rules', $destinationHeaders);
$this->assertEquals(200, $listResp['headers']['status-code']);
$foundRule = null;
foreach ($listResp['body']['rules'] as $r) {
if ($r['domain'] === $domain) {
$foundRule = $r;
break;
}
}
$this->assertNotNull($foundRule, 'Migrated rule not found on destination');
$this->assertEquals($domain, $foundRule['domain']);
$this->assertEquals('api', $foundRule['type']);
$this->assertEquals('manual', $foundRule['trigger']);
// Cleanup on destination
$this->client->call(Client::METHOD_DELETE, '/proxy/rules/' . $foundRule['$id'], $destinationHeaders);
// Cleanup on source
$this->client->call(Client::METHOD_DELETE, '/proxy/rules/' . $sourceRule['$id'], $sourceHeaders);
}
/**
* Import documents from a CSV file.
*/