diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 659fc327d9..73f2c1ec45 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1048,8 +1048,8 @@ class Builds extends Action 'deploymentId' => $deployment->getId(), 'deploymentInternalId' => $deployment->getSequence(), 'deploymentResourceType' => 'site', - 'deploymentResourceId' => $deployment->getId(), - 'deploymentResourceInternalId' => $deployment->getSequence(), + 'deploymentResourceId' => $resource->getId(), + 'deploymentResourceInternalId' => $resource->getSequence(), 'deploymentVcsProviderBranch' => $branchName, 'status' => 'verified', 'certificateId' => '', diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 25a899bf12..3065b2377f 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -1008,7 +1008,6 @@ class Deletes extends Action */ Console::info("Deleting rules for site " . $siteId); $this->deleteByGroup('rules', [ - Query::equal('type', ['deployment']), Query::equal('deploymentResourceType', ['site']), Query::equal('deploymentResourceInternalId', [$siteInternalId]), Query::equal('projectInternalId', [$project->getSequence()]) @@ -1094,7 +1093,6 @@ class Deletes extends Action */ Console::info("Deleting rules for function " . $functionId); $this->deleteByGroup('rules', [ - Query::equal('type', ['deployment']), Query::equal('deploymentResourceType', ['function']), Query::equal('deploymentResourceInternalId', [$functionInternalId]), Query::equal('projectInternalId', [$project->getSequence()]), diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 585ac56280..508ddede4a 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -1727,6 +1727,70 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(404, $function['headers']['status-code']); } + public function testDeleteFunctionRulesCleanup(): void + { + $functionId = $this->setupFunction([ + 'functionId' => ID::unique(), + 'name' => 'Test Rules Cleanup Function', + 'runtime' => 'node-22', + 'entrypoint' => 'index.js', + 'timeout' => 15, + ]); + + $this->assertNotEmpty($functionId); + + // Create a manual deployment rule (type = 'deployment') + $domain = $this->setupFunctionDomain($functionId); + $this->assertNotEmpty($domain); + + // Create a redirect rule (type = 'redirect') + $redirectDomain = \uniqid() . '-redirect-cleanup.custom.localhost'; + $redirectRule = $this->client->call(Client::METHOD_POST, '/proxy/rules/redirect', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'domain' => $redirectDomain, + 'url' => 'https://appwrite.io', + 'statusCode' => 301, + 'resourceType' => 'function', + 'resourceId' => $functionId, + ]); + + $this->assertEquals(201, $redirectRule['headers']['status-code']); + $this->assertNotEmpty($redirectRule['body']['$id']); + + // Verify both rules exist (no type filter — catches all rule types) + $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('deploymentResourceId', [$functionId])->toString() + ] + ]); + + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertGreaterThanOrEqual(2, $rules['body']['total']); + + // Delete the function + $this->cleanupFunction($functionId); + + // Verify ALL rules (deployment + redirect) are cleaned up + $this->assertEventually(function () use ($functionId) { + $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('deploymentResourceId', [$functionId])->toString() + ] + ]); + + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(0, $rules['body']['total']); + }, 5000, 500); + } + public function testExecutionTimeout() { $functionId = $this->setupFunction([ diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 823bd481a8..69dbd7fdf0 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -1439,6 +1439,71 @@ class SitesCustomServerTest extends Scope $this->assertEquals(404, $function['headers']['status-code']); } + public function testDeleteSiteRulesCleanup(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Test Rules Cleanup Site', + 'framework' => 'other', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './', + 'fallbackFile' => '', + ]); + + $this->assertNotEmpty($siteId); + + // Create a manual deployment rule (type = 'deployment') + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + + // Create a redirect rule (type = 'redirect') + $redirectDomain = \uniqid() . '-redirect-cleanup.custom.localhost'; + $redirectRule = $this->client->call(Client::METHOD_POST, '/proxy/rules/redirect', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'domain' => $redirectDomain, + 'url' => 'https://appwrite.io', + 'statusCode' => 301, + 'resourceType' => 'site', + 'resourceId' => $siteId, + ]); + + $this->assertEquals(201, $redirectRule['headers']['status-code']); + $this->assertNotEmpty($redirectRule['body']['$id']); + + // Verify both rules exist (no type filter — catches all rule types) + $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('deploymentResourceId', [$siteId])->toString() + ] + ]); + + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertGreaterThanOrEqual(2, $rules['body']['total']); + + // Delete the site + $this->cleanupSite($siteId); + + // Verify ALL rules (deployment + redirect) are cleaned up + $this->assertEventually(function () use ($siteId) { + $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('deploymentResourceId', [$siteId])->toString() + ] + ]); + + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(0, $rules['body']['total']); + }, 5000, 500); + } + public function testGetFrameworks(): void { $frameworks = $this->client->call(Client::METHOD_GET, '/sites/frameworks', array_merge([