diff --git a/app/config/frameworks.php b/app/config/frameworks.php index 82fd70bf5b..5440e9a538 100644 --- a/app/config/frameworks.php +++ b/app/config/frameworks.php @@ -138,7 +138,7 @@ return [ 'vue' => [ 'key' => 'vue', 'name' => 'Vue.js', - 'screenshotSleep' => 3000, + 'screenshotSleep' => 5000, 'buildRuntime' => 'node-22', 'runtimes' => getVersions($templateRuntimes['NODE']['versions'], 'node'), 'adapters' => [ diff --git a/app/controllers/general.php b/app/controllers/general.php index 3f105484e1..13dec5dac9 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -268,8 +268,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw if (\is_null($runtime)) { throw new AppwriteException(AppwriteException::FUNCTION_RUNTIME_UNSUPPORTED, 'Runtime "' . $resource->getAttribute('runtime', '') . '" is not supported'); } - - if ($deployment->getAttribute('status') !== 'ready') { + + $allowAnyStatus = !\is_null($apiKey) && $apiKey->isDeploymentStatusIgnored(); + if (!$allowAnyStatus && $deployment->getAttribute('status') !== 'ready') { throw new AppwriteException(AppwriteException::BUILD_NOT_READY); } diff --git a/src/Appwrite/Auth/Key.php b/src/Appwrite/Auth/Key.php index 89c28c4727..87e77b2e06 100644 --- a/src/Appwrite/Auth/Key.php +++ b/src/Appwrite/Auth/Key.php @@ -24,6 +24,7 @@ class Key protected bool $bannerDisabled = false, protected bool $projectCheckDisabled = false, protected bool $previewAuthDisabled = false, + protected bool $deploymentStatusIgnored = false, ) { } @@ -78,6 +79,11 @@ class Key { return $this->previewAuthDisabled; } + + public function isDeploymentStatusIgnored(): bool + { + return $this->deploymentStatusIgnored; + } public function isProjectCheckDisabled(): bool { @@ -139,6 +145,7 @@ class Key $bannerDisabled = $payload['bannerDisabled'] ?? false; $projectCheckDisabled = $payload['projectCheckDisabled'] ?? false; $previewAuthDisabled = $payload['previewAuthDisabled'] ?? false; + $deploymentStatusIgnored = $payload['deploymentStatusIgnored'] ?? false; $scopes = \array_merge($payload['scopes'] ?? [], $scopes); if (!$projectCheckDisabled && $projectId !== $project->getId()) { @@ -156,7 +163,8 @@ class Key $hostnameOverride, $bannerDisabled, $projectCheckDisabled, - $previewAuthDisabled + $previewAuthDisabled, + $deploymentStatusIgnored ); case API_KEY_STANDARD: $key = $project->find( diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 3f28e7a7ce..849fd514d0 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -778,24 +778,26 @@ class Builds extends Action } $executor->deleteRuntime($project->getId(), $deployment->getId(), '-build'); - + /** Update the build document */ $deployment->setAttribute('buildStartAt', DateTime::format((new \DateTime())->setTimestamp(floor($response['startTime'])))); $deployment->setAttribute('buildEndAt', $endTime); $deployment->setAttribute('buildDuration', \intval(\ceil($durationEnd - $durationStart))); - $deployment->setAttribute('status', 'ready'); $deployment->setAttribute('buildPath', $response['path']); $deployment->setAttribute('buildSize', $response['size']); $deployment->setAttribute('totalSize', $deployment->getAttribute('buildSize', 0) + $deployment->getAttribute('sourceSize', 0)); - + $logs = ''; foreach ($response['output'] as $log) { $logs .= $log['content']; } + $logs .= "Capturing screenshots ...\n"; $deployment->setAttribute('buildLogs', $logs); + + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); - + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); @@ -804,13 +806,8 @@ class Builds extends Action $queueForRealtime ->setPayload($deployment->getArrayCopy()) ->trigger(); - - if ($isVcsEnabled) { - $this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform); - } - - Console::success("Build id: $deploymentId created"); - + + /** Screenshot site */ if ($resource->getCollection() === 'sites') { try { $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ @@ -848,6 +845,7 @@ class Builds extends Action 'bannerDisabled' => true, 'projectCheckDisabled' => true, 'previewAuthDisabled' => true, + 'deploymentStatusIgnored' => true ]); // TODO: @Meldiron if becomes too slow, do concurrently @@ -864,17 +862,17 @@ class Builds extends Action $config['sleep'] = $framework['screenshotSleep']; } - $response = $client->fetch( + $fetchResponse = $client->fetch( url: 'http://appwrite-browser:3000/v1/screenshots', method: 'POST', body: $config ); - if ($response->getStatusCode() >= 400) { - throw new \Exception($response->getBody()); + if ($fetchResponse->getStatusCode() >= 400) { + throw new \Exception($fetchResponse->getBody()); } - $screenshot = $response->getBody(); + $screenshot = $fetchResponse->getBody(); $fileId = ID::unique(); $fileName = $fileId . '.png'; @@ -928,6 +926,20 @@ class Builds extends Action } } + /** Update the status */ + $deployment->setAttribute('status', 'ready'); + $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); + + $queueForRealtime + ->setPayload($deployment->getArrayCopy()) + ->trigger(); + + if ($isVcsEnabled) { + $this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForPlatform); + } + + Console::success("Build id: $deploymentId created"); + /** Set auto deploy */ if ($deployment->getAttribute('activate') === true) { $resource->setAttribute('live', true); @@ -1066,6 +1078,12 @@ class Builds extends Action Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); } } catch (\Throwable $th) { + Console::warning('Build failed:'); + Console::error($th->getMessage()); + Console::error($th->getFile()); + Console::error($th->getLine()); + Console::error($th->getTraceAsString()); + if ($dbForProject->getDocument('deployments', $deploymentId)->getAttribute('status') === 'canceled') { Console::info('Build has been canceled'); return;