diff --git a/app/config/collections.php b/app/config/collections.php index ce0ae19e06..f92e53ab21 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -485,10 +485,10 @@ $collections = [ ], ], - 'vcs' => [ + 'vcs_installations' => [ '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('vcs'), - 'name' => 'vcs', + '$id' => ID::custom('vcs_installations'), + 'name' => 'vcs_installations', 'attributes' => [ [ '$id' => ID::custom('installationId'), @@ -550,10 +550,10 @@ $collections = [ ], ], - 'vcs_map' => [ + 'vcs_repos' => [ '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('vcs_map'), - 'name' => 'vcs_map', + '$id' => ID::custom('vcs_repos'), + 'name' => 'vcs_repos', 'attributes' => [ [ '$id' => ID::custom('projectId'), diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index f684bfd470..cc09d8491a 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -514,10 +514,10 @@ App::put('/v1/functions/:functionId') $githubAppId = App::getEnv('VCS_GITHUB_APP_ID'); $projectInternalId = $project->getInternalId(); - $vcs = $dbForConsole->findOne('vcs', [ + $vcs_installations = $dbForConsole->findOne('vcs_installations', [ Query::equal('projectInternalId', [$projectInternalId]) ]); - $installationId = $vcs->getAttribute('installationId'); + $installationId = $vcs_installations->getAttribute('installationId'); var_dump($installationId); @@ -528,7 +528,7 @@ App::put('/v1/functions/:functionId') $code = $github->generateGitCloneCommand($repositoryId, $branchName); //Add document in VCS map collection - $vcs_mapping = new Document([ + $vcs_repos = new Document([ '$id' => ID::unique(), '$permissions' => [ Permission::read(Role::any()), @@ -543,7 +543,7 @@ App::put('/v1/functions/:functionId') 'resourceType' => "function" ]); - $vcs_mapping = $dbForConsole->createDocument('vcs_map', $vcs_mapping); + $vcs_repos = $dbForConsole->createDocument('vcs_repos', $vcs_repos); $deployment = $dbForProject->createDocument('deployments', new Document([ '$id' => $deploymentId, diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 01fb5ce76c..e67b560a62 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -38,7 +38,7 @@ App::get('/v1/vcs/github/installations') $response->redirect("https://github.com/apps/demoappkh/installations/new?state=$projectId"); }); -App::get('/v1/vcs/github/setup') +App::get('/v1/vcs/github/incominginstallation') ->desc('Capture installation id and state after GitHub App Installation') ->groups(['api', 'vcs']) ->label('scope', 'public') @@ -77,7 +77,7 @@ App::get('/v1/vcs/github/setup') 'accessToken' => null ]); - $github = $dbForConsole->createDocument('vcs', $github); + $github = $dbForConsole->createDocument('vcs_installations', $github); var_dump("hello"); @@ -107,7 +107,7 @@ App::get('v1/vcs/github/installations/:installationId/repositories') $response->json($repos); }); -App::post('/v1/vcs/github/incoming') +App::post('/v1/vcs/github/incomingwebhook') ->desc('Captures GitHub Webhook Events') ->groups(['api', 'vcs']) ->label('scope', 'public') @@ -118,88 +118,84 @@ App::post('/v1/vcs/github/incoming') ->inject('db') ->action( function (Request $request, Response $response, Database $dbForConsole, mixed $cache, mixed $db) { - //switch case on different types of incoming requests - //TODO: Handle method logic for installation and uninstallation - $cache = new Cache(new Redis($cache)); - - // parse the webhook payload $event = $request->getHeader('x-github-event', ''); $payload = $request->getRawPayload(); $github = new GitHub(); + $parsedPayload = $github->parseWebhookEventPayload($event, $payload); + $parsedPayload = json_decode($parsedPayload, true); - if ($event == "push" || $event == "pull_request") { //TODO: Change events to constants - // TODO: In case of PR, only create a new deployment when the action is opened and not closed - $parsedPayload = $github->parseWebhookEventPayload($event, $payload); - $parsedPayload = json_decode($parsedPayload, true); + if ($event == $github::EVENT_PUSH) { $branchName = $parsedPayload["branch"]; - if (($event == "push" && $branchName == "main") || $event == "pull_request") { - // in case of push events on main branch or new PR, map repo id to function id and trigger a deployment - $repositoryId = $parsedPayload["repositoryId"]; - $installationId = $parsedPayload["installationId"]; + $repositoryId = $parsedPayload["repositoryId"]; + $installationId = $parsedPayload["installationId"]; - // find function id from functions table - $resources = $dbForConsole->find('vcs_map', [ - Query::equal('repositoryId', [$repositoryId]), - Query::limit(100), - ]); + //find functionId from functions table + $resources = $dbForConsole->find('vcs_repos', [ + Query::equal('repositoryId', [$repositoryId]), + Query::limit(100), + ]); - foreach ($resources as $resource) { - $resourceType = $resource->getAttribute('resourceType'); + foreach ($resources as $resource) { + $resourceType = $resource->getAttribute('resourceType'); - if ($resourceType == "function") { - // start a new deployment - // TODO: For cloud, we might have different $db - $dbForProject = new Database(new MariaDB($db), $cache); - $dbForProject->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $dbForProject->setNamespace("_{$resource->getAttribute('projectInternalId')}"); + if ($resourceType == "function") { + // TODO: For cloud, we might have different $db + $dbForProject = new Database(new MariaDB($db), $cache); + $dbForProject->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); + $dbForProject->setNamespace("_{$resource->getAttribute('projectInternalId')}"); - $functionId = $resource->getAttribute('resourceId'); - //TODO: Why is Authorization::skip needed? - $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $projectId = $resource->getAttribute('projectId'); - //TODO: Why is Authorization::skip needed? - $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); - $deploymentId = ID::unique(); - $entrypoint = 'index.js'; //TODO: Read from function settings - $privateKey = App::getEnv('VCS_GITHUB_PRIVATE_KEY'); - $githubAppId = App::getEnv('VCS_GITHUB_APP_ID'); - $github->initialiseVariables($installationId, $privateKey, $githubAppId, 'vermakhushboo'); - $code = $github->generateGitCloneCommand($repositoryId, $branchName); - $activate = false; + $functionId = $resource->getAttribute('resourceId'); + //TODO: Why is Authorization::skip needed? + $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); + $projectId = $resource->getAttribute('projectId'); + //TODO: Why is Authorization::skip needed? + $project = Authorization::skip(fn () => $dbForConsole->getDocument('projects', $projectId)); + $deploymentId = ID::unique(); + $entrypoint = 'index.js'; //TODO: Read from function settings + $privateKey = App::getEnv('VCS_GITHUB_PRIVATE_KEY'); + $githubAppId = App::getEnv('VCS_GITHUB_APP_ID'); + $github->initialiseVariables($installationId, $privateKey, $githubAppId, 'vermakhushboo'); + $code = $github->generateGitCloneCommand($repositoryId, $branchName); + $activate = false; - if ($branchName == "main") { - $activate = true; // activate deployments only if there are on the main branch - } - - $deployment = $dbForProject->createDocument('deployments', new Document([ - '$id' => $deploymentId, - '$permissions' => [ - Permission::read(Role::any()), - Permission::update(Role::any()), - Permission::delete(Role::any()), - ], - 'resourceId' => $functionId, - 'resourceType' => 'functions', - 'entrypoint' => $entrypoint, - 'path' => $code, - 'search' => implode(' ', [$deploymentId, $entrypoint]), - 'activate' => $activate, - ])); - - $buildEvent = new Build(); - $buildEvent - ->setType(BUILD_TYPE_DEPLOYMENT) - ->setResource($function) - ->setDeployment($deployment) - ->setProject($project) - ->trigger(); - - //TODO: Add event? + if ($branchName == "main") { + $activate = true; } + + $deployment = $dbForProject->createDocument('deployments', new Document([ + '$id' => $deploymentId, + '$permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], + 'resourceId' => $functionId, + 'resourceType' => 'functions', + 'entrypoint' => $entrypoint, + 'path' => $code, + 'search' => implode(' ', [$deploymentId, $entrypoint]), + 'activate' => $activate, + ])); + + $buildEvent = new Build(); + $buildEvent + ->setType(BUILD_TYPE_DEPLOYMENT) + ->setResource($function) + ->setDeployment($deployment) + ->setProject($project) + ->trigger(); + + //TODO: Add event? } } + } else if ($event == $github::EVENT_INSTALLATION) { + $installationId = $parsedPayload["installationId"]; + // delete documents from all respective collections + } else if ($event == $github::EVENT_PULL_REQUEST) { + // find last push to this branch } + $response->json($parsedPayload); } ); diff --git a/composer.lock b/composer.lock index 3c569086c8..c35d5c63c9 100644 --- a/composer.lock +++ b/composer.lock @@ -1402,21 +1402,21 @@ }, { "name": "psr/http-client", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", "shasum": "" }, "require": { "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -1436,7 +1436,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP clients", @@ -1448,27 +1448,27 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/master" + "source": "https://github.com/php-fig/http-client/tree/1.0.2" }, - "time": "2020-06-29T06:28:15+00:00" + "time": "2023-04-10T20:12:12+00:00" }, { "name": "psr/http-factory", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + "reference": "e616d01114759c4c489f93b099585439f795fe35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", "shasum": "" }, "require": { "php": ">=7.0.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -1488,7 +1488,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interfaces for PSR-7 HTTP message factories", @@ -1503,9 +1503,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/master" + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" }, - "time": "2019-04-30T12:38:16+00:00" + "time": "2023-04-10T20:10:41+00:00" }, { "name": "psr/http-message", @@ -3160,7 +3160,7 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/vcs.git", - "reference": "73e743b1a82255f61f09304ba9a7e6a28cbfaf67" + "reference": "e790e4bad005f426a8a9050eeaa9921b1d455b80" }, "require": { "adhocore/jwt": "^1.1", @@ -3204,7 +3204,7 @@ "utopia", "vcs" ], - "time": "2023-04-06T12:10:08+00:00" + "time": "2023-04-11T14:48:22+00:00" }, { "name": "utopia-php/websocket", @@ -4226,16 +4226,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.18.0", + "version": "1.18.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "882eabc9b6a12e25c27091a261397f9c8792e722" + "reference": "22dcdfd725ddf99583bfe398fc624ad6c5004a0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/882eabc9b6a12e25c27091a261397f9c8792e722", - "reference": "882eabc9b6a12e25c27091a261397f9c8792e722", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/22dcdfd725ddf99583bfe398fc624ad6c5004a0f", + "reference": "22dcdfd725ddf99583bfe398fc624ad6c5004a0f", "shasum": "" }, "require": { @@ -4265,9 +4265,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.18.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.18.1" }, - "time": "2023-04-06T07:26:43+00:00" + "time": "2023-04-07T11:51:11+00:00" }, { "name": "phpunit/php-code-coverage",