Feat: Auto-delete deployments#10959
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughAdds a new integer field deploymentRetention (days) to collections and public models: databases, functions, and sites (default 0). Introduces APP_COMPUTE_DEPLOYMENT_MAX_RETENTION (100 * 365). Extends Functions and Sites APIs (create/update) to accept, validate (Range 0..MAX), and persist deploymentRetention, and propagates it into deployment flows. Adds a development-only mock endpoint POST /v1/mock/time-travels to set a resource's createdAt for tests. Refactors Maintenance to accept a run type (loop vs triggered). Deletes worker gains retention-based pruning that enumerates old function/site deployments and enqueues deletions. Adds e2e tests for Functions and Sites covering creation, validation, update flows, and maintenance-driven pruning. Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the 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. Comment |
Security Scan Results for PRDocker Image Scan Results
Source Code Scan Results🎉 No vulnerabilities found! |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
docker-compose.yml (1)
74-75: Dev‑only vendor mount is fine; be aware of host–container couplingMounting
./vendor/utopia-php/databaseover the container’s vendor copy is handy for local development, but it assumes the host path exists and is up‑to‑date. If the directory is missing or contains a different version, PHP in the container will see that instead of the image’s dependencies.If this becomes flaky across environments, consider guarding this mount behind a separate dev‑only compose override or documenting the expectation that
composer installhas been run on the host.tests/e2e/Services/Functions/FunctionsConsoleClientTest.php (1)
9-10: Retention E2E test is valuable; consider tightening assertions and docker assumptionsThe new
testFunctionDeploymentRetentionWithMaintenanceexercises the full retention path (time‑travel, maintenance trigger, delete worker), which is great.Two optional robustness improvements:
- After asserting
total === 2, also assert that the remaining deployment IDs are the expected “active” and recent inactive ones, and that the time‑traveled old one is gone.- Because this test shells out to
docker exec appwrite-task-maintenance ..., it implicitly assumes the docker CLI and that container name are available in the test environment. If you ever run this suite outside the dev docker‑compose setup, you may want a guard or skip condition when docker isn’t present.Also applies to: 542-594
app/config/collections/projects.php (1)
570-580: Schema fordeploymentRetentionon functions/sites matches runtime expectationsThe new
deploymentRetentionattributes on:
functions: integer, required, defaultnull(but API always writes a value, defaulting to0), andsites: integer, optional, default0are consistent with how the feature is used (0 meaning “keep all deployments”) and with the delete worker reading via
$resource->getAttribute('deploymentRetention', 0).Just ensure your migration/patch path sets an explicit value for existing functions if you rely on
required => trueat the database level for new or updated documents.Also applies to: 1095-1104
src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php (1)
49-105: Deployment retention wiring is correct; confirm desired update semanticsThe new
deploymentRetentionparameter is correctly:
- validated via
Range(0, APP_COMPUTE_DEPLOYMENT_MAX_RETENTION),- threaded into
action(...)as anint, and- persisted on the function document.
One behavioral point to confirm: because the param’s default is
0and there’s no fallback to the existing value, callingupdateFunctionwithout specifyingdeploymentRetentionwill always reset it to0(unlimited). If the endpoint is intended as a full “PUT‑style” update this is fine; if you want PATCH‑like behavior where omitted fields remain unchanged, you’d instead use a nullable param and only overwrite when a value is explicitly provided.If you decide you want PATCH‑style behavior later, we can switch the validator to
new Nullable(new Range(...))and only assign$deploymentRetentioninto the update payload when it’s non‑null.Also applies to: 117-138, 267-292
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
app/config/collections/projects.php(2 hunks)app/controllers/mock.php(2 hunks)app/init/constants.php(1 hunks)docker-compose.yml(1 hunks)src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php(3 hunks)src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php(4 hunks)src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php(3 hunks)src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php(3 hunks)src/Appwrite/Platform/Tasks/Maintenance.php(4 hunks)src/Appwrite/Platform/Workers/Deletes.php(5 hunks)src/Appwrite/Utopia/Response/Model/Func.php(1 hunks)src/Appwrite/Utopia/Response/Model/Site.php(1 hunks)tests/e2e/Services/Functions/FunctionsConsoleClientTest.php(2 hunks)tests/e2e/Services/Functions/FunctionsCustomServerTest.php(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
src/Appwrite/Utopia/Response/Model/Func.php (1)
src/Appwrite/Utopia/Response/Model.php (1)
addRule(90-102)
src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-363)
src/Appwrite/Utopia/Response/Model/Site.php (1)
src/Appwrite/Utopia/Response/Model.php (1)
addRule(90-102)
src/Appwrite/Platform/Workers/Deletes.php (2)
src/Appwrite/Event/Event.php (1)
Event(10-654)src/Appwrite/Platform/Modules/Functions/Http/Functions/Delete.php (1)
Delete(21-100)
src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-363)
src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-363)
src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-363)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: scan
🔇 Additional comments (12)
src/Appwrite/Platform/Tasks/Maintenance.php (1)
16-35: Type‑driven maintenance execution (loopvstrigger) is wired correctlyThe new
typeparam, closure extraction, and conditionalConsole::loopvs direct$action()keep existing behavior for looped runs while enabling one‑shot triggers (used in tests) without side effects. Param/injection order is consistent with the callback signature.Also applies to: 37-109
app/init/constants.php (1)
88-88: Deployment max retention constant is reasonable and consistent
APP_COMPUTE_DEPLOYMENT_MAX_RETENTION = 100 * 365matches the “days” semantics used elsewhere and gives a sane upper bound for validation without being effectively unbounded.src/Appwrite/Utopia/Response/Model/Func.php (1)
68-73: Function model exposesdeploymentRetentionconsistently with API semanticsAdding
deploymentRetentionas an integer field with default0and “0 = keep all deployments” description lines up with the HTTP param and backend logic. This should give clients the right expectations when reading function documents.src/Appwrite/Utopia/Response/Model/Site.php (1)
61-66: LGTM! Deployment retention field properly added to Site model.The
deploymentRetentionrule is correctly defined with appropriate type, description, default value, and example. The positioning betweenframeworkanddeploymentIdmaintains logical field ordering.src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php (2)
94-94: LGTM! Deployment retention parameter properly integrated.The parameter is correctly defined with Range validation using the global
APP_COMPUTE_DEPLOYMENT_MAX_RETENTIONconstant, clear documentation, and appropriate default value.
124-124: LGTM! Parameter correctly wired through action.The
deploymentRetentionparameter flows correctly from the action signature (line 124) to document persistence (line 159), maintaining consistency with other site attributes.Also applies to: 159-159
app/controllers/mock.php (1)
202-242: LGTM! Useful mock endpoint for testing time-dependent features.The time-travel endpoint provides a clean way to test deployment retention logic by manipulating timestamps. Key safeguards are in place:
- Development-environment restriction (lines 215-219)
- Project validation (lines 221-225)
- Resource type whitelist (lines 227-230)
- Proper use of
preserveDatescontext (line 239)src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php (2)
98-98: LGTM! Deployment retention update parameter properly defined.The parameter follows the same validation pattern as the Create endpoint, maintaining API consistency.
132-132: LGTM! Update flow correctly handles deployment retention.The parameter flows correctly from action signature (line 132) to document update (line 275), consistent with other updateable site attributes.
Also applies to: 275-275
src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php (2)
112-112: LGTM! Deployment retention parameter properly integrated for Functions.The parameter definition mirrors the Sites module implementation, ensuring consistent API behavior across compute resources.
152-152: LGTM! Function creation correctly persists deployment retention.The parameter flows correctly from action signature (line 152) to function document creation (line 223), maintaining consistency with the Sites module and other function attributes.
Also applies to: 223-223
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (1)
2633-2746: Comprehensive test coverage for deployment retention feature.The test effectively covers:
- Default behavior validation
- Successful creation with various retention values (0, 180)
- Validation of boundary conditions (negative and excessive values)
- Update workflow scenarios
The behavior at lines 2720-2728 where updating without the
deploymentRetentionparameter resets it to 0 is intentional by design—the parameter has a default value of 0 and is explicitly assigned on each update, rather than being conditionally preserved like some other optional parameters (e.g.,runtime). The test correctly validates this implementation behavior.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/e2e/Services/Sites/SitesConsoleClientTest.php (1)
144-196: Strengthen assertions to verify the correct deployments are retained/deletedThe maintenance retention flow is generally well covered, but the final check only asserts
total === 2. That would still pass if the wrong deployment were deleted (e.g., the active one) as long as any two remain.To make the test more robust, consider also asserting which IDs exist after maintenance, for example:
- $this->assertEventually(function () use ($siteId) { - $response = $this->listDeployments($siteId); - $this->assertSame(200, $response['headers']['status-code']); - $this->assertSame(2, $response['body']['total']); - }); + $this->assertEventually(function () use ($siteId, $deploymentIdInactive, $deploymentIdInactiveOld, $deploymentIdActive) { + $response = $this->listDeployments($siteId); + $this->assertSame(200, $response['headers']['status-code']); + $this->assertSame(2, $response['body']['total']); + + // Old inactive deployment should be gone + $deleted = $this->getDeployment($siteId, $deploymentIdInactiveOld); + $this->assertSame(404, $deleted['headers']['status-code']); + + // Recent inactive + active deployments should remain + $still1 = $this->getDeployment($siteId, $deploymentIdInactive); + $this->assertSame(200, $still1['headers']['status-code']); + + $still2 = $this->getDeployment($siteId, $deploymentIdActive); + $this->assertSame(200, $still2['headers']['status-code']); + });This guards both deletion correctness (only old non‑active is removed) and preservation of the active deployment.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
tests/e2e/Services/Sites/SitesConsoleClientTest.php(2 hunks)tests/e2e/Services/Sites/SitesCustomServerTest.php(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
- GitHub Check: Benchmark
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Messaging)
- GitHub Check: E2E Service Test (VCS)
- GitHub Check: E2E Service Test (Webhooks)
- GitHub Check: E2E Service Test (Proxy)
- GitHub Check: E2E Service Test (Projects)
- GitHub Check: E2E Service Test (Teams)
- GitHub Check: E2E Service Test (Locale)
- GitHub Check: E2E Service Test (Realtime)
- GitHub Check: E2E Service Test (Console)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (Databases/TablesDB)
- GitHub Check: E2E Service Test (Databases/Legacy)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E General Test
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: scan
🔇 Additional comments (1)
tests/e2e/Services/Sites/SitesConsoleClientTest.php (1)
9-9: Import ofUtopia\CLI\Consoleis appropriateThe new
use Utopia\CLI\Console;import is required forConsole::executein the maintenance test and is correctly scoped here.
✨ Benchmark results
⚡ Benchmark Comparison
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/Appwrite/Platform/Workers/Deletes.php (1)
315-374: Previous critical issues are now fixed. Consider adding explicit type cast for retention.The implementation now correctly:
- Scopes deletions by
resourceInternalIdandresourceType(lines 338-339)- Sets project context via
setProject($project)before triggering (line 355)However, there's a minor type safety concern:
- $retention = $resource->getAttribute('deploymentRetention', 0); + $retention = (int) $resource->getAttribute('deploymentRetention', 0);The strict equality check
$retention === 0on line 324 could behave unexpectedly if the attribute is stored/returned as a string"0"instead of integer0.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
app/controllers/mock.php(2 hunks)src/Appwrite/Platform/Workers/Deletes.php(5 hunks)tests/e2e/Services/Sites/SitesCustomServerTest.php(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/Appwrite/Platform/Workers/Deletes.php (1)
src/Appwrite/Event/Event.php (1)
Event(10-654)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
- GitHub Check: E2E Service Test (Messaging)
- GitHub Check: E2E Service Test (Webhooks)
- GitHub Check: E2E Service Test (Proxy)
- GitHub Check: E2E Service Test (Teams)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (Health)
- GitHub Check: E2E Service Test (Databases/TablesDB)
- GitHub Check: E2E Service Test (Avatars)
- GitHub Check: E2E Service Test (Databases/Legacy)
- GitHub Check: E2E Service Test (Locale)
- GitHub Check: E2E Service Test (Projects)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Realtime)
- GitHub Check: E2E Service Test (Console)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: Unit Test
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: E2E General Test
- GitHub Check: scan
🔇 Additional comments (2)
tests/e2e/Services/Sites/SitesCustomServerTest.php (1)
3080-3208: LGTM! The test comprehensively covers deploymentRetention lifecycle.The test validates:
- Default value (0) when not specified
- Explicit valid values (0, 180)
- Invalid boundary values (999999, -1) returning 400
- Update flow including value changes
- Cleanup of all created sites
The typo from the previous review (
$siteId[]vs$siteIds[]) has been correctly fixed.One behavior to verify: Lines 3176-3186 test that omitting
deploymentRetentionin an update request resets it to 0. Ensure this "reset to default on omission" is the intended API contract rather than "preserve existing value if not provided."app/controllers/mock.php (1)
235-239: Potential issue: Partial document update may not work as intended.The
$updateDocument only contains$createdAt. Depending on howupdateDocumentbehaves, this could either:
- Merge only the provided field (intended behavior)
- Overwrite the entire document, losing all other attributes
Consider fetching the existing document first and updating just the
$createdAtfield:- $update = new Document([ - '$createdAt' => $createdAt, - ]); - - $dbForProject->withPreserveDates(fn () => $dbForProject->updateDocument($collection, $resourceId, $update)); + $resource = $dbForProject->getDocument($collection, $resourceId); + + if ($resource->isEmpty()) { + throw new Exception(Exception::GENERAL_NOT_FOUND); + } + + $resource->setAttribute('$createdAt', $createdAt); + + $dbForProject->withPreserveDates(fn () => $dbForProject->updateDocument($collection, $resourceId, $resource));Verify that passing a partial Document to
updateDocumentcorrectly merges only the provided attributes without affecting other fields.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/Appwrite/Platform/Workers/Deletes.php (2)
317-318: Consider using modern PHPDoc style or removing redundant annotation.The inline
/* @var */comment is immediately followed by the assignment, making it redundant. Modern IDEs can infer the type from the callable return type.Apply this diff to use standard PHPDoc:
- /* @var $dbForProject Database */ - $dbForProject = $getProjectDB($project); + /** @var Database $dbForProject */ + $dbForProject = $getProjectDB($project);Or simply remove it:
- /* @var $dbForProject Database */ $dbForProject = $getProjectDB($project);
321-321: Add defensive type casting for deploymentRetention attribute.The getAttribute call should cast to int for safety. Without it, if the attribute is somehow stored as the string "0", the strict equality check on line 324 would fail, causing the code to proceed with deletion when retention should be unlimited.
Apply this diff:
- $retention = $resource->getAttribute('deploymentRetention', 0); + $retention = (int) $resource->getAttribute('deploymentRetention', 0);
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/Appwrite/Platform/Workers/Deletes.php(5 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-13T12:02:08.071Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 9752
File: app/config/collections/platform.php:1423-1423
Timestamp: 2025-05-13T12:02:08.071Z
Learning: In the Appwrite database schema, field names like 'resourceInternalId'/'resourceType' and 'deploymentInternalId'/'deploymentResourceType' are functionally equivalent and can coexist in the codebase without causing errors. The docker build and stack work fine with these naming inconsistencies.
Applied to files:
src/Appwrite/Platform/Workers/Deletes.php
📚 Learning: 2025-06-19T09:20:03.312Z
Learnt from: ItzNotABug
Repo: appwrite/appwrite PR: 9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php:57-59
Timestamp: 2025-06-19T09:20:03.312Z
Learning: In table-related endpoints (such as `src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php`), parameter descriptions should use "table" and "row" terminology instead of "collection" and "document" for clarity and consistency.
Applied to files:
src/Appwrite/Platform/Workers/Deletes.php
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
- GitHub Check: E2E Service Test (Messaging)
- GitHub Check: E2E Service Test (VCS)
- GitHub Check: E2E Service Test (Health)
- GitHub Check: E2E Service Test (Migrations)
- GitHub Check: E2E Service Test (Proxy)
- GitHub Check: E2E Service Test (Tokens)
- GitHub Check: E2E Service Test (Sites)
- GitHub Check: E2E Service Test (Teams)
- GitHub Check: E2E Service Test (Avatars)
- GitHub Check: E2E Service Test (Projects)
- GitHub Check: E2E Service Test (Console)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Databases/TablesDB)
- GitHub Check: Unit Test
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: E2E General Test
- GitHub Check: scan
🔇 Additional comments (3)
src/Appwrite/Platform/Workers/Deletes.php (3)
9-9: LGTM: DeleteEvent dependency injection is correctly wired.The import, injection, and action signature properly integrate the queueForDeletes event handler into the worker.
Also applies to: 67-67, 90-91
195-195: LGTM: Maintenance flow integration is correct.The deleteOldDeployments call is properly placed within the maintenance workflow and receives the correct parameters.
315-368: Well-structured retention-based cleanup implementation.The deleteOldDeployments method correctly:
- Scopes deletions to each specific resource via resourceInternalId and resourceType (lines 332-333)
- Sets project context on queued delete events (line 349)
- Excludes active deployments (lines 337-339)
- Processes both functions and sites collections (lines 355-367)
The critical issues from the previous review (missing resource scoping and project context) have been addressed.
There was a problem hiding this comment.
Pull request overview
This PR adds support for auto-deleting old non-active deployments for both functions and sites. The feature allows users to configure a retention period (in days) for non-active deployments, with a value of 0 meaning unlimited retention. The auto-deletion is handled by the existing maintenance worker that runs periodically, with an enhanced capability to trigger manually for testing purposes.
Key Changes:
- Added
deploymentRetentionfield to functions and sites collections with configurable retention period (0-36,500 days) - Implemented automatic cleanup logic in the Deletes worker to remove deployments older than the specified retention period
- Enhanced the Maintenance task with a
--typeparameter supporting both "loop" (continuous) and "trigger" (one-time) execution modes
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| app/config/collections/projects.php | Added deploymentRetention field to both functions and sites collection schemas |
| app/init/constants.php | Defined APP_COMPUTE_DEPLOYMENT_MAX_RETENTION constant (36,500 days = 100 years) |
| src/Appwrite/Utopia/Response/Model/Func.php | Added deploymentRetention field to Function API response model |
| src/Appwrite/Utopia/Response/Model/Site.php | Added deploymentRetention field to Site API response model |
| src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php | Added deploymentRetention parameter to function creation endpoint |
| src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php | Added deploymentRetention parameter to function update endpoint |
| src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php | Added deploymentRetention parameter to site creation endpoint |
| src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php | Added deploymentRetention parameter to site update endpoint |
| src/Appwrite/Platform/Workers/Deletes.php | Implemented deleteOldDeployments method to clean up expired deployments during maintenance |
| src/Appwrite/Platform/Tasks/Maintenance.php | Enhanced with type parameter to support both continuous loop and one-time trigger execution |
| app/controllers/mock.php | Added /mock/time-travels endpoint for testing by manipulating deployment creation timestamps |
| tests/e2e/Services/Functions/FunctionsCustomServerTest.php | Added comprehensive tests for deployment retention parameter validation |
| tests/e2e/Services/Functions/FunctionsConsoleClientTest.php | Added integration test verifying deployment cleanup via maintenance task |
| tests/e2e/Services/Sites/SitesCustomServerTest.php | Added comprehensive tests for deployment retention parameter validation |
| tests/e2e/Services/Sites/SitesConsoleClientTest.php | Added integration test verifying deployment cleanup via maintenance task |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
What does this PR do?
Adds support for auto-deleting old non-active deployments
Test Plan
New tests
Related PRs and Issues
x
Checklist