diff --git a/.ci/Makefile b/.ci/Makefile index acec7e96d..68bfacdfc 100644 --- a/.ci/Makefile +++ b/.ci/Makefile @@ -33,6 +33,10 @@ ifneq ($(PHP_VERSION), 7.2) SEL_DISTRO := bullseye endif +ifeq ($(PHP_VERSION), 8.5) + SEL_DISTRO := bookworm +endif + CONAN_USER_HOME:=/tmp/conan_user_home MAP_CONAN_HOME_TO_DOCKER_HOST_CMD_LINE_ARG:= diff --git a/.ci/packer_cache.sh b/.ci/packer_cache.sh index 3b947b728..ec7c534fb 100755 --- a/.ci/packer_cache.sh +++ b/.ci/packer_cache.sh @@ -16,6 +16,7 @@ php:8.1-fpm php:8.2-fpm php:8.3-fpm php:8.4-fpm +php:8.5-fpm ruby:2.7.1-alpine3.12 ubuntu:20.04 " @@ -27,7 +28,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 8.3 8.4 + for version in 7.2 7.3 7.4 8.0 8.1 8.2 8.3 8.4 8.5 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 6d1641581..9d12a2d43 100644 --- a/.ci/shared.sh +++ b/.ci/shared.sh @@ -16,7 +16,7 @@ set -e # *) 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 8.3 8.4) +export ELASTIC_APM_PHP_TESTS_SUPPORTED_PHP_VERSIONS=(7.2 7.3 7.4 8.0 8.1 8.2 8.3 8.4 8.5) 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 d1628ecd2..fbfc10446 100644 --- a/.github/workflows/loop.yml +++ b/.github/workflows/loop.yml @@ -24,6 +24,7 @@ jobs: - "8.2" - "8.3" - "8.4" + - "8.5" dockerfile: - "Dockerfile" - "Dockerfile.alpine" diff --git a/.github/workflows/phpt.yml b/.github/workflows/phpt.yml index cfbe0b2b6..5c67b9c9c 100644 --- a/.github/workflows/phpt.yml +++ b/.github/workflows/phpt.yml @@ -29,6 +29,7 @@ jobs: - "8.2" - "8.3" - "8.4" + - "8.5" steps: # - uses: actions/checkout@v6 # - name: Fetch and extract latest release of apm-agent-php diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 472cf1cde..a12420bfd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -59,6 +59,7 @@ jobs: - "8.2" - "8.3" - "8.4" + - "8.5" data: ${{ fromJson(needs.setup-build-matrix.outputs.matrix-combinations).include }} env: PHP_VERSION: ${{ matrix.php-version }} @@ -92,6 +93,7 @@ jobs: - "8.2" - "8.3" - "8.4" + - "8.5" dockerfile: - "Dockerfile" - "Dockerfile.alpine" diff --git a/Dockerfile b/Dockerfile index bfb2c2326..d58a8f2ec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,18 +12,19 @@ RUN if [ ${PHP_VERSION} = 7.2 ] && [ ${SEL_DISTRO} = buster ]; then \ RUN apt-get -qq update \ && apt-get -qq -y --no-install-recommends install \ - procps \ - rsyslog \ - curl \ - unzip \ - wget \ - && rm -rf /var/lib/apt/lists/* - -RUN docker-php-ext-install \ - mysqli \ - pcntl \ - pdo_mysql \ - opcache + procps \ + rsyslog \ + curl \ + unzip \ + wget \ + && rm -rf /var/lib/apt/lists/* + +RUN MODULES="mysqli pcntl pdo_mysql"; \ + case "${PHP_VERSION}" in \ + 8.5*) ;; \ + *) MODULES="$MODULES opcache" ;; \ + esac; \ + docker-php-ext-install $MODULES COPY --from=composer:latest /usr/bin/composer /usr/bin/composer @@ -38,4 +39,9 @@ ENV TEST_PHP_JUNIT=/app/build/junit.xml ENV ELASTIC_APM_ENABLED=false # Create a link to extensions directory to make it easier accessible (paths are different between php releases) -RUN ln -s `find /usr/local/lib/php/extensions/ -name opcache.so | head -n1 | xargs dirname` /tmp/extensions +RUN OPCACHE_PATH=$(find /usr/local/lib/php/extensions/ -name opcache.so -o -name opcache.a | head -n1); \ + if [ -z "$OPCACHE_PATH" ]; then \ + ln -s $(find /usr/local/lib/php/extensions/ -type d | head -n1) /tmp/extensions; \ + else \ + ln -s $(dirname "$OPCACHE_PATH") /tmp/extensions; \ + fi diff --git a/Dockerfile.alpine b/Dockerfile.alpine index 5235c2da8..2ec7c0c56 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -2,7 +2,7 @@ ARG PHP_VERSION=7.2 FROM php:${PHP_VERSION}-fpm-alpine RUN apk update \ - && apk add \ + && apk add \ bash \ logrotate \ procps \ @@ -12,11 +12,12 @@ RUN apk update \ git \ unzip -RUN docker-php-ext-install \ - mysqli \ - pcntl \ - pdo_mysql \ - opcache +RUN MODULES="mysqli pcntl pdo_mysql"; \ + case "${PHP_VERSION}" in \ + 8.5*) ;; \ + *) MODULES="$MODULES opcache" ;; \ + esac; \ + docker-php-ext-install $MODULES COPY --from=composer:latest /usr/bin/composer /usr/bin/composer @@ -31,4 +32,9 @@ ENV TEST_PHP_JUNIT=/app/build/junit.xml ENV ELASTIC_APM_ENABLED=false # Create a link to extensions directory to make it easier accessible (paths are different between php releases) -RUN ln -s `find /usr/local/lib/php/extensions/ -name opcache.so | head -n1 | xargs dirname` /tmp/extensions +RUN OPCACHE_PATH=$(find /usr/local/lib/php/extensions/ -name opcache.so -o -name opcache.a | head -n1); \ + if [ -z "$OPCACHE_PATH" ]; then \ + ln -s $(find /usr/local/lib/php/extensions/ -type d | head -n1) /tmp/extensions; \ + else \ + ln -s $(dirname "$OPCACHE_PATH") /tmp/extensions; \ + fi diff --git a/agent/extension_phpt_test/docker-compose.yml b/agent/extension_phpt_test/docker-compose.yml index e9ed3e29e..2c53a953e 100644 --- a/agent/extension_phpt_test/docker-compose.yml +++ b/agent/extension_phpt_test/docker-compose.yml @@ -1,141 +1,197 @@ version: "2.1" services: - phpt_72: - build: - context: . - dockerfile: images/Dockerfile - args: - PHP_VERSION: 7.2 - networks: - - elastic-net - volumes: - - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini - - ../native/_build/linux-x86-64-release/ext:/opt/elastic - - ../php:/opt/elastic/php - - ./results:/results - - ./allowedToFailLists/:/allowedToFailLists - - ./baselineFailures/:/baselineFailures/ - - ./testsToRemove/:/testsToRemove/ - depends_on: - - elasticsearch - - apm-server - phpt_73: - build: - context: . - dockerfile: images/Dockerfile - args: - PHP_VERSION: 7.3 - networks: - - elastic-net - volumes: - - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini - - ../native/_build/linux-x86-64-release/ext:/opt/elastic - - ../php:/opt/elastic/php - - ./results:/results - - ./allowedToFailLists/:/allowedToFailLists - - ./baselineFailures/:/baselineFailures/ - - ./testsToRemove/:/testsToRemove/ - depends_on: - - elasticsearch - - apm-server - phpt_74: - build: - context: . - dockerfile: images/Dockerfile - args: - PHP_VERSION: 7.4 - networks: - - elastic-net - volumes: - - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini - - ../native/_build/linux-x86-64-release/ext:/opt/elastic - - ../php:/opt/elastic/php - - ./results:/results - - ./allowedToFailLists/:/allowedToFailLists - - ./baselineFailures/:/baselineFailures/ - - ./testsToRemove/:/testsToRemove/ - depends_on: - - elasticsearch - - apm-server - phpt_80: - build: - context: . - dockerfile: images/Dockerfile - args: - PHP_VERSION: 8.0 - networks: - - elastic-net - volumes: - - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini - - ../native/_build/linux-x86-64-release/ext:/opt/elastic - - ../php:/opt/elastic/php - - ./results:/results - - ./allowedToFailLists/:/allowedToFailLists - - ./baselineFailures/:/baselineFailures/ - - ./testsToRemove/:/testsToRemove/ - depends_on: - - elasticsearch - - apm-server - phpt_81: - build: - context: . - dockerfile: images/Dockerfile - args: - PHP_VERSION: 8.1 - networks: - - elastic-net - volumes: - - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini - - ../native/_build/linux-x86-64-release/ext:/opt/elastic - - ../php:/opt/elastic/php - - ./results:/results - - ./allowedToFailLists/:/allowedToFailLists - - ./baselineFailures/:/baselineFailures/ - - ./testsToRemove/:/testsToRemove/ - depends_on: - - elasticsearch - - apm-server - phpt_82: - build: - context: . - dockerfile: images/Dockerfile - args: - PHP_VERSION: 8.2 - networks: - - elastic-net - volumes: - - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini - - ../native/_build/linux-x86-64-release/ext:/opt/elastic - - ../php:/opt/elastic/php - - ./results:/results - - ./allowedToFailLists/:/allowedToFailLists - - ./baselineFailures/:/baselineFailures/ - - ./testsToRemove/:/testsToRemove/ - depends_on: - - elasticsearch - - apm-server + phpt_72: + build: + context: . + dockerfile: images/Dockerfile + args: + PHP_VERSION: 7.2 + networks: + - elastic-net + volumes: + - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini + - ../native/_build/linux-x86-64-release/ext:/opt/elastic + - ../php:/opt/elastic/php + - ./results:/results + - ./allowedToFailLists/:/allowedToFailLists + - ./baselineFailures/:/baselineFailures/ + - ./testsToRemove/:/testsToRemove/ + depends_on: + - elasticsearch + - apm-server + phpt_73: + build: + context: . + dockerfile: images/Dockerfile + args: + PHP_VERSION: 7.3 + networks: + - elastic-net + volumes: + - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini + - ../native/_build/linux-x86-64-release/ext:/opt/elastic + - ../php:/opt/elastic/php + - ./results:/results + - ./allowedToFailLists/:/allowedToFailLists + - ./baselineFailures/:/baselineFailures/ + - ./testsToRemove/:/testsToRemove/ + depends_on: + - elasticsearch + - apm-server + phpt_74: + build: + context: . + dockerfile: images/Dockerfile + args: + PHP_VERSION: 7.4 + networks: + - elastic-net + volumes: + - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini + - ../native/_build/linux-x86-64-release/ext:/opt/elastic + - ../php:/opt/elastic/php + - ./results:/results + - ./allowedToFailLists/:/allowedToFailLists + - ./baselineFailures/:/baselineFailures/ + - ./testsToRemove/:/testsToRemove/ + depends_on: + - elasticsearch + - apm-server + phpt_80: + build: + context: . + dockerfile: images/Dockerfile + args: + PHP_VERSION: 8.0 + networks: + - elastic-net + volumes: + - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini + - ../native/_build/linux-x86-64-release/ext:/opt/elastic + - ../php:/opt/elastic/php + - ./results:/results + - ./allowedToFailLists/:/allowedToFailLists + - ./baselineFailures/:/baselineFailures/ + - ./testsToRemove/:/testsToRemove/ + depends_on: + - elasticsearch + - apm-server + phpt_81: + build: + context: . + dockerfile: images/Dockerfile + args: + PHP_VERSION: 8.1 + networks: + - elastic-net + volumes: + - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini + - ../native/_build/linux-x86-64-release/ext:/opt/elastic + - ../php:/opt/elastic/php + - ./results:/results + - ./allowedToFailLists/:/allowedToFailLists + - ./baselineFailures/:/baselineFailures/ + - ./testsToRemove/:/testsToRemove/ + depends_on: + - elasticsearch + - apm-server + phpt_82: + build: + context: . + dockerfile: images/Dockerfile + args: + PHP_VERSION: 8.2 + networks: + - elastic-net + volumes: + - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini + - ../native/_build/linux-x86-64-release/ext:/opt/elastic + - ../php:/opt/elastic/php + - ./results:/results + - ./allowedToFailLists/:/allowedToFailLists + - ./baselineFailures/:/baselineFailures/ + - ./testsToRemove/:/testsToRemove/ + depends_on: + - elasticsearch + - apm-server + phpt_83: + build: + context: . + dockerfile: images/Dockerfile + args: + PHP_VERSION: 8.3 + networks: + - elastic-net + volumes: + - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini + - ../native/_build/linux-x86-64-release/ext:/opt/elastic + - ../php:/opt/elastic/php + - ./results:/results + - ./allowedToFailLists/:/allowedToFailLists + - ./baselineFailures/:/baselineFailures/ + - ./testsToRemove/:/testsToRemove/ + depends_on: + - elasticsearch + - apm-server + phpt_84: + build: + context: . + dockerfile: images/Dockerfile + args: + PHP_VERSION: 8.4 + networks: + - elastic-net + volumes: + - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini + - ../native/_build/linux-x86-64-release/ext:/opt/elastic + - ../php:/opt/elastic/php + - ./results:/results + - ./allowedToFailLists/:/allowedToFailLists + - ./baselineFailures/:/baselineFailures/ + - ./testsToRemove/:/testsToRemove/ + depends_on: + - elasticsearch + - apm-server + phpt_85: + build: + context: . + dockerfile: images/Dockerfile + args: + PHP_VERSION: 8.5 + networks: + - elastic-net + volumes: + - ./config/99-elastic.ini:/usr/local/etc/php/conf.d/99-elastic.ini + - ../native/_build/linux-x86-64-release/ext:/opt/elastic + - ../php:/opt/elastic/php + - ./results:/results + - ./allowedToFailLists/:/allowedToFailLists + - ./baselineFailures/:/baselineFailures/ + - ./testsToRemove/:/testsToRemove/ + depends_on: + - elasticsearch + - apm-server - - apm-server: - image: docker.elastic.co/apm/apm-server:7.14.0 - container_name: apm-server - networks: - - elastic-net - environment: - - output.elasticsearch.hosts=["elasticsearch:9200"] - logging: - driver: none - elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:7.14.0 - container_name: elasticsearch - environment: - - discovery.type=single-node - - ELASTICSEARCH_USERNAME=elastic - - ELASTICSEARCH_PASSWORD=elastic - networks: - - elastic-net - logging: - driver: none + apm-server: + image: docker.elastic.co/apm/apm-server:7.14.0 + container_name: apm-server + networks: + - elastic-net + environment: + - output.elasticsearch.hosts=["elasticsearch:9200"] + logging: + driver: none + elasticsearch: + image: docker.elastic.co/elasticsearch/elasticsearch:7.14.0 + container_name: elasticsearch + environment: + - discovery.type=single-node + - ELASTICSEARCH_USERNAME=elastic + - ELASTICSEARCH_PASSWORD=elastic + networks: + - elastic-net + logging: + driver: none networks: elastic-net: diff --git a/agent/extension_phpt_test/images/Dockerfile b/agent/extension_phpt_test/images/Dockerfile index 7c10a5135..ea2382066 100644 --- a/agent/extension_phpt_test/images/Dockerfile +++ b/agent/extension_phpt_test/images/Dockerfile @@ -5,7 +5,12 @@ RUN apt-get update && apt-get install -y libcurl4 libcurl4-openssl-dev gdb RUN docker-php-source extract -RUN docker-php-ext-install pdo pdo_mysql opcache curl +RUN MODULES="pdo pdo_mysql curl"; \ + case "${PHP_VERSION}" in \ + 8.5*) ;; \ + *) MODULES="$MODULES opcache" ;; \ + esac; \ + docker-php-ext-install $MODULES RUN php -m diff --git a/agent/extension_phpt_test/scripts/run.sh b/agent/extension_phpt_test/scripts/run.sh index 7f5c4112a..142cad283 100755 --- a/agent/extension_phpt_test/scripts/run.sh +++ b/agent/extension_phpt_test/scripts/run.sh @@ -21,6 +21,12 @@ elif [ $PHP_VERSION == "8.1" ]; then PHP_API_VERSION="20210902" elif [ $PHP_VERSION == "8.2" ]; then PHP_API_VERSION="20220829" +elif [ $PHP_VERSION == "8.3" ]; then + PHP_API_VERSION="20230831" +elif [ $PHP_VERSION == "8.4" ]; then + PHP_API_VERSION="20240924" +elif [ $PHP_VERSION == "8.5" ]; then + PHP_API_VERSION="20250925" fi mkdir -m 666 -p /results/${PHP_VERSION} diff --git a/agent/native/CMakeLists.txt b/agent/native/CMakeLists.txt index 22252ec7b..3b6e129c1 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 83 84) +set(_supported_php_versions 72 73 74 80 81 82 83 84 85) function(get_php_api_from_release php_version ret_val) block(SCOPE_FOR VARIABLES) @@ -55,6 +55,7 @@ function(get_php_api_from_release php_version ret_val) set(_php_release_82 20220829) set(_php_release_83 20230831) set(_php_release_84 20240924) + set(_php_release_85 20250925) set(${ret_val} ${_php_release_${php_version}}) return(PROPAGATE ${ret_val}) diff --git a/agent/native/building/dependencies/php85/conandata.yml b/agent/native/building/dependencies/php85/conandata.yml new file mode 100644 index 000000000..2eca7a06f --- /dev/null +++ b/agent/native/building/dependencies/php85/conandata.yml @@ -0,0 +1,41 @@ +name: "php-headers-85" +version: "1.0" +php_source_version: 8.5.0 + +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" + 8.4.1: + linux: + - url: "https://www.php.net/distributions/php-8.4.1.tar.gz" + contentsRoot: "php-8.4.1" + 8.5.0: + linux: + - url: "https://www.php.net/distributions/php-8.5.0.tar.gz" + contentsRoot: "php-8.5.0" diff --git a/agent/native/building/dependencies/php85/conanfile.py b/agent/native/building/dependencies/php85/conanfile.py new file mode 100644 index 000000000..2f1ec5fcc --- /dev/null +++ b/agent/native/building/dependencies/php85/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 cbe148df1..3b20eca31 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.3.2 + // Up to date with PHP v8.5.0 switch ( kind ) { /** @@ -97,7 +97,9 @@ String zendAstKindToString( zend_ast_kind kind ) ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_CLASS ); ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_CLASS_CONST ); ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_CLASS_CONST_DECL ); + #if PHP_VERSION_ID < ELASTIC_APM_BUILD_PHP_VERSION_ID( 8, 5, 0 ) /* removed in PHP 8.5 */ ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_CLONE ); + #endif ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_CLOSURE ); ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_CLOSURE_USES ); ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_COALESCE ); @@ -112,7 +114,9 @@ String zendAstKindToString( zend_ast_kind kind ) ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_ECHO ); ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_EMPTY ); ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_ENCAPS_LIST ); + #if PHP_VERSION_ID < ELASTIC_APM_BUILD_PHP_VERSION_ID( 8, 5, 0 ) /* removed in PHP 8.5 */ ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_EXIT ); + #endif ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_EXPR_LIST ); ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_FOR ); ELASTIC_APM_GEN_ENUM_TO_STRING_SWITCH_CASE( ZEND_AST_FOREACH ); diff --git a/agent/native/ext/AST_instrumentation.cpp b/agent/native/ext/AST_instrumentation.cpp index 360f79aa2..8bab47ca9 100644 --- a/agent/native/ext/AST_instrumentation.cpp +++ b/agent/native/ext/AST_instrumentation.cpp @@ -195,7 +195,7 @@ bool isZendAstListKind( zend_ast_kind kind ) * - Increment minor part of PHP version in static_assert below */ static_assert( - PHP_VERSION_ID < ELASTIC_APM_BUILD_PHP_VERSION_ID( 8, 5, 0 ), + PHP_VERSION_ID < ELASTIC_APM_BUILD_PHP_VERSION_ID( 8, 6, 0 ), "Make sure g_astNodeMaxChildCount is correct. See max number of children in enum _zend_ast_kind in /Zend/zend_ast.h" ); static constexpr size_t g_astNodeMaxChildCount = diff --git a/agent/native/loader/code/phpdetection.cpp b/agent/native/loader/code/phpdetection.cpp index 42f58e653..64e724889 100644 --- a/agent/native/loader/code/phpdetection.cpp +++ b/agent/native/loader/code/phpdetection.cpp @@ -56,9 +56,10 @@ bool isThreadSafe() { std::tuple getZendModuleApiVersion(std::string_view zendVersion) { using namespace std::string_view_literals; - constexpr size_t knownVersionsCount = 17; + constexpr size_t knownVersionsCount = 18; constexpr std::array, knownVersionsCount> knownPhpVersions {{ + {"4.5"sv, 20250925, true}, // PHP 8.5 {"4.4"sv, 20240924, true}, // PHP 8.4 {"4.3"sv, 20230831, true}, // PHP 8.3 {"4.2"sv, 20220829, true}, // PHP 8.2 diff --git a/agent/php/ElasticApm/Impl/Log/LoggableTrait.php b/agent/php/ElasticApm/Impl/Log/LoggableTrait.php index 279ea5aa1..eec6a3770 100644 --- a/agent/php/ElasticApm/Impl/Log/LoggableTrait.php +++ b/agent/php/ElasticApm/Impl/Log/LoggableTrait.php @@ -83,7 +83,9 @@ protected function toLogLoggableTraitImpl(LogStreamInterface $stream, array $cus continue; } - $reflectionProperty->setAccessible(true); + if (PHP_VERSION_ID < 80100) { + $reflectionProperty->setAccessible(true); + } $propName = $reflectionProperty->name; if (array_key_exists($propName, $customPropValues)) { continue; diff --git a/composer.json b/composer.json index 923abda65..7f6e6906c 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ { "name": "Sergey Kleyman" } ], "require": { - "php": "^7.2||8.0.*||8.1.*||8.2.*||8.3.*||8.4.*", + "php": "^7.2||8.0.*||8.1.*||8.2.*||8.3.*||8.4.*||8.5.*", "ext-json": "*", "ext-pcntl": "*", "psr/log": "^1.0" diff --git a/packaging/Dockerfile.apk-v3 b/packaging/Dockerfile.apk-v3 new file mode 100644 index 000000000..605781e7f --- /dev/null +++ b/packaging/Dockerfile.apk-v3 @@ -0,0 +1,16 @@ +FROM alpine:3.21 + +RUN apk add --no-cache alpine-sdk sudo + +RUN adduser -D builder \ + && addgroup builder abuild \ + && echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + +RUN su builder -c "abuild-keygen -a -n" \ + && cp /home/builder/.abuild/*.pub /etc/apk/keys/ + +COPY create-apk-v3.sh /bin/ +RUN chmod +x /bin/create-apk-v3.sh + +WORKDIR /app +ENTRYPOINT ["/bin/create-apk-v3.sh"] diff --git a/packaging/Makefile b/packaging/Makefile index 88b886324..2374ec144 100644 --- a/packaging/Makefile +++ b/packaging/Makefile @@ -1,6 +1,7 @@ SHELL = /bin/bash MAKEFLAGS += --no-print-directory IMAGE:=php-packaging +IMAGE_APK_V3:=php-packaging-apk-v3 IMAGE_TAG:=latest NAME:=apm-agent-php VERSION?=$(shell grep 'VERSION' ../agent/php/ElasticApm/ElasticApm.php | cut -d= -f2 | tr -d " " | sed "s/'\(.*\)'.*/\1/g") @@ -13,6 +14,11 @@ RELEASE_VERSION?= GITHUB_RELEASES_URL=https://github.com/elastic/apm-agent-php/releases/download BUILD_ARCH := $(if $(BUILD_ARCH),$(BUILD_ARCH),"x86-64") +DOCKER_PLATFORM := linux/amd64 +ifeq ($(BUILD_ARCH), arm64) + DOCKER_PLATFORM := linux/arm64 +endif + ifeq ($(shell [ $(PHP_VERSION) \< 8.4 ] && echo true), true) RPM_IMAGE_VERSION = 0.0.3 # PHP < 8.4 - image using centos else @@ -25,6 +31,10 @@ ifneq ($(PHP_VERSION), 7.2) SEL_DISTRO := bullseye endif +ifeq ($(PHP_VERSION), 8.5) + SEL_DISTRO := bookworm +endif + .PHONY: help .DEFAULT_GOAL := help help: ## Display this help text @@ -39,7 +49,7 @@ prepare: ## Build docker image for the packaging docker build --build-arg IMAGE_TAG=$(IMAGE_TAG) -t $(IMAGE) . || exit 1 .PHONY: build-docker-images -build-docker-images: prepare prepare-apk prepare-deb prepare-rpm prepare-tar prepare-deb-apache prepare-deb-fpm ## Build all the docker images +build-docker-images: prepare prepare-apk-v3-image prepare-apk prepare-deb prepare-rpm prepare-tar prepare-deb-apache prepare-deb-fpm ## Build all the docker images @echo 'Build docker images' create-%: prepare ## Create the specific package @@ -60,7 +70,27 @@ create-%: prepare ## Create the specific package .PHONY: apk apk: FPM_FLAGS="--depends=bash" -apk: create-apk ## Create the apk installer +apk: create-apk ## Create the apk v2 installer (Alpine <=3.20) + +.PHONY: prepare-apk-v3-image +prepare-apk-v3-image: ## Build docker image for APK v3 packaging + docker build -t $(IMAGE_APK_V3) -f Dockerfile.apk-v3 . || exit 1 + +.PHONY: apk-v3 +apk-v3: prepare-apk-v3-image ## Create the apk v3 installer (Alpine 3.21+) + @echo "::group::$@" + @echo "Creating APK v3 package..." + mkdir -p $(PWD)/$(OUTPUT) + docker run --rm \ + -v $(PWD):/app \ + -e NAME=$(NAME) \ + -e VERSION=$(VERSION) \ + -e OUTPUT=$(OUTPUT) \ + -e PHP_AGENT_DIR=$(PHP_AGENT_DIR) \ + -e BUILD_ARCH=$(BUILD_ARCH) \ + -e GIT_SHA=$(GIT_SHA) \ + -w /app $(IMAGE_APK_V3) + @echo "::endgroup::" .PHONY: deb deb: create-deb ## Create the deb installer @@ -76,7 +106,7 @@ version: ## Show the fpm version docker run --rm $(IMAGE) --version || exit 1 .PHONY: package -package: apk deb rpm tar ## Create all the installers +package: apk apk-v3 deb rpm tar ## Create all the installers .PHONY: info info: apk-info deb-info rpm-info tar-info ## Show the package metadata for all the installers diff --git a/packaging/create-apk-v3.sh b/packaging/create-apk-v3.sh new file mode 100755 index 000000000..73dd6b27e --- /dev/null +++ b/packaging/create-apk-v3.sh @@ -0,0 +1,123 @@ +#!/usr/bin/env sh +set -x + +## Create APK v3 package using abuild on Alpine 3.21+ +## This produces packages compatible with apk-tools 3.x + +PACKAGE_ARCH="" +if [ "${BUILD_ARCH}" = "x86-64" ]; then + PACKAGE_ARCH="x86_64" +elif [ "${BUILD_ARCH}" = "arm64" ]; then + PACKAGE_ARCH="aarch64" +else + echo "Architecture not supported" + exit 1 +fi + +BUILD_TARGET="linuxmusl-${BUILD_ARCH}" +BUILD_EXT_DIR=agent/native/_build/${BUILD_TARGET}-release/ext +BUILD_LOADER_DIR=agent/native/_build/${BUILD_TARGET}-release/loader/code + +echo "Fetching agent libraries from ${BUILD_EXT_DIR}" +echo "Package architecture ${PACKAGE_ARCH}" + +if [ ! -d "${BUILD_EXT_DIR}" ]; then + echo "Agent libraries not built! Missing folder ${BUILD_EXT_DIR}" + exit 1 +fi + +touch build/elastic-apm.ini + +# Prepare extensions in temp dir +EXTENSIONS_DIR=/tmp/extensions +mkdir -p ${EXTENSIONS_DIR} +cp ${BUILD_EXT_DIR}/*.so ${EXTENSIONS_DIR}/ +cp ${BUILD_LOADER_DIR}/*.so ${EXTENSIONS_DIR}/ + +# Alpine pkgver does not allow dashes +PKGVER=$(echo ${VERSION} | tr '-' '_') + +# Setup APKBUILD workspace +WORK_DIR=/tmp/apk-v3-build +ABUILD_DIR=${WORK_DIR}/${NAME} +rm -rf ${WORK_DIR} +mkdir -p ${ABUILD_DIR} + +# Post-install trigger +cat > ${ABUILD_DIR}/${NAME}.post-install << 'EOF' +#!/bin/sh +/opt/elastic/apm-agent-php/bin/post-install.sh +EOF + +# Pre-deinstall trigger +cat > ${ABUILD_DIR}/${NAME}.pre-deinstall << 'EOF' +#!/bin/sh +/opt/elastic/apm-agent-php/bin/before-uninstall.sh +EOF + +# Create APKBUILD +cat > ${ABUILD_DIR}/APKBUILD << BUILDEOF +# Maintainer: APM Team +pkgname=${NAME} +pkgver=${PKGVER} +pkgrel=0 +pkgdesc="PHP agent for Elastic APM (Git Commit: ${GIT_SHA})" +url="https://github.com/elastic/apm-agent-php" +arch="all" +license="Apache-2.0" +depends="bash" +install="\$pkgname.post-install \$pkgname.pre-deinstall" +options="!check !fhs !strip !tracedeps" + +package() { + local dest="\$pkgdir${PHP_AGENT_DIR}" + + install -d "\$dest/extensions" + for f in ${EXTENSIONS_DIR}/*.so; do + install -m755 "\$f" "\$dest/extensions/" + done + + mkdir -p "\$dest/src" + cp -r /app/agent/php/* "\$dest/src/" + + install -d "\$dest/etc" + install -m644 /app/build/elastic-apm.ini "\$dest/etc/" + install -m644 /app/packaging/elastic-apm-custom-template.ini "\$dest/etc/elastic-apm-custom.ini" + + install -d "\$dest/bin" + install -m755 /app/packaging/post-install.sh "\$dest/bin/post-install.sh" + install -m755 /app/packaging/before-uninstall.sh "\$dest/bin/before-uninstall.sh" + + install -d "\$dest/docs" + install -m644 /app/README.md "\$dest/docs/README.md" +} +BUILDEOF + +#print debug info +echo "APKBUILD content:" +cat ${ABUILD_DIR}/APKBUILD || true + + +# Build as non-root user (abuild requirement) +chown -R builder:builder ${WORK_DIR} ${EXTENSIONS_DIR} +OUTPUT_DIR=${WORK_DIR}/output +su builder -c "cd ${ABUILD_DIR} && abuild -F -d -P ${OUTPUT_DIR}" + +# Find the built package +APK_FILE=$(find ${OUTPUT_DIR} -name "*.apk" ! -name "APKINDEX*" | head -1) +if [ -z "${APK_FILE}" ]; then + echo "ERROR: No APK file found in build output" + ls -laR ${OUTPUT_DIR} || true + exit 1 +fi + +# Copy to output with architecture in filename +NEW_NAME="${NAME}-${PKGVER}-r0.${PACKAGE_ARCH}.apk" +mkdir -p ${OUTPUT} +cp ${APK_FILE} ${OUTPUT}/${NEW_NAME} + +# Create sha512 checksum +cd ${OUTPUT} +sha512sum "${NEW_NAME}" > "${NEW_NAME}.sha512" + +echo "APK v3 package created: ${OUTPUT}/${NEW_NAME}" diff --git a/packaging/post-install.sh b/packaging/post-install.sh index 472af4852..5578a7a74 100755 --- a/packaging/post-install.sh +++ b/packaging/post-install.sh @@ -206,11 +206,12 @@ function is_php_supported() { [ "${PHP_MAJOR_MINOR}" == "8.1" ] || \ [ "${PHP_MAJOR_MINOR}" == "8.2" ] || \ [ "${PHP_MAJOR_MINOR}" == "8.3" ] || \ - [ "${PHP_MAJOR_MINOR}" == "8.4" ] + [ "${PHP_MAJOR_MINOR}" == "8.4" ] || \ + [ "${PHP_MAJOR_MINOR}" == "8.5" ] then return 0 else - echo 'Failed. The supported PHP versions are 7.2-8.4.' + echo 'Failed. The supported PHP versions are 7.2-8.5.' return 1 fi } diff --git a/packaging/test/alpine/entrypoint.sh b/packaging/test/alpine/entrypoint.sh index 01704c232..14f54fc14 100755 --- a/packaging/test/alpine/entrypoint.sh +++ b/packaging/test/alpine/entrypoint.sh @@ -51,13 +51,27 @@ validate_agent_installation() { #### MAIN #### ############## if [ "${TYPE}" = "release-github" ] ; then - PACKAGE=apm-agent-php_${VERSION}_all.apk + if apk --version 2>&1 | grep -q "apk-tools 3"; then + echo "Detected apk-tools v3, downloading APK v3 format package" + APKARCH=$(apk --print-arch) + PKGVER=$(echo ${VERSION} | tr '-' '_') + PACKAGE=apm-agent-php-${PKGVER}-r0.${APKARCH}.apk + else + echo "Detected apk-tools v2, downloading APK v2 format package" + PACKAGE=apm-agent-php_${VERSION}_all.apk + fi download "${PACKAGE}" "${BUILD_RELEASES_FOLDER}" "${GITHUB_RELEASES_URL}/v${VERSION}" apk add --allow-untrusted --verbose --no-cache "${BUILD_RELEASES_FOLDER}/${PACKAGE}" else ls -l $BUILD_PACKAGES - ## Install apk package and configure the agent accordingly - apk add --allow-untrusted --verbose --no-cache $BUILD_PACKAGES/*.apk + ## Install apk package - select v2 or v3 format based on apk-tools version + if apk --version 2>&1 | grep -q "apk-tools 3"; then + echo "Detected apk-tools v3, installing APK v3 format package" + apk add --allow-untrusted --verbose --no-cache $BUILD_PACKAGES/apm-agent-php-*-r0.*.apk + else + echo "Detected apk-tools v2, installing APK v2 format package" + apk add --allow-untrusted --verbose --no-cache $BUILD_PACKAGES/apm-agent-php_*.apk + fi fi validate_if_agent_is_enabled diff --git a/packaging/test/docker-compose.yml b/packaging/test/docker-compose.yml index 85e9ff9ab..0d9ca1a03 100644 --- a/packaging/test/docker-compose.yml +++ b/packaging/test/docker-compose.yml @@ -1,5 +1,13 @@ version: "3" services: + deb-fpm-php85: + image: elasticobservability/apm-agent-php-dev:packages-test-deb-fpm-php-8.5-0.0.1 + build: + context: ubuntu + dockerfile: fpm/Dockerfile + args: + - PHP_VERSION=8.5 + - SEL_DISTRO=bookworm deb-fpm-php84: image: elasticobservability/apm-agent-php-dev:packages-test-deb-fpm-php-8.4-0.0.1 build: @@ -62,6 +70,14 @@ services: + deb-apache-php85: + image: elasticobservability/apm-agent-php-dev:packages-test-deb-apache-php-8.5-0.0.1 + build: + context: ubuntu + dockerfile: apache/Dockerfile + args: + - PHP_VERSION=8.5 + - SEL_DISTRO=bookworm deb-apache-php84: image: elasticobservability/apm-agent-php-dev:packages-test-deb-apache-php-8.4-0.0.1 build: @@ -122,6 +138,14 @@ services: - PHP_VERSION=7.2 + deb-php85: + image: elasticobservability/apm-agent-php-dev:packages-test-deb-php-8.5-0.0.1 + build: + context: ubuntu + dockerfile: Dockerfile + args: + - PHP_VERSION=8.5 + - SEL_DISTRO=bookworm deb-php84: image: elasticobservability/apm-agent-php-dev:packages-test-deb-php-8.4-0.0.1 build: @@ -181,6 +205,13 @@ services: args: - PHP_VERSION=7.2 + rpm-php85: + image: elasticobservability/apm-agent-php-dev:packages-test-rpm-php-8.5-0.1.1 + build: + context: fedora + dockerfile: Dockerfile + args: + - PHP_VERSION=8.5 rpm-php84: image: elasticobservability/apm-agent-php-dev:packages-test-rpm-php-8.4-0.1.1 build: @@ -238,6 +269,13 @@ services: args: - PHP_VERSION=7.2 + apk-php85: + image: elasticobservability/apm-agent-php-dev:packages-test-apk-php-8.5-0.0.1 + build: + context: alpine + dockerfile: Dockerfile + args: + - PHP_VERSION=8.5 apk-php84: image: elasticobservability/apm-agent-php-dev:packages-test-apk-php-8.4-0.0.1 build: diff --git a/packaging/test/ubuntu/Dockerfile b/packaging/test/ubuntu/Dockerfile index 9cb81d34a..f05b6fe2b 100644 --- a/packaging/test/ubuntu/Dockerfile +++ b/packaging/test/ubuntu/Dockerfile @@ -14,7 +14,6 @@ RUN if [ ${PHP_VERSION} = 7.2 ] && [ ${SEL_DISTRO} = buster ]; then \ RUN apt-get -qq update \ && apt-get -qq -y --no-install-recommends install apt-transport-https \ && apt-get -qq -y --no-install-recommends install \ - dpkg-sig \ gnupg \ gnupg2 \ git \ diff --git a/packaging/test/ubuntu/entrypoint.sh b/packaging/test/ubuntu/entrypoint.sh index 7809ae404..7399a5499 100755 --- a/packaging/test/ubuntu/entrypoint.sh +++ b/packaging/test/ubuntu/entrypoint.sh @@ -61,7 +61,7 @@ if [[ "${TYPE}" == "deb" || "${TYPE}" == "deb-uninstall" ]] ; then elif [ "${TYPE}" == "release-github" ] ; then PACKAGE=apm-agent-php_${VERSION}_all.deb download "${PACKAGE}" "${BUILD_RELEASES_FOLDER}" "${GITHUB_RELEASES_URL}/v${VERSION}" - dpkg-sig --verify "${BUILD_RELEASES_FOLDER}/${PACKAGE}" + gpg --verify "${BUILD_RELEASES_FOLDER}/${PACKAGE}.asc" "${BUILD_RELEASES_FOLDER}/${PACKAGE}" dpkg -i "${BUILD_RELEASES_FOLDER}/${PACKAGE}" elif [ "${TYPE}" == "release-tar-github" ] ; then PACKAGE=apm-agent-php-linux-x86-64.tar diff --git a/tests/ElasticApmTests/ComponentTests/GenerateUnpackScriptsTest.php b/tests/ElasticApmTests/ComponentTests/GenerateUnpackScriptsTest.php index 60322db0d..3d9b39dd1 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', '8.3', '8.4']; + private const SUPPORTED_PHP_VERSIONS = ['7.2', '7.3', self::PHP_VERSION_7_4, '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']; private const LINUX_PACKAGE_TYPE_DEB = 'deb'; private const LINUX_PACKAGE_TYPE_RPM = 'rpm'; diff --git a/tests/ElasticApmTests/Util/runSelectPhpUnitConfigFile.php b/tests/ElasticApmTests/Util/runSelectPhpUnitConfigFile.php index 0ae773b42..a477b5705 100644 --- a/tests/ElasticApmTests/Util/runSelectPhpUnitConfigFile.php +++ b/tests/ElasticApmTests/Util/runSelectPhpUnitConfigFile.php @@ -25,5 +25,5 @@ use ElasticApmTests\Util\SelectPhpUnitConfigFile; -$phpUnitConfigFileName = SelectPhpUnitConfigFile::run($argv); +$phpUnitConfigFileName = SelectPhpUnitConfigFile::run($_SERVER['argv']); echo $phpUnitConfigFileName;