Compare commits

...
Author SHA1 Message Date
loks0nandClaude Sonnet 4.6 953359a580 Add named phpunit suites, bundle quick services into GeneralGroup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 01:18:31 +01:00
loks0nandClaude Sonnet 4.6 d0fcbb9ae8 Move service definitions into matrix job, fix parallel flag boolean ambiguity
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 00:38:27 +01:00
loks0nandClaude Sonnet 4.6 c33989bc54 Bundle fast e2e services into a single shared job
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 00:25:33 +01:00
loks0nandClaude Sonnet 4.6 e77d3d343c Update docs to reflect MongoDB default and compose-based DB switching
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 00:17:47 +01:00
loks0nandClaude Sonnet 4.6 7fcbc0b24a Fix inverted functional flag expression in e2e_service matrix
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 00:06:34 +01:00
loks0nandClaude Sonnet 4.6 d51de156a2 Remove dead COMPOSE_PROFILES from .env
No services use profiles: after the compose refactor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 00:04:06 +01:00
loks0nandClaude Sonnet 4.6 f686f37979 Move PostgreSQL to base compose so vectorsDB always runs
PostgreSQL is always needed for vectorsDB regardless of the primary
database. compose/postgresql.yml now only disables MongoDB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 23:58:11 +01:00
loks0nandClaude Sonnet 4.6 6c0e04a283 Make env field fully explicit, drop mongodb.env
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 23:41:59 +01:00
loks0nandClaude Sonnet 4.6 3a2ff2618b Move COMPOSE_FILE selection into CI matrix, out of env files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 23:39:37 +01:00
loks0nandClaude Sonnet 4.6 27d3c217e5 Rename matrix script variables to minimal names
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 23:34:37 +01:00
loks0nandClaude Sonnet 4.6 46cf1d6fc6 Replace database env overrides with per-database compose files
Move MariaDB and PostgreSQL into compose/ overlay files instead of
starting all three databases and switching via env vars. MongoDB stays
in the base compose as the default. CI uses COMPOSE_ENV_FILES at the
job level to load the correct env file per matrix database entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 23:32:57 +01:00
11 changed files with 282 additions and 229 deletions
-1
View File
@@ -39,7 +39,6 @@ _APP_REDIS_HOST=redis
_APP_REDIS_PORT=6379
_APP_REDIS_PASS=
_APP_REDIS_USER=
COMPOSE_PROFILES=mariadb,mongodb,postgresql
_APP_DB_ADAPTER=mongodb
_APP_DB_HOST=mongodb
_APP_DB_PORT=27017
+116 -177
View File
@@ -174,22 +174,46 @@ jobs:
outputs:
databases: ${{ steps.generate.outputs.databases }}
modes: ${{ steps.generate.outputs.modes }}
services: ${{ steps.generate.outputs.services }}
steps:
- name: Generate matrix
id: generate
uses: actions/github-script@v8
with:
script: |
const allDatabases = ['MariaDB', 'PostgreSQL', 'MongoDB'];
const allModes = ['dedicated', 'shared_v1', 'shared_v2'];
const databases = [
{ name: 'MariaDB', env: '.env,compose/mariadb.env', compose: 'docker-compose.yml:compose/mariadb.yml' },
{ name: 'PostgreSQL', env: '.env,compose/postgresql.env', compose: 'docker-compose.yml:compose/postgresql.yml' },
{ name: 'MongoDB', env: '.env', compose: 'docker-compose.yml' },
];
const modes = ['dedicated', 'shared_v1', 'shared_v2'];
const defaultDatabases = ['MongoDB'];
const services = [
{ name: 'Account', parallel: true },
{ name: 'Avatars', parallel: true, runner: 'blacksmith-4vcpu-ubuntu-2404' },
{ name: 'Databases', runner: 'blacksmith-4vcpu-ubuntu-2404' },
{ name: 'TablesDB', runner: 'blacksmith-4vcpu-ubuntu-2404' },
{ name: 'Functions', runner: 'blacksmith-4vcpu-ubuntu-2404' },
{ name: 'FunctionsSchedule', parallel: true },
{ name: 'GraphQL', parallel: true },
{ name: 'Projects', parallel: true },
{ name: 'Realtime', runner: 'blacksmith-4vcpu-ubuntu-2404' },
{ name: 'Sites', parallel: true, runner: 'blacksmith-4vcpu-ubuntu-2404' },
{ name: 'Teams', parallel: true },
{ name: 'Users', parallel: true },
{ name: 'ProjectWebhooks', parallel: true },
{ name: 'Migrations', parallel: true },
{ name: 'Project', parallel: true },
];
core.setOutput('services', JSON.stringify(services));
const defaultDatabases = [databases.find(d => d.name === 'MongoDB')];
const defaultModes = ['dedicated'];
const pr = context.payload.pull_request;
if (!pr) {
core.setOutput('databases', JSON.stringify(allDatabases));
core.setOutput('modes', JSON.stringify(allModes));
core.setOutput('databases', JSON.stringify(databases));
core.setOutput('modes', JSON.stringify(modes));
return;
}
@@ -210,8 +234,8 @@ jobs:
const decode = (content) => JSON.parse(Buffer.from(content, 'base64').toString());
const databaseChanged = getDbVersion(decode(base.content)) !== getDbVersion(decode(head.content));
core.setOutput('databases', JSON.stringify(databaseChanged ? allDatabases : defaultDatabases));
core.setOutput('modes', JSON.stringify(databaseChanged ? allModes : defaultModes));
core.setOutput('databases', JSON.stringify(databaseChanged ? databases : defaultDatabases));
core.setOutput('modes', JSON.stringify(databaseChanged ? modes : defaultModes));
build:
name: Build
@@ -288,81 +312,19 @@ jobs:
run: docker compose exec -T appwrite vars
- name: Run Unit Tests
uses: itznotabug/php-retry@v3
with:
max_attempts: 2
retry_wait_seconds: 60
timeout_minutes: 15
job_id: ${{ job.check_run_id }}
github_token: ${{ secrets.GITHUB_TOKEN }}
test_dir: tests/unit
command: >-
docker compose exec
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
appwrite test /usr/src/code/tests/unit
timeout-minutes: 15
run: >-
docker compose exec
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
appwrite test /usr/src/code/tests/unit
e2e_general:
name: Tests / E2E / General
name: Tests / E2E / ${{ matrix.database.name }} (${{ matrix.mode }}) / General
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
pull-requests: write
steps:
- name: checkout
uses: actions/checkout@v6
- name: Download Docker Image
uses: actions/download-artifact@v7
with:
name: ${{ env.IMAGE }}
path: /tmp
- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Load and Start Appwrite
timeout-minutes: 5
run: |
docker load --input /tmp/${{ env.IMAGE }}.tar
docker compose pull --quiet --ignore-buildable
docker compose up -d --quiet-pull --wait
- name: Wait for Open Runtimes
timeout-minutes: 3
run: |
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
echo "Waiting for Executor to come online"
sleep 1
done
- name: Run General Tests
uses: itznotabug/php-retry@v3
with:
max_attempts: 2
retry_wait_seconds: 60
timeout_minutes: 15
job_id: ${{ job.check_run_id }}
github_token: ${{ secrets.GITHUB_TOKEN }}
test_dir: tests/e2e/General
command: >-
docker compose exec -T
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
appwrite test /usr/src/code/tests/e2e/General
- name: Failure Logs
if: failure()
run: |
echo "=== Appwrite Logs ==="
docker compose logs
e2e_service:
name: Tests / E2E / ${{ matrix.database }} (${{ matrix.mode }}) / ${{ matrix.service }}
runs-on: ${{ matrix.runner || 'ubuntu-latest' }}
needs: [build, matrix]
env:
COMPOSE_FILE: ${{ matrix.database.compose }}
COMPOSE_ENV_FILES: ${{ matrix.database.env }}
permissions:
contents: read
pull-requests: write
@@ -371,45 +333,6 @@ jobs:
matrix:
database: ${{ fromJSON(needs.matrix.outputs.databases) }}
mode: ${{ fromJSON(needs.matrix.outputs.modes) }}
service: [
Account,
Avatars,
Console,
Databases,
TablesDB,
Functions,
FunctionsSchedule,
GraphQL,
Health,
Locale,
Projects,
Realtime,
Sites,
Proxy,
Storage,
Tokens,
Teams,
Users,
ProjectWebhooks,
Webhooks,
VCS,
Messaging,
Migrations,
Project
]
include:
- service: Databases
runner: blacksmith-4vcpu-ubuntu-2404
- service: Sites
runner: blacksmith-4vcpu-ubuntu-2404
- service: Functions
runner: blacksmith-4vcpu-ubuntu-2404
- service: Avatars
runner: blacksmith-4vcpu-ubuntu-2404
- service: Realtime
runner: blacksmith-4vcpu-ubuntu-2404
- service: TablesDB
runner: blacksmith-4vcpu-ubuntu-2404
steps:
- name: Checkout repository
uses: actions/checkout@v6
@@ -420,25 +343,6 @@ jobs:
name: ${{ env.IMAGE }}
path: /tmp
- name: Set database environment
run: |
if [ "${{ matrix.database }}" = "MariaDB" ]; then
echo "COMPOSE_PROFILES=mariadb" >> $GITHUB_ENV
echo "_APP_DB_ADAPTER=mariadb" >> $GITHUB_ENV
echo "_APP_DB_HOST=mariadb" >> $GITHUB_ENV
echo "_APP_DB_PORT=3306" >> $GITHUB_ENV
elif [ "${{ matrix.database }}" = "MongoDB" ]; then
echo "COMPOSE_PROFILES=mongodb" >> $GITHUB_ENV
echo "_APP_DB_ADAPTER=mongodb" >> $GITHUB_ENV
echo "_APP_DB_HOST=mongodb" >> $GITHUB_ENV
echo "_APP_DB_PORT=27017" >> $GITHUB_ENV
elif [ "${{ matrix.database }}" = "PostgreSQL" ]; then
echo "COMPOSE_PROFILES=postgresql" >> $GITHUB_ENV
echo "_APP_DB_ADAPTER=postgresql" >> $GITHUB_ENV
echo "_APP_DB_HOST=postgresql" >> $GITHUB_ENV
echo "_APP_DB_PORT=5432" >> $GITHUB_ENV
fi
- name: Login to Docker Hub
uses: docker/login-action@v4
with:
@@ -465,26 +369,75 @@ jobs:
done
- name: Run tests
uses: itznotabug/php-retry@v3
timeout-minutes: 20
run: >-
docker compose exec -T
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
appwrite vendor/bin/paratest --processes $(nproc) --functional --testsuite GeneralGroup --exclude-group abuseEnabled --exclude-group screenshots
- name: Failure Logs
if: failure()
run: |
echo "=== Appwrite Logs ==="
docker compose logs
e2e_service:
name: Tests / E2E / ${{ matrix.database.name }} (${{ matrix.mode }}) / ${{ matrix.service.name }}
runs-on: ${{ matrix.service.runner || 'ubuntu-latest' }}
needs: [build, matrix]
env:
COMPOSE_FILE: ${{ matrix.database.compose }}
COMPOSE_ENV_FILES: ${{ matrix.database.env }}
permissions:
contents: read
pull-requests: write
strategy:
fail-fast: false
matrix:
database: ${{ fromJSON(needs.matrix.outputs.databases) }}
mode: ${{ fromJSON(needs.matrix.outputs.modes) }}
service: ${{ fromJSON(needs.matrix.outputs.services) }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Download Docker Image
uses: actions/download-artifact@v7
with:
max_attempts: 2
retry_wait_seconds: 60
timeout_minutes: 20
job_id: ${{ job.check_run_id }}
github_token: ${{ secrets.GITHUB_TOKEN }}
test_dir: tests/e2e/Services/${{ matrix.service }}
command: |
SERVICE_PATH="/usr/src/code/tests/e2e/Services/${{ matrix.service }}"
name: ${{ env.IMAGE }}
path: /tmp
# Services that rely on sequential test method execution (shared static state)
FUNCTIONAL_FLAG="--functional"
case "${{ matrix.service }}" in
Databases|TablesDB|Functions|Realtime) FUNCTIONAL_FLAG="" ;;
esac
- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
docker compose exec -T \
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
appwrite vendor/bin/paratest --processes $(nproc) $FUNCTIONAL_FLAG "$SERVICE_PATH" --exclude-group abuseEnabled --exclude-group screenshots --log-junit tests/e2e/Services/${{ matrix.service }}/junit.xml
- name: Load and Start Appwrite
timeout-minutes: 5
env:
_APP_BROWSER_HOST: http://invalid-browser/v1
_APP_DATABASE_SHARED_TABLES: ${{ matrix.mode != 'dedicated' && 'database_db_main' || '' }}
_APP_DATABASE_SHARED_TABLES_V1: ${{ matrix.mode == 'shared_v1' && 'database_db_main' || '' }}
run: |
docker load --input /tmp/${{ env.IMAGE }}.tar
docker compose pull --quiet --ignore-buildable
docker compose up -d --quiet-pull --wait
- name: Wait for Open Runtimes
timeout-minutes: 3
run: |
while ! docker compose logs openruntimes-executor | grep -q "Executor is ready."; do
echo "Waiting for Executor to come online"
sleep 1
done
- name: Run tests
timeout-minutes: 20
run: |
docker compose exec -T \
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}" \
appwrite vendor/bin/paratest --processes $(nproc) ${{ matrix.service.parallel && '--functional' || '' }} --testsuite ${{ matrix.service.name }} --exclude-group abuseEnabled --exclude-group screenshots
- name: Failure Logs
if: failure()
@@ -531,18 +484,11 @@ jobs:
docker compose up -d --quiet-pull --wait
- name: Run tests
uses: itznotabug/php-retry@v3
with:
max_attempts: 2
retry_wait_seconds: 60
timeout_minutes: 15
job_id: ${{ job.check_run_id }}
github_token: ${{ secrets.GITHUB_TOKEN }}
test_dir: tests/e2e
command: >-
docker compose exec -T
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
appwrite test /usr/src/code/tests/e2e --group=abuseEnabled
timeout-minutes: 15
run: >-
docker compose exec -T
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
appwrite test /usr/src/code/tests/e2e --group=abuseEnabled
- name: Failure Logs
if: failure()
@@ -596,18 +542,11 @@ jobs:
done
- name: Run tests
uses: itznotabug/php-retry@v3
with:
max_attempts: 2
retry_wait_seconds: 60
timeout_minutes: 15
job_id: ${{ job.check_run_id }}
github_token: ${{ secrets.GITHUB_TOKEN }}
test_dir: tests/e2e/Services/Sites
command: >-
docker compose exec -T
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
appwrite test /usr/src/code/tests/e2e/Services/Sites --group=screenshots
timeout-minutes: 15
run: >-
docker compose exec -T
-e _APP_E2E_RESPONSE_FORMAT="${{ github.event.inputs.response_format }}"
appwrite test /usr/src/code/tests/e2e/Services/Sites --group=screenshots
- name: Failure Logs
if: failure()
+1 -1
View File
@@ -20,7 +20,7 @@ Self-hosted Backend-as-a-Service platform. Hybrid monolithic-microservice archit
- PHP 8.3+, Swoole 6.x (async runtime, replaces PHP-FPM)
- Utopia PHP framework (HTTP routing, CLI, DI, queue)
- MongoDB (default), MariaDB, MySQL, PostgreSQL (adapters via utopia-php/database)
- MongoDB (default), MariaDB, PostgreSQL (adapters via utopia-php/database; use `compose/mariadb.yml` or `compose/postgresql.yml` overlays to switch)
- Redis (cache, queue, pub/sub)
- Docker + Traefik (reverse proxy)
- PHPUnit 12, Pint (PSR-12), PHPStan level 3
+1 -1
View File
@@ -296,7 +296,7 @@ Appwrite stack is a combination of a variety of open-source technologies and too
### Other Technologies
- Redis - for managing cache and in-memory data (currently, we do not use Redis for persistent data).
- MariaDB - for database storage and queries.
- MongoDB - default database for storage and queries (MariaDB and PostgreSQL also supported via compose overlays).
- InfluxDB - for managing stats and time-series based data
- Statsd - for sending data over UDP protocol (using Telegraf)
- ClamAV - for validating and scanning storage files.
+3
View File
@@ -0,0 +1,3 @@
_APP_DB_ADAPTER=mariadb
_APP_DB_HOST=mariadb
_APP_DB_PORT=3306
+36
View File
@@ -0,0 +1,36 @@
x-logging: &x-logging
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
services:
mongodb:
scale: 0
mariadb:
image: mariadb:10.11 # fix issues when upgrading using: mysql_upgrade -u root -p
container_name: appwrite-mariadb
<<: *x-logging
networks:
- appwrite
volumes:
- appwrite-mariadb:/var/lib/mysql:rw
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=${_APP_DB_ROOT_PASS}
- MYSQL_DATABASE=${_APP_DB_SCHEMA}
- MYSQL_USER=${_APP_DB_USER}
- MYSQL_PASSWORD=${_APP_DB_PASS}
- MARIADB_AUTO_UPGRADE=1
command: "mysqld --innodb-flush-method=fsync"
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 5s
timeout: 5s
retries: 12
volumes:
appwrite-mariadb:
+3
View File
@@ -0,0 +1,3 @@
_APP_DB_ADAPTER=postgresql
_APP_DB_HOST=postgresql
_APP_DB_PORT=5432
+3
View File
@@ -0,0 +1,3 @@
services:
mongodb:
scale: 0
-1
View File
@@ -4,7 +4,6 @@
services:
appwrite-mongo-express:
profiles: ["mongodb"]
image: mongo-express
container_name: appwrite-mongo-express
networks:
+13 -37
View File
@@ -1261,28 +1261,27 @@ services:
retries: 20
start_period: 5s
mariadb:
image: mariadb:10.11 # fix issues when upgrading using: mysql_upgrade -u root -p
container_name: appwrite-mariadb
postgresql:
image: appwrite/postgres:0.1.0
container_name: appwrite-postgresql
<<: *x-logging
networks:
- appwrite
volumes:
- appwrite-mariadb:/var/lib/mysql:rw
- appwrite-postgresql:/var/lib/postgresql/18/data:rw
ports:
- "3306:3306"
- "5432:5432"
environment:
- MYSQL_ROOT_PASSWORD=${_APP_DB_ROOT_PASS}
- MYSQL_DATABASE=${_APP_DB_SCHEMA}
- MYSQL_USER=${_APP_DB_USER}
- MYSQL_PASSWORD=${_APP_DB_PASS}
- MARIADB_AUTO_UPGRADE=1
command: "mysqld --innodb-flush-method=fsync"
- POSTGRES_DB=${_APP_DB_SCHEMA}
- POSTGRES_USER=${_APP_DB_USER}
- POSTGRES_PASSWORD=${_APP_DB_PASS}
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
test: ["CMD-SHELL", "pg_isready -U ${_APP_DB_USER} -d ${_APP_DB_SCHEMA}"]
interval: 5s
timeout: 5s
retries: 12
retries: 10
start_period: 10s
command: "postgres"
mongodb:
image: mongo:8.2.5
@@ -1320,28 +1319,6 @@ services:
retries: 10
start_period: 30s
postgresql:
image: appwrite/postgres:0.1.0
container_name: appwrite-postgresql
<<: *x-logging
networks:
- appwrite
volumes:
- appwrite-postgresql:/var/lib/postgresql/18/data:rw
ports:
- "5432:5432"
environment:
- POSTGRES_DB=${_APP_DB_SCHEMA}
- POSTGRES_USER=${_APP_DB_USER}
- POSTGRES_PASSWORD=${_APP_DB_PASS}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${_APP_DB_USER} -d ${_APP_DB_SCHEMA}"]
interval: 5s
timeout: 5s
retries: 10
start_period: 10s
command: "postgres"
ollama:
image: appwrite/ollama:0.1.1
container_name: ollama
@@ -1464,10 +1441,9 @@ networks:
volumes:
appwrite-mariadb:
appwrite-postgresql:
appwrite-mongodb:
appwrite-mongodb-keyfile:
appwrite-postgresql:
appwrite-redis:
appwrite-cache:
appwrite-uploads:
+106 -11
View File
@@ -16,28 +16,123 @@
<testsuite name="unit">
<directory>./tests/unit</directory>
</testsuite>
<testsuite name="e2e">
<file>./tests/e2e/Client.php</file>
<testsuite name="General">
<directory>./tests/e2e/General</directory>
<directory>./tests/e2e/Scopes</directory>
<directory>./tests/e2e/Services/Teams</directory>
<directory>./tests/e2e/Services/Realtime</directory>
<directory>./tests/e2e/Services/Account</directory>
<directory>./tests/e2e/Services/Users</directory>
</testsuite>
<testsuite name="Console">
<directory>./tests/e2e/Services/Console</directory>
</testsuite>
<testsuite name="Health">
<directory>./tests/e2e/Services/Health</directory>
</testsuite>
<testsuite name="Locale">
<directory>./tests/e2e/Services/Locale</directory>
</testsuite>
<testsuite name="Tokens">
<directory>./tests/e2e/Services/Tokens</directory>
</testsuite>
<testsuite name="VCS">
<directory>./tests/e2e/Services/VCS</directory>
</testsuite>
<testsuite name="Webhooks">
<directory>./tests/e2e/Services/Webhooks</directory>
</testsuite>
<testsuite name="GeneralGroup">
<directory>./tests/e2e/General</directory>
<directory>./tests/e2e/Scopes</directory>
<directory>./tests/e2e/Services/Console</directory>
<directory>./tests/e2e/Services/Health</directory>
<directory>./tests/e2e/Services/Locale</directory>
<directory>./tests/e2e/Services/Messaging</directory>
<directory>./tests/e2e/Services/Proxy</directory>
<directory>./tests/e2e/Services/Storage</directory>
<directory>./tests/e2e/Services/Tokens</directory>
<directory>./tests/e2e/Services/VCS</directory>
<directory>./tests/e2e/Services/Webhooks</directory>
</testsuite>
<testsuite name="Account">
<directory>./tests/e2e/Services/Account</directory>
</testsuite>
<testsuite name="Avatars">
<directory>./tests/e2e/Services/Avatars</directory>
</testsuite>
<testsuite name="Databases">
<directory>./tests/e2e/Services/Databases</directory>
</testsuite>
<testsuite name="Functions">
<file>./tests/e2e/Services/Functions/FunctionsBase.php</file>
<file>./tests/e2e/Services/Functions/FunctionsCustomServerTest.php</file>
<file>./tests/e2e/Services/Functions/FunctionsCustomClientTest.php</file>
</testsuite>
<testsuite name="FunctionsSchedule">
<directory>./tests/e2e/Services/FunctionsSchedule</directory>
</testsuite>
<testsuite name="GraphQL">
<directory>./tests/e2e/Services/GraphQL</directory>
</testsuite>
<testsuite name="Messaging">
<directory>./tests/e2e/Services/Messaging</directory>
</testsuite>
<testsuite name="Migrations">
<directory>./tests/e2e/Services/Migrations</directory>
</testsuite>
<testsuite name="Project">
<directory>./tests/e2e/Services/Project</directory>
</testsuite>
<testsuite name="ProjectWebhooks">
<directory>./tests/e2e/Services/ProjectWebhooks</directory>
</testsuite>
<testsuite name="Projects">
<directory>./tests/e2e/Services/Projects</directory>
</testsuite>
<testsuite name="Proxy">
<directory>./tests/e2e/Services/Proxy</directory>
</testsuite>
<testsuite name="Realtime">
<directory>./tests/e2e/Services/Realtime</directory>
</testsuite>
<testsuite name="Sites">
<directory>./tests/e2e/Services/Sites</directory>
</testsuite>
<testsuite name="Storage">
<directory>./tests/e2e/Services/Storage</directory>
</testsuite>
<testsuite name="TablesDB">
<directory>./tests/e2e/Services/TablesDB</directory>
</testsuite>
<testsuite name="Teams">
<directory>./tests/e2e/Services/Teams</directory>
</testsuite>
<testsuite name="Users">
<directory>./tests/e2e/Services/Users</directory>
</testsuite>
<testsuite name="e2e">
<directory>./tests/e2e/General</directory>
<directory>./tests/e2e/Scopes</directory>
<directory>./tests/e2e/Services/Account</directory>
<directory>./tests/e2e/Services/Avatars</directory>
<directory>./tests/e2e/Services/Console</directory>
<directory>./tests/e2e/Services/Databases</directory>
<directory>./tests/e2e/Services/FunctionsSchedule</directory>
<directory>./tests/e2e/Services/GraphQL</directory>
<directory>./tests/e2e/Services/Health</directory>
<directory>./tests/e2e/Services/Locale</directory>
<directory>./tests/e2e/Services/Projects</directory>
<directory>./tests/e2e/Services/Storage</directory>
<directory>./tests/e2e/Services/Tokens</directory>
<directory>./tests/e2e/Services/Webhooks</directory>
<directory>./tests/e2e/Services/ProjectWebhooks</directory>
<directory>./tests/e2e/Services/Messaging</directory>
<directory>./tests/e2e/Services/Migrations</directory>
<directory>./tests/e2e/Services/Project</directory>
<directory>./tests/e2e/Services/ProjectWebhooks</directory>
<directory>./tests/e2e/Services/Projects</directory>
<directory>./tests/e2e/Services/Proxy</directory>
<directory>./tests/e2e/Services/Realtime</directory>
<directory>./tests/e2e/Services/Sites</directory>
<directory>./tests/e2e/Services/Storage</directory>
<directory>./tests/e2e/Services/TablesDB</directory>
<directory>./tests/e2e/Services/Teams</directory>
<directory>./tests/e2e/Services/Tokens</directory>
<directory>./tests/e2e/Services/Users</directory>
<directory>./tests/e2e/Services/VCS</directory>
<directory>./tests/e2e/Services/Webhooks</directory>
<file>./tests/e2e/Services/Functions/FunctionsBase.php</file>
<file>./tests/e2e/Services/Functions/FunctionsCustomServerTest.php</file>
<file>./tests/e2e/Services/Functions/FunctionsCustomClientTest.php</file>