Skip to content
Draft
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
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ updates:
- dependency-name: "phpstan/phpstan-strict-rules"
- dependency-name: "phpunit/phpunit"
versions: [ ">= 11.0" ]
# pcov for phpunit 10, version match is currently one version off. Check packagist
# requirements again raising phpunit/phpunit version and align it correspondingly.
- dependency-name: "phpunit/pcov"
versions: [ ">= 10.0" ]
- dependency-name: "rector/type-perfect"
- dependency-name: "saschaegerer/phpstan-typo3"
- dependency-name: "ssch/typo3-*"
Expand Down
84 changes: 29 additions & 55 deletions .github/workflows/codecoverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,81 +9,55 @@ on:
permissions:
contents: read
jobs:
# @todo Rethink the whole implementation. It's possible to consider creating the part coverage logs directly
# for all unit, unitRandom and functional tests in the `ci.yml` workflow and using this only to merge
# and upload it. That would avoid reexecuting only for a subset of matrix run here again.
# In general there are two different approaches when doing the above mentioned considerations:
#
# * Use job artifacts to get all of the `Build/coverage/*.pcov` files and merge it using the pcov tool
# * Use parallel partly upload in ci.yaml unit, unitRandom, functional test runs and use this to finish
# the parallel execution. See: https://github.com/coverallsapp/github-action#complete-parallel-job-example
code-coverage:
name: Calculate code coverage
permissions:
actions: write
runs-on: ubuntu-24.04
env:
DB_DATABASE: typo3
DB_USER: root
DB_PASSWORD: root
DB_HOST: localhost
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: "${{ matrix.php-version }}"
ini-file: development
tools: composer:v2, phive
extensions: mysqli
coverage: xdebug
- name: Install development tools
run: phive --no-progress install --trust-gpg-keys D8406D0D82947747293778314AA394086372C20A
- name: Show Composer version
run: composer --version
- name: Show the Composer version
run: ./Build/Scripts/runTests.sh -s composer -- --version
- name: Show the Composer configuration
run: composer config --global --list
- name: Cache dependencies installed with composer
uses: actions/cache@v5
with:
key: "php-${{ matrix.php-version }}-typo3-${{ matrix.typo3-version }}-${{ matrix.composer-dependencies }}-composer-${{ hashFiles('**/composer.json') }}"
path: ~/.cache/composer
restore-keys: "php-${{ matrix.php-version }}-typo3-${{ matrix.typo3-version }}-${{ matrix.composer-dependencies }}-composer-\n"
- name: Install TYPO3 Core
env:
TYPO3: "${{ matrix.typo3-version }}"
run: |
composer require --no-ansi --no-interaction --no-progress --no-install typo3/cms-core:^"$TYPO3"
composer show
- name: Install lowest dependencies with composer
if: "matrix.composer-dependencies == 'Min'"
run: ./Build/Scripts/runTests.sh -s composer config --global --list
- name: Install composer dependencies
run: |
composer update --no-ansi --no-interaction --no-progress --with-dependencies --prefer-lowest
composer show
- name: Install highest dependencies with composer
if: "matrix.composer-dependencies == 'Max'"
run: |
composer update --no-ansi --no-interaction --no-progress --with-dependencies
composer show
- name: Start MySQL
run: "sudo /etc/init.d/mysql start"
./Build/Scripts/runTests.sh -p ${{ matrix.php-version }} -t ${{matrix.typo3-version}} -s composerUpdate${{matrix.composer-dependencies}}
# @todo Consider to execute all unit tests with coverage and using job artifacts to merge them in one place
# instead of executing only one run here with coverage. Could also be combined directly uploading the
# parallel executions as partly upload and using this workflow only to make the final webhook call.
- name: Run unit tests with coverage
run: composer check:coverage:unit
- name: Show generated coverage files
run: "ls -lahR build/coverage/"
run: |
./Build/Scripts/runTests.sh -p ${{ matrix.php-version }} -s unit -m
# @todo Consider to execute all functional tests with coverage and using job artifacts to merge them in one place
# instead of executing only one run here with coverage. Could also be combined directly uploading the
# parallel executions as partly upload and using this workflow only to make the final webhook call.
- name: Run functional tests with coverage
run: |
export typo3DatabaseName="$DB_DATABASE";
export typo3DatabaseHost="$DB_HOST";
export typo3DatabaseUsername="$DB_USER";
export typo3DatabasePassword="$DB_PASSWORD";
composer check:coverage:functional
./Build/Scripts/runTests.sh -p ${{ matrix.php-version }} -s functional -m
- name: Show generated coverage files
run: "ls -lahR build/coverage/"
run: |
ls -lahR Build/coverage/
# @todo
- name: Merge coverage results
run: composer check:coverage:merge
run: |
./Build/Scripts/runTests.sh -p ${{ matrix.php-version }} -s coverageMerge
- name: Show combined coverage files
run: "ls -lahR build/logs/"
run: "ls -lahR Build/logs/"
- name: Upload coverage results to Coveralls
uses: coverallsapp/github-action@v2
env:
github-token: ${{ secrets.GITHUB_TOKEN }}
# Note: This is the only path that the Coveralls GitHub Action supports.
# So we cannot use something like .Build/coverage/clover.xml here.
file: build/logs/clover.xml
file: Build/logs/clover.xml
strategy:
fail-fast: false
matrix:
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
/.php-cs-fixer.cache
/.phpunit.result.cache
/Documentation-GENERATED-temp/
/build
/Build/coverage
/Build/logs
/composer.lock
/generate-documentation.sh
/nbproject
Expand Down
67 changes: 64 additions & 3 deletions Build/Scripts/runTests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,16 @@ printSummary() {
echo "DBMS: ${DBMS} driver pdo_sqlite" >&2
;;
esac
if [[ "${CREATE_COVERAGE}" -eq 1 ]]; then
echo "COVERAGE-LOG-FILE: ${COVERAGE_LOG_FILE}"
fi
fi
if [[ ${TEST_SUITE} =~ ^unit ]]; then
if [[ "${CREATE_COVERAGE}" -eq 1 ]]; then
echo "COVERAGE-LOG-FILE: ${COVERAGE_LOG_FILE}"
fi
fi

if [[ ${SUITE_EXIT_CODE} -eq 0 ]]; then
echo "SUCCESS" >&2
else
Expand Down Expand Up @@ -192,6 +201,7 @@ Options:
- composerUnused: Finds unused Composer packages.
- composerUpdateMax: "composer update", with no platform.php config.
- composerUpdateMin: "composer update --prefer-lowest", with platform.php set to PHP version x.x.0.
- coverageMerge: Merge gathered coverage files into one set.
- docsGenerate: Renders the extension ReST documentation.
- fix: Runs all automatic code style fixes.
- functional: PHP functional tests
Expand Down Expand Up @@ -308,6 +318,11 @@ Options:
Only with -s cgl|composerNormalize|npm|lintJs|lintCss
Activate dry-run in checks so they do not actively change files and only print broken ones.

-m
Only for functional|functionalDeprecated|unit|unitDeprecated|unitRandom
Activate collecting coverage metrics for executed test variant. The metrics are saved generic
to "Build/coverage/<test-identifier>" to allow merging results later with "-s coverageMerge".

-u
Update existing typo3/core-testing-*:latest container images and remove dangling local volumes.
New images are published once in a while and only the latest ones are supported by core testing.
Expand Down Expand Up @@ -381,14 +396,17 @@ CI_PARAMS="${CI_PARAMS:-}"
CONTAINER_HOST="host.docker.internal"
# shellcheck disable=SC2034 # This variable will be needed when we try to clean up the root folder
PHPSTAN_CONFIG_FILE="Build/phpstan/phpstan.neon"
CREATE_COVERAGE=0
COVERAGE_ADDITIONAL=""
COVERAGE_LOG_FILE=""

# Option parsing updates above default vars
# Reset in case getopts has been used previously in the shell
OPTIND=1
# Array for invalid options
INVALID_OPTIONS=()
# Simple option parsing based on getopts (! not getopt)
while getopts "a:b:s:d:i:p:t:xy:o:nhu" OPT; do
while getopts "a:b:s:d:i:p:t:xy:o:nmhu" OPT; do
case ${OPT} in
s)
TEST_SUITE=${OPTARG}
Expand Down Expand Up @@ -432,6 +450,9 @@ while getopts "a:b:s:d:i:p:t:xy:o:nhu" OPT; do
n)
CGLCHECK_DRY_RUN=1
;;
m)
CREATE_COVERAGE=1
;;
h)
loadHelp
echo "${HELP}"
Expand Down Expand Up @@ -512,6 +533,10 @@ else
CONTAINER_COMMON_PARAMS="${CONTAINER_INTERACTIVE} ${CI_PARAMS} --rm --network ${NETWORK} -v ${ROOT_DIR}:${ROOT_DIR} -w ${ROOT_DIR}"
fi

if test ${PHP_XDEBUG_ON} -eq 1 && test ${CREATE_COVERAGE} -eq 1; then
echo "Option \"-m\" and \"-x\" cannot be used together. Remove one."
exit 1
fi
if [ ${PHP_XDEBUG_ON} -eq 0 ]; then
XDEBUG_MODE="-e XDEBUG_MODE=off"
XDEBUG_CONFIG=" "
Expand All @@ -520,6 +545,15 @@ else
XDEBUG_CONFIG="client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal"
fi

if [ ${CREATE_COVERAGE} -eq 1 ]; then
XDEBUG_MODE="-e XDEBUG_MODE=coverage"
XDEBUG_CONFIG=" "
else
# Ensure to reset even if provided in case collecting coverage is not enabled
COVERAGE_ADDITIONAL=""
fi
[[ -n "${COVERAGE_ADDITIONAL}" ]] && COVERAGE_ADDITIONAL="${COVERAGE_ADDITIONAL}-"

# Suite execution
case ${TEST_SUITE} in
cgl)
Expand Down Expand Up @@ -576,6 +610,13 @@ case ${TEST_SUITE} in
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-unused-${SUFFIX} -e COMPOSER_CACHE_DIR=.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} /bin/sh -c "${COMMAND}"
SUITE_EXIT_CODE=$?
;;
coverageMerge)
[[ ! -d "Build/coverage/" ]] && echo "Nothing to merge" && SUITE_EXIT_CODE=1 && printSummary && exit 1
[[ ! -d "Build/logs/" ]] && mkdir -p "Build/logs"
COMMAND=".Build/bin/phpcov merge --clover=Build/logs/clover.xml Build/coverage/"
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-unused-${SUFFIX} -e COMPOSER_CACHE_DIR=.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} /bin/sh -c "${COMMAND}"
SUITE_EXIT_CODE=$?
;;
docsGenerate)
mkdir -p Documentation-GENERATED-temp
chown -R ${HOST_UID}:${HOST_PID} Documentation-GENERATED-temp
Expand All @@ -596,9 +637,14 @@ case ${TEST_SUITE} in
SUITE_EXIT_CODE=$?
;;
functional)
# Default COMMAND_ARRAY for non-coverage runs. Will be overridden for coverage runs for functional test type.
COMMAND_ARRAY=(.Build/bin/phpunit -c Build/phpunit/FunctionalTests.xml --exclude-group not-"${DBMS}" "$@")
[[ "${CREATE_COVERAGE}" -eq 1 ]] && mkdir -p Build/coverage Build/logs
case ${DBMS} in
mariadb)
COVERAGE_LOG_FILE="functional-$(echo "core${CORE_VERSION}" | sed -e 's/\./-/')-$(echo "php${PHP_VERSION}" | sed -e 's/\.//')-$(echo "mariadb${DBMS_VERSION}" | sed -e 's/\./_/')-$(echo "driver${DATABASE_DRIVER}" | sed -e 's/\.//').cov"
# shellcheck disable=SC2206 # Fighting shellcheck check moaning about things we need
[[ "${CREATE_COVERAGE}" -eq 1 ]] && COMMAND_ARRAY=(.Build/bin/phpunit -c Build/phpunit/FunctionalTests.xml --exclude-group not-"${DBMS}" --coverage-php=Build/coverage/${COVERAGE_LOG_FILE} "$@")
echo "Using driver: ${DATABASE_DRIVER}"
${CONTAINER_BIN} run --rm ${CI_PARAMS} --name mariadb-func-${SUFFIX} --network ${NETWORK} -d -e MYSQL_ROOT_PASSWORD=funcp --tmpfs /var/lib/mysql/:rw,noexec,nosuid ${IMAGE_MARIADB} >/dev/null
waitFor mariadb-func-${SUFFIX} 3306
Expand All @@ -607,6 +653,9 @@ case ${TEST_SUITE} in
SUITE_EXIT_CODE=$?
;;
mysql)
COVERAGE_LOG_FILE="functional-$(echo "core${CORE_VERSION}" | sed -e 's/\./-/')-$(echo "php${PHP_VERSION}" | sed -e 's/\.//')-$(echo "mysql${DBMS_VERSION}" | sed -e 's/\./_/')-$(echo "driver${DATABASE_DRIVER}" | sed -e 's/\.//').cov"
# shellcheck disable=SC2206 # Fighting shellcheck check moaning about things we need
[[ "${CREATE_COVERAGE}" -eq 1 ]] && COMMAND_ARRAY=(.Build/bin/phpunit -c Build/phpunit/FunctionalTests.xml --exclude-group not-"${DBMS}" --coverage-php=Build/coverage/${COVERAGE_LOG_FILE} "$@")
echo "Using driver: ${DATABASE_DRIVER}"
${CONTAINER_BIN} run --rm ${CI_PARAMS} --name mysql-func-${SUFFIX} --network ${NETWORK} -d -e MYSQL_ROOT_PASSWORD=funcp --tmpfs /var/lib/mysql/:rw,noexec,nosuid ${IMAGE_MYSQL} >/dev/null
waitFor mysql-func-${SUFFIX} 3306
Expand All @@ -615,13 +664,19 @@ case ${TEST_SUITE} in
SUITE_EXIT_CODE=$?
;;
postgres)
COVERAGE_LOG_FILE="functional-$(echo "core${CORE_VERSION}" | sed -e 's/\./-/')-$(echo "php${PHP_VERSION}" | sed -e 's/\.//')-$(echo "postgres${DBMS_VERSION}" | sed -e 's/\./_/')-$(echo "driver${DATABASE_DRIVER}" | sed -e 's/\.//').cov"
# shellcheck disable=SC2206 # Fighting shellcheck check moaning about things we need
[[ "${CREATE_COVERAGE}" -eq 1 ]] && COMMAND_ARRAY=(.Build/bin/phpunit -c Build/phpunit/FunctionalTests.xml --exclude-group not-"${DBMS}" --coverage-php=Build/coverage/${COVERAGE_LOG_FILE} "$@")
${CONTAINER_BIN} run --rm ${CI_PARAMS} --name postgres-func-${SUFFIX} --network ${NETWORK} -d -e POSTGRES_PASSWORD=funcp -e POSTGRES_USER=funcu --tmpfs /var/lib/postgresql/data:rw,noexec,nosuid ${IMAGE_POSTGRES} >/dev/null
waitFor postgres-func-${SUFFIX} 5432
CONTAINERPARAMS="-e typo3DatabaseDriver=pdo_pgsql -e typo3DatabaseName=bamboo -e typo3DatabaseUsername=funcu -e typo3DatabaseHost=postgres-func-${SUFFIX} -e typo3DatabasePassword=funcp"
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name functional-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${CONTAINERPARAMS} ${IMAGE_PHP} "${COMMAND_ARRAY[@]}"
SUITE_EXIT_CODE=$?
;;
sqlite)
COVERAGE_LOG_FILE="functional-$(echo "core${CORE_VERSION}" | sed -e 's/\./-/')-$(echo "php${PHP_VERSION}" | sed -e 's/\.//')-sqlite.cov"
# shellcheck disable=SC2206 # Fighting shellcheck check moaning about things we need
[[ "${CREATE_COVERAGE}" -eq 1 ]] && COMMAND_ARRAY=(.Build/bin/phpunit -c Build/phpunit/FunctionalTests.xml --exclude-group not-"${DBMS}" --coverage-php=Build/coverage/${COVERAGE_LOG_FILE} "$@")
CONTAINERPARAMS="-e typo3DatabaseDriver=pdo_sqlite"
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name functional-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${CONTAINERPARAMS} ${IMAGE_PHP} "${COMMAND_ARRAY[@]}"
SUITE_EXIT_CODE=$?
Expand Down Expand Up @@ -687,11 +742,17 @@ case ${TEST_SUITE} in
SUITE_EXIT_CODE=$?
;;
unit)
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name unit-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${IMAGE_PHP} .Build/bin/phpunit -c Build/phpunit/UnitTests.xml "$@"
COVERAGE_LOG_FILE="unit-$(echo "core${CORE_VERSION}" | sed -e 's/\./-/')-$(echo "php${PHP_VERSION}" | sed -e 's/\.//').cov"
[[ "${CREATE_COVERAGE}" -eq 1 ]] && mkdir -p Build/coverage Build/logs
[[ "${CREATE_COVERAGE}" -eq 1 ]] && PHPUNIT_COVERAGE_OPTION="--coverage-php=Build/coverage/${COVERAGE_LOG_FILE}" || PHPUNIT_COVERAGE_OPTION=""
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name unit-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${IMAGE_PHP} .Build/bin/phpunit -c Build/phpunit/UnitTests.xml ${PHPUNIT_COVERAGE_OPTION} "$@"
SUITE_EXIT_CODE=$?
;;
unitRandom)
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name unit-random-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${IMAGE_PHP} .Build/bin/phpunit -c Build/phpunit/UnitTests.xml --order-by=random ${PHPUNIT_RANDOM} "$@"
[[ "${CREATE_COVERAGE}" -eq 1 ]] && mkdir -p Build/coverage Build/logs
COVERAGE_LOG_FILE="unitrandom-$(echo "core${CORE_VERSION}" | sed -e 's/\./-/')-$(echo "php${PHP_VERSION}" | sed -e 's/\.//').cov"
[[ "${CREATE_COVERAGE}" -eq 1 ]] && PHPUNIT_COVERAGE_OPTION="--coverage-php=Build/coverage/${COVERAGE_LOG_FILE}" || PHPUNIT_COVERAGE_OPTION=""
${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name unit-random-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${IMAGE_PHP} .Build/bin/phpunit -c Build/phpunit/UnitTests.xml ${PHPUNIT_COVERAGE_OPTION} --order-by=random ${PHPUNIT_RANDOM} "$@"
SUITE_EXIT_CODE=$?
;;
update)
Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"phpstan/phpstan": "1.12.32 || 2.1.38",
"phpstan/phpstan-phpunit": "1.4.2 || 2.0.12",
"phpstan/phpstan-strict-rules": "1.6.2 || 2.0.8",
"phpunit/phpcov": "9.0.2",
"phpunit/phpunit": "10.5.63",
"rector/type-perfect": "1.0.0 || 2.1.2",
"saschaegerer/phpstan-typo3": "1.10.2 || 2.1.1",
Expand Down Expand Up @@ -123,15 +124,15 @@
"check:coverage:functional": [
"@check:tests:create-directories",
"@coverage:create-directories",
"phpunit -c Build/phpunit/FunctionalTests.xml --coverage-php=build/coverage/functional.cov"
"phpunit -c Build/phpunit/FunctionalTests.xml --coverage-php=Build/coverage/functional.cov"
],
"check:coverage:merge": [
"@coverage:create-directories",
"@php tools/phpcov merge --clover=build/logs/clover.xml build/coverage/"
"@php tools/phpcov merge --clover=Build/logs/clover.xml Build/coverage/"
],
"check:coverage:unit": [
"@coverage:create-directories",
"phpunit -c Build/phpunit/UnitTests.xml --coverage-php=build/coverage/unit.cov"
"phpunit -c Build/phpunit/UnitTests.xml --coverage-php=Build/coverage/unit.cov"
],
"check:json:lint": "find . ! -path '*/.cache/*' ! -path '*/.Build/*' ! -path '*/node_modules/*' -name '*.json' | xargs -r php .Build/bin/jsonlint -q",
"check:php": [
Expand Down Expand Up @@ -165,7 +166,7 @@
"check:typoscript:lint": "typoscript-lint -c Build/typoscript-lint/config.yml --ansi -n --fail-on-warnings -vvv Configuration/TypoScript Tests/Functional/Controller/Fixtures/TypoScript",
"check:xliff:lint": "php Build/Scripts/xliffLint.sh lint:xliff Resources/Private/Language",
"check:yaml:lint": "find . ! -path '*.Build/*' ! -path '*node_modules/*' \\( -name '*.yaml' -o -name '*.yml' \\) | xargs -r php ./.Build/bin/yaml-lint",
"coverage:create-directories": "mkdir -p build/coverage build/logs",
"coverage:create-directories": "mkdir -p Build/coverage Build/logs",
"docs:generate": "docker run --rm --pull always -v $(pwd):/project -it ghcr.io/typo3-documentation/render-guides:latest --config=Documentation",
"fix": [
"@fix:composer:normalize",
Expand Down
8 changes: 8 additions & 0 deletions phive.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<!-- /*
@todo phpcov is installed as composer dev dependency now to have it available for runTests.sh based
execution to avoid adding `phive` already to the image only possible with custom image builds.
As this is the only tool and also in a outdated version, verify this and remove phive based
tool setup. There is no use in pipelines anymore and this is unused beside local development
tools. Also check contribution/development documentation to remove mentioning the phive install
and requirement.
*/-->
<phar name="phpcov" version="^9.0.2" installed="9.0.2" location="./tools/phpcov" copy="false"/>
</phive>