From 1ec221960de84166ed8aa941abbc8fa9b34fbf9c Mon Sep 17 00:00:00 2001 From: Pawel Filipczak Date: Mon, 29 Jan 2024 13:38:06 +0100 Subject: [PATCH] Enable support for PHP 8.3 (#1097) (#1127) --- .ci/Makefile | 8 ++- .ci/packer_cache.sh | 3 +- .ci/shared.sh | 22 +++++--- .github/workflows/loop.yml | 1 + .github/workflows/phpt.yml | 1 + .github/workflows/test.yml | 2 + Dockerfile | 3 +- agent/native/CMakeLists.txt | 3 +- .../building/dependencies/php83/conandata.yml | 33 +++++++++++ .../building/dependencies/php83/conanfile.py | 56 +++++++++++++++++++ agent/native/ext/AST_debug.cpp | 7 ++- agent/native/loader/code/phpdetection.cpp | 2 +- composer.json | 2 +- docs/supported-technologies.asciidoc | 2 +- packaging/Makefile | 9 ++- packaging/post-install.sh | 5 +- packaging/test/docker-compose.yml | 38 +++++++++++++ packaging/test/ubuntu/Dockerfile | 4 +- .../GenerateUnpackScriptsTest.php | 2 +- 19 files changed, 180 insertions(+), 23 deletions(-) create mode 100644 agent/native/building/dependencies/php83/conandata.yml create mode 100644 agent/native/building/dependencies/php83/conanfile.py diff --git a/.ci/Makefile b/.ci/Makefile index d7475fc2f..588ede8ea 100644 --- a/.ci/Makefile +++ b/.ci/Makefile @@ -11,6 +11,7 @@ MAKEFLAGS += --no-print-directory IMAGE := test-php PHP_VERSION ?= 7.2 DOCKERFILE ?= Dockerfile +SEL_DISTRO=buster LOOPS ?= 50 SUFFIX := ifeq ($(DOCKERFILE), Dockerfile.alpine) @@ -18,6 +19,11 @@ ifeq ($(DOCKERFILE), Dockerfile.alpine) SUFFIX := -alpine endif +ifneq ($(PHP_VERSION), 7.2) + SEL_DISTRO := bullseye +endif + + CONAN_USER_HOME:=/tmp/conan_user_home MAP_CONAN_HOME_TO_DOCKER_HOST_CMD_LINE_ARG:= ifdef MAP_CONAN_HOME_TO_DOCKER_HOST @@ -37,7 +43,7 @@ help: ## Display this help text prepare: ## Build docker image for building and testing the project @echo "::group::$@" # Helping to group logs in GitHub actions docker build \ - --build-arg PHP_VERSION=${PHP_VERSION} \ + --build-arg PHP_VERSION=${PHP_VERSION} --build-arg SEL_DISTRO=${SEL_DISTRO}\ --tag $(IMAGE):${PHP_VERSION}$(SUFFIX) \ -f ${DOCKERFILE} . @echo "::endgroup::" diff --git a/.ci/packer_cache.sh b/.ci/packer_cache.sh index 9d1bb18e6..12b96fead 100755 --- a/.ci/packer_cache.sh +++ b/.ci/packer_cache.sh @@ -14,6 +14,7 @@ php:7.4-fpm php:8.0-fpm php:8.1-fpm php:8.2-fpm +php:8.3-fpm ruby:2.7.1-alpine3.12 ubuntu:20.04 " @@ -25,7 +26,7 @@ if [ -x "$(command -v docker)" ]; then # Make sure list of PHP versions supported by the Elastic APM PHP Agent is in sync. # See the comment in .ci/shared.sh - for version in 7.2 7.3 7.4 8.0 8.1 8.2 + for version in 7.2 7.3 7.4 8.0 8.1 8.2 8.3 do PHP_VERSION=${version} make -f .ci/Makefile prepare || true DOCKERFILE=Dockerfile.alpine PHP_VERSION=${version} make -f .ci/Makefile prepare || true diff --git a/.ci/shared.sh b/.ci/shared.sh index 0c6ff0e46..63963943e 100644 --- a/.ci/shared.sh +++ b/.ci/shared.sh @@ -3,16 +3,20 @@ set -e # # Make sure list of PHP versions supported by the Elastic APM PHP Agent is in sync -# 1) .ci/shared.sh (this file; update ELASTIC_APM_PHP_TESTS_SUPPORTED_PHP_VERSIONS below) -# 2) .ci/Jenkinsfile (the list of PHP versions might appear more than once - search for "list of PHP versions") -# 3) .github/workflows/test.yml (update jobs -> test -> strategy -> matrix -> php-version) -# 4) .github/workflows/loop.yml (update jobs -> loop-matrix -> strategy -> matrix -> php-version) -# 5) .ci/packer_cache.sh (the list of PHP versions might appear more than once - search for "list of PHP versions") -# 6) packaging/post-install.sh (the list of PHP versions might appear more than once - search for "list of PHP versions") -# 7) composer.json -# 8) tests/ElasticApmTests/ComponentTests/GenerateUnpackScriptsTest.php (search for "list of PHP versions") +# *) .ci/shared.sh (this file; update ELASTIC_APM_PHP_TESTS_SUPPORTED_PHP_VERSIONS below) +# *) .github/workflows/test.yml (update jobs -> test -> strategy -> matrix -> php-version) +# *) .github/workflows/phpt.yml +# *) .github/workflows/loop.yml (update jobs -> loop-matrix -> strategy -> matrix -> php-version) +# *) .ci/packer_cache.sh (the list of PHP versions might appear more than once - search for "list of PHP versions") +# *) packaging/post-install.sh (the list of PHP versions might appear more than once - search for "list of PHP versions") +# *) composer.json +# *) tests/ElasticApmTests/ComponentTests/GenerateUnpackScriptsTest.php (search for "list of PHP versions") +# *) CMakeList.txt and conan dependencies +# *) phpdetection.cpp in agent loader +# *) docker-compose.yml in packaging/test + # -export ELASTIC_APM_PHP_TESTS_SUPPORTED_PHP_VERSIONS=(7.2 7.3 7.4 8.0 8.1 8.2) +export ELASTIC_APM_PHP_TESTS_SUPPORTED_PHP_VERSIONS=(7.2 7.3 7.4 8.0 8.1 8.2 8.3) export ELASTIC_APM_PHP_TESTS_SUPPORTED_LINUX_NATIVE_PACKAGE_TYPES=(apk deb rpm) export ELASTIC_APM_PHP_TESTS_SUPPORTED_LINUX_PACKAGE_TYPES=("${ELASTIC_APM_PHP_TESTS_SUPPORTED_LINUX_NATIVE_PACKAGE_TYPES[@]}" tar) diff --git a/.github/workflows/loop.yml b/.github/workflows/loop.yml index c2bfb221e..a5b7169d8 100644 --- a/.github/workflows/loop.yml +++ b/.github/workflows/loop.yml @@ -22,6 +22,7 @@ jobs: - "8.0" - "8.1" - "8.2" + - "8.3" dockerfile: - "Dockerfile" - "Dockerfile.alpine" diff --git a/.github/workflows/phpt.yml b/.github/workflows/phpt.yml index aca6b26f9..808d6bb27 100644 --- a/.github/workflows/phpt.yml +++ b/.github/workflows/phpt.yml @@ -27,6 +27,7 @@ jobs: - "8.0" - "8.1" - "8.2" + - "8.3" steps: # - uses: actions/checkout@v4 # - name: Fetch and extract latest release of apm-agent-php diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d591f705b..2132bcaac 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,6 +43,7 @@ jobs: - "8.0" - "8.1" - "8.2" + - "8.3" arch: - "linux-x86-64" - "linuxmusl-x86-64" @@ -76,6 +77,7 @@ jobs: - "8.0" - "8.1" - "8.2" + - "8.3" dockerfile: - "Dockerfile" - "Dockerfile.alpine" diff --git a/Dockerfile b/Dockerfile index a7f193e20..552d00d54 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,6 @@ ARG PHP_VERSION=7.2 -FROM php:${PHP_VERSION}-fpm-buster +ARG SEL_DISTRO=buster +FROM php:${PHP_VERSION}-fpm-${SEL_DISTRO} RUN apt-get -qq update \ && apt-get -qq -y --no-install-recommends install \ diff --git a/agent/native/CMakeLists.txt b/agent/native/CMakeLists.txt index c4b66fb5e..2758c03c8 100644 --- a/agent/native/CMakeLists.txt +++ b/agent/native/CMakeLists.txt @@ -43,7 +43,7 @@ include(elastic_conan_debugsymbols) # Install project dependencies -set(_supported_php_versions 72 73 74 80 81 82) +set(_supported_php_versions 72 73 74 80 81 82 83) function(get_php_api_from_release php_version ret_val) block(SCOPE_FOR VARIABLES) @@ -53,6 +53,7 @@ function(get_php_api_from_release php_version ret_val) set(_php_release_80 20200930) set(_php_release_81 20210902) set(_php_release_82 20220829) + set(_php_release_83 20230831) set(${ret_val} ${_php_release_${php_version}}) return(PROPAGATE ${ret_val}) diff --git a/agent/native/building/dependencies/php83/conandata.yml b/agent/native/building/dependencies/php83/conandata.yml new file mode 100644 index 000000000..01b31fd3a --- /dev/null +++ b/agent/native/building/dependencies/php83/conandata.yml @@ -0,0 +1,33 @@ +name: "php-headers-83" +version: "1.0" +php_source_version: 8.3.2 + +sources: + 7.2.34: + linux: + - url: "https://www.php.net/distributions/php-7.2.34.tar.gz" + contentsRoot: "php-7.2.34" + 7.3.33: + linux: + - url: "https://www.php.net/distributions/php-7.3.33.tar.gz" + contentsRoot: "php-7.3.33" + 7.4.33: + linux: + - url: "https://www.php.net/distributions/php-7.4.33.tar.gz" + contentsRoot: "php-7.4.33" + 8.0.28: + linux: + - url: "https://www.php.net/distributions/php-8.0.28.tar.gz" + contentsRoot: "php-8.0.28" + 8.1.18: + linux: + - url: "https://www.php.net/distributions/php-8.1.18.tar.gz" + contentsRoot: "php-8.1.18" + 8.2.5: + linux: + - url: "https://www.php.net/distributions/php-8.2.5.tar.gz" + contentsRoot: "php-8.2.5" + 8.3.2: + linux: + - url: "https://www.php.net/distributions/php-8.3.2.tar.gz" + contentsRoot: "php-8.3.2" diff --git a/agent/native/building/dependencies/php83/conanfile.py b/agent/native/building/dependencies/php83/conanfile.py new file mode 100644 index 000000000..2f1ec5fcc --- /dev/null +++ b/agent/native/building/dependencies/php83/conanfile.py @@ -0,0 +1,56 @@ +import os +import shutil + +from conans import tools, ConanFile, AutoToolsBuildEnvironment + +class PhpHeadersForPHP81Conan(ConanFile): + description = "PHP headers package required to build Elastic APM agent without additional PHP dependencies" + license = "The PHP License, version 3.01" + homepage = "https://php.net/" + url = "https://php.net/" + author = "pawel.filipczak@elastic.co" + + settings = "os", "compiler", "build_type", "arch" + platform = "linux" + + def init(self): + self.name = self.conan_data["name"] + self.version = self.conan_data["version"] # version of the package + self.php_version = self.conan_data["php_source_version"] # version of the PHP to build + self.source_temp_dir = "php-src" + + def requirements(self): + self.requires("libxml2/2.9.9") + self.requires("sqlite3/3.29.0") + + def source(self): + for source in self.conan_data["sources"][self.php_version][self.platform]: + + if "contentsRoot" in source: + # small hack - it can't contain custom fields, so we're removing it from source (got an unexpected keyword argument) + contentRoot = source["contentsRoot"] + del source["contentsRoot"] + tools.get(**source) + os.rename(contentRoot, self.source_temp_dir) + else: + self.output.error("Could not find 'contentsRoot' in conandata.yml") + raise Exception("Could not find 'contentsRoot' in conandata.yml") + + def build(self): + with tools.chdir(os.path.join(self.source_folder, self.source_temp_dir)): + buildEnv = AutoToolsBuildEnvironment(self) + envVariables = buildEnv.vars + envVariables['ac_cv_php_xml2_config_path'] = os.path.join(self.deps_cpp_info["libxml2"].rootpath, "bin/xml2-config") + envVariables['LIBXML_LIBS'] = os.path.join(self.deps_cpp_info["libxml2"].rootpath, self.deps_cpp_info["libxml2"].libdirs[0]) + envVariables['LIBXML_CFLAGS'] = "-I{}".format(os.path.join(self.deps_cpp_info["libxml2"].rootpath, self.deps_cpp_info["libxml2"].includedirs[0])) + envVariables['SQLITE_LIBS'] = os.path.join(self.deps_cpp_info["sqlite3"].rootpath, self.deps_cpp_info["sqlite3"].libdirs[0]) + envVariables['SQLITE_CFLAGS'] = "-I{}".format(os.path.join(self.deps_cpp_info["sqlite3"].rootpath, self.deps_cpp_info["sqlite3"].includedirs[0])) + self.run("./buildconf --force") + buildEnv.configure(args=[""], vars=envVariables, build=False, host=False) + + def package(self): + source = os.path.join(self.source_folder, self.source_temp_dir) + self.copy("*.h", src=source, dst='include', keep_path=True) + + def package_id(self): + del self.info.settings.compiler.version diff --git a/agent/native/ext/AST_debug.cpp b/agent/native/ext/AST_debug.cpp index 78cbcbc28..4794d91cd 100644 --- a/agent/native/ext/AST_debug.cpp +++ b/agent/native/ext/AST_debug.cpp @@ -75,7 +75,7 @@ String zendAstKindToString( zend_ast_kind kind ) return (#enumMember) \ /**/ - // Up to date with PHP v8.2.3 + // Up to date with PHP v8.3.2 switch ( kind ) { /** @@ -224,6 +224,11 @@ String zendAstKindToString( zend_ast_kind kind ) ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_TYPE_INTERSECTION ); #endif + + #if PHP_VERSION_ID >= ELASTIC_APM_BUILD_PHP_VERSION_ID( 8, 3, 0 ) /* if PHP version from 8.3.0 */ + ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_MODIFIER_LIST ); + #endif + default: return NULL; } diff --git a/agent/native/loader/code/phpdetection.cpp b/agent/native/loader/code/phpdetection.cpp index b51f87687..5f618308d 100644 --- a/agent/native/loader/code/phpdetection.cpp +++ b/agent/native/loader/code/phpdetection.cpp @@ -59,7 +59,7 @@ std::tuple getZendModuleApiVersion(std::string_view constexpr size_t knownVersionsCount = 16; constexpr std::array, knownVersionsCount> knownPhpVersions {{ - {"4.3"sv, 20230831, false}, // PHP 8.3 + {"4.3"sv, 20230831, true}, // PHP 8.3 {"4.2"sv, 20220829, true}, // PHP 8.2 {"4.1"sv, 20210902, true}, // PHP 8.1 {"4.0"sv, 20200930, true}, // PHP 8.0 diff --git a/composer.json b/composer.json index c42409c1c..8ca7db8c5 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ { "name": "Sergey Kleyman" } ], "require": { - "php": "^7.2||8.0.*||8.1.*||8.2.*", + "php": "^7.2||8.0.*||8.1.*||8.2.*||8.3.*", "ext-json": "*", "ext-pcntl": "*", "psr/log": "^1.0" diff --git a/docs/supported-technologies.asciidoc b/docs/supported-technologies.asciidoc index 903b88ca7..20a4c54a3 100644 --- a/docs/supported-technologies.asciidoc +++ b/docs/supported-technologies.asciidoc @@ -20,7 +20,7 @@ The agent supports Linux operating system. [[supported-php-versions]] === PHP versions -The agent supports PHP versions 7.2-8.2. +The agent supports PHP versions 7.2-8.3. [float] [[unsupported-php-sapis]] diff --git a/packaging/Makefile b/packaging/Makefile index d71784f2c..fa524660c 100644 --- a/packaging/Makefile +++ b/packaging/Makefile @@ -6,11 +6,16 @@ VERSION?=$(shell grep 'VERSION' ../agent/php/ElasticApm/ElasticApm.php | cut -d= OUTPUT:=build/packages PHP_AGENT_DIR:=/opt/elastic/apm-agent-php PHP_VERSION?=7.2 +SEL_DISTRO?=buster GIT_SHA?=$(shell git rev-parse HEAD || echo "unknown") RELEASE_VERSION?= GITHUB_RELEASES_URL=https://github.com/elastic/apm-agent-php/releases/download export FPM_FLAGS= +ifneq ($(PHP_VERSION), 7.2) + SEL_DISTRO := bullseye +endif + .PHONY: help .DEFAULT_GOAL := help help: ## Display this help text @@ -127,7 +132,7 @@ prepare-deb-fpm: ## Build the docker image for the deb smoke tests for fpm prepare-deb: ## Build the docker image for the deb smoke tests @echo "::group::$@" # Helping to group logs in GitHub actions cd $(PWD)/packaging/test/ubuntu ;\ - docker build --build-arg PHP_VERSION=$(PHP_VERSION) -t $@ . || exit 1 ;\ + docker build --build-arg PHP_VERSION=$(PHP_VERSION) --build-arg SEL_DISTRO=$(SEL_DISTRO) -t $@ . || exit 1 ;\ cd - @echo "::endgroup::" @@ -135,7 +140,7 @@ prepare-deb: ## Build the docker image for the deb smoke tests prepare-tar: ## Build the docker image for the tar smoke tests @echo "::group::$@" # Helping to group logs in GitHub actions cd $(PWD)/packaging/test/ubuntu ;\ - docker build --build-arg PHP_VERSION=$(PHP_VERSION) -t $@ . || exit 1 ;\ + docker build --build-arg PHP_VERSION=$(PHP_VERSION) --build-arg SEL_DISTRO=$(SEL_DISTRO) -t $@ . || exit 1 ;\ cd - @echo "::endgroup::" diff --git a/packaging/post-install.sh b/packaging/post-install.sh index 486f06178..c40f5da2f 100755 --- a/packaging/post-install.sh +++ b/packaging/post-install.sh @@ -204,11 +204,12 @@ function is_php_supported() { [ "${PHP_MAJOR_MINOR}" == "7.4" ] || \ [ "${PHP_MAJOR_MINOR}" == "8.0" ] || \ [ "${PHP_MAJOR_MINOR}" == "8.1" ] || \ - [ "${PHP_MAJOR_MINOR}" == "8.2" ] + [ "${PHP_MAJOR_MINOR}" == "8.2" ] || \ + [ "${PHP_MAJOR_MINOR}" == "8.3" ] then return 0 else - echo 'Failed. The supported PHP versions are 7.2-8.2.' + echo 'Failed. The supported PHP versions are 7.2-8.3.' return 1 fi } diff --git a/packaging/test/docker-compose.yml b/packaging/test/docker-compose.yml index d14a9fe6a..b94d35435 100644 --- a/packaging/test/docker-compose.yml +++ b/packaging/test/docker-compose.yml @@ -1,5 +1,13 @@ version: "3" services: + deb-fpm-php83: + image: elasticobservability/apm-agent-php-dev:packages-test-deb-fpm-php-8.3-0.0.1 + build: + context: ubuntu + dockerfile: fpm/Dockerfile + args: + - PHP_VERSION=8.3 + - SEL_DISTRO=bullseye deb-fpm-php82: image: elasticobservability/apm-agent-php-dev:packages-test-deb-fpm-php-8.2-0.0.1 build: @@ -46,6 +54,14 @@ services: + deb-apache-php83: + image: elasticobservability/apm-agent-php-dev:packages-test-deb-apache-php-8.3-0.0.1 + build: + context: ubuntu + dockerfile: apache/Dockerfile + args: + - PHP_VERSION=8.3 + - SEL_DISTRO=bullseye deb-apache-php82: image: elasticobservability/apm-agent-php-dev:packages-test-deb-apache-php-8.2-0.0.1 build: @@ -90,6 +106,14 @@ services: - PHP_VERSION=7.2 + deb-php83: + image: elasticobservability/apm-agent-php-dev:packages-test-deb-php-8.3-0.0.1 + build: + context: ubuntu + dockerfile: Dockerfile + args: + - PHP_VERSION=8.3 + - SEL_DISTRO=bullseye deb-php82: image: elasticobservability/apm-agent-php-dev:packages-test-deb-php-8.2-0.0.1 build: @@ -133,6 +157,13 @@ services: args: - PHP_VERSION=7.2 + rpm-php83: + image: elasticobservability/apm-agent-php-dev:packages-test-rpm-php-8.3-0.0.1 + build: + context: centos + dockerfile: Dockerfile + args: + - PHP_VERSION=8.3 rpm-php82: image: elasticobservability/apm-agent-php-dev:packages-test-rpm-php-8.2-0.0.1 build: @@ -176,6 +207,13 @@ services: args: - PHP_VERSION=7.2 + apk-php83: + image: elasticobservability/apm-agent-php-dev:packages-test-apk-php-8.3-0.0.1 + build: + context: alpine + dockerfile: Dockerfile + args: + - PHP_VERSION=8.3 apk-php82: image: elasticobservability/apm-agent-php-dev:packages-test-apk-php-8.2-0.0.1 build: diff --git a/packaging/test/ubuntu/Dockerfile b/packaging/test/ubuntu/Dockerfile index bc8865dec..f0f09c668 100644 --- a/packaging/test/ubuntu/Dockerfile +++ b/packaging/test/ubuntu/Dockerfile @@ -1,5 +1,7 @@ ARG PHP_VERSION=7.2 -FROM php:${PHP_VERSION}-fpm-buster +ARG SEL_DISTRO=buster + +FROM php:${PHP_VERSION}-fpm-${SEL_DISTRO} RUN apt-get -qq update \ && apt-get -qq -y --no-install-recommends install \ diff --git a/tests/ElasticApmTests/ComponentTests/GenerateUnpackScriptsTest.php b/tests/ElasticApmTests/ComponentTests/GenerateUnpackScriptsTest.php index c22ca132d..c5f82c498 100644 --- a/tests/ElasticApmTests/ComponentTests/GenerateUnpackScriptsTest.php +++ b/tests/ElasticApmTests/ComponentTests/GenerateUnpackScriptsTest.php @@ -52,7 +52,7 @@ final class GenerateUnpackScriptsTest extends ComponentTestCaseBase implements L private const PHP_VERSION_7_4 = '7.4'; // Make sure list of PHP versions supported by the Elastic APM PHP Agent is in sync. // See the comment in .ci/shared.sh - private const SUPPORTED_PHP_VERSIONS = ['7.2', '7.3', self::PHP_VERSION_7_4, '8.0', '8.1', '8.2']; + private const SUPPORTED_PHP_VERSIONS = ['7.2', '7.3', self::PHP_VERSION_7_4, '8.0', '8.1', '8.2', '8.3']; private const LINUX_PACKAGE_TYPE_DEB = 'deb'; private const LINUX_PACKAGE_TYPE_RPM = 'rpm';