Skip to content

Commit 863361e

Browse files
authored
Merge pull request #77 from utopia-php/copilot/add-forgejo-adapter-and-tests
Eliminate duplication in Forgejo adapter and tests
2 parents 03b76ad + 89ede13 commit 863361e

File tree

6 files changed

+162
-17
lines changed

6 files changed

+162
-17
lines changed

docker-compose.yml

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,23 @@ services:
77
- ./tests:/usr/local/src/tests
88
- ./phpunit.xml:/usr/local/src/phpunit.xml
99
- gitea-data:/data:ro
10+
- forgejo-data:/forgejo-data:ro
1011
environment:
1112
- TESTS_GITHUB_PRIVATE_KEY
1213
- TESTS_GITHUB_APP_IDENTIFIER
1314
- TESTS_GITHUB_INSTALLATION_ID
1415
- TESTS_GITEA_URL=http://gitea:3000
15-
- TESTS_GITEA_REQUEST_CATCHER_URL=http://request-catcher:5000
16+
- TESTS_GITEA_REQUEST_CATCHER_URL=http://request-catcher:5000
17+
- TESTS_FORGEJO_URL=http://forgejo:3000
1618
depends_on:
1719
gitea:
1820
condition: service_healthy
1921
gitea-bootstrap:
2022
condition: service_completed_successfully
23+
forgejo:
24+
condition: service_healthy
25+
forgejo-bootstrap:
26+
condition: service_completed_successfully
2127
request-catcher:
2228
condition: service_started
2329

@@ -58,12 +64,57 @@ services:
5864
command: >
5965
-c "
6066
su git -c \"gitea admin user create --username $$GITEA_ADMIN_USERNAME --password $$GITEA_ADMIN_PASSWORD --email $$GITEA_ADMIN_EMAIL --admin --must-change-password=false\" || true &&
61-
TOKEN=$$(su git -c \"gitea admin user generate-access-token --username $$GITEA_ADMIN_USERNAME --token-name $$GITEA_ADMIN_USERNAME-token --scopes all --raw\") &&
62-
echo $$TOKEN > /data/gitea/token.txt
67+
if [ ! -f /data/gitea/token.txt ]; then
68+
TOKEN=$$(su git -c \"gitea admin user generate-access-token --username $$GITEA_ADMIN_USERNAME --token-name $$GITEA_ADMIN_USERNAME-token --scopes all --raw\") &&
69+
echo $$TOKEN > /data/gitea/token.txt;
70+
fi
6371
"
6472
request-catcher:
6573
image: appwrite/requestcatcher:1.1.0
6674
ports:
6775
- "5000:5000"
76+
77+
forgejo:
78+
image: codeberg.org/forgejo/forgejo:9
79+
environment:
80+
- USER_UID=1000
81+
- USER_GID=1000
82+
- FORGEJO__database__DB_TYPE=sqlite3
83+
- FORGEJO__security__INSTALL_LOCK=true
84+
- FORGEJO__webhook__ALLOWED_HOST_LIST=*
85+
- FORGEJO__webhook__SKIP_TLS_VERIFY=true
86+
- FORGEJO__webhook__DELIVER_TIMEOUT=10
87+
- FORGEJO__server__LOCAL_ROOT_URL=http://forgejo:3000/
88+
volumes:
89+
- forgejo-data:/data
90+
healthcheck:
91+
test: ["CMD", "curl", "-f", "http://localhost:3000/api/healthz"]
92+
interval: 10s
93+
timeout: 5s
94+
retries: 10
95+
start_period: 10s
96+
97+
forgejo-bootstrap:
98+
image: codeberg.org/forgejo/forgejo:9
99+
volumes:
100+
- forgejo-data:/data
101+
depends_on:
102+
forgejo:
103+
condition: service_healthy
104+
entrypoint: /bin/sh
105+
environment:
106+
- FORGEJO_ADMIN_USERNAME=${FORGEJO_ADMIN_USERNAME:-utopia}
107+
- FORGEJO_ADMIN_PASSWORD=${FORGEJO_ADMIN_PASSWORD:-password}
108+
- FORGEJO_ADMIN_EMAIL=${FORGEJO_ADMIN_EMAIL:-utopia@example.com}
109+
command: >
110+
-c "
111+
su git -c \"forgejo admin user create --username $$FORGEJO_ADMIN_USERNAME --password $$FORGEJO_ADMIN_PASSWORD --email $$FORGEJO_ADMIN_EMAIL --admin --must-change-password=false\" || true &&
112+
if [ ! -f /data/gitea/token.txt ]; then
113+
TOKEN=$$(su git -c \"forgejo admin user generate-access-token --username $$FORGEJO_ADMIN_USERNAME --token-name $$FORGEJO_ADMIN_USERNAME-token --scopes all --raw\") &&
114+
echo $$TOKEN > /data/gitea/token.txt;
115+
fi
116+
"
117+
68118
volumes:
69-
gitea-data:
119+
gitea-data:
120+
forgejo-data:

src/VCS/Adapter/Git/Forgejo.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Utopia\VCS\Adapter\Git;
4+
5+
class Forgejo extends Gitea
6+
{
7+
protected string $endpoint = 'http://forgejo:3000/api/v1';
8+
9+
/**
10+
* Get Adapter Name
11+
*
12+
* @return string
13+
*/
14+
public function getName(): string
15+
{
16+
return 'forgejo';
17+
}
18+
19+
protected function getHookType(): string
20+
{
21+
return 'forgejo';
22+
}
23+
}

src/VCS/Adapter/Git/Gitea.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,11 @@ public function createPullRequest(string $owner, string $repositoryName, string
494494
return $responseBody;
495495
}
496496

497+
protected function getHookType(): string
498+
{
499+
return 'gitea';
500+
}
501+
497502
/**
498503
* Create a webhook on a repository
499504
*
@@ -511,7 +516,7 @@ public function createWebhook(string $owner, string $repositoryName, string $url
511516
"/repos/{$owner}/{$repositoryName}/hooks",
512517
['Authorization' => "token $this->accessToken"],
513518
[
514-
'type' => 'gitea',
519+
'type' => $this->getHookType(),
515520
'active' => true,
516521
'events' => $events,
517522
'config' => [

tests/VCS/Adapter/ForgejoTest.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace Utopia\Tests\Adapter;
4+
5+
use Utopia\Cache\Adapter\None;
6+
use Utopia\Cache\Cache;
7+
use Utopia\System\System;
8+
use Utopia\VCS\Adapter\Git;
9+
use Utopia\VCS\Adapter\Git\Forgejo;
10+
11+
class ForgejoTest extends GiteaTest
12+
{
13+
protected static string $accessToken = '';
14+
15+
protected static string $owner = '';
16+
17+
protected string $webhookEventHeader = 'X-Forgejo-Event';
18+
protected string $webhookSignatureHeader = 'X-Forgejo-Signature';
19+
protected string $avatarDomain = 'http://localhost:3000/avatars/';
20+
21+
protected function createVCSAdapter(): Git
22+
{
23+
return new Forgejo(new Cache(new None()));
24+
}
25+
26+
public function setUp(): void
27+
{
28+
if (empty(static::$accessToken)) {
29+
$this->setupForgejo();
30+
}
31+
32+
$adapter = new Forgejo(new Cache(new None()));
33+
$forgejoUrl = System::getEnv('TESTS_FORGEJO_URL', 'http://forgejo:3000');
34+
35+
$adapter->initializeVariables(
36+
installationId: '',
37+
privateKey: '',
38+
appId: '',
39+
accessToken: static::$accessToken,
40+
refreshToken: ''
41+
);
42+
$adapter->setEndpoint($forgejoUrl);
43+
if (empty(static::$owner)) {
44+
$orgName = 'test-org-' . \uniqid();
45+
static::$owner = $adapter->createOrganization($orgName);
46+
}
47+
48+
$this->vcsAdapter = $adapter;
49+
}
50+
51+
protected function setupForgejo(): void
52+
{
53+
$tokenFile = '/forgejo-data/gitea/token.txt';
54+
55+
if (file_exists($tokenFile)) {
56+
$contents = file_get_contents($tokenFile);
57+
if ($contents !== false) {
58+
static::$accessToken = trim($contents);
59+
}
60+
}
61+
}
62+
}

tests/VCS/Adapter/GitHubTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Utopia\Tests\VCS\Adapter;
3+
namespace Utopia\Tests\Adapter;
44

55
use Utopia\Cache\Adapter\None;
66
use Utopia\Cache\Cache;

tests/VCS/Adapter/GiteaTest.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Utopia\Tests\VCS\Adapter;
3+
namespace Utopia\Tests\Adapter;
44

55
use Utopia\Cache\Adapter\None;
66
use Utopia\Cache\Cache;
@@ -15,6 +15,10 @@ class GiteaTest extends Base
1515
protected static string $owner = '';
1616
protected static string $defaultBranch = 'main';
1717

18+
protected string $webhookEventHeader = 'X-Gitea-Event';
19+
protected string $webhookSignatureHeader = 'X-Gitea-Signature';
20+
protected string $avatarDomain = 'gravatar.com';
21+
1822
protected function createVCSAdapter(): Git
1923
{
2024
return new Gitea(new Cache(new None()));
@@ -45,7 +49,7 @@ public function setUp(): void
4549
$this->vcsAdapter = $adapter;
4650
}
4751

48-
private function setupGitea(): void
52+
protected function setupGitea(): void
4953
{
5054
$tokenFile = '/data/gitea/token.txt';
5155

@@ -778,7 +782,7 @@ public function testGetCommit(): void
778782
$this->assertSame($commitHash, $result['commitHash']);
779783
$this->assertSame('utopia', $result['commitAuthor']);
780784
$this->assertStringStartsWith($customMessage, $result['commitMessage']);
781-
$this->assertStringContainsString('gravatar.com', $result['commitAuthorAvatar']);
785+
$this->assertStringContainsString($this->avatarDomain, $result['commitAuthorAvatar']);
782786
$this->assertNotEmpty($result['commitUrl']);
783787

784788
$this->vcsAdapter->deleteRepository(static::$owner, $repositoryName);
@@ -806,7 +810,7 @@ public function testGetLatestCommit(): void
806810
$this->assertNotEmpty($commit1['commitHash']);
807811
$this->assertSame('utopia', $commit1['commitAuthor']);
808812
$this->assertStringStartsWith($firstMessage, $commit1['commitMessage']);
809-
$this->assertStringContainsString('gravatar.com', $commit1['commitAuthorAvatar']);
813+
$this->assertStringContainsString($this->avatarDomain, $commit1['commitAuthorAvatar']);
810814
$this->assertNotEmpty($commit1['commitUrl']);
811815

812816
$commit1Hash = $commit1['commitHash'];
@@ -1530,14 +1534,14 @@ public function testWebhookPushEvent(): void
15301534
$webhookData = $this->getLastWebhookRequest();
15311535
$this->assertNotEmpty($webhookData, 'No webhook received');
15321536
$this->assertNotEmpty($webhookData['data'] ?? '', 'Webhook payload is empty');
1533-
$this->assertSame('push', $webhookData['headers']['X-Gitea-Event'] ?? '', 'Expected push event');
1537+
$this->assertSame('push', $webhookData['headers'][$this->webhookEventHeader] ?? '', 'Expected push event');
15341538
}, 15000, 500);
15351539

15361540
$payload = $webhookData['data'];
15371541
$headers = $webhookData['headers'] ?? [];
1538-
$signature = $headers['X-Gitea-Signature'] ?? '';
1542+
$signature = $headers[$this->webhookSignatureHeader] ?? '';
15391543

1540-
$this->assertNotEmpty($signature, 'Missing X-Gitea-Signature header');
1544+
$this->assertNotEmpty($signature, 'Missing ' . $this->webhookSignatureHeader . ' header');
15411545
$this->assertTrue(
15421546
$this->vcsAdapter->validateWebhookEvent($payload, $signature, $secret),
15431547
'Webhook signature validation failed'
@@ -1569,7 +1573,7 @@ public function testWebhookPullRequestEvent(): void
15691573
$this->vcsAdapter->createFile(static::$owner, $repositoryName, 'feature.txt', 'content', 'Add feature', 'feature-branch');
15701574

15711575
$catcherUrl = System::getEnv('TESTS_GITEA_REQUEST_CATCHER_URL', 'http://request-catcher:5000');
1572-
$this->vcsAdapter->createWebhook(static::$owner, $repositoryName, $catcherUrl . '/webhook', $secret);
1576+
$this->vcsAdapter->createWebhook(static::$owner, $repositoryName, $catcherUrl . '/webhook', $secret, ['pull_request']);
15731577

15741578
// Clear after setup so only PR event will arrive
15751579
$this->deleteLastWebhookRequest();
@@ -1589,14 +1593,14 @@ public function testWebhookPullRequestEvent(): void
15891593
$webhookData = $this->getLastWebhookRequest();
15901594
$this->assertNotEmpty($webhookData, 'No webhook received');
15911595
$this->assertNotEmpty($webhookData['data'] ?? '', 'Webhook payload is empty');
1592-
$this->assertSame('pull_request', $webhookData['headers']['X-Gitea-Event'] ?? '', 'Expected pull_request event');
1596+
$this->assertSame('pull_request', $webhookData['headers'][$this->webhookEventHeader] ?? '', 'Expected pull_request event');
15931597
}, 15000, 500);
15941598

15951599
$payload = $webhookData['data'];
15961600
$headers = $webhookData['headers'] ?? [];
1597-
$signature = $headers['X-Gitea-Signature'] ?? '';
1601+
$signature = $headers[$this->webhookSignatureHeader] ?? '';
15981602

1599-
$this->assertNotEmpty($signature, 'Missing X-Gitea-Signature header');
1603+
$this->assertNotEmpty($signature, 'Missing ' . $this->webhookSignatureHeader . ' header');
16001604
$this->assertTrue(
16011605
$this->vcsAdapter->validateWebhookEvent($payload, $signature, $secret),
16021606
'Webhook signature validation failed'

0 commit comments

Comments
 (0)