Merge pull request #8330 from appwrite/feat-vcs-get-contents
Feat: vcs.getRepositoryContents()
This commit is contained in:
commit
c64e9e1fab
6 changed files with 218 additions and 23 deletions
|
@ -464,6 +464,67 @@ App::get('/v1/vcs/github/callback')
|
|||
->redirect($redirectSuccess);
|
||||
});
|
||||
|
||||
App::get('/v1/vcs/github/installations/:installationId/providerRepositories/:providerRepositoryId/contents')
|
||||
->desc('Get files and directories of a VCS repository')
|
||||
->groups(['api', 'vcs'])
|
||||
->label('scope', 'vcs.read')
|
||||
->label('sdk.namespace', 'vcs')
|
||||
->label('sdk.auth', [APP_AUTH_TYPE_ADMIN])
|
||||
->label('sdk.method', 'getRepositoryContents')
|
||||
->label('sdk.description', '')
|
||||
->label('sdk.response.code', Response::STATUS_CODE_OK)
|
||||
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
|
||||
->label('sdk.response.model', Response::MODEL_VCS_CONTENT_LIST)
|
||||
->param('installationId', '', new Text(256), 'Installation Id')
|
||||
->param('providerRepositoryId', '', new Text(256), 'Repository Id')
|
||||
->param('providerRootDirectory', '', new Text(256, 0), 'Path to get contents of nested directory', true)
|
||||
->inject('gitHub')
|
||||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('dbForConsole')
|
||||
->action(function (string $installationId, string $providerRepositoryId, string $providerRootDirectory, GitHub $github, Response $response, Document $project, Database $dbForConsole) {
|
||||
$installation = $dbForConsole->getDocument('installations', $installationId);
|
||||
|
||||
if ($installation->isEmpty()) {
|
||||
throw new Exception(Exception::INSTALLATION_NOT_FOUND);
|
||||
}
|
||||
|
||||
$providerInstallationId = $installation->getAttribute('providerInstallationId');
|
||||
$privateKey = System::getEnv('_APP_VCS_GITHUB_PRIVATE_KEY');
|
||||
$githubAppId = System::getEnv('_APP_VCS_GITHUB_APP_ID');
|
||||
$github->initializeVariables($providerInstallationId, $privateKey, $githubAppId);
|
||||
|
||||
$owner = $github->getOwnerName($providerInstallationId);
|
||||
try {
|
||||
$repositoryName = $github->getRepositoryName($providerRepositoryId) ?? '';
|
||||
if (empty($repositoryName)) {
|
||||
throw new Exception(Exception::PROVIDER_REPOSITORY_NOT_FOUND);
|
||||
}
|
||||
} catch (RepositoryNotFound $e) {
|
||||
throw new Exception(Exception::PROVIDER_REPOSITORY_NOT_FOUND);
|
||||
}
|
||||
|
||||
$contents = $github->listRepositoryContents($owner, $repositoryName, $providerRootDirectory);
|
||||
|
||||
$vcsContents = [];
|
||||
foreach ($contents as $content) {
|
||||
$isDirectory = false;
|
||||
if($content['type'] === GitHub::CONTENTS_DIRECTORY) {
|
||||
$isDirectory = true;
|
||||
}
|
||||
|
||||
$vcsContents[] = new Document([
|
||||
'isDirectory' => $isDirectory,
|
||||
'name' => $content['name'] ?? '',
|
||||
'size' => $content['size'] ?? 0
|
||||
]);
|
||||
}
|
||||
|
||||
$response->dynamic(new Document([
|
||||
'contents' => $vcsContents
|
||||
]), Response::MODEL_VCS_CONTENT_LIST);
|
||||
});
|
||||
|
||||
App::post('/v1/vcs/github/installations/:installationId/providerRepositories/:providerRepositoryId/detection')
|
||||
->desc('Detect runtime settings from source code')
|
||||
->groups(['api', 'vcs'])
|
||||
|
@ -505,6 +566,7 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories/:pr
|
|||
}
|
||||
|
||||
$files = $github->listRepositoryContents($owner, $repositoryName, $providerRootDirectory);
|
||||
$files = \array_column($files, 'name');
|
||||
$languages = $github->listRepositoryLanguages($owner, $repositoryName);
|
||||
|
||||
$detectorFactory = new Detector($files, $languages);
|
||||
|
@ -586,6 +648,7 @@ App::get('/v1/vcs/github/installations/:installationId/providerRepositories')
|
|||
return function () use ($repo, $github) {
|
||||
try {
|
||||
$files = $github->listRepositoryContents($repo['organization'], $repo['name'], '');
|
||||
$files = \array_column($files, 'name');
|
||||
$languages = $github->listRepositoryLanguages($repo['organization'], $repo['name']);
|
||||
|
||||
$detectorFactory = new Detector($files, $languages);
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
"utopia-php/storage": "0.18.*",
|
||||
"utopia-php/swoole": "0.8.*",
|
||||
"utopia-php/system": "0.8.*",
|
||||
"utopia-php/vcs": "0.6.*",
|
||||
"utopia-php/vcs": "0.7.*",
|
||||
"utopia-php/websocket": "0.1.*",
|
||||
"matomo/device-detector": "6.1.*",
|
||||
"dragonmantank/cron-expression": "3.3.2",
|
||||
|
|
38
composer.lock
generated
38
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "e002600539435ca8eaaace6e73b4004d",
|
||||
"content-hash": "90c87617f6a2639e3c6c3a1920e7d7de",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
|
@ -1569,16 +1569,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/cache",
|
||||
"version": "0.10.1",
|
||||
"version": "0.10.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/cache.git",
|
||||
"reference": "87ee4fc91e50d4ddfef650aa999ea12be3a99583"
|
||||
"reference": "b22c6eb6d308de246b023efd0fc9758aee8b8247"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/cache/zipball/87ee4fc91e50d4ddfef650aa999ea12be3a99583",
|
||||
"reference": "87ee4fc91e50d4ddfef650aa999ea12be3a99583",
|
||||
"url": "https://api.github.com/repos/utopia-php/cache/zipball/b22c6eb6d308de246b023efd0fc9758aee8b8247",
|
||||
"reference": "b22c6eb6d308de246b023efd0fc9758aee8b8247",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1613,9 +1613,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/cache/issues",
|
||||
"source": "https://github.com/utopia-php/cache/tree/0.10.1"
|
||||
"source": "https://github.com/utopia-php/cache/tree/0.10.2"
|
||||
},
|
||||
"time": "2024-06-18T13:20:25+00:00"
|
||||
"time": "2024-06-25T20:36:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/cli",
|
||||
|
@ -2756,16 +2756,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/vcs",
|
||||
"version": "0.6.7",
|
||||
"version": "0.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/vcs.git",
|
||||
"reference": "8d8ff1ac68e991b95adb6f91fcde8f9bb8f24974"
|
||||
"reference": "4745fcf385cb8f5b645be447cc1631930853c8af"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/vcs/zipball/8d8ff1ac68e991b95adb6f91fcde8f9bb8f24974",
|
||||
"reference": "8d8ff1ac68e991b95adb6f91fcde8f9bb8f24974",
|
||||
"url": "https://api.github.com/repos/utopia-php/vcs/zipball/4745fcf385cb8f5b645be447cc1631930853c8af",
|
||||
"reference": "4745fcf385cb8f5b645be447cc1631930853c8af",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2799,9 +2799,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/vcs/issues",
|
||||
"source": "https://github.com/utopia-php/vcs/tree/0.6.7"
|
||||
"source": "https://github.com/utopia-php/vcs/tree/0.7.0"
|
||||
},
|
||||
"time": "2024-06-05T17:38:29+00:00"
|
||||
"time": "2024-06-26T09:44:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/websocket",
|
||||
|
@ -2988,16 +2988,16 @@
|
|||
"packages-dev": [
|
||||
{
|
||||
"name": "appwrite/sdk-generator",
|
||||
"version": "0.38.7",
|
||||
"version": "0.38.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||
"reference": "0a66c1149ef05ed9f45ce1c897c4a0ce9ee5e95a"
|
||||
"reference": "6367c57ddbcf7b88cacb900c4fe7ef3f28bf38ef"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/0a66c1149ef05ed9f45ce1c897c4a0ce9ee5e95a",
|
||||
"reference": "0a66c1149ef05ed9f45ce1c897c4a0ce9ee5e95a",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/6367c57ddbcf7b88cacb900c4fe7ef3f28bf38ef",
|
||||
"reference": "6367c57ddbcf7b88cacb900c4fe7ef3f28bf38ef",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3033,9 +3033,9 @@
|
|||
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
|
||||
"support": {
|
||||
"issues": "https://github.com/appwrite/sdk-generator/issues",
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/0.38.7"
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/0.38.8"
|
||||
},
|
||||
"time": "2024-06-10T00:23:02+00:00"
|
||||
"time": "2024-06-17T00:42:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/deprecations",
|
||||
|
|
|
@ -100,6 +100,7 @@ use Appwrite\Utopia\Response\Model\UsageStorage;
|
|||
use Appwrite\Utopia\Response\Model\UsageUsers;
|
||||
use Appwrite\Utopia\Response\Model\User;
|
||||
use Appwrite\Utopia\Response\Model\Variable;
|
||||
use Appwrite\Utopia\Response\Model\VcsContent;
|
||||
use Appwrite\Utopia\Response\Model\Webhook;
|
||||
use Exception;
|
||||
use Swoole\Http\Response as SwooleHTTPResponse;
|
||||
|
@ -233,6 +234,8 @@ class Response extends SwooleResponse
|
|||
public const MODEL_BRANCH = 'branch';
|
||||
public const MODEL_BRANCH_LIST = 'branchList';
|
||||
public const MODEL_DETECTION = 'detection';
|
||||
public const MODEL_VCS_CONTENT = 'vcsContent';
|
||||
public const MODEL_VCS_CONTENT_LIST = 'vcsContentList';
|
||||
|
||||
// Functions
|
||||
public const MODEL_FUNCTION = 'function';
|
||||
|
@ -364,6 +367,7 @@ class Response extends SwooleResponse
|
|||
->setModel(new BaseList('Target list', self::MODEL_TARGET_LIST, 'targets', self::MODEL_TARGET))
|
||||
->setModel(new BaseList('Migrations List', self::MODEL_MIGRATION_LIST, 'migrations', self::MODEL_MIGRATION))
|
||||
->setModel(new BaseList('Migrations Firebase Projects List', self::MODEL_MIGRATION_FIREBASE_PROJECT_LIST, 'projects', self::MODEL_MIGRATION_FIREBASE_PROJECT))
|
||||
->setModel(new BaseList('VCS Content List', self::MODEL_VCS_CONTENT_LIST, 'contents', self::MODEL_VCS_CONTENT))
|
||||
// Entities
|
||||
->setModel(new Database())
|
||||
->setModel(new Collection())
|
||||
|
@ -406,6 +410,7 @@ class Response extends SwooleResponse
|
|||
->setModel(new Installation())
|
||||
->setModel(new ProviderRepository())
|
||||
->setModel(new Detection())
|
||||
->setModel(new VcsContent())
|
||||
->setModel(new Branch())
|
||||
->setModel(new Runtime())
|
||||
->setModel(new Deployment())
|
||||
|
|
55
src/Appwrite/Utopia/Response/Model/VcsContent.php
Normal file
55
src/Appwrite/Utopia/Response/Model/VcsContent.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Utopia\Response\Model;
|
||||
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
|
||||
class VcsContent extends Model
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->addRule('size', [
|
||||
'type' => self::TYPE_INTEGER,
|
||||
'description' => 'Content size in bytes. Only files have size, and for directories, 0 is returned.',
|
||||
'default' => 0,
|
||||
'required' => false,
|
||||
'example' => 1523,
|
||||
])
|
||||
->addRule('isDirectory', [
|
||||
'type' => self::TYPE_BOOLEAN,
|
||||
'description' => 'If a content is a directory. Directories can be used to check nested contents.',
|
||||
'default' => false,
|
||||
'required' => false,
|
||||
'example' => true
|
||||
])
|
||||
->addRule('name', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Name of directory or file.',
|
||||
'default' => "",
|
||||
'example' => 'Main.java',
|
||||
'array' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'VcsContents';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return Response::MODEL_VCS_CONTENT;
|
||||
}
|
||||
}
|
|
@ -19,9 +19,9 @@ class VCSConsoleClientTest extends Scope
|
|||
use ProjectCustom;
|
||||
use SideConsole;
|
||||
|
||||
public string $providerInstallationId = '42954928';
|
||||
public string $providerRepositoryId = '705764267';
|
||||
public string $providerRepositoryId2 = '708688544';
|
||||
public string $providerInstallationId = '42954928'; // appwrite-test
|
||||
public string $providerRepositoryId = '705764267'; // ruby-starter (public)
|
||||
public string $providerRepositoryId2 = '708688544'; // function1.4 (private)
|
||||
|
||||
public function testGitHubAuthorize(): string
|
||||
{
|
||||
|
@ -85,6 +85,78 @@ class VCSConsoleClientTest extends Scope
|
|||
$this->assertEquals(404, $runtime['headers']['status-code']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testGitHubAuthorize
|
||||
*/
|
||||
public function testContents(string $installationId): void
|
||||
{
|
||||
/**
|
||||
* Test for SUCCESS
|
||||
*/
|
||||
|
||||
$runtime = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/providerRepositories/' . $this->providerRepositoryId . '/contents', array_merge([
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $runtime['headers']['status-code']);
|
||||
$this->assertGreaterThan(0, $runtime['body']['total']);
|
||||
$this->assertIsArray($runtime['body']['contents']);
|
||||
$this->assertGreaterThan(0, \count($runtime['body']['contents']));
|
||||
|
||||
$gemfileContent = null;
|
||||
foreach ($runtime['body']['contents'] as $content) {
|
||||
if ($content['name'] === "Gemfile") {
|
||||
$gemfileContent = $content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->assertNotNull($gemfileContent);
|
||||
$this->assertFalse($gemfileContent['isDirectory']);
|
||||
$this->assertGreaterThan(0, $gemfileContent['size']); // Should be ~50 bytes
|
||||
$this->assertLessThan(100, $gemfileContent['size']);
|
||||
|
||||
$libContent = null;
|
||||
foreach ($runtime['body']['contents'] as $content) {
|
||||
if ($content['name'] === "lib") {
|
||||
$libContent = $content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->assertNotNull($libContent);
|
||||
$this->assertTrue($libContent['isDirectory']);
|
||||
$this->assertEquals(0, $gemfileContent['size']);
|
||||
|
||||
$runtime = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/providerRepositories/' . $this->providerRepositoryId . '/contents?providerRootDirectory=lib', array_merge([
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $runtime['headers']['status-code']);
|
||||
$this->assertGreaterThan(0, $runtime['body']['total']);
|
||||
$this->assertIsArray($runtime['body']['contents']);
|
||||
$this->assertGreaterThan(0, \count($runtime['body']['contents']));
|
||||
|
||||
$mainRbContent = null;
|
||||
foreach ($runtime['body']['contents'] as $content) {
|
||||
if ($content['name'] === "main.rb") {
|
||||
$mainRbContent = $content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->assertNotNull($mainRbContent);
|
||||
$this->assertFalse($mainRbContent['isDirectory']);
|
||||
$this->assertGreaterThan(0, $gemfileContent['size']);
|
||||
|
||||
/**
|
||||
* Test for FAILURE
|
||||
*/
|
||||
|
||||
$runtime = $this->client->call(Client::METHOD_POST, '/vcs/github/installations/' . $installationId . '/providerRepositories/randomRepositoryId/contents', array_merge([
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(404, $runtime['headers']['status-code']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testGitHubAuthorize
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue