diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a2b3970 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,20 @@ +# Git +.git + +# IntelliJ +.idea +*.iml + +# Composer +vendor + +# PHP code sniffer +.php_cs.cache + +# PHP Unit +build +.phpunit.result.cache + +# Dev / Testing +test.php +coverage/* diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8b7b10e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +# This file is for unifying the coding style for different editors and IDEs. +# More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[Dockerfile] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..eec5cb0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + - package-ecosystem: "composer" + directory: "/" + schedule: + interval: "daily" + time: "08:00" + timezone: "Europe/Paris" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + time: "08:00" + timezone: "Europe/Paris" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a8ce69f..8ddd95e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,91 +1,24 @@ name: test on: - push: - pull_request: + push: + pull_request: jobs: - test: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: - - ubuntu-latest - - services: - mysql: - image: mysql:5.7 - env: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - MYSQL_USER: root - MYSQL_PASSWORD: '' - MYSQL_DATABASE: test_database - ports: - - 3306:3306 - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - - redis: - image: redis - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 6379:6379 - - steps: - - name: Verify MySQL connection from host - run: | - sudo apt-get install -y mysql-client - mysql --host 127.0.0.1 --port 3306 -uroot --password="" -e "SHOW DATABASES" - - - uses: actions/checkout@v2 - - - uses: shivammathur/setup-php@v2 - with: - php-version: '7.4' - coverage: xdebug - - - name: Set files permission - run: | - sudo chown -R www-data:www-data /var/lib/php/sessions/ - sudo chmod -R 777 /var/lib/php/sessions/ - - - name: Validate composer.json and composer.lock - run: composer validate - - - name: Cache Composer packages - id: composer-cache - uses: actions/cache@v2 - with: - path: vendor - key: ${{ runner.os }}-node-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Install dependencies - if: steps.composer-cache.outputs.cache-hit != 'true' - run: composer install --prefer-dist --no-progress --no-suggest - - - name: PHPCS - if: ${{ runner.os != 'Windows' }} - run: | - vendor/bin/php-cs-fixer fix --diff --dry-run - - - name: PHPUnit - run: | - vendor/bin/phpunit --colors --coverage-text --coverage-clover coverage/clover.xml - env: - MYSQL_HOST: 127.0.0.1 - MYSQL_PORT: ${{ job.services.mysql.ports[3306] }} - MYSQL_USER: root - MYSQL_PASSWORD: - - - name: Upload coverage - uses: codecov/codecov-action@v1.0.7 - if: success() - with: - token: ${{ secrets.CODECOV_TOKEN }} - file: ./coverage/clover.xml \ No newline at end of file + test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Pull + run: docker-compose pull --quiet + - name: Build + run: docker-compose build + - name: Test + run: docker-compose run lib composer ci + - name: Upload coverage + uses: codecov/codecov-action@v1.0.14 + if: success() + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: ./coverage/clover.xml diff --git a/.gitignore b/.gitignore index 88592f9..b1593b1 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ build/ # Dev / Testing test.php -coverage/ \ No newline at end of file +coverage/* +!coverage/.gitkeep \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..22211cb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +ARG PHPVERSION="7.4" +FROM php:$PHPVERSION-cli-alpine + +RUN apk --update --no-cache add \ + mysql-client \ + && rm -rf /tmp/* /var/cache/apk/* + +RUN docker-php-ext-install \ + pdo_mysql + +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer + +WORKDIR /app + +COPY composer.json . +COPY composer.lock . +RUN composer validate +RUN composer install --no-interaction --no-progress --no-suggest + +COPY . . + +ENTRYPOINT ["./entrypoint.sh"] diff --git a/README.md b/README.md index a9ba1e6..112a189 100644 --- a/README.md +++ b/README.md @@ -196,6 +196,4 @@ composer require predis/predis ``` ## How to Dev -`composer ci` for php-cs-fixer and phpunit and coverage -`composer lint` for php-cs-fixer -`composer test` for phpunit and coverage \ No newline at end of file +`docker-compose run lib composer ci` for launching tests diff --git a/composer.json b/composer.json index 5f492d7..addf755 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "php-cs-fixer fix" ], "test": [ - "phpunit --colors --coverage-html ./coverage" + "phpdbg -qrr vendor/bin/phpunit --colors --coverage-text --coverage-clover ./coverage/clover.xml" ] } } diff --git a/coverage/.gitkeep b/coverage/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f82a44e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,25 @@ +version: "3.8" + +services: + mariadb: + image: mariadb:10.4 + environment: + - "MYSQL_ALLOW_EMPTY_PASSWORD=yes" + - "MYSQL_DATABASE=test_database" + restart: "on-failure" + + redis: + image: redis:6 + restart: "on-failure" + + lib: + build: ./ + depends_on: + - mariadb + - redis + environment: + - "MYSQL_HOST=mariadb" + - "REDIS_HOST=redis" + volumes: + - "./coverage:/app/coverage" + restart: "no" diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..e8b4842 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +DB_TIMEOUT=${DB_TIMEOUT:-45} + +# Check MySQL up +MYSQL_CMD="mysql -h ${MYSQL_HOST} -P ${MYSQL_PORT:-3306} -u ${MYSQL_USER:-root}" +echo "Waiting ${DB_TIMEOUT}s for MySQL database to be ready..." +counter=1 +while ! ${MYSQL_CMD} -e "show databases;" > /dev/null 2>&1; do + sleep 1 + counter=$((counter + 1)) + if [ ${counter} -gt "${DB_TIMEOUT}" ]; then + >&2 echo "ERROR: Failed to connect to MySQL database on $MYSQL_HOST" + exit 1 + fi; +done +echo "MySQL database ready!" + +exec "$@" diff --git a/phpcs.xml b/phpcs.xml index d60ac10..747b08f 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -7,6 +7,6 @@ src - + - \ No newline at end of file + diff --git a/tests/DatabaseEncryptionTest.php b/tests/DatabaseEncryptionTest.php index 73fec4a..42fb6d9 100644 --- a/tests/DatabaseEncryptionTest.php +++ b/tests/DatabaseEncryptionTest.php @@ -26,11 +26,15 @@ public static function setUpBeforeClass(): void { $conf = new Configurator([ 'driver' => 'mysql', - 'host' => '127.0.0.1', + 'host' => 'mariadb', 'user' => 'root', 'password' => '', 'database' => 'test_database' ]); + + $mysqlHost = getenv('MYSQL_HOST', true); + $conf->setHost(($mysqlHost !== false) ? $mysqlHost : '127.0.0.1'); + static::$db = new \Rancoud\Database\Database($conf); $sql = ' @@ -319,11 +323,15 @@ public function testSetNewDatabaseWithArray(): void $params = [ 'driver' => 'mysql', - 'host' => '127.0.0.1', + 'host' => 'mariadb', 'user' => 'root', 'password' => '', 'database' => 'test_database' ]; + + $mysqlHost = getenv('MYSQL_HOST', true); + $params['host'] = ($mysqlHost !== false) ? $mysqlHost : '127.0.0.1'; + $database->setNewDatabase($params); $sessionId = 'sessionId'; @@ -348,14 +356,17 @@ public function testSetNewDatabaseWithConfigurator(): void $database = new DatabaseEncryption(); $database->setKey('randomKey'); - $params = [ + $conf = new Configurator([ 'driver' => 'mysql', - 'host' => '127.0.0.1', + 'host' => 'mariadb', 'user' => 'root', 'password' => '', 'database' => 'test_database' - ]; - $conf = new Configurator($params); + ]); + + $mysqlHost = getenv('MYSQL_HOST', true); + $conf->setHost(($mysqlHost !== false) ? $mysqlHost : '127.0.0.1'); + $database->setNewDatabase($conf); $sessionId = 'sessionId'; diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php index 9784f9a..5452818 100644 --- a/tests/DatabaseTest.php +++ b/tests/DatabaseTest.php @@ -26,11 +26,15 @@ public static function setUpBeforeClass(): void { $conf = new Configurator([ 'driver' => 'mysql', - 'host' => '127.0.0.1', + 'host' => 'mariadb', 'user' => 'root', 'password' => '', 'database' => 'test_database' ]); + + $mysqlHost = getenv('MYSQL_HOST', true); + $conf->setHost(($mysqlHost !== false) ? $mysqlHost : '127.0.0.1'); + static::$db = new \Rancoud\Database\Database($conf); $sql = ' @@ -288,11 +292,15 @@ public function testSetNewDatabaseWithArray(): void $database = new Database(); $params = [ 'driver' => 'mysql', - 'host' => '127.0.0.1', + 'host' => 'mariadb', 'user' => 'root', 'password' => '', 'database' => 'test_database' ]; + + $mysqlHost = getenv('MYSQL_HOST', true); + $params['host'] = ($mysqlHost !== false) ? $mysqlHost : '127.0.0.1'; + $database->setNewDatabase($params); $sessionId = 'sessionId'; @@ -314,14 +322,17 @@ public function testSetNewDatabaseWithArray(): void public function testSetNewDatabaseWithConfigurator(): void { $database = new Database(); - $params = [ + $conf = new Configurator([ 'driver' => 'mysql', - 'host' => '127.0.0.1', + 'host' => 'mariadb', 'user' => 'root', 'password' => '', 'database' => 'test_database' - ]; - $conf = new Configurator($params); + ]); + + $mysqlHost = getenv('MYSQL_HOST', true); + $conf->setHost(($mysqlHost !== false) ? $mysqlHost : '127.0.0.1'); + $database->setNewDatabase($conf); $sessionId = 'sessionId'; diff --git a/tests/RedisEncryptionTest.php b/tests/RedisEncryptionTest.php index 11a38a6..3eb1472 100644 --- a/tests/RedisEncryptionTest.php +++ b/tests/RedisEncryptionTest.php @@ -22,9 +22,13 @@ public static function setUpBeforeClass(): void { $params = [ 'scheme' => 'tcp', - 'host' => '127.0.0.1', + 'host' => 'redis', 'port' => 6379, ]; + + $redisHost = getenv('REDIS_HOST', true); + $params['host'] = ($redisHost !== false) ? $redisHost : '127.0.0.1'; + static::$redis = new Predis($params); static::$redis->flushdb(); } @@ -173,9 +177,13 @@ public function testSetNewRedis(): void $params = [ 'scheme' => 'tcp', - 'host' => '127.0.0.1', + 'host' => 'redis', 'port' => 6379, ]; + + $redisHost = getenv('REDIS_HOST', true); + $params['host'] = ($redisHost !== false) ? $redisHost : '127.0.0.1'; + $redis->setNewRedis($params); $sessionId = 'sessionId'; diff --git a/tests/RedisTest.php b/tests/RedisTest.php index f025218..a8228da 100644 --- a/tests/RedisTest.php +++ b/tests/RedisTest.php @@ -22,9 +22,13 @@ public static function setUpBeforeClass(): void { $params = [ 'scheme' => 'tcp', - 'host' => '127.0.0.1', + 'host' => 'redis', 'port' => 6379, ]; + + $redisHost = getenv('REDIS_HOST', true); + $params['host'] = ($redisHost !== false) ? $redisHost : '127.0.0.1'; + static::$redis = new Predis($params); static::$redis->flushdb(); } @@ -139,9 +143,13 @@ public function testSetNewRedis(): void $redis = new Redis(); $params = [ 'scheme' => 'tcp', - 'host' => '127.0.0.1', + 'host' => 'redis', 'port' => 6379, ]; + + $redisHost = getenv('REDIS_HOST', true); + $params['host'] = ($redisHost !== false) ? $redisHost : '127.0.0.1'; + $redis->setNewRedis($params); $sessionId = 'sessionId'; diff --git a/tests/SessionTest.php b/tests/SessionTest.php index 5ec43b5..e638470 100644 --- a/tests/SessionTest.php +++ b/tests/SessionTest.php @@ -110,7 +110,7 @@ public function testStartException(): void { $this->expectException(SessionException::class); $this->expectExceptionMessage('Session already started'); - + Session::setReadWrite(); Session::start(); Session::start(); @@ -124,7 +124,7 @@ public function testUseDefaultDriverWhenAlreadyStartedException(): void { $this->expectException(SessionException::class); $this->expectExceptionMessage('Session already started'); - + Session::setReadWrite(); Session::start(); Session::useDefaultDriver(); @@ -138,7 +138,7 @@ public function testUseFileDriverWhenAlreadyStartedException(): void { $this->expectException(SessionException::class); $this->expectExceptionMessage('Session already started'); - + Session::setReadWrite(); Session::start(); Session::useFileDriver(); @@ -152,7 +152,7 @@ public function testUseCustomDriverWhenAlreadyStartedException(): void { $this->expectException(SessionException::class); $this->expectExceptionMessage('Session already started'); - + Session::setReadWrite(); Session::start(); Session::useCustomDriver(new File()); @@ -240,11 +240,15 @@ public function testUseNewDatabaseDriver(): void { $params = [ 'driver' => 'mysql', - 'host' => '127.0.0.1', + 'host' => 'mysql', 'user' => 'root', 'password' => '', 'database' => 'test_database' ]; + + $mysqlHost = getenv('MYSQL_HOST', true); + $params['host'] = ($mysqlHost !== false) ? $mysqlHost : '127.0.0.1'; + Session::useNewDatabaseDriver($params); Session::start(); @@ -259,11 +263,15 @@ public function testUseNewDatabaseEncryptionDriver(): void { $params = [ 'driver' => 'mysql', - 'host' => '127.0.0.1', + 'host' => 'mysql', 'user' => 'root', 'password' => '', 'database' => 'test_database' ]; + + $mysqlHost = getenv('MYSQL_HOST', true); + $params['host'] = ($mysqlHost !== false) ? $mysqlHost : '127.0.0.1'; + Session::useNewDatabaseEncryptionDriver($params, 'randomKey'); Session::start(); @@ -279,11 +287,15 @@ public function testUseCurrentDatabaseDriver(): void { $conf = new \Rancoud\Database\Configurator([ 'driver' => 'mysql', - 'host' => '127.0.0.1', + 'host' => 'mysql', 'user' => 'root', 'password' => '', 'database' => 'test_database' ]); + + $mysqlHost = getenv('MYSQL_HOST', true); + $conf->setHost(($mysqlHost !== false) ? $mysqlHost : '127.0.0.1'); + $db = new \Rancoud\Database\Database($conf); Session::useCurrentDatabaseDriver($db); Session::start(); @@ -301,11 +313,15 @@ public function testUseCurrentDatabaseEncryptionDriver(): void $userId = 50; $conf = new \Rancoud\Database\Configurator([ 'driver' => 'mysql', - 'host' => '127.0.0.1', + 'host' => 'mysql', 'user' => 'root', 'password' => '', 'database' => 'test_database' ]); + + $mysqlHost = getenv('MYSQL_HOST', true); + $conf->setHost(($mysqlHost !== false) ? $mysqlHost : '127.0.0.1'); + $db = new \Rancoud\Database\Database($conf); Session::useCurrentDatabaseEncryptionDriver($db, 'randomKey'); static::assertInstanceOf(\Rancoud\Session\DatabaseEncryption::class, Session::getDriver()); @@ -328,9 +344,13 @@ public function testUseNewRedisDriver(): void { $params = [ 'scheme' => 'tcp', - 'host' => '127.0.0.1', + 'host' => 'redis', 'port' => 6379, ]; + + $redisHost = getenv('REDIS_HOST', true); + $params['host'] = ($redisHost !== false) ? $redisHost : '127.0.0.1'; + Session::useNewRedisDriver($params); Session::start(); @@ -345,9 +365,13 @@ public function testUseNewRedisEncryptionDriver(): void { $params = [ 'scheme' => 'tcp', - 'host' => '127.0.0.1', + 'host' => 'redis', 'port' => 6379, ]; + + $redisHost = getenv('REDIS_HOST', true); + $params['host'] = ($redisHost !== false) ? $redisHost : '127.0.0.1'; + Session::useNewRedisEncryptionDriver($params, 'randomKey'); Session::start(); @@ -362,9 +386,13 @@ public function testUseCurrentRedisDriver(): void { $params = [ 'scheme' => 'tcp', - 'host' => '127.0.0.1', + 'host' => 'redis', 'port' => 6379, ]; + + $redisHost = getenv('REDIS_HOST', true); + $params['host'] = ($redisHost !== false) ? $redisHost : '127.0.0.1'; + $redis = new \Predis\Client($params); Session::useCurrentRedisDriver($redis); Session::start(); @@ -380,9 +408,13 @@ public function testUseCurrentRedisEncryptionDriver(): void { $params = [ 'scheme' => 'tcp', - 'host' => '127.0.0.1', + 'host' => 'redis', 'port' => 6379, ]; + + $redisHost = getenv('REDIS_HOST', true); + $params['host'] = ($redisHost !== false) ? $redisHost : '127.0.0.1'; + $redis = new \Predis\Client($params); Session::useCurrentRedisEncryptionDriver($redis, 'randomKey'); Session::start(); @@ -410,7 +442,7 @@ public function testUseEncryptionDriverThrowExceptionWhenMethodIncrorrect(): voi { $this->expectException(SessionException::class); $this->expectExceptionMessage('Method unknowed: incorrect'); - + Session::useFileEncryptionDriver('randomKey', 'incorrect'); } @@ -444,7 +476,7 @@ public function testSetOptionThrowException(): void { $this->expectException(SessionException::class); $this->expectExceptionMessage('Incorrect option: azerty'); - + Session::getOption('azerty'); } @@ -593,11 +625,15 @@ public function testGc(): void { $conf = new \Rancoud\Database\Configurator([ 'driver' => 'mysql', - 'host' => '127.0.0.1', + 'host' => 'mysql', 'user' => 'root', 'password' => '', 'database' => 'test_database' ]); + + $mysqlHost = getenv('MYSQL_HOST', true); + $conf->setHost(($mysqlHost !== false) ? $mysqlHost : '127.0.0.1'); + $db = new \Rancoud\Database\Database($conf); $db->truncateTables('sessions');