mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 08:58:35 +00:00
Merge pull request #9445 from appwrite/chore-rename-redeploy-endpoint
Chore: Migrate redeploy endpoint
This commit is contained in:
commit
4428ed1f7d
11 changed files with 193 additions and 23 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Builds;
|
||||
namespace Appwrite\Platform\Modules\Functions\Http\Deployments\Duplicate;
|
||||
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
|
|
@ -22,16 +22,17 @@ class Create extends Action
|
|||
|
||||
public static function getName()
|
||||
{
|
||||
return 'createDeploymentBuild';
|
||||
return 'createDuplicateDeployment';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST)
|
||||
->setHttpPath('/v1/functions/:functionId/deployments/:deploymentId/build')
|
||||
->setHttpPath('/v1/functions/:functionId/deployments/duplicate')
|
||||
->httpAlias('/v1/functions/:functionId/deployments/:deploymentId/build')
|
||||
->httpAlias('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId')
|
||||
->desc('Rebuild deployment')
|
||||
->desc('Create duplicate deployment')
|
||||
->groups(['api', 'functions'])
|
||||
->label('scope', 'functions.write')
|
||||
->label('resourceType', RESOURCE_TYPE_FUNCTIONS)
|
||||
|
|
@ -40,15 +41,15 @@ class Create extends Action
|
|||
->label('audits.resource', 'function/{request.functionId}')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'functions',
|
||||
name: 'createBuild',
|
||||
name: 'createDuplicateDeployment',
|
||||
description: <<<EOT
|
||||
Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.
|
||||
EOT,
|
||||
auth: [AuthType::KEY],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_NOCONTENT,
|
||||
model: Response::MODEL_NONE,
|
||||
code: Response::STATUS_CODE_ACCEPTED,
|
||||
model: Response::MODEL_DEPLOYMENT,
|
||||
)
|
||||
]
|
||||
))
|
||||
|
|
@ -107,6 +108,8 @@ class Create extends Action
|
|||
->setParam('functionId', $function->getId())
|
||||
->setParam('deploymentId', $deployment->getId());
|
||||
|
||||
$response->noContent();
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
|
||||
->dynamic($deployment, Response::MODEL_DEPLOYMENT);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
namespace Appwrite\Platform\Modules\Functions\Services;
|
||||
|
||||
use Appwrite\Platform\Modules\Functions\Http\Deployments\Builds\Create as CreateBuild;
|
||||
use Appwrite\Platform\Modules\Functions\Http\Deployments\Builds\Update as UpdateBuild;
|
||||
use Appwrite\Platform\Modules\Functions\Http\Deployments\Create as CreateDeployment;
|
||||
use Appwrite\Platform\Modules\Functions\Http\Deployments\Delete as DeleteDeployment;
|
||||
use Appwrite\Platform\Modules\Functions\Http\Deployments\Download\Get as DownloadDeployment;
|
||||
use Appwrite\Platform\Modules\Functions\Http\Deployments\Duplicate\Create as CreateDuplicateDeployment;
|
||||
use Appwrite\Platform\Modules\Functions\Http\Deployments\Get as GetDeployment;
|
||||
use Appwrite\Platform\Modules\Functions\Http\Deployments\Template\Create as CreateTemplateDeployment;
|
||||
use Appwrite\Platform\Modules\Functions\Http\Deployments\Vcs\Create as CreateVcsDeployment;
|
||||
|
|
@ -62,7 +62,7 @@ class Http extends Service
|
|||
$this->addAction(CreateTemplateDeployment::getName(), new CreateTemplateDeployment());
|
||||
$this->addAction(CreateVcsDeployment::getName(), new CreateVcsDeployment());
|
||||
$this->addAction(DownloadDeployment::getName(), new DownloadDeployment());
|
||||
$this->addAction(CreateBuild::getName(), new CreateBuild());
|
||||
$this->addAction(CreateDuplicateDeployment::getName(), new CreateDuplicateDeployment());
|
||||
$this->addAction(UpdateBuild::getName(), new UpdateBuild());
|
||||
|
||||
// Executions
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Builds;
|
||||
namespace Appwrite\Platform\Modules\Sites\Http\Deployments\Duplicate;
|
||||
|
||||
use Appwrite\Event\Build;
|
||||
use Appwrite\Event\Event;
|
||||
|
|
@ -25,15 +25,15 @@ class Create extends Action
|
|||
|
||||
public static function getName()
|
||||
{
|
||||
return 'createDeploymentBuild';
|
||||
return 'createDuplicateDeployment';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST)
|
||||
->setHttpPath('/v1/sites/:siteId/deployments/:deploymentId/build')
|
||||
->desc('Rebuild deployment')
|
||||
->setHttpPath('/v1/sites/:siteId/deployments/duplicate')
|
||||
->desc('Create duplicate deployment')
|
||||
->groups(['api', 'sites'])
|
||||
->label('scope', 'sites.write')
|
||||
->label('event', 'sites.[siteId].deployments.[deploymentId].update')
|
||||
|
|
@ -41,15 +41,15 @@ class Create extends Action
|
|||
->label('audits.resource', 'site/{request.siteId}')
|
||||
->label('sdk', new Method(
|
||||
namespace: 'sites',
|
||||
name: 'createDeploymentBuild',
|
||||
name: 'createDuplicateDeployment',
|
||||
description: <<<EOT
|
||||
Create a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.
|
||||
EOT,
|
||||
auth: [AuthType::KEY],
|
||||
responses: [
|
||||
new SDKResponse(
|
||||
code: Response::STATUS_CODE_NOCONTENT,
|
||||
model: Response::MODEL_NONE,
|
||||
code: Response::STATUS_CODE_ACCEPTED,
|
||||
model: Response::MODEL_DEPLOYMENT,
|
||||
)
|
||||
]
|
||||
))
|
||||
|
|
@ -130,6 +130,8 @@ class Create extends Action
|
|||
->setParam('siteId', $site->getId())
|
||||
->setParam('deploymentId', $deployment->getId());
|
||||
|
||||
$response->noContent();
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
|
||||
->dynamic($deployment, Response::MODEL_DEPLOYMENT);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
namespace Appwrite\Platform\Modules\Sites\Services;
|
||||
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\Builds\Create as CreateBuild;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\Builds\Update as UpdateBuild;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\Create as CreateDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\Delete as DeleteDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\Download\Get as DownloadDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\Duplicate\Create as CreateDuplicateDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\Get as GetDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\Template\Create as CreateTemplateDeployment;
|
||||
use Appwrite\Platform\Modules\Sites\Http\Deployments\Vcs\Create as CreateVcsDeployment;
|
||||
|
|
@ -57,7 +57,7 @@ class Http extends Service
|
|||
$this->addAction(UpdateSiteDeployment::getName(), new UpdateSiteDeployment());
|
||||
$this->addAction(DeleteDeployment::getName(), new DeleteDeployment());
|
||||
$this->addAction(DownloadDeployment::getName(), new DownloadDeployment());
|
||||
$this->addAction(CreateBuild::getName(), new CreateBuild());
|
||||
$this->addAction(CreateDuplicateDeployment::getName(), new CreateDuplicateDeployment());
|
||||
$this->addAction(UpdateBuild::getName(), new UpdateBuild());
|
||||
|
||||
// Logs
|
||||
|
|
|
|||
|
|
@ -87,6 +87,16 @@ trait FunctionsBase
|
|||
return $function;
|
||||
}
|
||||
|
||||
protected function updateFunction(string $functionId, mixed $params): mixed
|
||||
{
|
||||
$function = $this->client->call(Client::METHOD_PUT, '/functions/' . $functionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $function;
|
||||
}
|
||||
|
||||
protected function createVariable(string $functionId, mixed $params): mixed
|
||||
{
|
||||
$variable = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/variables', array_merge([
|
||||
|
|
@ -325,6 +335,39 @@ trait FunctionsBase
|
|||
return $response;
|
||||
}
|
||||
|
||||
protected function setupDuplicateDeployment(string $functionId, string $deploymentId): string
|
||||
{
|
||||
$deployment = $this->createDuplicateDeployment($functionId, $deploymentId);
|
||||
$this->assertEquals(202, $deployment['headers']['status-code']);
|
||||
|
||||
$deploymentId = $deployment['body']['$id'];
|
||||
$this->assertNotEmpty($deploymentId);
|
||||
|
||||
$this->assertEventually(function () use ($functionId, $deploymentId) {
|
||||
$deployment = $this->getDeployment($functionId, $deploymentId);
|
||||
$this->assertEquals('ready', $deployment['body']['status'], 'Deployment status is not ready, deployment: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT));
|
||||
}, 100000, 500);
|
||||
|
||||
$this->assertEventually(function () use ($functionId, $deploymentId) {
|
||||
$function = $this->getFunction($functionId);
|
||||
$this->assertEquals($deploymentId, $function['body']['deployment'], 'Deployment is not activated, deployment: ' . json_encode($function['body'], JSON_PRETTY_PRINT));
|
||||
}, 100000, 500);
|
||||
|
||||
return $deploymentId;
|
||||
}
|
||||
|
||||
protected function createDuplicateDeployment(string $functionId, string $deploymentId): mixed
|
||||
{
|
||||
$deployment = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/deployments/duplicate', array_merge([
|
||||
'content-type' => 'multipart/form-data',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'deploymentId' => $deploymentId,
|
||||
]);
|
||||
|
||||
return $deployment;
|
||||
}
|
||||
|
||||
protected function updateFunctionDeployment(string $functionId, string $deploymentId): mixed
|
||||
{
|
||||
$function = $this->client->call(Client::METHOD_PATCH, '/functions/' . $functionId . '/deployment', array_merge([
|
||||
|
|
|
|||
|
|
@ -1990,6 +1990,46 @@ class FunctionsCustomServerTest extends Scope
|
|||
$this->cleanupFunction($functionId);
|
||||
}
|
||||
|
||||
public function testDuplicateDeployment(): void
|
||||
{
|
||||
$functionId = $this->setupFunction([
|
||||
'functionId' => ID::unique(),
|
||||
'runtime' => 'node-18.0',
|
||||
'name' => 'Duplicate Deployment Test',
|
||||
'entrypoint' => 'index.js',
|
||||
'commands' => ''
|
||||
]);
|
||||
$this->assertNotEmpty($functionId);
|
||||
|
||||
$deploymentId1 = $this->setupDeployment($functionId, [
|
||||
'code' => $this->packageFunction('node'),
|
||||
'activate' => true
|
||||
]);
|
||||
$this->assertNotEmpty($deploymentId1);
|
||||
|
||||
$execution = $this->createExecution($functionId);
|
||||
$this->assertEquals(201, $execution['headers']['status-code']);
|
||||
$this->assertStringContainsString('APPWRITE_FUNCTION_ID', $execution['body']['responseBody']);
|
||||
|
||||
$site = $this->updateFunction($functionId, [
|
||||
'runtime' => 'node-18.0',
|
||||
'name' => 'Duplicate Deployment Test',
|
||||
'entrypoint' => 'index.js',
|
||||
'commands' => 'rm index.js && mv maintenance.js index.js'
|
||||
]);
|
||||
$this->assertEquals(200, $site['headers']['status-code']);
|
||||
$this->assertStringContainsString('maintenance.js', $site['body']['commands']);
|
||||
|
||||
$deploymentId2 = $this->setupDuplicateDeployment($functionId, $deploymentId1);
|
||||
$this->assertNotEmpty($deploymentId2);
|
||||
|
||||
$execution = $this->createExecution($functionId);
|
||||
$this->assertEquals(201, $execution['headers']['status-code']);
|
||||
$this->assertStringContainsString('Maintenance', $execution['body']['responseBody']);
|
||||
|
||||
$this->cleanupFunction($functionId);
|
||||
}
|
||||
|
||||
public function testUpdateDeploymentStatus(): void
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -1620,7 +1620,7 @@ trait Base
|
|||
}';
|
||||
case self::$RETRY_BUILD:
|
||||
return 'mutation retryBuild($functionId: String!, $deploymentId: String!, $buildId: String!) {
|
||||
functionsCreateBuild(functionId: $functionId, deploymentId: $deploymentId, buildId: $buildId) {
|
||||
functionsCreateDuplicateDeployment(functionId: $functionId, deploymentId: $deploymentId, buildId: $buildId) {
|
||||
status
|
||||
}
|
||||
}';
|
||||
|
|
|
|||
|
|
@ -186,8 +186,8 @@ class FunctionsServerTest extends Scope
|
|||
'x-appwrite-project' => $projectId,
|
||||
], $this->getHeaders()), $gqlPayload);
|
||||
|
||||
$this->assertIsNotArray($response['body']);
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
$this->assertIsArray($response['body']['data']);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
public function testGetFunctions(): array
|
||||
|
|
|
|||
|
|
@ -244,6 +244,39 @@ trait SitesBase
|
|||
return $deployment;
|
||||
}
|
||||
|
||||
protected function setupDuplicateDeployment(string $siteId, string $deploymentId): string
|
||||
{
|
||||
$deployment = $this->createDuplicateDeployment($siteId, $deploymentId);
|
||||
$this->assertEquals(202, $deployment['headers']['status-code']);
|
||||
|
||||
$deploymentId = $deployment['body']['$id'];
|
||||
$this->assertNotEmpty($deploymentId);
|
||||
|
||||
$this->assertEventually(function () use ($siteId, $deploymentId) {
|
||||
$deployment = $this->getDeployment($siteId, $deploymentId);
|
||||
$this->assertEquals('ready', $deployment['body']['status'], 'Deployment status is not ready, deployment: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT));
|
||||
}, 100000, 500);
|
||||
|
||||
$this->assertEventually(function () use ($siteId, $deploymentId) {
|
||||
$site = $this->getSite($siteId);
|
||||
$this->assertEquals($deploymentId, $site['body']['deploymentId'], 'Deployment is not activated, deployment: ' . json_encode($site['body'], JSON_PRETTY_PRINT));
|
||||
}, 100000, 500);
|
||||
|
||||
return $deploymentId;
|
||||
}
|
||||
|
||||
protected function createDuplicateDeployment(string $siteId, string $deploymentId): mixed
|
||||
{
|
||||
$deployment = $this->client->call(Client::METHOD_POST, '/sites/' . $siteId . '/deployments/duplicate', array_merge([
|
||||
'content-type' => 'multipart/form-data',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'deploymentId' => $deploymentId,
|
||||
]);
|
||||
|
||||
return $deployment;
|
||||
}
|
||||
|
||||
protected function createTemplateDeployment(string $siteId, mixed $params = []): mixed
|
||||
{
|
||||
$deployment = $this->client->call(Client::METHOD_POST, '/sites/' . $siteId . '/deployments/template', array_merge([
|
||||
|
|
|
|||
|
|
@ -1744,6 +1744,52 @@ class SitesCustomServerTest extends Scope
|
|||
$this->cleanupSite($siteId);
|
||||
}
|
||||
|
||||
public function testDuplicateDeployment(): void
|
||||
{
|
||||
$siteId = $this->setupSite([
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'framework' => 'other',
|
||||
'name' => 'Duplicate deployment Site',
|
||||
'adapter' => 'static',
|
||||
'fallbackFile' => '404.html',
|
||||
'siteId' => ID::unique()
|
||||
]);
|
||||
$this->assertNotEmpty($siteId);
|
||||
|
||||
$domain = $this->setupSiteDomain($siteId);
|
||||
$this->assertNotEmpty($domain);
|
||||
$proxyClient = new Client();
|
||||
$proxyClient->setEndpoint('http://' . $domain);
|
||||
|
||||
$deploymentId1 = $this->setupDeployment($siteId, [
|
||||
'code' => $this->packageSite('static-spa'),
|
||||
'activate' => true
|
||||
]);
|
||||
$this->assertNotEmpty($deploymentId1);
|
||||
|
||||
$response = $proxyClient->call(Client::METHOD_GET, '/not-found');
|
||||
$this->assertStringContainsString("Customized 404 page", $response['body']);
|
||||
|
||||
$site = $this->updateSite([
|
||||
'$id' => $siteId,
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'framework' => 'other',
|
||||
'name' => 'Duplicate deployment Site',
|
||||
'adapter' => 'static',
|
||||
'fallbackFile' => 'index.html',
|
||||
]);
|
||||
$this->assertEquals(200, $site['headers']['status-code']);
|
||||
$this->assertEquals('index.html', $site['body']['fallbackFile']);
|
||||
|
||||
$deploymentId2 = $this->setupDuplicateDeployment($siteId, $deploymentId1);
|
||||
$this->assertNotEmpty($deploymentId2);
|
||||
|
||||
$response = $proxyClient->call(Client::METHOD_GET, '/not-found');
|
||||
$this->assertStringContainsString("Index page", $response['body']);
|
||||
|
||||
$this->cleanupSite($siteId);
|
||||
}
|
||||
|
||||
public function testUpdateDeploymentStatus(): void
|
||||
{
|
||||
$siteId = $this->setupSite([
|
||||
|
|
|
|||
3
tests/resources/functions/node/maintenance.js
Normal file
3
tests/resources/functions/node/maintenance.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = async(context) => {
|
||||
return context.res.send('Maintenance');
|
||||
}
|
||||
Loading…
Reference in a new issue