diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php
index 9021c6c518..32e12a4932 100644
--- a/app/controllers/api/vcs.php
+++ b/app/controllers/api/vcs.php
@@ -113,14 +113,15 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
if ($latestComment !== false && !$latestComment->isEmpty()) {
$latestCommentId = $latestComment->getAttribute('providerCommentId', '');
+
$comment = new Comment();
$comment->parseComment($github->getComment($owner, $repositoryName, $latestCommentId));
- $comment->addBuild($project, $resource, $commentStatus, $deploymentId, $action);
+ $comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '', '');
$latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()));
} else {
$comment = new Comment();
- $comment->addBuild($project, $resource, $commentStatus, $deploymentId, $action);
+ $comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '', '');
$latestCommentId = \strval($github->createComment($owner, $repositoryName, $providerPullRequestId, $comment->generateComment()));
if (!empty($latestCommentId)) {
@@ -157,7 +158,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
$latestCommentId = $comment->getAttribute('providerCommentId', '');
$comment = new Comment();
$comment->parseComment($github->getComment($owner, $repositoryName, $latestCommentId));
- $comment->addBuild($project, $resource, $commentStatus, $deploymentId, $action);
+ $comment->addBuild($project, $resource, $resourceType, $commentStatus, $deploymentId, $action, '', '');
$latestCommentId = \strval($github->updateComment($owner, $repositoryName, $latestCommentId, $comment->generateComment()));
}
diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php
index bf598dd9d1..a528a14c02 100644
--- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php
+++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php
@@ -22,6 +22,7 @@ use Utopia\Database\Exception\Conflict;
use Utopia\Database\Exception\Restricted;
use Utopia\Database\Exception\Structure;
use Utopia\Database\Helpers\ID;
+use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
use Utopia\Logger\Log;
use Utopia\Platform\Action;
@@ -690,28 +691,6 @@ class Builds extends Action
$build = $dbForProject->updateDocument('builds', $buildId, $build);
- if ($isVcsEnabled) {
- $this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForConsole);
- }
-
- Console::success("Build id: $buildId created");
-
- /** Set auto deploy */
- if ($deployment->getAttribute('activate') === true) {
- $resource->setAttribute('deploymentInternalId', $deployment->getInternalId());
- $resource->setAttribute('live', true);
- switch ($resource->getCollection()) {
- case 'functions':
- $resource->setAttribute('deployment', $deployment->getId());
- $resource = $dbForProject->updateDocument('functions', $resource->getId(), $resource);
- break;
- case 'sites':
- $resource->setAttribute('deploymentId', $deployment->getId());
- $resource = $dbForProject->updateDocument('sites', $resource->getId(), $resource);
- break;
- }
- }
-
// Preview deployments for sites
if ($resource->getCollection() === 'sites') {
$ruleId = ID::unique();
@@ -737,6 +716,28 @@ class Builds extends Action
);
}
+ if ($isVcsEnabled) {
+ $this->runGitAction('ready', $github, $providerCommitHash, $owner, $repositoryName, $project, $resource, $deployment->getId(), $dbForProject, $dbForConsole);
+ }
+
+ Console::success("Build id: $buildId created");
+
+ /** Set auto deploy */
+ if ($deployment->getAttribute('activate') === true) {
+ $resource->setAttribute('deploymentInternalId', $deployment->getInternalId());
+ $resource->setAttribute('live', true);
+ switch ($resource->getCollection()) {
+ case 'functions':
+ $resource->setAttribute('deployment', $deployment->getId());
+ $resource = $dbForProject->updateDocument('functions', $resource->getId(), $resource);
+ break;
+ case 'sites':
+ $resource->setAttribute('deploymentId', $deployment->getId());
+ $resource = $dbForProject->updateDocument('sites', $resource->getId(), $resource);
+ break;
+ }
+ }
+
if ($dbForProject->getDocument('builds', $buildId)->getAttribute('status') === 'canceled') {
Console::info('Build has been canceled');
return;
@@ -976,9 +977,34 @@ class Builds extends Action
// Wrap in try/finally to ensure lock file gets deleted
try {
+ $resourceType = match($resource->getCollection()) {
+ 'functions' => 'function',
+ 'sites' => 'site',
+ default => throw new \Exception('Invalid resource type')
+ };
+
+ $rule = Authorization::skip(fn () => $dbForConsole->findOne('rules', [
+ Query::equal("projectInternalId", [$project->getInternalId()]),
+ Query::equal("resourceType", ["deployment"]),
+ Query::equal("resourceInternalId", [$deployment->getInternalId()])
+ ]));
+
+ $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https';
+ $previewUrl = match($resource->getCollection()) {
+ 'functions' => '',
+ 'sites' => !empty($rule) ? ("{$protocol}://" . $rule->getAttribute('domain', '')) : '',
+ default => throw new \Exception('Invalid resource type')
+ };
+
+ $previweQrCode = match($resource->getCollection()) {
+ 'functions' => '',
+ 'sites' => 'https://cloud.appwrite.io/v1/avatars/qr?text=' . $previewUrl,
+ default => throw new \Exception('Invalid resource type')
+ };
+
$comment = new Comment();
$comment->parseComment($github->getComment($owner, $repositoryName, $commentId));
- $comment->addBuild($project, $resource, $status, $deployment->getId(), ['type' => 'logs']);
+ $comment->addBuild($project, $resource, $resourceType, $status, $deployment->getId(), ['type' => 'logs'], $previewUrl, $previweQrCode);
$github->updateComment($owner, $repositoryName, $commentId, $comment->generateComment());
} finally {
$dbForConsole->deleteDocument('vcsCommentLocks', $commentId);
diff --git a/src/Appwrite/Vcs/Comment.php b/src/Appwrite/Vcs/Comment.php
index 18379f1099..e1d423d772 100644
--- a/src/Appwrite/Vcs/Comment.php
+++ b/src/Appwrite/Vcs/Comment.php
@@ -27,19 +27,22 @@ class Comment
return \count($this->builds) === 0;
}
- public function addBuild(Document $project, Document $function, string $buildStatus, string $deploymentId, array $action): void
+ public function addBuild(Document $project, Document $resource, string $resourceType, string $buildStatus, string $deploymentId, array $action, string $previewUrl, string $previewQrCode): void
{
// Unique index
- $id = $project->getId() . '_' . $function->getId();
+ $id = $project->getId() . '_' . $resource->getId();
$this->builds[$id] = [
'projectName' => $project->getAttribute('name'),
'projectId' => $project->getId(),
- 'functionName' => $function->getAttribute('name'),
- 'functionId' => $function->getId(),
+ 'resourceName' => $resource->getAttribute('name'),
+ 'resourceId' => $resource->getId(),
+ 'resourceType' => $resourceType,
'buildStatus' => $buildStatus,
'deploymentId' => $deploymentId,
'action' => $action,
+ 'previewQrCode' => $previewQrCode,
+ 'previewUrl' => $previewUrl,
];
}
@@ -55,68 +58,108 @@ class Comment
if (!\array_key_exists($build['projectId'], $projects)) {
$projects[$build['projectId']] = [
'name' => $build['projectName'],
- 'functions' => []
+ 'function' => [],
+ 'site' => []
];
}
- $projects[$build['projectId']]['functions'][$build['functionId']] = [
- 'name' => $build['functionName'],
- 'status' => $build['buildStatus'],
- 'deploymentId' => $build['deploymentId'],
- 'action' => $build['action'],
- ];
+ if ($build['resourceType'] === 'site') {
+ $projects[$build['projectId']]['site'][$build['resourceId']] = [
+ 'name' => $build['resourceName'],
+ 'status' => $build['buildStatus'],
+ 'deploymentId' => $build['deploymentId'],
+ 'action' => $build['action'],
+ 'previewUrl' => $build['previewUrl'],
+ 'previewQrCode' => $build['previewQrCode']
+ ];
+ } elseif ($build['resourceType'] === 'function') {
+ $projects[$build['projectId']]['function'][$build['resourceId']] = [
+ 'name' => $build['resourceName'],
+ 'status' => $build['buildStatus'],
+ 'deploymentId' => $build['deploymentId'],
+ 'action' => $build['action'],
+ ];
+ }
}
foreach ($projects as $projectId => $project) {
- $text .= "**{$project['name']}** `{$projectId}`\n\n";
- $text .= "| Function | ID | Status | Action |\n";
- $text .= "| :- | :- | :- | :- |\n";
-
$protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https';
$hostname = System::getEnv('_APP_DOMAIN');
- foreach ($project['functions'] as $functionId => $function) {
- if ($function['status'] === 'waiting' || $function['status'] === 'processing' || $function['status'] === 'building') {
- $text .= "**Your function deployment is in progress. Please check back in a few minutes for the updated status.**\n\n";
- } elseif ($function['status'] === 'ready') {
- $text .= "**Your function has been successfully deployed.**\n\n";
- } else {
- $text .= "**Your function deployment has failed. Please check the logs for more details and retry.**\n\n";
+ $text .= "Project name: **{$project['name']}** \nProject ID: `{$projectId}`\n\n";
+
+ if (\count($project['site']) > 0) {
+
+ $text .= "| Site | ID | Status | Previews | Action |\n";
+ $text .= "| :- | :- | :- | :- | :- |\n";
+
+ foreach ($project['site'] as $siteId => $site) {
+ $generateImage = function (string $status) use ($protocol, $hostname) {
+ $extention = $status === 'building' ? 'gif' : 'png';
+ $imagesUrl = $protocol . '://' . $hostname . '/console/images/vcs/';
+ $imageUrl = '
';
+
+ return $imageUrl;
+ };
+
+ $status = match ($site['status']) {
+ 'waiting' => $generateImage('waiting') . ' Waiting to build',
+ 'processing' => $generateImage('processing') . ' Processing',
+ 'building' => $generateImage('building') . ' Building',
+ 'ready' => $generateImage('ready') . ' Ready',
+ 'failed' => $generateImage('failed') . ' Failed',
+ };
+
+ if ($site['action']['type'] === 'logs') {
+ $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $projectId . '/sites/site-' . $siteId . '/deployment-' . $site['deploymentId'] . ')';
+ } else {
+ $action = '[Authorize](' . $site['action']['url'] . ')';
+ }
+
+ $previews = '[Preview URL](' . $site['previewUrl'] . ') [QR Code](' . $site['previewQrCode'] . ')';
+
+ $text .= "| {$site['name']} | `{$siteId}` | {$status} | {$previews} | {$action} |\n";
}
- $text .= "Project name: **{$project['name']}** \nProject ID: `{$projectId}`\n\n";
+ $text .= "\n\n";
+ }
+
+ if (\count($project['function']) > 0) {
+
$text .= "| Function | ID | Status | Action |\n";
$text .= "| :- | :- | :- | :- |\n";
- $generateImage = function (string $status) use ($protocol, $hostname) {
- $extention = $status === 'building' ? 'gif' : 'png';
- $imagesUrl = $protocol . '://' . $hostname . '/images/vcs/';
- $imageUrl = '
';
+ foreach ($project['function'] as $functionId => $function) {
+ $generateImage = function (string $status) use ($protocol, $hostname) {
+ $extention = $status === 'building' ? 'gif' : 'png';
+ $imagesUrl = $protocol . '://' . $hostname . '/images/vcs/';
+ $imageUrl = '
';
+ return $imageUrl;
+ };
- return $imageUrl;
- };
+ $status = match ($function['status']) {
+ 'waiting' => $generateImage('waiting') . ' Waiting to build',
+ 'processing' => $generateImage('processing') . ' Processing',
+ 'building' => $generateImage('building') . ' Building',
+ 'ready' => $generateImage('ready') . ' Ready',
+ 'failed' => $generateImage('failed') . ' Failed',
+ };
- $status = match ($function['status']) {
- 'waiting' => $generateImage('waiting') . ' Waiting to build',
- 'processing' => $generateImage('processing') . ' Processing',
- 'building' => $generateImage('building') . ' Building',
- 'ready' => $generateImage('ready') . ' Ready',
- 'failed' => $generateImage('failed') . ' Failed',
- };
+ if ($function['action']['type'] === 'logs') {
+ $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $projectId . '/functions/function-' . $functionId . '/deployment-' . $function['deploymentId'] . ')';
+ } else {
+ $action = '[Authorize](' . $function['action']['url'] . ')';
+ }
- if ($function['action']['type'] === 'logs') {
- $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $projectId . '/functions/function-' . $functionId . '/deployment-' . $function['deploymentId'] . ')';
- } else {
- $action = '[Authorize](' . $function['action']['url'] . ')';
+ $text .= "| {$function['name']} | `{$functionId}` | {$status} | {$action} |\n";
}
- $text .= "| {$function['name']} | `{$functionId}` | {$status} | {$action} |\n";
+ $text .= "\n\n";
}
- $text .= "\n\n";
}
- $functionUrl = $protocol . '://' . $hostname . '/console/project-' . $projectId . '/functions/function-' . $functionId;
- $text .= "Only deployments on the production branch are activated automatically. If you'd like to activate this deployment, navigate to [your deployments]($functionUrl). Learn more about Appwrite [Function deployments](https://appwrite.io/docs/functions).\n\n";
+
+ $text .= "Only deployments on the production branch are activated automatically. Learn more about Appwrite [Functions](https://appwrite.io/docs/functions) and [Sites](https://appwrite.io/docs/sites).\n\n";
$tip = $this->tips[array_rand($this->tips)];
$text .= "> **💡 Did you know?** \n " . $tip . "\n\n";