name: Test suite on: workflow_call: inputs: all_variations: required: true type: boolean branch: required: true type: string permissions: contents: read jobs: LINUX_PPC64: if: ${{ fromJson(inputs.branch).jobs.LINUX_PPC64 }} name: LINUX_PPC64_ASAN_DEBUG_ZTS # This runs on a self-hosted runner; see https://wiki.php.net/systems/ci runs-on: [self-hosted, gentoo, ppc64] steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: System info run: | echo "::group::Show host CPU info" lscpu echo "::endgroup::" echo "::group::Show installed packages" cat /var/lib/portage/world echo "::endgroup::" - name: ./configure uses: ./.github/actions/configure-gentoo with: configurationParameters: >- CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function" CC=clang-17 CXX=clang++-17 --enable-debug --enable-zts skipSlow: false # FIXME: This should likely include slow extensions - name: make run: make -j$(/usr/bin/nproc) >/dev/null # Skip an install action for now - name: Tests uses: ./.github/actions/test-gentoo # There is no PPC JIT, so rip this out with: runTestsParameters: >- --asan -x - name: Extra tests uses: ./.github/actions/extra-tests ALPINE: if: ${{ fromJson(inputs.branch).jobs.ALPINE }} name: ALPINE_X64_ASAN_DEBUG_ZTS runs-on: ubuntu-24.04 container: image: 'alpine:3.22' steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: apk uses: ./.github/actions/apk - name: System info run: | echo "::group::Show host CPU info" lscpu echo "::endgroup::" echo "::group::Show installed package versions" apk list echo "::endgroup::" - name: ccache uses: ./.github/actions/ccache with: name: "${{ github.job }}" cc: clang-20 cxx: clang++-20 - name: ./configure uses: ./.github/actions/configure-alpine with: configurationParameters: >- CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function" --enable-debug --enable-zts skipSlow: true # FIXME: This should likely include slow extensions - name: make run: make -j$(/usr/bin/nproc) >/dev/null - name: make install uses: ./.github/actions/install-alpine - name: Test Tracing JIT uses: ./.github/actions/test-alpine with: enableOpcache: true jitType: tracing runTestsParameters: >- --asan -x - name: Extra tests uses: ./.github/actions/extra-tests LINUX_X64: if: ${{ fromJson(inputs.branch).jobs.LINUX_X64 }} services: mysql: image: mysql:8.4 ports: - 3306:3306 env: MYSQL_DATABASE: test MYSQL_ROOT_PASSWORD: root postgres: image: postgres env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: test firebird: image: jacobalberty/firebird ports: - 3050:3050 env: ISC_PASSWORD: test FIREBIRD_DATABASE: test.fdb FIREBIRD_USER: test FIREBIRD_PASSWORD: test strategy: fail-fast: false matrix: ${{ fromJson(inputs.branch).jobs.LINUX_X64.matrix }} name: "LINUX_X64${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }} steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: Create MSSQL container uses: ./.github/actions/setup-mssql - name: apt uses: ./.github/actions/apt-x64 with: asan: ${{ matrix.asan && 'true' || 'false' }} - name: System info run: | echo "::group::Show host CPU info" lscpu echo "::endgroup::" echo "::group::Show installed package versions" dpkg -l echo "::endgroup::" - name: Setup Caddy server uses: ./.github/actions/setup-caddy - name: ccache uses: ./.github/actions/ccache with: # This duplicates the "job.name" expression above because # GitHub has no way to query the job name (github.job is the # job id, not the job name) name: "LINUX_X64${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" - name: ./configure uses: ./.github/actions/configure-x64 with: configurationParameters: >- ${{ matrix.asan && 'CFLAGS="-fsanitize=undefined,address -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address"' || '' }} ${{ matrix.variation && 'CFLAGS="-DZEND_RC_DEBUG=1 -DPROFITABILITY_CHECKS=0 -DZEND_VERIFY_FUNC_INFO=1 -DZEND_VERIFY_TYPE_INFERENCE"' || '' }} ${{ (matrix.variation && fromJson(inputs.branch).jobs.LINUX_X64.config.variation_enable_zend_max_execution_timers) && '--enable-zend-max-execution-timers' || '' }} --${{ matrix.debug && 'enable' || 'disable' }}-debug ${{ matrix.debug && 'CXXFLAGS="-D_GLIBCXX_ASSERTIONS"' || '' }} --${{ matrix.zts && 'enable' || 'disable' }}-zts asan: ${{ matrix.asan && 'true' || 'false' }} skipSlow: ${{ (matrix.asan && !inputs.all_variations) && 'true' || 'false' }} - name: make run: make -j$(/usr/bin/nproc) >/dev/null - name: make install uses: ./.github/actions/install-linux - name: Setup if: ${{ !matrix.asan || inputs.all_variations }} uses: ./.github/actions/setup-x64 - name: Test if: ${{ inputs.all_variations || !matrix.asan }} uses: ./.github/actions/test-linux with: runTestsParameters: >- ${{ matrix.asan && '--asan' || '' }} ${{ matrix.repeat && '--repeat 2' || '' }} ${{ matrix.variation && '-d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0' || '' }} idleCpu: ${{ matrix.asan && 'true' || 'false' }} - name: Test Tracing JIT if: ${{ inputs.all_variations || matrix.asan }} uses: ./.github/actions/test-linux with: enableOpcache: true jitType: tracing runTestsParameters: >- ${{ matrix.asan && '--asan' || '' }} ${{ (matrix.asan && !inputs.all_variations) && '-x' || '' }} ${{ matrix.repeat && '--repeat 2' || '' }} ${{ matrix.variation && '-d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0' || '' }} - name: Test OpCache if: ${{ inputs.all_variations }} uses: ./.github/actions/test-linux with: enableOpcache: true runTestsParameters: >- ${{ matrix.asan && '--asan' || '' }} ${{ matrix.repeat && '--repeat 2' || '' }} ${{ matrix.variation && '-d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0' || '' }} - name: Test Function JIT # ASAN frequently timeouts. Each test run takes ~90 minutes, we can # avoid running into the 6 hour timeout by skipping the function JIT. if: ${{ !matrix.asan }} uses: ./.github/actions/test-linux with: enableOpcache: true jitType: function runTestsParameters: >- ${{ matrix.repeat && '--repeat 2' || '' }} ${{ matrix.variation && '-d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0' || '' }} - name: Extra tests uses: ./.github/actions/extra-tests - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files LINUX_X32: if: ${{ fromJson(inputs.branch).jobs.LINUX_X32 }} strategy: fail-fast: false matrix: ${{ fromJson(inputs.branch).jobs.LINUX_X32.matrix }} name: "LINUX_X32_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" runs-on: ubuntu-latest container: image: ubuntu:${{ fromJson(inputs.branch).config.ubuntu_version }} env: MYSQL_TEST_HOST: mysql PDO_MYSQL_TEST_DSN: mysql:host=mysql;dbname=test PDO_MYSQL_TEST_HOST: mysql PDO_FIREBIRD_TEST_DSN: firebird:dbname=firebird:test.fdb services: mysql: image: mysql:8.4 ports: - 3306:3306 env: MYSQL_DATABASE: test MYSQL_ROOT_PASSWORD: root firebird: image: jacobalberty/firebird ports: - 3050:3050 env: ISC_PASSWORD: test FIREBIRD_DATABASE: test.fdb FIREBIRD_USER: test FIREBIRD_PASSWORD: test steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: apt uses: ./.github/actions/apt-x32 - name: ccache uses: ./.github/actions/ccache with: name: "LINUX_X32_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" - name: System info run: | echo "::group::Show host CPU info" lscpu echo "::endgroup::" echo "::group::Show installed package versions" dpkg -l echo "::endgroup::" - name: ./configure uses: ./.github/actions/configure-x32 with: configurationParameters: >- --${{ matrix.debug && 'enable' || 'disable' }}-debug --${{ matrix.zts && 'enable' || 'disable' }}-zts - name: make run: make -j$(/usr/bin/nproc) >/dev/null - name: make install uses: ./.github/actions/install-linux-x32 - name: Test if: ${{ inputs.all_variations }} uses: ./.github/actions/test-linux - name: Test Tracing JIT uses: ./.github/actions/test-linux with: enableOpcache: true jitType: tracing - name: Test OpCache if: ${{ inputs.all_variations }} uses: ./.github/actions/test-linux with: enableOpcache: true - name: Test Function JIT if: ${{ inputs.all_variations }} uses: ./.github/actions/test-linux with: enableOpcache: true jitType: function - name: Extra tests uses: ./.github/actions/extra-tests MACOS: if: ${{ fromJson(inputs.branch).jobs.MACOS }} strategy: fail-fast: false matrix: ${{ fromJson(inputs.branch).jobs.MACOS.matrix }} name: "MACOS_${{ matrix.arch }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" runs-on: macos-${{ matrix.arch == 'X64' && '15-intel' || fromJson(inputs.branch).jobs.MACOS.config.arm64_version }} steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: Update clang timeout-minutes: 10 uses: ./.github/actions/macos-update-clang - name: brew timeout-minutes: 10 uses: ./.github/actions/brew - name: ccache uses: ./.github/actions/ccache with: name: "MACOS_${{ matrix.arch }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" - name: ./configure uses: ./.github/actions/configure-macos with: configurationParameters: >- --${{ matrix.debug && 'enable' || 'disable' }}-debug --${{ matrix.zts && 'enable' || 'disable' }}-zts - name: make run: |- export PATH="$(brew --prefix)/opt/bison/bin:$PATH" make -j$(sysctl -n hw.logicalcpu) >/dev/null - name: make install run: sudo make install - name: Test if: ${{ inputs.all_variations }} uses: ./.github/actions/test-macos - name: Test Tracing JIT if: ${{ matrix.arch == 'X64' || !matrix.zts }} uses: ./.github/actions/test-macos with: enableOpcache: true jitType: tracing - name: Test OpCache if: ${{ inputs.all_variations || (matrix.arch == 'ARM64' && matrix.zts) }} uses: ./.github/actions/test-macos with: enableOpcache: true - name: Test Function JIT if: ${{ inputs.all_variations && (matrix.arch == 'X64' || !matrix.zts) }} uses: ./.github/actions/test-macos with: enableOpcache: true jitType: function - name: Extra tests uses: ./.github/actions/extra-tests - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files COVERAGE: if: ${{ fromJson(inputs.branch).jobs.COVERAGE }} services: mysql: image: mysql:8.4 ports: - 3306:3306 env: MYSQL_DATABASE: test MYSQL_ROOT_PASSWORD: root postgres: image: postgres env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: test firebird: image: jacobalberty/firebird ports: - 3050:3050 env: ISC_PASSWORD: test FIREBIRD_DATABASE: test.fdb FIREBIRD_USER: test FIREBIRD_PASSWORD: test runs-on: ubuntu-24.04 steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: Create MSSQL container uses: ./.github/actions/setup-mssql - name: apt uses: ./.github/actions/apt-x64 - name: Install gcovr run: sudo -H pip install gcovr - name: ./configure uses: ./.github/actions/configure-x64 with: configurationParameters: --enable-debug --disable-zts --enable-gcov - name: make run: make -j$(/usr/bin/nproc) >/dev/null - name: make install uses: ./.github/actions/install-linux - name: Setup uses: ./.github/actions/setup-x64 # We only test with OpCache, the difference in coverage is negligible - name: Test OpCache uses: ./.github/actions/test-linux with: enableOpcache: true jitType: tracing - name: Generate coverage report if: ${{ !cancelled() }} run: make gcovr-xml - uses: codecov/codecov-action@v6 if: ${{ !cancelled() }} with: disable_search: true fail_ci_if_error: true files: gcovr.xml token: ${{ secrets.CODECOV_TOKEN }} verbose: true COMMUNITY: if: ${{ fromJson(inputs.branch).jobs.COMMUNITY }} strategy: fail-fast: false matrix: ${{ fromJson(inputs.branch).jobs.COMMUNITY.matrix }} name: "COMMUNITY_${{ matrix.type }}" runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }} env: ASAN_OPTIONS: exitcode=139 UBSAN_OPTIONS: print_stacktrace=1 USE_ZEND_ALLOC: 0 USE_TRACKED_ALLOC: 1 steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: apt uses: ./.github/actions/apt-x64 - name: ccache uses: ./.github/actions/ccache with: name: "COMMUNITY_${{ matrix.type }}" - name: ./configure uses: ./.github/actions/configure-x64 with: # CFLAGS removes O2, so we have to add it again... configurationParameters: >- --enable-zts ${{ matrix.type == 'asan' && '--enable-debug CFLAGS="-fsanitize=undefined,address -fno-sanitize-recover -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address"' || '' }} ${{ matrix.type == 'verify_type_inference' && 'CFLAGS="-DZEND_VERIFY_TYPE_INFERENCE -O2"' || '' }} - name: make run: make -j$(/usr/bin/nproc) >/dev/null - name: make install uses: ./.github/actions/install-linux - name: Setup run: | sudo service mysql start mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test" mysql -uroot -proot -e "SET GLOBAL local_infile = true" - name: Enable Opcache run: | echo memory_limit=-1 >> /etc/php.d/opcache.ini echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini echo opcache.enable=1 >> /etc/php.d/opcache.ini echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini echo opcache.memory_consumption=256M >> /etc/php.d/opcache.ini echo opcache.file_update_protection=0 >> /etc/php.d/opcache.ini echo opcache.interned_strings_buffer=64 >> /etc/php.d/opcache.ini echo opcache.max_accelerated_files=100000 >> /etc/php.d/opcache.ini - name: Enable JIT if: ${{ matrix.type != 'verify_type_inference' }} run: | echo opcache.jit=tracing >> /etc/php.d/opcache.ini echo opcache.jit_buffer_size=1G >> /etc/php.d/opcache.ini echo opcache.jit_max_root_traces=100000 >> /etc/php.d/opcache.ini echo opcache.jit_max_side_traces=100000 >> /etc/php.d/opcache.ini echo opcache.jit_max_exit_counters=100000 >> /etc/php.d/opcache.ini echo opcache.jit_hot_loop=1 >> /etc/php.d/opcache.ini echo opcache.jit_hot_func=1 >> /etc/php.d/opcache.ini echo opcache.jit_hot_return=1 >> /etc/php.d/opcache.ini echo opcache.jit_hot_side_exit=1 >> /etc/php.d/opcache.ini php -v - name: Test AMPHP if: ${{ !cancelled() }} run: | repositories="amp cache dns file http parallel parser pipeline process serialization socket sync websocket-client websocket-server" X=0 for repository in $repositories; do echo "::group::$repository" git clone "https://github.com/amphp/$repository.git" "amphp-$repository" --depth 1 cd "amphp-$repository" git rev-parse HEAD php /usr/bin/composer install --no-progress --ignore-platform-req=php+ EXIT_CODE=0 vendor/bin/phpunit || EXIT_CODE=$? echo -e "\n::endgroup::" if [ ${EXIT_CODE:-0} -gt 128 ]; then X=1; echo "Failed" fi cd .. done exit $X - name: Test Laravel if: ${{ !cancelled() }} run: | branch=${{ fromJson(inputs.branch).jobs.COMMUNITY.config.laravel_version }} git clone https://github.com/laravel/framework.git --depth=1 ${branch:+--branch="$branch"} cd framework git rev-parse HEAD php /usr/bin/composer install --no-progress --ignore-platform-req=php+ # Hack to disable a test that hangs php -r '$c = file_get_contents("tests/Filesystem/FilesystemTest.php"); $c = str_replace("public function testSharedGet()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n public function testSharedGet()", $c); file_put_contents("tests/Filesystem/FilesystemTest.php", $c);' php vendor/bin/phpunit --exclude-group skip || EXIT_CODE=$? if [ ${EXIT_CODE:-0} -gt 128 ]; then exit 1 fi - name: Test ReactPHP if: ${{ !cancelled() }} run: | repositories="async cache child-process datagram dns event-loop promise promise-stream promise-timer stream" X=0 for repository in $repositories; do echo "::group::$repository" git clone "https://github.com/reactphp/$repository.git" "reactphp-$repository" --depth 1 cd "reactphp-$repository" git rev-parse HEAD php /usr/bin/composer install --no-progress --ignore-platform-req=php+ EXIT_CODE=0 vendor/bin/phpunit || EXIT_CODE=$? echo -e "\n::endgroup::" if [ $[EXIT_CODE:-0} -gt 128 ]; then X=1; echo "Failed" fi cd .. done exit $X - name: Test Revolt PHP if: ${{ !cancelled() }} run: | git clone https://github.com/revoltphp/event-loop.git --depth=1 cd event-loop git rev-parse HEAD php /usr/bin/composer install --no-progress --ignore-platform-req=php+ vendor/bin/phpunit || EXIT_CODE=$? if [ ${EXIT_CODE:-0} -gt 128 ]; then exit 1 fi - name: Test Symfony if: ${{ !cancelled() }} run: | branch=${{ fromJson(inputs.branch).jobs.COMMUNITY.config.symfony_version }} git clone https://github.com/symfony/symfony.git --depth=1 ${branch:+--branch="$branch"} cd symfony git rev-parse HEAD php /usr/bin/composer install --no-progress --ignore-platform-req=php+ php ./phpunit install # Test causes a heap-buffer-overflow but I cannot reproduce it locally... php -r '$c = file_get_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php"); $c = str_replace("public function testSanitizeDeepNestedString()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n public function testSanitizeDeepNestedString()", $c); file_put_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php", $c);' # Buggy FFI test in Symfony, see https://github.com/symfony/symfony/issues/47668 php -r '$c = file_get_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php"); $c = str_replace("public function testCastNonTrailingCharPointer()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n public function testCastNonTrailingCharPointer()", $c); file_put_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php", $c);' export SYMFONY_DEPRECATIONS_HELPER=max[total]=999 X=0 for component in $(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -printf '%h\n'); do echo "::group::$component" EXIT_CODE=0 php ./phpunit $component --exclude-group tty --exclude-group benchmark --exclude-group intl-data --exclude-group transient --exclude-group skip || EXIT_CODE=$? echo -e "\n::endgroup::" if [ ${EXIT_CODE:-0} -gt 128 ]; then X=1; echo "Failed" fi done exit $X - name: Test PHPUnit if: ${{ !cancelled() }} run: | git clone https://github.com/sebastianbergmann/phpunit.git --branch=main --depth=1 cd phpunit git rev-parse HEAD php /usr/bin/composer install --no-progress --ignore-platform-req=php+ php ./phpunit || EXIT_CODE=$? if [ ${EXIT_CODE:-0} -gt 128 ]; then exit 1 fi - name: 'Symfony Preloading' # composer create-project will automatically pick the right Symfony version for us. if: ${{ !cancelled() }} run: | php /usr/bin/composer create-project symfony/symfony-demo symfony_demo --no-progress --ignore-platform-req=php+ cd symfony_demo git rev-parse HEAD sed -i 's/PHP_SAPI/"cli-server"/g' var/cache/dev/App_KernelDevDebugContainer.preload.php php -d opcache.preload=var/cache/dev/App_KernelDevDebugContainer.preload.php public/index.php - name: Test Wordpress if: ${{ !cancelled() }} run: | git clone https://github.com/WordPress/wordpress-develop.git wordpress --depth=1 cd wordpress git rev-parse HEAD php /usr/bin/composer install --no-progress --ignore-platform-req=php+ cp wp-tests-config-sample.php wp-tests-config.php sed -i 's/youremptytestdbnamehere/test/g' wp-tests-config.php sed -i 's/yourusernamehere/root/g' wp-tests-config.php sed -i 's/yourpasswordhere/root/g' wp-tests-config.php php vendor/bin/phpunit || EXIT_CODE=$? if [ $EXIT_CODE -gt 128 ]; then exit 1 fi OPCACHE_VARIATION: if: ${{ fromJson(inputs.branch).jobs.OPCACHE_VARIATION }} services: mysql: image: mysql:8.4 ports: - 3306:3306 env: MYSQL_DATABASE: test MYSQL_ROOT_PASSWORD: root postgres: image: postgres env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: test firebird: image: jacobalberty/firebird ports: - 3050:3050 env: ISC_PASSWORD: test FIREBIRD_DATABASE: test.fdb FIREBIRD_USER: test FIREBIRD_PASSWORD: test name: OPCACHE_VARIATION runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }} steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: Create MSSQL container uses: ./.github/actions/setup-mssql - name: apt uses: ./.github/actions/apt-x64 - name: ccache uses: ./.github/actions/ccache with: name: "${{ github.job }}" - name: ./configure uses: ./.github/actions/configure-x64 with: configurationParameters: >- --enable-debug --disable-zts - name: make run: make -j$(/usr/bin/nproc) >/dev/null - name: make install uses: ./.github/actions/install-linux - name: Setup uses: ./.github/actions/setup-x64 - name: Test File Cache (prime shm) uses: ./.github/actions/test-linux with: enableOpcache: true runTestsParameters: >- --file-cache-prime - name: Test File Cache (prime shm, use shm) uses: ./.github/actions/test-linux with: enableOpcache: true runTestsParameters: >- --file-cache-use - name: Test File Cache (prime shm, use file) uses: ./.github/actions/test-linux with: enableOpcache: true runTestsParameters: >- --file-cache-use -d opcache.file_cache_only=1 - name: Test File Cache Only (prime) uses: ./.github/actions/test-linux with: enableOpcache: true runTestsParameters: >- --file-cache-prime -d opcache.file_cache_only=1 - name: Test File Cache Only (use) uses: ./.github/actions/test-linux with: enableOpcache: true runTestsParameters: >- --file-cache-use -d opcache.file_cache_only=1 - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files MSAN: if: ${{ fromJson(inputs.branch).jobs.MSAN }} name: MSAN runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }} steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: apt uses: ./.github/actions/apt-x64 - name: ccache uses: ./.github/actions/ccache with: name: "${{ github.job }}" cc: clang cxx: clang++ - name: ./configure run: | export CFLAGS="-DZEND_TRACK_ARENA_ALLOC" ./buildconf --force # msan requires all used libraries to be instrumented, # so we should avoiding linking against anything but libc here ./configure \ --enable-debug \ --enable-zts \ --enable-option-checking=fatal \ --prefix=/usr \ --without-sqlite3 \ --without-pdo-sqlite \ --without-libxml \ --disable-dom \ --disable-simplexml \ --disable-xml \ --disable-xmlreader \ --disable-xmlwriter \ --without-pcre-jit \ --disable-opcache-jit \ --enable-phpdbg \ --enable-fpm \ --with-pdo-mysql=mysqlnd \ --with-mysqli=mysqlnd \ --disable-mysqlnd-compression-support \ --without-pear \ --enable-exif \ --enable-sysvsem \ --enable-sysvshm \ --enable-shmop \ --enable-pcntl \ --enable-mbstring \ --disable-mbregex \ --enable-sockets \ --enable-bcmath \ --enable-calendar \ --enable-ftp \ --enable-zend-test \ --enable-werror \ --enable-memory-sanitizer \ --with-config-file-path=/etc \ --with-config-file-scan-dir=/etc/php.d \ --enable-dl-test=shared - name: make run: make -j$(/usr/bin/nproc) >/dev/null - name: make install run: | sudo make install sudo mkdir -p /etc/php.d sudo chmod 777 /etc/php.d echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini echo pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/pdo_mysql.ini - name: Setup run: | set -x sudo service mysql start mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test" # Ensure local_infile tests can run. mysql -uroot -proot -e "SET GLOBAL local_infile = true" sudo locale-gen de_DE - name: Test uses: ./.github/actions/test-linux with: runTestsParameters: >- --msan - name: Test Opcache uses: ./.github/actions/test-linux with: enableOpcache: true runTestsParameters: >- --msan - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files LIBMYSQLCLIENT: if: ${{ fromJson(inputs.branch).jobs.LIBMYSQLCLIENT }} name: LIBMYSQLCLIENT runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }} steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: apt run: | sudo apt-get update -y | true sudo apt install bison re2c - name: Setup run: | sudo service mysql start mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test" # Ensure local_infile tests can run. mysql -uroot -proot -e "SET GLOBAL local_infile = true" - name: Build mysql-8.0 uses: ./.github/actions/build-libmysqlclient with: configurationParameters: '--enable-werror' libmysql: mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz - name: Test mysql-8.0 uses: ./.github/actions/test-libmysqlclient - name: Build mysql-8.4 uses: ./.github/actions/build-libmysqlclient with: configurationParameters: '--enable-werror' libmysql: mysql-8.4.0-linux-glibc2.28-x86_64.tar.xz - name: Test mysql-8.4 uses: ./.github/actions/test-libmysqlclient - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files WINDOWS: if: ${{ fromJson(inputs.branch).jobs.WINDOWS }} strategy: fail-fast: false matrix: ${{ fromJson(inputs.branch).jobs.WINDOWS.matrix }} name: "WINDOWS_${{ matrix.x64 && 'X64' || 'X86' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}${{ matrix.asan && '_ASAN' || ''}}${{ matrix.clang && '_CLANG' || ''}}" runs-on: ${{ fromJson(inputs.branch).jobs.WINDOWS.config.runs_on }} env: PHP_BUILD_CACHE_BASE_DIR: C:\build-cache PHP_BUILD_OBJ_DIR: C:\obj PHP_BUILD_CACHE_SDK_DIR: C:\build-cache\sdk PHP_BUILD_SDK_BRANCH: php-sdk-2.7.1 PHP_BUILD_CRT: ${{ fromJson(inputs.branch).jobs.WINDOWS.config.vs_crt_version }} PLATFORM: ${{ matrix.x64 && 'x64' || 'x86' }} THREAD_SAFE: "${{ matrix.zts && '1' || '0' }}" INTRINSICS: "${{ matrix.zts && 'AVX2' || '' }}" PARALLEL: -j2 OPCACHE: "${{ matrix.opcache && '1' || '0' }}" ASAN: "${{ matrix.asan && '1' || '0' }}" CLANG_TOOLSET: "${{ matrix.clang && '1' || '0' }}" steps: - name: git config run: git config --global core.autocrlf false && git config --global core.eol lf - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: Setup uses: ./.github/actions/setup-windows - name: Build run: .github/scripts/windows/build.bat - name: Test run: .github/scripts/windows/test.bat FREEBSD: if: ${{ fromJson(inputs.branch).jobs.FREEBSD }} strategy: fail-fast: false matrix: ${{ fromJson(inputs.branch).jobs.FREEBSD.matrix }} name: "FREEBSD_${{ matrix.zts && 'ZTS' || 'NTS' }}" runs-on: ubuntu-latest timeout-minutes: 50 steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} - name: FreeBSD uses: ./.github/actions/freebsd with: configurationParameters: >- --${{ matrix.zts && 'enable' || 'disable' }}-zts runExtraTests: true SOLARIS: if: ${{ fromJson(inputs.branch).jobs.SOLARIS }} name: "SOLARIS" runs-on: ubuntu-latest timeout-minutes: 50 steps: - name: git checkout uses: actions/checkout@v5 with: ref: ${{ fromJson(inputs.branch).ref }} - name: Solaris uses: ./.github/actions/solaris with: configurationParameters: --disable-zts runExtraTests: true BENCHMARKING: name: BENCHMARKING if: ${{ fromJson(inputs.branch).jobs.BENCHMARKING }} runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }} timeout-minutes: 50 steps: - name: git checkout uses: actions/checkout@v6 with: ref: ${{ fromJson(inputs.branch).ref }} fetch-depth: 0 # ASLR can cause a lot of noise due to missed sse opportunities for memcpy # and other operations, so we disable it during benchmarking. - name: Disable ASLR run: echo 0 | sudo tee /proc/sys/kernel/randomize_va_space - name: apt run: | set -x sudo apt-get update sudo apt-get install \ bison \ libgmp-dev \ libonig-dev \ libsqlite3-dev \ openssl \ re2c \ valgrind - name: ccache uses: ./.github/actions/ccache with: name: "${{ github.job }}" - name: ./configure run: | set -x ./buildconf --force ./configure \ --disable-debug \ --enable-mbstring \ --enable-option-checking=fatal \ --enable-sockets \ --enable-werror \ --prefix=/usr \ --with-config-file-scan-dir=/etc/php.d \ --with-gmp \ --with-mysqli=mysqlnd \ --with-openssl \ --with-pdo-sqlite \ --with-valgrind - name: make run: make -j$(/usr/bin/nproc) >/dev/null - name: make install run: | set -x sudo make install sudo mkdir -p /etc/php.d sudo chmod 777 /etc/php.d echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini ${{ !fromJson(inputs.branch).jobs.BENCHMARKING.config.integrated_opcache && 'echo zend_extension=opcache.so >> /etc/php.d/opcache.ini' || '' }} echo opcache.enable=1 >> /etc/php.d/opcache.ini echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini - name: Setup run: | git config --global user.name "Benchmark" git config --global user.email "benchmark@php.net" sudo service mysql start mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS wordpress" mysql -uroot -proot -e "CREATE USER 'wordpress'@'localhost' IDENTIFIED BY 'wordpress'; FLUSH PRIVILEGES;" mysql -uroot -proot -e "GRANT ALL PRIVILEGES ON *.* TO 'wordpress'@'localhost' WITH GRANT OPTION;" - name: git checkout benchmarking-data uses: actions/checkout@v6 with: repository: php/benchmarking-data ssh-key: ${{ secrets.BENCHMARKING_DATA_DEPLOY_KEY }} path: benchmark/repos/data - name: Benchmark run: php benchmark/benchmark.php true - name: Store result if: github.event_name == 'push' run: | set -x cd benchmark/repos/data git pull --autostash if [ -e ".git/MERGE_HEAD" ]; then echo "Merging, can't proceed" exit 1 fi git add . if git diff --cached --quiet; then exit 0 fi git commit -m "Add result for ${{ github.repository }}@${{ github.sha }}" git push - name: Show diff if: github.event_name == 'pull_request' run: |- set -x php benchmark/generate_diff.php \ ${{ github.sha }} \ ${{ github.event.pull_request.base.sha }} \ > $GITHUB_STEP_SUMMARY - uses: actions/upload-artifact@v6 with: name: profiles path: ${{ github.workspace }}/benchmark/profiles retention-days: 30