From 83bcf22752fcd7e6ab58e1219769e6cec5913db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= <323649642+oc-tmueller@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:41:33 +0200 Subject: [PATCH] feat(php-unit): fail when core's error handler swallowed PHP errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A test bootstrap that loads lib/base.php without PHPUNIT_RUN gets core's production OC\Log\ErrorHandler, and PHPUnit's own handler backs off. Every notice, warning and deprecation then went to owncloud.log, and the job stayed green. wopi's unit suite and notes' integration suite are built that way today. Record the size of owncloud.log before the PHPUnit steps. Afterwards, fail if any entry appended since then was logged with app "PHP". Only that handler writes such entries, so the check tests the failure itself, however the bootstrap is put together. Refs owncloud/core#41904 Co-Authored-By: Claude Opus 5.5 Signed-off-by: Thomas Müller <323649642+oc-tmueller@users.noreply.github.com> --- .github/workflows/php-unit.yml | 24 +++++++++++++++++++ .../unreleased/php-unit-swallowed-php-errors | 11 +++++++++ 2 files changed, 35 insertions(+) create mode 100644 changelog/unreleased/php-unit-swallowed-php-errors diff --git a/.github/workflows/php-unit.yml b/.github/workflows/php-unit.yml index f27222e..122dd35 100644 --- a/.github/workflows/php-unit.yml +++ b/.github/workflows/php-unit.yml @@ -311,6 +311,10 @@ jobs: ls -l config cat config/config.php + - name: Mark owncloud.log before the tests + run: | + echo "OC_LOG_MARK=$(stat -c %s data/owncloud.log 2>/dev/null || echo 0)" >> "$GITHUB_ENV" + - name: Run PHPUnit env: APP_NAME: ${{ inputs.app-name }} @@ -326,6 +330,26 @@ jobs: cd "apps/${APP_NAME}" make test-php-integration + # Core's OC\Log\ErrorHandler logs every entry with app "PHP". Inside PHPUnit it is active + # when the test bootstrap loaded lib/base.php without defining PHPUNIT_RUN, and then PHPUnit's + # own handler backs off, so notices, warnings and deprecations never fail the suite. A PHP + # subprocess started by a test (e.g. occ) installs it too. + - name: Check for PHP errors swallowed by core's error handler + if: ${{ !cancelled() && env.OC_LOG_MARK != '' }} + run: | + log=data/owncloud.log + [ -f "$log" ] || exit 0 + mark="$OC_LOG_MARK" + if [ "$(stat -c %s "$log")" -lt "$mark" ]; then + mark=0 + fi + entries=$(tail -c +"$((mark + 1))" "$log" | jq -R -c 'fromjson? | select(.app == "PHP")') + if [ -n "$entries" ]; then + printf '%s\n' "$entries" | head -n 20 + echo "::error::$(printf '%s\n' "$entries" | wc -l) PHP error(s) went to owncloud.log instead of failing PHPUnit. Usually the test bootstrap loads lib/base.php without defining PHPUNIT_RUN: define it first, or bootstrap through core's tests/bootstrap.php. A PHP subprocess started by a test (e.g. occ) logs the same way. See https://github.com/owncloud/core/issues/41904" + exit 1 + fi + - name: Tail log if: always() run: | diff --git a/changelog/unreleased/php-unit-swallowed-php-errors b/changelog/unreleased/php-unit-swallowed-php-errors new file mode 100644 index 0000000..fd3ad38 --- /dev/null +++ b/changelog/unreleased/php-unit-swallowed-php-errors @@ -0,0 +1,11 @@ +Enhancement: Fail PHP Unit when core's error handler swallowed PHP errors + +An app's test bootstrap that loads lib/base.php without defining PHPUNIT_RUN gets +core's production OC\Log\ErrorHandler. PHPUnit's own handler then backs off, and +every notice, warning and deprecation raised during the suite was written to +owncloud.log while the job stayed green. The workflow now fails when the PHPUnit +or integration steps added entries logged with app "PHP" to owncloud.log. Only +that handler writes such entries. + +https://github.com/owncloud/core/issues/41904 +https://github.com/owncloud/reusable-workflows/pull/101