Skip to content

Unit

Unit #17501

Workflow file for this run

name: Unit
on:
pull_request:
push:
schedule:
- cron: '0 0/2 * * *'
jobs:
smoke-test:
name: Smoke
runs-on: ubuntu-latest
container:
image: ghcr.io/mvorisek/image-php:${{ matrix.php }}
strategy:
fail-fast: false
matrix:
php: ['latest']
type: ['Phpunit']
include:
- php: 'latest'
type: 'CodingStyle'
- php: 'latest'
type: 'StaticAnalysis'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure PHP
run: |
rm /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
php --version
- name: Setup cache 1/2
id: composer-cache
run: |
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Setup cache 2/2
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-smoke-${{ matrix.php }}-${{ matrix.type }}-${{ hashFiles('composer.json') }}
restore-keys: |
${{ runner.os }}-composer-
- name: Install PHP dependencies
run: |
if [ "${{ matrix.type }}" != "Phpunit" ] && [ "${{ matrix.type }}" != "StaticAnalysis" ]; then composer remove --no-interaction --no-update phpunit/phpunit ergebnis/phpunit-slow-test-detector --dev; fi
if [ "${{ matrix.type }}" != "CodingStyle" ]; then composer remove --no-interaction --no-update friendsofphp/php-cs-fixer ergebnis/composer-normalize --dev; fi
if [ "${{ matrix.type }}" != "StaticAnalysis" ]; then composer remove --no-interaction --no-update phpstan/\* --dev; fi
composer update --ansi --prefer-dist --no-interaction --no-progress --optimize-autoloader
- name: "Run tests (only for Phpunit)"
if: startsWith(matrix.type, 'Phpunit')
run: |
vendor/bin/phpunit --exclude-group none --no-coverage --fail-on-warning --fail-on-risky $(if vendor/bin/phpunit --version | grep -q '^PHPUnit 9\.'; then echo -v; else echo --fail-on-notice --fail-on-deprecation --display-notices --display-deprecations --display-warnings --display-errors --display-incomplete --display-skipped; fi)
- name: Check Coding Style (only for CodingStyle)
if: matrix.type == 'CodingStyle'
run: |
vendor/bin/php-cs-fixer fix --dry-run --using-cache=no --diff --verbose
composer config --unset version && composer config --unset require-release
composer validate --strict --no-check-lock && composer normalize --dry-run --no-check-lock
- name: Run Static Analysis (only for StaticAnalysis)
if: matrix.type == 'StaticAnalysis'
run: |
echo "memory_limit = 2G" > /usr/local/etc/php/conf.d/custom-memory-limit.ini
vendor/bin/phpstan analyse -v
unit-test:
name: Unit
runs-on: ubuntu-latest
container:
image: ghcr.io/mvorisek/image-php:${{ matrix.php }}
strategy:
fail-fast: false
matrix:
php: ['7.4', '8.0', '8.1', '8.2', '8.3']
type: ['Phpunit', 'Phpunit Lowest']
include:
- php: 'latest'
type: 'Phpunit Burn'
env:
LOG_COVERAGE: "${{ fromJSON('{true: \"1\", false: \"\"}')[matrix.php == '8.3' && matrix.type == 'Phpunit' && (github.event_name == 'pull_request' || (github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master')))] }}"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure PHP
run: |
if [ -n "$LOG_COVERAGE" ]; then echo "xdebug.mode=coverage" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; else rm /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; fi
php --version
- name: Setup cache 1/2
id: composer-cache
run: |
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Setup cache 2/2
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ matrix.type }}-${{ hashFiles('composer.json') }}
restore-keys: |
${{ runner.os }}-composer-
- name: Install PHP dependencies
run: |
if [ "${{ matrix.type }}" != "Phpunit" ] && [ "${{ matrix.type }}" != "Phpunit Lowest" ] && [ "${{ matrix.type }}" != "Phpunit Burn" ]; then composer remove --no-interaction --no-update phpunit/phpunit ergebnis/phpunit-slow-test-detector --dev; fi
if [ "${{ matrix.type }}" != "CodingStyle" ]; then composer remove --no-interaction --no-update friendsofphp/php-cs-fixer ergebnis/composer-normalize --dev; fi
if [ "${{ matrix.type }}" != "StaticAnalysis" ]; then composer remove --no-interaction --no-update phpstan/\* --dev; fi
if [ -n "$LOG_COVERAGE" ]; then composer require --no-interaction --no-install phpunit/phpcov; fi
composer update --ansi --prefer-dist --no-interaction --no-progress --optimize-autoloader
if [ "${{ matrix.type }}" = "Phpunit Lowest" ]; then composer update --ansi --prefer-dist --prefer-lowest --prefer-stable --no-interaction --no-progress --optimize-autoloader; fi
if [ "${{ matrix.type }}" = "Phpunit Burn" ]; then sed -i 's~public function runBare(): void~public function runBare(): void { gc_collect_cycles(); $memDiffs = array_fill(0, '"$(if [ \"$GITHUB_EVENT_NAME\" == \"schedule\" ]; then echo 1024; else echo 64; fi)"', 0); $emitter = Event\\Facade::emitter(); for ($i = -1; $i < count($memDiffs); ++$i) { $this->_runBare(); if ($this->inIsolation) { $dispatcher = \\Closure::bind(static fn () => $emitter->dispatcher, null, Event\\DispatchingEmitter::class)(); if ($i === -1) { $dispatcherEvents = $dispatcher->flush()->asArray(); } else { $dispatcher->flush(); } foreach ($dispatcherEvents as $event) { $dispatcher->dispatch($event); } } gc_collect_cycles(); $mem = memory_get_usage(); if ($i !== -1) { $memDiffs[$i] = $mem - $memPrev; } $memPrev = $mem; rsort($memDiffs); if (array_sum($memDiffs) >= 4096 * 1024 || $memDiffs[2] > 0) { $e = new AssertionFailedError("Memory leak detected! (" . implode(" + ", array_map(static fn ($v) => number_format($v / 1024, 3, ".", " "), array_filter($memDiffs))) . " KB, " . ($i + 2) . " iterations)"); $this->status = TestStatus::failure($e->getMessage()); $emitter->testFailed($this->valueObjectForEvents(), Event\\Code\\ThrowableBuilder::from($e), Event\\Code\\ComparisonFailureBuilder::from($e)); $this->onNotSuccessfulTest($e); } } } private function _runBare(): void~' vendor/phpunit/phpunit/src/Framework/TestCase.php && cat vendor/phpunit/phpunit/src/Framework/TestCase.php | grep '_runBare('; fi
- name: Init
run: |
if [ -n "$LOG_COVERAGE" ]; then mkdir coverage; fi
- name: "Run tests"
run: |
php -d opcache.enable_cli=1 vendor/bin/phpunit --exclude-group none $(if [ -n "$LOG_COVERAGE" ]; then echo --coverage-text; else echo --no-coverage; fi) --fail-on-warning --fail-on-risky $(if vendor/bin/phpunit --version | grep -q '^PHPUnit 9\.'; then echo -v; else echo --fail-on-notice --fail-on-deprecation --display-notices --display-deprecations --display-warnings --display-errors --display-incomplete --display-skipped; fi)
- name: Upload coverage logs 1/2 (only for coverage)
if: env.LOG_COVERAGE
run: |
ls -l coverage | wc -l
php -d memory_limit=2G vendor/bin/phpcov merge coverage/ --clover coverage/merged.xml
- name: Upload coverage logs 2/2 (only for coverage)
if: env.LOG_COVERAGE
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
files: coverage/merged.xml
docs-test:
name: Docs
runs-on: ubuntu-latest
container:
image: ghcr.io/mvorisek/image-php:latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Python and dependencies
run: |
apk add python3 py3-pip
python --version
python -m venv .venv
source .venv/bin/activate
(cd docs && pip install -r requirements.txt)
- name: Build
run: |
mv docs/baseline.txt docs/baseline.orig.txt
source .venv/bin/activate
(cd docs && python -m sphinx -T -b html . out 2>&1 | tee baseline.txt)
sed -i -r 's~[^:]*/docs/([^:]*:)([0-9]+:)?~\1~;t;d' docs/baseline.txt
- name: Diff build baseline
run: |
diff -u docs/baseline.orig.txt docs/baseline.txt