Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ APP_SECRET=630dc0d699fd37e720aff268f75583ed
APP_TIMEZONE=

###> doctrine/doctrine-bundle ###
DATABASE_DRIVER=mysql # or postgresql, or sqlite
DATABASE_DRIVER=mysql # or pgsql, or sqlite
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# For a PostgreSQL database, use: "postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=11&charset=UTF-8"
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db" (without the quotes so Symfony can resolve it if it's an absolute path)
Expand Down
5 changes: 3 additions & 2 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ SYMFONY_DEPRECATIONS_HELPER=999999
PANTHER_APP_ENV=panther
PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots

DATABASE_URL="mysql://davis:davis@127.0.0.1:3306/davis_test?serverVersion=10.9.3-MariaDB&charset=utf8mb4"
DATABASE_DRIVER=sqlite
DATABASE_URL="sqlite:///%kernel.project_dir%/var/data_test.db"

MAILER_DSN=smtp://localhost:465?encryption=ssl&auth_mode=login&username=&password=

API_KEY=change_me
API_KEY=change_me
121 changes: 64 additions & 57 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,58 @@ jobs:
run: vendor/bin/php-cs-fixer fix --ansi

phpunit:
name: PHPUnit (PHP ${{ matrix.php }})
name: PHPUnit / SQLite (PHP ${{ matrix.php }})
runs-on: ubuntu-latest
container:
image: php:${{ matrix.php }}-alpine
options: >-
--tmpfs /tmp:exec
--tmpfs /var/tmp:exec
strategy:
matrix:
php:
- '8.2'
- '8.3'
- '8.4'
- '8.5'
fail-fast: false

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install SQLite / GD / ZIP PHP extensions
run: |
apk add $PHPIZE_DEPS icu-libs icu-dev libpng-dev libzip-dev sqlite-dev
docker-php-ext-configure intl
docker-php-ext-configure gd
docker-php-ext-configure zip
docker-php-ext-install pdo pdo_sqlite intl gd zip

- name: Install Composer
run: wget -qO - https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet

- name: Install dependencies with Composer
run: composer install --no-progress --no-interaction --ansi

- name: Run tests with PHPUnit
env:
DATABASE_DRIVER: sqlite
DATABASE_URL: sqlite:///%kernel.project_dir%/var/data_test.db
run: vendor/bin/phpunit --colors=always

phpunit-mariadb:
name: PHPUnit / MariaDB (PHP 8.4)
runs-on: ubuntu-latest
container:
image: php:8.4-alpine
options: >-
--tmpfs /tmp:exec
--tmpfs /var/tmp:exec
services:
mysql:
image: mariadb:10.11
env:
# Corresponds to what is in .env.test
MYSQL_DATABASE: davis_test
MYSQL_USER: davis
MYSQL_PASSWORD: davis
Expand All @@ -96,17 +136,6 @@ jobs:
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 3306:3306

strategy:
matrix:
php:
- '8.2'
- '8.3'
- '8.4'
- '8.5'
fail-fast: false

steps:
- name: Checkout
Expand All @@ -128,8 +157,9 @@ jobs:

- name: Run tests with PHPUnit
env:
DATABASE_DRIVER: mysql
DATABASE_URL: mysql://davis:davis@mysql:3306/davis_test
run: vendor/bin/phpunit --process-isolation --colors=always
run: vendor/bin/phpunit --colors=always

migrations:
name: Migrations (${{ matrix.database }})
Expand Down Expand Up @@ -195,6 +225,7 @@ jobs:
- name: Run migrations (MySQL)
if: matrix.database == 'mysql'
env:
DATABASE_DRIVER: mysql
DATABASE_URL: mysql://davis:davis@mysql:3306/davis_test
run: |
php bin/console doctrine:database:create --if-not-exists --env=test
Expand All @@ -204,6 +235,7 @@ jobs:
- name: Run migrations (PostgreSQL)
if: matrix.database == 'postgresql'
env:
DATABASE_DRIVER: pgsql
DATABASE_URL: postgresql://davis:davis@postgres:5432/davis_test?serverVersion=15&charset=utf8
run: |
php bin/console doctrine:database:create --if-not-exists --env=test
Expand All @@ -213,45 +245,36 @@ jobs:
- name: Run migrations (SQLite)
if: matrix.database == 'sqlite'
env:
DATABASE_DRIVER: sqlite
DATABASE_URL: sqlite:///%kernel.project_dir%/var/data_test.db
run: |
php bin/console doctrine:migrations:migrate --no-interaction --env=test
php bin/console doctrine:schema:validate --skip-sync --env=test

smoke-test:
name: Application Smoke Test
name: SQLite DAV Smoke Test
runs-on: ubuntu-latest
container:
image: php:8.4-alpine
options: >-
--tmpfs /tmp:exec
--tmpfs /var/tmp:exec

services:
mysql:
image: mariadb:10.11
env:
MYSQL_DATABASE: davis_test
MYSQL_USER: davis
MYSQL_PASSWORD: davis
MYSQL_ROOT_PASSWORD: root
options: >-
--health-cmd "mysqladmin ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
APP_ENV: test
DATABASE_DRIVER: sqlite
DATABASE_URL: sqlite:///%kernel.project_dir%/var/smoke_test.db

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install extensions and curl
run: |
apk add $PHPIZE_DEPS icu-libs icu-dev libpng-dev libzip-dev curl
apk add $PHPIZE_DEPS icu-libs icu-dev libpng-dev libzip-dev sqlite-dev curl
docker-php-ext-configure intl
docker-php-ext-configure gd
docker-php-ext-configure zip
docker-php-ext-install pdo pdo_mysql intl gd zip
docker-php-ext-install pdo pdo_sqlite intl gd zip

- name: Install Composer
run: wget -qO - https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer --quiet
Expand All @@ -260,39 +283,23 @@ jobs:
run: composer install --no-progress --no-interaction --ansi --optimize-autoloader

- name: Prepare application
env:
DATABASE_URL: mysql://davis:davis@mysql:3306/davis_test
APP_ENV: test
run: |
php bin/console doctrine:database:create --if-not-exists --env=test
php bin/console doctrine:migrations:migrate --no-interaction --env=test
php bin/console doctrine:fixtures:load --no-interaction --env=test
php bin/console cache:clear --env=test

- name: Start Symfony server in background
env:
DATABASE_URL: mysql://davis:davis@mysql:3306/davis_test
APP_ENV: test
run: |
php -S 127.0.0.1:8000 -t public/ &
php -S 127.0.0.1:8000 -t public/ public/index.php &
echo $! > server.pid
sleep 3

- name: Test application responds
run: |
# Test that the app responds with a successful HTTP status
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8000/)
echo "HTTP Response code: $RESPONSE"
if [ "$RESPONSE" -ge 200 ] && [ "$RESPONSE" -lt 400 ]; then
echo "✅ Application is responding correctly"
else
echo "❌ Application returned unexpected status code: $RESPONSE"
exit 1
fi

- name: Test dashboard
continue-on-error: true
run: |
curl -f http://127.0.0.1:8000/dashboard || echo "No health endpoint available"
for attempt in 1 2 3 4 5 6 7 8 9 10; do
curl --silent --fail http://127.0.0.1:8000/ > /dev/null && exit 0
sleep 1
done
exit 1

- name: Exercise CalDAV and CardDAV
run: tests/smoke-dav.sh

- name: Stop server
if: always()
Expand Down
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ Comes with already built Docker images in two flavours: [standalone](https://git

# 🔩 Requirements

- PHP > 8.2 (with `pdo_mysql` [or `pdo_pgsql`, `pdo_sqlite`], `gd` and `intl` extensions), compatible up to PHP 8.5 (_See dependencies table below_)
- A compatible database layer, such as MySQL or MariaDB (recommended), PostgreSQL (not extensively tested yet) or SQLite (not extensively tested yet)
- PHP >= 8.2 (with `pdo_sqlite`, `pdo_mysql` or `pdo_pgsql`, plus the `gd` and `intl` extensions), compatible up to PHP 8.5 (_See dependencies table below_)
- SQLite, MySQL/MariaDB or PostgreSQL. SQLite is the simplest option for a standalone installation and is covered by the full test suite; PostgreSQL is not extensively tested yet.
- Composer > 2 (_The last release compatible with Composer 1 is [v1.6.2](https://github.com/tchapi/davis/releases/tag/v1.6.2)_)
- The [`imap`](https://www.php.net/manual/en/imap.installation.php) and [`ldap`](https://www.php.net/manual/en/ldap.installation.php) PHP extensions if you want to use either authentication methods (_these are not enabled / compiled by default except in the Docker image_)

Expand Down Expand Up @@ -85,7 +85,7 @@ Dependencies
And set `APP_ENV=prod` in your `.env.local` file (see below)


3. At least put the correct credentials to your database (driver and url) in your `.env.local` file so you can easily create the necessary tables.
3. Configure the database driver and URL in your `.env.local` file.

4. Run the migrations to create all the necessary tables:

Expand All @@ -111,11 +111,20 @@ Create your own `.env.local` file to change the necessary variables, if you plan
>
> In a production environnement, the `APP_ENV` variable MUST be set to `prod` to prevent leaking sensitive data.

**a. The database driver and url** (_you should already have it configured since you created the database previously_)
**a. The database driver and URL**

```shell
DATABASE_DRIVER=mysql # or postgresql, or sqlite
DATABASE_URL=mysql://db_user:db_pass@host:3306/db_name?serverVersion=10.9.3-MariaDB&charset=utf8mb4
# SQLite
DATABASE_DRIVER=sqlite
DATABASE_URL=sqlite:///%kernel.project_dir%/var/data.db

# MySQL/MariaDB
# DATABASE_DRIVER=mysql
# DATABASE_URL=mysql://db_user:db_pass@host:3306/db_name?serverVersion=10.9.3-MariaDB&charset=utf8mb4

# PostgreSQL
# DATABASE_DRIVER=pgsql
# DATABASE_URL=postgresql://db_user:db_pass@host:5432/db_name
```

**b. The admin password for the backend**
Expand Down
7 changes: 7 additions & 0 deletions tests/Fixtures/Dav/addressbook-query.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<card:addressbook-query xmlns:d="DAV:" xmlns:card="urn:ietf:params:xml:ns:carddav">
<d:prop>
<d:getetag/>
<card:address-data/>
</d:prop>
</card:addressbook-query>
10 changes: 10 additions & 0 deletions tests/Fixtures/Dav/calendar-query.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
<d:prop>
<d:getetag/>
<c:calendar-data/>
</d:prop>
<c:filter>
<c:comp-filter name="VCALENDAR"/>
</c:filter>
</c:calendar-query>
7 changes: 7 additions & 0 deletions tests/Fixtures/Dav/contact.vcf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
BEGIN:VCARD
VERSION:3.0
UID:davis-smoke-contact
FN:Davis CardDAV Smoke Test
N:Smoke Test;Davis;;;
EMAIL:davis@example.invalid
END:VCARD
11 changes: 11 additions & 0 deletions tests/Fixtures/Dav/event.ics
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Davis test suite//EN
BEGIN:VEVENT
UID:davis-smoke-event
DTSTAMP:20260101T000000Z
DTSTART:20260102T100000Z
DTEND:20260102T103000Z
SUMMARY:Davis CalDAV smoke test
END:VEVENT
END:VCALENDAR
28 changes: 15 additions & 13 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\Process\Process;

require dirname(__DIR__).'/vendor/autoload.php';

Expand All @@ -10,19 +11,20 @@
(new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
}

// Create the test database, update the schema and resets the fixture before each test.
// Note: `--quiet` is needed here for each step so that PHPUnit doesn't fail.
$actions = [
'doctrine:database:create --if-not-exists ',
'doctrine:schema:update --complete --force',
'doctrine:fixtures:load --no-interaction',
// Reset the schema and fixtures before each isolated test process. Database
// provisioning belongs to the environment running the suite; SQLite creates
// its database file when Doctrine first connects.
$commands = [
['doctrine:schema:drop', '--full-database', '--force', '--quiet'],
['doctrine:schema:create', '--quiet'],
['doctrine:fixtures:load', '--no-interaction', '--quiet'],
];

foreach ($actions as $action) {
passthru(sprintf(
'APP_ENV=%s php "%s/../bin/console" %s --quiet',
$_ENV['APP_ENV'],
__DIR__,
$action,
));
foreach ($commands as $command) {
$process = new Process([
PHP_BINARY,
dirname(__DIR__).'/bin/console',
...$command,
], env: ['APP_ENV' => $_ENV['APP_ENV']]);
$process->mustRun();
}
Loading