Skip to content

Commit fb6455b

Browse files
committed
Add script to patch missing repos documents
1 parent 4f2f76d commit fb6455b

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ RUN chmod +x /usr/local/bin/doctor && \
100100
RUN chmod +x /usr/local/bin/hamster && \
101101
chmod +x /usr/local/bin/volume-sync && \
102102
chmod +x /usr/local/bin/patch-delete-schedule-updated-at-attribute && \
103+
chmod +x /usr/local/bin/patch-recreate-repositories-documents && \
103104
chmod +x /usr/local/bin/patch-delete-project-collections && \
104105
chmod +x /usr/local/bin/delete-orphaned-projects && \
105106
chmod +x /usr/local/bin/clear-card-cache && \
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
php /usr/src/code/app/cli.php patch-recreate-repositories-documents $@
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<?php
2+
3+
namespace Appwrite\Platform\Tasks;
4+
5+
use Utopia\Platform\Action;
6+
use Appwrite\Event\Certificate;
7+
use Utopia\App;
8+
use Utopia\CLI\Console;
9+
use Utopia\Database\Database;
10+
use Utopia\Database\Document;
11+
use Utopia\Database\Helpers\ID;
12+
use Utopia\Database\Helpers\Permission;
13+
use Utopia\Database\Helpers\Role;
14+
use Utopia\Database\Query;
15+
use Utopia\Validator\Hostname;
16+
use Utopia\Validator\Text;
17+
18+
class patchRecreateRepositoriesDocuments extends Action
19+
{
20+
public static function getName(): string
21+
{
22+
return 'patch-recreate-repositories-documents';
23+
}
24+
25+
public function __construct()
26+
{
27+
$this
28+
->desc('Recreate missing repositories in consoleDB from projectDBs. They can be missing if you used Appwrite 1.4.10 or 1.4.11, and deleted a function.')
29+
->param('after', '', new Text(36), 'After cursor', true)
30+
->param('projectId', '', new Text(36), 'Select project to validate', true)
31+
->inject('dbForConsole')
32+
->inject('getProjectDB')
33+
->callback(fn ($after, $projectId, $dbForConsole, $getProjectDB) => $this->action($after, $projectId, $dbForConsole, $getProjectDB));
34+
}
35+
36+
public function action($after, $projectId, Database $dbForConsole, callable $getProjectDB): void
37+
{
38+
Console::info("Starting the patch");
39+
40+
$startTime = microtime(true);
41+
42+
if(!empty($projectId)) {
43+
$project = $dbForConsole->getDocument('projects', $projectId);
44+
$dbForProject = call_user_func($getProjectDB, $project);
45+
$this->recreateRepositories($dbForConsole, $dbForProject, $project);
46+
} else {
47+
$queries = [];
48+
if(!empty($after)) {
49+
Console::info("Iterating remaining projects after project with ID {$after}");
50+
$project = $dbForConsole->getDocument('projects', $after);
51+
$queries = [Query::cursorAfter($project)];
52+
} else {
53+
Console::info("Iterating all projects");
54+
}
55+
$this->foreachDocument($dbForConsole, 'projects', $queries, function(Document $project) use($getProjectDB, $dbForConsole){
56+
$dbForProject = call_user_func($getProjectDB, $project);
57+
$this->recreateRepositories($dbForConsole, $dbForProject, $project);
58+
});
59+
}
60+
61+
$endTime = microtime(true);
62+
$timeTaken = $endTime - $startTime;
63+
64+
$hours = (int)($timeTaken / 3600);
65+
$timeTaken -= $hours * 3600;
66+
$minutes = (int)($timeTaken / 60);
67+
$timeTaken -= $minutes * 60;
68+
$seconds = (int)$timeTaken;
69+
$milliseconds = ($timeTaken - $seconds) * 1000;
70+
Console::info("Recreate patch completed in $hours h, $minutes m, $seconds s, $milliseconds mis ( total $timeTaken milliseconds)");
71+
}
72+
73+
protected function foreachDocument(Database $database, string $collection, array $queries = [], callable $callback = null): void
74+
{
75+
$limit = 1000;
76+
$results = [];
77+
$sum = $limit;
78+
$latestDocument = null;
79+
80+
while ($sum === $limit) {
81+
$newQueries = $queries;
82+
83+
if ($latestDocument != null) {
84+
array_unshift($newQueries, Query::cursorAfter($latestDocument));
85+
}
86+
$newQueries[] = Query::limit($limit);
87+
$results = $database->find($collection, $newQueries);
88+
89+
if (empty($results)) {
90+
return;
91+
}
92+
93+
$sum = count($results);
94+
95+
foreach ($results as $document) {
96+
if (is_callable($callback)) {
97+
$callback($document);
98+
}
99+
}
100+
$latestDocument = $results[array_key_last($results)];
101+
}
102+
}
103+
104+
public function recreateRepositories(Database $dbForConsole, Database $dbForProject, Document $project): void
105+
{
106+
$projectId = $project->getId();
107+
Console::log("Running patch for project {$projectId}");
108+
109+
$this->foreachDocument($dbForProject, 'functions', [], function(Document $function) use ($dbForConsole, $project) {
110+
$isConnected = !empty($function->getAttribute('providerRepositoryId', ''));
111+
112+
if($isConnected) {
113+
$repository = $dbForConsole->getDocument('repositories', $function->getAttribute('repositoryId', ''));
114+
115+
if($repository->isEmpty()) {
116+
$projectId = $project->getId();
117+
$functionId = $function->getId();
118+
Console::success("Recreating repositories document for project ID {$projectId}, function ID {$functionId}");
119+
120+
$repository = $dbForConsole->createDocument('repositories', new Document([
121+
'$id' => ID::unique(),
122+
'$permissions' => [
123+
Permission::read(Role::any()),
124+
Permission::update(Role::any()),
125+
Permission::delete(Role::any()),
126+
],
127+
'installationId' => $function->getAttribute('installationId', ''),
128+
'installationInternalId' => $function->getAttribute('installationInternalId', ''),
129+
'projectId' => $project->getId(),
130+
'projectInternalId' => $project->getInternalId(),
131+
'providerRepositoryId' => $function->getAttribute('providerRepositoryId', ''),
132+
'resourceId' => $function->getId(),
133+
'resourceInternalId' => $function->getInternalId(),
134+
'resourceType' => 'function',
135+
'providerPullRequestIds' => []
136+
]));
137+
}
138+
}
139+
});
140+
}
141+
}

0 commit comments

Comments
 (0)