diff --git a/.github/actions/configure/action.yml b/.github/actions/configure/action.yml new file mode 100644 index 0000000000000..a8d8fafad2fbd --- /dev/null +++ b/.github/actions/configure/action.yml @@ -0,0 +1,118 @@ +name: ./configure +inputs: + configuration-parameters: + required: false +runs: + using: composite + steps: + - shell: bash + run: | + if [ "$ARCH" == "macos" ]; then + export PATH="/usr/local/opt/bison/bin:$PATH" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/openssl@1.1/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/krb5/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/libffi/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/libxml2/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/libxslt/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/zlib/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/icu4c/lib/pkgconfig" + fi + + ./buildconf --force + + configureParameters=( + --enable-bcmath + --enable-calendar + --enable-dba + --enable-exif + --enable-fpm + --enable-ftp + --enable-gd + --enable-intl + --enable-mbstring + --enable-option-checking=fatal + --enable-pcntl + --enable-shmop + --enable-soap + --enable-sockets + --enable-sysvmsg + --enable-sysvsem + --enable-sysvshm + #--enable-werror + --enable-xmlreader + --enable-zend-test + --prefix=${{ env.ARCH != 'macos' && '/usr' || '/usr/local' }} + --with-bz2${{ env.ARCH == 'macos' && '=/usr/local/opt/bzip2' || '' }} + --with-config-file-path=/etc + --with-config-file-scan-dir=/etc/php.d + --with-curl + --with-ffi + --with-freetype + --with-gettext${{ env.ARCH == 'macos' && '=/usr/local/opt/gettext' || '' }} + --with-gmp${{ env.ARCH == 'macos' && '=/usr/local/opt/gmp' || '' }} + --with-jpeg + --with-kerberos + --with-mhash + --with-mysqli=mysqlnd + --with-openssl + --with-pdo-mysql=mysqlnd + --with-pdo-pgsql${{ env.ARCH == 'macos' && '=/usr/local/opt/libpq' || '' }} + --with-pdo-sqlite + --with-pgsql${{ env.ARCH == 'macos' && '=/usr/local/opt/libpq' || '' }} + --with-pspell=${{ env.ARCH != 'macos' && '/usr' || '/usr/local/opt/aspell' }} + --with-readline${{ env.ARCH == 'macos' && '=/usr/local/opt/readline' || '' }} + --with-sodium + --with-tidy${{ env.ARCH == 'macos' && '=/usr/local/opt/tidyp' || '' }} + --with-webp + --with-xsl + --with-zip + --with-zlib + --without-pear + ${{ inputs.configuration-parameters }} + ) + + if [ "$ARCH" == "linux-x64" ]; then + configureParameters+=( + --enable-flatfile + --enable-inifile + --with-cdb + --with-enchant=/usr + --with-imap + --with-imap-ssl + --with-kerberos + --with-ldap + --with-ldap-sasl + --with-lmdb + --with-oci8=shared,instantclient,/opt/oracle/instantclient + --with-password-argon2 + --with-pdo-dblib + --with-pdo-firebird + --with-pdo-oci=shared,instantclient,/opt/oracle/instantclient + --with-pdo-odbc=unixODBC,/usr + --with-qdbm + --with-snmp + --with-tcadb + --with-unixODBC + ) + fi + + if [ "$ARCH" == "linux-i386" ]; then + configureParameters+=(--build=i686-pc-linux-gnu) + fi + + if [ "$ARCH" != "macos" ]; then + configureParameters+=( + --enable-phpdbg + --with-xpm + --with-zlib-dir=/usr + ) + fi + + if [ "$ARCH" == "macos" ]; then + configureParameters+=( + --with-iconv=/usr/local/opt/libiconv + --with-libxml + ) + fi + + ./configure "${configureParameters[@]}" diff --git a/.github/actions/deps/action.yml b/.github/actions/deps/action.yml new file mode 100644 index 0000000000000..2a4f9823ee46c --- /dev/null +++ b/.github/actions/deps/action.yml @@ -0,0 +1,141 @@ +name: Install dependencies +runs: + using: composite + steps: + - shell: bash + run: | + if [[ "$ARCH" == linux-* ]]; then + sudo DEBIAN_FRONTEND=noninteractive apt install -y \ + autoconf \ + bison \ + build-essential \ + pkg-config \ + re2c \ + locales \ + ldap-utils \ + openssl \ + slapd \ + language-pack-de \ + libgmp-dev \ + libicu-dev \ + libtidy-dev \ + libenchant-dev \ + libaspell-dev \ + libpspell-dev \ + libsasl2-dev \ + libxpm-dev \ + libzip-dev \ + libbz2-dev \ + libsqlite3-dev \ + libwebp-dev \ + libonig-dev \ + libkrb5-dev \ + libgssapi-krb5-2 \ + libcurl4-openssl-dev \ + libxml2-dev \ + libxslt1-dev \ + libpq-dev \ + libreadline-dev \ + libldap2-dev \ + libsodium-dev \ + libargon2-0-dev \ + libmm-dev \ + libsnmp-dev \ + postgresql \ + postgresql-contrib \ + snmpd \ + snmp-mibs-downloader \ + freetds-dev \ + unixodbc-dev \ + llvm \ + libc-client-dev \ + dovecot-core \ + dovecot-pop3d \ + dovecot-imapd \ + sendmail \ + firebird-dev \ + liblmdb-dev \ + libtokyocabinet-dev \ + libdb-dev \ + libqdbm-dev \ + libjpeg-dev \ + libpng-dev \ + libfreetype6-dev \ + unzip + mkdir /opt/oracle + wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip + unzip instantclient-basiclite-linuxx64.zip + wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip + unzip instantclient-sdk-linuxx64.zip + mv instantclient_*_* /opt/oracle/instantclient + # Interferes with libldap2 headers. + rm /opt/oracle/instantclient/sdk/include/ldap.h + fi + #if [ "$ARCH" == "linux-i386" ]; then + # sudo dpkg --add-architecture i386 + # sudo apt-get update -y | true + # sudo apt-get install -y gcc-multilib + # sudo apt-get install -y g++-multilib + # sudo apt-get purge -y libxml2 + # # TODO: Reenable postgresql + postgresql-contrib packages once they work again. + # sudo apt-get purge -y libpq5 + # sudo apt-get install -y libc6:i386 + # sudo apt-get install -y bison \ + # re2c \ + # locales \ + # language-pack-de \ + # libssl-dev:i386 \ + # zlib1g-dev:i386 \ + # libxml2-dev:i386 \ + # libgmp-dev:i386 \ + # libicu-dev:i386 \ + # libtidy-dev:i386 \ + # libaspell-dev:i386 \ + # libpspell-dev:i386 \ + # libsasl2-dev:i386 \ + # libxpm-dev:i386 \ + # libjpeg-dev:i386 \ + # libpng-dev:i386 \ + # libzip-dev:i386 \ + # libbz2-dev:i386 \ + # libsqlite3-dev:i386 \ + # libwebp-dev:i386 \ + # libonig-dev:i386 \ + # libkrb5-dev:i386 \ + # libgssapi-krb5-2:i386 \ + # libcurl4-openssl-dev:i386 \ + # libxml2-dev:i386 \ + # libxslt1-dev:i386 \ + # libpq-dev:i386 \ + # libreadline-dev:i386 \ + # libffi-dev:i386 \ + # libfreetype6-dev:i386 \ + # libsodium-dev:i386 + #fi + if [ "$ARCH" == "macos" ]; then + brew install pkg-config \ + autoconf \ + bison \ + re2c + brew install openssl@1.1 \ + krb5 \ + bzip2 \ + enchant \ + libffi \ + libpng \ + webp \ + freetype \ + intltool \ + icu4c \ + libiconv \ + zlib \ + t1lib \ + gd \ + libzip \ + gmp \ + tidyp \ + libxml2 \ + libxslt \ + postgresql + brew link icu4c gettext --force + fi diff --git a/.github/actions/install/action.yml b/.github/actions/install/action.yml new file mode 100644 index 0000000000000..9413ce195e191 --- /dev/null +++ b/.github/actions/install/action.yml @@ -0,0 +1,18 @@ +name: Install +runs: + using: composite + steps: + - shell: bash + run: | + if [ "$ARCH" != "macos" ]; then + set -e + sudo make install + sudo mkdir /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 + echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini + echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini + else + sudo make install + fi diff --git a/.github/actions/mssql/action.yml b/.github/actions/mssql/action.yml new file mode 100644 index 0000000000000..4a939a8b48758 --- /dev/null +++ b/.github/actions/mssql/action.yml @@ -0,0 +1,23 @@ +name: Create mssql container +runs: + using: composite + steps: + - shell: bash + run: | + apt-get update + apt-get -y install sudo + + # Install docker to when running inside a container + echo $DOCKER_CONTAINER + + apt-get update + apt install -y curl + curl https://gitlab.com/docker-32bit/ubuntu/raw/master/build-image.sh | bash + + docker run \ + -e "ACCEPT_EULA=Y" \ + -e "SA_PASSWORD=" \ + -p 1433:1433 \ + --name sql1 \ + -h sql1 \ + -d mcr.microsoft.com/mssql/server:2019-CU8-ubuntu-16.04 diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 0000000000000..227b105464d94 --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,34 @@ +name: Setup +runs: + using: composite + steps: + - shell: bash + run: | + set -e + sudo service mysql start + mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test" + + if [ "$ARCH" == "linux-x64" ]; then + sudo service postgresql start + sudo service slapd start + # Ensure local_infile tests can run. + mysql -uroot -proot -e "SET GLOBAL local_infile = true" + sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" + sudo -u postgres psql -c "CREATE DATABASE test;" + docker exec sql1 /opt/mssql-tools/bin/sqlcmd -S 127.0.0.1 -U SA -P "" -Q "create login pdo_test with password='password', check_policy=off; create user pdo_test for login pdo_test; grant alter, control to pdo_test;" + sudo locale-gen de_DE + + ./.github/scripts/setup-slapd.sh + + set -e + sudo cp ext/snmp/tests/snmpd.conf /etc/snmp + sudo cp ext/snmp/tests/bigtest /etc/snmp + sudo service snmpd restart + + set -e + sudo groupadd -g 5000 vmail + sudo useradd -m -d /var/vmail -s /bin/false -u 5000 -g vmail vmail + sudo cp ext/imap/tests/setup/dovecot.conf /etc/dovecot/dovecot.conf + sudo cp ext/imap/tests/setup/dovecotpass /etc/dovecot/dovecotpass + sudo service dovecot restart + fi diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml new file mode 100644 index 0000000000000..10112254b5b4b --- /dev/null +++ b/.github/actions/test/action.yml @@ -0,0 +1,32 @@ +name: Test +inputs: + run-tests-parameters: + default: '' + required: false +runs: + using: composite + steps: + - shell: bash + run: | + if [ "$ARCH" != "macos" ]; then + export MYSQL_TEST_USER=root + export MYSQL_TEST_PASSWD=root + export PDO_MYSQL_TEST_DSN="mysql:host=localhost;dbname=test" + export PDO_MYSQL_TEST_USER=root + export PDO_MYSQL_TEST_PASS=root + export PDO_DBLIB_TEST_DSN="dblib:host=127.0.0.1;dbname=master;version=7.0" + export PDO_DBLIB_TEST_USER="pdo_test" + export PDO_DBLIB_TEST_PASS="password" + fi + if [ "$ARCH" == "macos" ]; then + export CI_NO_IPV6=1 + fi + export REPORT_EXIT_STATUS=no + export SKIP_IO_CAPTURE_TESTS=1 + sapi/cli/php run-tests.php -P -q ${{ inputs.run-tests-parameters }} \ + -j$(${{ env.ARCH != 'macos' && '/usr/bin/nproc' || 'sysctl -n hw.logicalcpu' }}) \ + -g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP \ + --offline \ + --show-diff \ + --show-slow 1000 \ + --set-timeout 120 diff --git a/.github/generate_ci.php b/.github/generate_ci.php new file mode 100644 index 0000000000000..0d015848aa7f8 --- /dev/null +++ b/.github/generate_ci.php @@ -0,0 +1,174 @@ + 'Push', + 'on' => ['push' => ['paths-ignore' => [ + 'docs/*', + 'NEWS', + 'UPGRADING', + 'UPGRADING.INTERNALS', + 'README.md', + 'CONTRIBUTING.md', + 'CODING_STANDARDS.md', + ]]], + 'jobs' => [ + 'test' => [ + 'strategy' => [ + 'matrix' => [ + 'include' => [ + // [ + // 'arch' => ['name' => 'linux-x64', 'container' => null], + // 'debug' => true, + // 'zts' => false, + // ], + // [ + // 'arch' => ['name' => 'linux-x64', 'container' => null], + // 'debug' => false, + // 'zts' => true, + // ], + [ + 'arch' => ['name' => 'linux-i386', 'container' => 'i386/ubuntu:latest'], + 'debug' => true, + 'zts' => true, + ], + // [ + // 'arch' => ['name' => 'macos', 'container' => null], + // 'debug' => true, + // 'zts' => false, + // ], + ] + ], + 'fail-fast' => false, + ], + // Generate + 'name' => "\${{ matrix.arch.name }}-\${{ matrix.debug && 'debug' || 'release' }}-\${{ matrix.zts && 'zts' || 'nts' }}", + 'runs-on' => "\${{ startsWith(matrix.arch.name, 'linux-') && 'ubuntu-20.04' || 'macOS-10.15' }}", + 'container' => '${{ matrix.arch.container }}', + 'env' => [ + 'ARCH' => '${{ matrix.arch.name }}', + 'DOCKER_CONTAINER' => '${{ matrix.arch.container }}', + ], + 'steps' => [ + step_checkout(), + step_mssql(), + step_deps(), + step_configure(), + step_make(), + step_make_install(), + step_setup(), + ...step_tests(extended: false), + ], + ], + ], + ]; + + file_put_contents(__DIR__ . '/workflows/push.yml', GENERATION_WARNING . yaml_emit($result)); +} + +function step_checkout(?string $branch = null): array { + // actions/checkout@v2 doesn't work in docker containers which is used for i386 builds + // https://github.com/actions/checkout/issues/334 + $step = ['name' => 'git checkout', 'uses' => 'actions/checkout@v1', 'with' => ['fetch-depth' => 1]]; + if ($branch !== null) $step['with']['ref'] = $branch; + return $step; +} + +function step_mssql(): array { + return ['name' => 'Create mssql container', 'if' => "env.ARCH != 'macos'", 'uses' => './.github/actions/mssql']; +} + +function step_deps(): array { + return ['name' => 'Install dependencies', 'uses' => './.github/actions/deps']; +} + +function step_configure(): array { + return ['name' => './configure', 'uses' => './.github/actions/configure', 'with' => [ + 'configuration-parameters' => <<<'BASH' + --${{ inputs.debug && 'enable' || 'disable' }}-debug + --${{ inputs.zts && 'enable' || 'disable' }}-zts + BASH, + ]]; +} + +function step_make(): array { + return ['name' => 'make', 'run' => <<<'BASH' + if [ "$ARCH" == "macos" ]; then + export PATH="/usr/local/opt/bison/bin:$PATH" + fi + make -j$(${{ env.ARCH != 'macos' && '/usr/bin/nproc' || 'sysctl -n hw.logicalcpu' }}) >/dev/null + BASH]; +} + +function step_make_install(): array { + return ['name' => 'make install', 'uses' => './.github/actions/install']; +} + +function step_setup(): array { + return ['name' => 'Setup', 'if' => "env.ARCH != 'macos'", 'uses' => './.github/actions/setup']; +} + +function step_tests(bool $extended = false): array { + $protect_memory = "\${{ env.ARCH == 'macos' && '-d opcache.protect_memory=1' }}"; + + $steps = [ + step_test('Test'), + step_test('Tracing JIT', << $name, + 'uses' => './.github/actions/test', + ]; + if ($run_tests_parameters) { + $step['with']['run-tests-parameters'] = $run_tests_parameters; + } + return $step; +} + +generate(); diff --git a/.github/scripts/setup-slapd.sh b/.github/scripts/setup-slapd.sh new file mode 100755 index 0000000000000..7ea3cb33b3d0e --- /dev/null +++ b/.github/scripts/setup-slapd.sh @@ -0,0 +1,185 @@ +#!/bin/sh +set -ev + +# Create TLS certificate +sudo mkdir -p /etc/ldap/ssl + +alt_names() { + ( + ( + (hostname && hostname -a && hostname -A && hostname -f) | + xargs -n 1 | + sort -u | + sed -e 's/\(\S\+\)/DNS:\1/g' + ) && ( + (hostname -i && hostname -I && echo "127.0.0.1 ::1") | + xargs -n 1 | + sort -u | + sed -e 's/\(\S\+\)/IP:\1/g' + ) + ) | paste -d, -s +} + +sudo openssl req -newkey rsa:4096 -x509 -nodes -days 3650 \ + -out /etc/ldap/ssl/server.crt -keyout /etc/ldap/ssl/server.key \ + -subj "/C=US/ST=Arizona/L=Localhost/O=localhost/CN=localhost" \ + -addext "subjectAltName = `alt_names`" + +sudo chown -R openldap:openldap /etc/ldap/ssl + +# Display the TLS certificate (should be world readable) +openssl x509 -noout -text -in /etc/ldap/ssl/server.crt + +# Point to the certificate generated +if ! grep -q 'TLS_CACERT \/etc\/ldap\/ssl\/server.crt' /etc/ldap/ldap.conf; then + sudo sed -e 's|^\s*TLS_CACERT|# TLS_CACERT|' -i /etc/ldap/ldap.conf + echo 'TLS_CACERT /etc/ldap/ssl/server.crt' | sudo tee -a /etc/ldap/ldap.conf +fi + +# Configure LDAP protocols to serve. +sudo sed -e 's|^\s*SLAPD_SERVICES\s*=.*$|SLAPD_SERVICES="ldap:/// ldaps:/// ldapi:///"|' -i /etc/default/slapd + +# Configure LDAP database. +DBDN=`sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config '(&(olcRootDN=*)(olcSuffix=*))' dn | grep -i '^dn:' | sed -e 's/^dn:\s*//'`; + +sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/ppolicy.ldif + +sudo service slapd restart + +sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// << EOF +dn: $DBDN +changetype: modify +replace: olcSuffix +olcSuffix: dc=my-domain,dc=com +- +replace: olcRootDN +olcRootDN: cn=Manager,dc=my-domain,dc=com +- +replace: olcRootPW +olcRootPW: secret + +dn: cn=config +changetype: modify +add: olcTLSCACertificateFile +olcTLSCACertificateFile: /etc/ldap/ssl/server.crt +- +add: olcTLSCertificateFile +olcTLSCertificateFile: /etc/ldap/ssl/server.crt +- +add: olcTLSCertificateKeyFile +olcTLSCertificateKeyFile: /etc/ldap/ssl/server.key +- +add: olcTLSVerifyClient +olcTLSVerifyClient: never +- +add: olcAuthzRegexp +olcAuthzRegexp: uid=usera,cn=digest-md5,cn=auth cn=usera,dc=my-domain,dc=com +- +replace: olcLogLevel +olcLogLevel: -1 + +dn: cn=module{0},cn=config +changetype: modify +add: olcModuleLoad +olcModuleLoad: sssvlv +- +add: olcModuleLoad +olcModuleLoad: ppolicy +- +add: olcModuleLoad +olcModuleLoad: dds +EOF + +sudo service slapd restart + +sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// << EOF +dn: olcOverlay=sssvlv,$DBDN +objectClass: olcOverlayConfig +objectClass: olcSssVlvConfig +olcOverlay: sssvlv +olcSssVlvMax: 10 +olcSssVlvMaxKeys: 5 + +dn: olcOverlay=ppolicy,$DBDN +objectClass: olcOverlayConfig +objectClass: olcPPolicyConfig +olcOverlay: ppolicy +### This would clutter our DIT and make tests to fail, while ppolicy does not +### seem to work as we expect (it does not seem to provide expected controls) +## olcPPolicyDefault: cn=default,ou=pwpolicies,dc=my-domain,dc=com +## olcPPolicyHashCleartext: FALSE +## olcPPolicyUseLockout: TRUE + +dn: olcOverlay=dds,$DBDN +objectClass: olcOverlayConfig +objectClass: olcDdsConfig +olcOverlay: dds +EOF + +sudo service slapd restart + +sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// << EOF +dn: $DBDN +changetype: modify +add: olcDbIndex +olcDbIndex: entryExpireTimestamp eq +EOF + +sudo service slapd restart + +ldapadd -H ldapi:/// -D cn=Manager,dc=my-domain,dc=com -w secret </dev/null + - name: make install + uses: ./.github/actions/install + - name: Setup + if: env.ARCH != 'macos' + uses: ./.github/actions/setup + - name: Test + uses: ./.github/actions/test + - name: Tracing JIT + uses: ./.github/actions/test + with: + run-tests-parameters: |2- + -d zend_extension=opcache.so \ + -d opcache.jit_buffer_size=16M \ + ${{ env.ARCH == 'macos' && '-d opcache.protect_memory=1' }} +...