Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.git
.github
.php-cs-fixer.cache
vendor
coverage
7 changes: 6 additions & 1 deletion .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ jobs:

strategy:
matrix:
php: [8.0, 8.1]
php: [8.3.36]

steps:
- uses: actions/checkout@v2

- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}

- name: Validate composer.json and composer.lock
run: composer validate --strict

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ composer.lock
phpunit.xml
cache.properties
coverage.xml
/coverage/
.php_cs.cache
.phpunit.result.cache
.php-cs-fixer.cache
31 changes: 31 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# syntax=docker/dockerfile:1
FROM php:8.3.36-cli

RUN apt-get update \
&& apt-get install -y --no-install-recommends unzip \
&& rm -rf /var/lib/apt/lists/* \
&& docker-php-ext-install pdo_mysql

RUN pecl install xdebug \
&& docker-php-ext-enable xdebug

ENV XDEBUG_MODE=off

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /app

COPY . .

RUN --mount=type=secret,id=host-ca,target=/run/secrets/host-ca.pem,required=false \
if [ -s /run/secrets/host-ca.pem ]; then \
cat /etc/ssl/certs/ca-certificates.crt /run/secrets/host-ca.pem > /tmp/ca-certificates.crt && \
COMPOSER_CAFILE=/tmp/ca-certificates.crt \
SSL_CERT_FILE=/tmp/ca-certificates.crt \
composer install --prefer-dist --no-interaction --no-progress && \
rm /tmp/ca-certificates.crt; \
else \
composer install --prefer-dist --no-interaction --no-progress; \
fi

CMD ["composer", "test"]
45 changes: 43 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,53 @@ $ composer require linio/database

## Tests

To run the test suite, you need install the dependencies via composer, then
run PHPUnit.
Run the test suite in Docker with PHP 8.3.36 and MySQL; PHP does not need to be
installed on the host:

$ docker compose run --build --rm tests

If your network uses a custom CA certificate bundle, set `SSL_CERT_FILE` to
that bundle. When Docker Bake requests permission to read the bundle outside
the project, build with access limited to that file, then run the tests:

```bash
docker compose build --print | docker buildx bake --file - \
--allow "fs.read=${SSL_CERT_FILE:?Set SSL_CERT_FILE to your CA bundle}" \
--load tests
docker compose run --rm tests
```

Docker mounts the certificate bundle as a build secret to download Composer
dependencies. The temporary combined CA bundle is removed in the same build
step and is not stored in the image.

The MySQL container remains running after the tests finish. Stop and remove it
with:

$ docker compose down

To run the test suite directly on the host instead, install the Composer
dependencies and run PHPUnit:

$ composer install
$ vendor/bin/phpunit

### Code coverage in Docker

Rebuild the test image after updating the Dockerfile. Xdebug is installed but
disabled for normal test runs. Enable it to generate coverage reports:

```bash
docker compose run --rm -e XDEBUG_MODE=coverage tests vendor/bin/phpunit \
--coverage-text \
--coverage-html /coverage/html \
--coverage-clover /coverage/clover.xml
```

The `coverage` directory is mounted from the host so the reports remain
available after the container exits. Open the HTML report on macOS with
`open coverage/html/index.html`. Reports are excluded from Git and Docker builds.

## Usage

```php
Expand Down
32 changes: 32 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
services:
tests:
build:
context: .
secrets:
- host-ca
depends_on:
mysql:
condition: service_healthy
environment:
TEST_DATABASE_HOST: mysql
TEST_DATABASE_PORT: 3306
TEST_DATABASE_DBNAME: framework_database_test
TEST_DATABASE_USERNAME: root
TEST_DATABASE_PASSWORD: "123456"
volumes:
- ./coverage:/coverage

mysql:
image: mysql:8.4
environment:
MYSQL_ROOT_PASSWORD: "123456"
MYSQL_DATABASE: framework_database_test
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-p123456"]
interval: 5s
timeout: 5s
retries: 20

secrets:
host-ca:
file: ${SSL_CERT_FILE:-/dev/null}
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "library",
"license": "BSD-3-Clause",
"require": {
"php": "^8.1",
"php": "~8.3.36 || ~8.4.27",
"psr/log": "^1.0.1 || ^2.0 || ^3.0"
},
"require-dev": {
Expand Down
2 changes: 1 addition & 1 deletion src/Adapter/AdapterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function rollBack(): void;
/**
* @throws DatabaseException
*/
public function getLastInsertId(string $name = null): ?string;
public function getLastInsertId(?string $name = null): ?string;

/**
* @throws DatabaseException Support for the database has not been implemented yet
Expand Down
2 changes: 1 addition & 1 deletion src/Adapter/PdoAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ public function rollBack(): void
/**
* @throws DatabaseException
*/
public function getLastInsertId(string $name = null): ?string
public function getLastInsertId(?string $name = null): ?string
{
try {
$lastInsertId = $this->getPdo()->lastInsertId($name);
Expand Down
2 changes: 1 addition & 1 deletion src/DatabaseManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ public function rollBack(): bool
/**
* @throws DatabaseException
*/
public function getLastInsertId(string $name = null): ?string
public function getLastInsertId(?string $name = null): ?string
{
try {
return $this->getWriteAdapter()->getLastInsertId($name);
Expand Down
Loading