From e518e14f74ef25bad76a41f5dcff47b46e28eccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Michon?= Date: Tue, 27 Dec 2022 17:21:49 +0100 Subject: [PATCH 01/19] feat(composer): install PECL extension --- bin/compile | 1 + lib/composer | 11 ++++++++--- lib/pecl | 25 +++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 lib/pecl diff --git a/bin/compile b/bin/compile index 1611b113..568d4d53 100755 --- a/bin/compile +++ b/bin/compile @@ -12,6 +12,7 @@ source $basedir/../lib/composer source $basedir/../lib/datadog source $basedir/../lib/scout source $basedir/../lib/newrelic +source $basedir/../lib/pecl if [ "$PHP_BUILDPACK_NO_NODE" != "true" ] ; then source $basedir/../lib/nodejs diff --git a/lib/composer b/lib/composer index 95ba30cc..b4082078 100644 --- a/lib/composer +++ b/lib/composer @@ -50,7 +50,7 @@ function install_composer_deps() { chmod a+x "$CACHE_DIR/composer.phar" echo "$checksum" > $CACHE_DIR/composer.phar.md5 else - echo "Checksums match. Fetching from cache." + echo "Checksums match. Fetching Composer from cache." fi cp "$CACHE_DIR/composer.phar" "$target/vendor/composer/bin/" @@ -76,13 +76,19 @@ function install_composer_deps() { sodium_version=$sodium_php72_php73_version fi fetch_package "$PHP_BASE_URL" "libsodium-${sodium_version}" "/app/vendor/libsodium" | indent + else + # TODO How to check if the extension is in the cache? + local ext_version=$(jq --raw-output ".require | .[\"ext-${ext}\"]" < "${BUILD_DIR}/composer.json") + install_pecl_extension $ext "$ext_version" | indent fi + + # TODO I don't think this instruction should be executed for all extensions fetch_package "$PHP_BASE_URL" "ext/$(php_api_version)/php-${ext}" "/app/vendor/php" 2>/dev/null || true | indent done fi if [ -n "$COMPOSER_GITHUB_TOKEN" ]; then - status "Configuring the github authentication for Composer" + status "Configuring the GitHub authentication for Composer" php "vendor/composer/bin/composer.phar" config -g github-oauth.github.com "$COMPOSER_GITHUB_TOKEN" --no-interaction fi @@ -101,4 +107,3 @@ function install_composer_deps() { cd "$cwd" } | indent } - diff --git a/lib/pecl b/lib/pecl new file mode 100644 index 00000000..f3ac5ec0 --- /dev/null +++ b/lib/pecl @@ -0,0 +1,25 @@ +function install_pecl_extension() { + local extension_name="${1}" + local version="${2}" + + local build_dir=$(pwd) + local ext_dir=/app/vendor/php/lib/php/extensions/no-debug-non-zts-$(php_api_version) + local temp_dir=$(mktmpdir "pecl-extension") + + status "Installing PHP extension ${extension_name} version ${version}" + + pushd "${temp_dir}" > /dev/null + + curl --silent --location "https://pecl.php.net/get/${extension_name}-${version}.tgz" | tar xz + + pushd ${extension_name}-${version} > /dev/null + /app/vendor/php/bin/phpize > /dev/null + ./configure --with-php-config=/app/vendor/php/bin/php-config --with-${extension_name}=${build_dir}/.apt/usr > /dev/null + + make > /dev/null + cp modules/${extension_name}.so "${ext_dir}/${extension_name}.so" + echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" + + popd > /dev/null + popd > /dev/null +} From eb2a08f670e6da899067857928f59e91279cf140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Michon?= Date: Wed, 28 Dec 2022 13:38:51 +0100 Subject: [PATCH 02/19] feat(composer): make use of the cache for PECL extensions --- lib/composer | 3 +-- lib/pecl | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/composer b/lib/composer index b4082078..1073e6db 100644 --- a/lib/composer +++ b/lib/composer @@ -77,9 +77,8 @@ function install_composer_deps() { fi fetch_package "$PHP_BASE_URL" "libsodium-${sodium_version}" "/app/vendor/libsodium" | indent else - # TODO How to check if the extension is in the cache? local ext_version=$(jq --raw-output ".require | .[\"ext-${ext}\"]" < "${BUILD_DIR}/composer.json") - install_pecl_extension $ext "$ext_version" | indent + install_pecl_extension $ext "$ext_version" "$CACHE_DIR" | indent fi # TODO I don't think this instruction should be executed for all extensions diff --git a/lib/pecl b/lib/pecl index f3ac5ec0..559a1c70 100644 --- a/lib/pecl +++ b/lib/pecl @@ -1,12 +1,22 @@ function install_pecl_extension() { local extension_name="${1}" local version="${2}" + local cache_dir="${3}" - local build_dir=$(pwd) local ext_dir=/app/vendor/php/lib/php/extensions/no-debug-non-zts-$(php_api_version) + + local cache_extension_file="${cache_dir}/${extension_name}-${version}.so" + if [ -f "${cache_extension_file}" ]; then + echo "Installing PECL extension ${extension_name} version ${version} from the cache" + cp "${cache_extension_file}" "${ext_dir}/${extension_name}.so" + echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" + return + fi + + local build_dir=$(pwd) local temp_dir=$(mktmpdir "pecl-extension") - status "Installing PHP extension ${extension_name} version ${version}" + echo "Installing PECL extension ${extension_name} version ${version}" pushd "${temp_dir}" > /dev/null @@ -18,6 +28,7 @@ function install_pecl_extension() { make > /dev/null cp modules/${extension_name}.so "${ext_dir}/${extension_name}.so" + cp modules/${extension_name}.so "${cache_extension_file}" echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" popd > /dev/null From 2b4f51ad33178fcd899d14b4a5f1291b2e03c3de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Thomas?= Date: Thu, 12 Jan 2023 15:54:49 +0100 Subject: [PATCH 03/19] fix(pecl): allows to specify zend_extension configuration as env var --- lib/pecl | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/pecl b/lib/pecl index 559a1c70..79318c4e 100644 --- a/lib/pecl +++ b/lib/pecl @@ -1,3 +1,16 @@ + +function enable_pecl_extension() { + local extension_name="${1}" + local is_zend_extension_var_name="PHP_PECL_EXTENSION_IS_ZEND_$extension_name" + local is_zend_extension=$(printenv $is_zend_extension_var_name) + + if [[ -z $is_zend_extension ]] ; then + echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" + else + echo "zen_extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" + fi +} + function install_pecl_extension() { local extension_name="${1}" local version="${2}" @@ -9,7 +22,7 @@ function install_pecl_extension() { if [ -f "${cache_extension_file}" ]; then echo "Installing PECL extension ${extension_name} version ${version} from the cache" cp "${cache_extension_file}" "${ext_dir}/${extension_name}.so" - echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" + enable_pecl_extension ${extension_name} return fi @@ -29,7 +42,7 @@ function install_pecl_extension() { make > /dev/null cp modules/${extension_name}.so "${ext_dir}/${extension_name}.so" cp modules/${extension_name}.so "${cache_extension_file}" - echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" + enable_pecl_extension ${extension_name} popd > /dev/null popd > /dev/null From a2b288a389ccb9fafaa01b1fb93ea8534b368b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Thomas?= Date: Thu, 12 Jan 2023 16:56:42 +0100 Subject: [PATCH 04/19] fix(pecl): correct zend typo --- lib/pecl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pecl b/lib/pecl index 79318c4e..4fb1dc32 100644 --- a/lib/pecl +++ b/lib/pecl @@ -4,10 +4,10 @@ function enable_pecl_extension() { local is_zend_extension_var_name="PHP_PECL_EXTENSION_IS_ZEND_$extension_name" local is_zend_extension=$(printenv $is_zend_extension_var_name) - if [[ -z $is_zend_extension ]] ; then + if [[ -z $is_zend_extension ]] ; then echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" else - echo "zen_extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" + echo "zend_extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" fi } From 7a0c2323c6d0852d9e19362c2afcd927958c8ef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Thomas?= Date: Thu, 12 Jan 2023 17:38:58 +0100 Subject: [PATCH 05/19] fix(pecl): allows to configure build args --- lib/pecl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/pecl b/lib/pecl index 4fb1dc32..f75f00ed 100644 --- a/lib/pecl +++ b/lib/pecl @@ -37,7 +37,11 @@ function install_pecl_extension() { pushd ${extension_name}-${version} > /dev/null /app/vendor/php/bin/phpize > /dev/null - ./configure --with-php-config=/app/vendor/php/bin/php-config --with-${extension_name}=${build_dir}/.apt/usr > /dev/null + + local configure_extension_args_var_name="PHP_PECL_EXTENSION_CONFIGURE_ARGS_$extension_name" + local configure_extension_args=$(printenv $configure_extension_args_var_name) + + ./configure --with-php-config=/app/vendor/php/bin/php-config $configure_extension_args > /dev/null make > /dev/null cp modules/${extension_name}.so "${ext_dir}/${extension_name}.so" From afd1a1a4421023e289049b4d5473eb65ac9b5914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Thomas?= Date: Fri, 13 Jan 2023 10:43:35 +0100 Subject: [PATCH 06/19] fix(pecl): allows to substitute $BUILD_DIR --- lib/pecl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pecl b/lib/pecl index f75f00ed..c9491826 100644 --- a/lib/pecl +++ b/lib/pecl @@ -4,7 +4,7 @@ function enable_pecl_extension() { local is_zend_extension_var_name="PHP_PECL_EXTENSION_IS_ZEND_$extension_name" local is_zend_extension=$(printenv $is_zend_extension_var_name) - if [[ -z $is_zend_extension ]] ; then + if [[ $is_zend_extension = "true" ]] ; then echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" else echo "zend_extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" @@ -40,8 +40,9 @@ function install_pecl_extension() { local configure_extension_args_var_name="PHP_PECL_EXTENSION_CONFIGURE_ARGS_$extension_name" local configure_extension_args=$(printenv $configure_extension_args_var_name) + local flags=$(echo $configure_extension_args | sed "s/\$BUILD_DIR/$build_dir/") - ./configure --with-php-config=/app/vendor/php/bin/php-config $configure_extension_args > /dev/null + ./configure --with-php-config=/app/vendor/php/bin/php-config $flags > /dev/null make > /dev/null cp modules/${extension_name}.so "${ext_dir}/${extension_name}.so" From c5aea708d8e483c1b90b3adc3229661735a1fbdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Thomas?= Date: Fri, 13 Jan 2023 11:05:07 +0100 Subject: [PATCH 07/19] fix(pecl): change sed delimiter to allows path substitution --- lib/pecl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pecl b/lib/pecl index c9491826..78cfe4de 100644 --- a/lib/pecl +++ b/lib/pecl @@ -40,7 +40,7 @@ function install_pecl_extension() { local configure_extension_args_var_name="PHP_PECL_EXTENSION_CONFIGURE_ARGS_$extension_name" local configure_extension_args=$(printenv $configure_extension_args_var_name) - local flags=$(echo $configure_extension_args | sed "s/\$BUILD_DIR/$build_dir/") + local flags=$(echo $configure_extension_args | sed "s|\$BUILD_DIR|$build_dir|") ./configure --with-php-config=/app/vendor/php/bin/php-config $flags > /dev/null From 078bddcb8bb8f915b4a04f1ecb45fbc3dda51bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Thomas?= Date: Fri, 13 Jan 2023 11:10:37 +0100 Subject: [PATCH 08/19] fix(pecl): invert zend condition --- lib/pecl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pecl b/lib/pecl index 78cfe4de..82ab0ed7 100644 --- a/lib/pecl +++ b/lib/pecl @@ -5,9 +5,9 @@ function enable_pecl_extension() { local is_zend_extension=$(printenv $is_zend_extension_var_name) if [[ $is_zend_extension = "true" ]] ; then - echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" - else echo "zend_extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" + else + echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" fi } From 17ab35f884562cdb5640c5e415a3a4d6fdfb3012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Thomas?= Date: Fri, 13 Jan 2023 14:15:02 +0100 Subject: [PATCH 09/19] feat(pecl): allows to retrieve the latest version of an extension using a wildcard --- lib/pecl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/pecl b/lib/pecl index 82ab0ed7..b8e31950 100644 --- a/lib/pecl +++ b/lib/pecl @@ -16,6 +16,9 @@ function install_pecl_extension() { local version="${2}" local cache_dir="${3}" + if [[ $version = '*' ]]; then + local version=$(curl --silent "https://pecl.php.net/rest/r/$extension_name/latest.txt") + fi local ext_dir=/app/vendor/php/lib/php/extensions/no-debug-non-zts-$(php_api_version) local cache_extension_file="${cache_dir}/${extension_name}-${version}.so" From db3894be53c841b506cf4459627af7e1ed2df614 Mon Sep 17 00:00:00 2001 From: Quentin Escudier Date: Mon, 23 Jan 2023 11:23:54 +0100 Subject: [PATCH 10/19] feat(oci8); oci8 is now available, some code should be 'cleaned' --- lib/composer | 4 ++++ lib/pecl | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/lib/composer b/lib/composer index 1073e6db..4f102061 100644 --- a/lib/composer +++ b/lib/composer @@ -77,6 +77,10 @@ function install_composer_deps() { fi fetch_package "$PHP_BASE_URL" "libsodium-${sodium_version}" "/app/vendor/libsodium" | indent else + if [[ $ext = 'oci8' ]]; then + install_oracle_client_extension + fi + local ext_version=$(jq --raw-output ".require | .[\"ext-${ext}\"]" < "${BUILD_DIR}/composer.json") install_pecl_extension $ext "$ext_version" "$CACHE_DIR" | indent fi diff --git a/lib/pecl b/lib/pecl index b8e31950..9b9f1415 100644 --- a/lib/pecl +++ b/lib/pecl @@ -11,6 +11,21 @@ function enable_pecl_extension() { fi } +function install_oracle_client_extension() { + mkdir oracle/ + + curl --silent https://download.oracle.com/otn_software/linux/instantclient/instantclient-basic-linuxx64.zip --output oracleclient.zip + unzip -q oracleclient.zip -d oracle/ + rm oracleclient.zip + + export ORACLE_HOME=$(echo $(pwd)/oracle/instantclient_*) # TODO: Find a better way than * to catch the name of the client folder + export LD_LIBRARY_PATH=$ORACLE_HOME:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH + + curl --silent https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip --output oraclesdk.zip + unzip -q oraclesdk.zip -d oracle/ +} + function install_pecl_extension() { local extension_name="${1}" local version="${2}" @@ -45,6 +60,11 @@ function install_pecl_extension() { local configure_extension_args=$(printenv $configure_extension_args_var_name) local flags=$(echo $configure_extension_args | sed "s|\$BUILD_DIR|$build_dir|") + if [[ $extension_name = 'oci8' ]]; then + flags="--with-oci8=instantclient,$ORACLE_HOME" + fi + + echo "COMMAND ======= ./configure --with-php-config=/app/vendor/php/bin/php-config $flags > /dev/null" ./configure --with-php-config=/app/vendor/php/bin/php-config $flags > /dev/null make > /dev/null From 1ee469d1606624dd96bdb70487a8e5667845256c Mon Sep 17 00:00:00 2001 From: Quentin Escudier Date: Tue, 24 Jan 2023 18:33:25 +0100 Subject: [PATCH 11/19] fix(oci8): oracle client installed in /app/vendor/oracle-client and libaio installed via apt buildpack libaio and oracle-client must be cached to avoid download at each deploy --- bin/compile | 1 + lib/composer | 7 +++---- lib/pecl | 50 ++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/bin/compile b/bin/compile index 568d4d53..405a651e 100755 --- a/bin/compile +++ b/bin/compile @@ -475,6 +475,7 @@ mv /app/vendor/php vendor/php [ -d "/app/vendor/libtidy" ] && mv /app/vendor/libtidy vendor/libtidy [ -d "/app/vendor/libsodium" ] && mv /app/vendor/libsodium vendor/libsodium [ -d "/app/vendor/libwebp" ] && mv /app/vendor/libwebp vendor/libwebp +[ -d "/app/vendor/oracle-client" ] && mv /app/vendor/oracle-client vendor/oracle-client mkdir -p "bin" "vendor/bin" diff --git a/lib/composer b/lib/composer index 4f102061..18c95d9b 100644 --- a/lib/composer +++ b/lib/composer @@ -78,13 +78,12 @@ function install_composer_deps() { fetch_package "$PHP_BASE_URL" "libsodium-${sodium_version}" "/app/vendor/libsodium" | indent else if [[ $ext = 'oci8' ]]; then - install_oracle_client_extension + install_apt_libaio "${BUILD_DIR}" "$CACHE_DIR" + install_oracle_client_extension "${BUILD_DIR}" fi - local ext_version=$(jq --raw-output ".require | .[\"ext-${ext}\"]" < "${BUILD_DIR}/composer.json") - install_pecl_extension $ext "$ext_version" "$CACHE_DIR" | indent + install_pecl_extension $ext "$ext_version" "${BUILD_DIR}" "$CACHE_DIR" | indent fi - # TODO I don't think this instruction should be executed for all extensions fetch_package "$PHP_BASE_URL" "ext/$(php_api_version)/php-${ext}" "/app/vendor/php" 2>/dev/null || true | indent done diff --git a/lib/pecl b/lib/pecl index 9b9f1415..0560bab9 100644 --- a/lib/pecl +++ b/lib/pecl @@ -11,25 +11,52 @@ function enable_pecl_extension() { fi } +function install_apt_libaio() { + # ---- + # Install libaio to install oci8 + echo "Installing libaio for oci8" + + local build_dir="${1}" + local cache_dir="${2}" + + echo "libaio1" > "${build_dir}/Aptfile" + + apt_deps_buildpack_dir=$(mktemp apt_buildpack_XXXX) + rm "${apt_deps_buildpack_dir}" + + readonly apt_buildpack_url="https://github.com/Scalingo/apt-buildpack.git" + git clone --depth=1 "${apt_buildpack_url}" "${build_dir}/$apt_deps_buildpack_dir" > /dev/null + + "${build_dir}/${apt_deps_buildpack_dir}/bin/compile" "${build_dir}" "${cache_dir}" "${env_dir}" > /dev/null +} + function install_oracle_client_extension() { - mkdir oracle/ + # ---- + # Install oracle client + local build_dir="/app" + local oracle_install_dir="${build_dir}/vendor/oracle-client/" + mkdir -p "${oracle_install_dir}" curl --silent https://download.oracle.com/otn_software/linux/instantclient/instantclient-basic-linuxx64.zip --output oracleclient.zip - unzip -q oracleclient.zip -d oracle/ + unzip -q oracleclient.zip -d "${oracle_install_dir}" rm oracleclient.zip - export ORACLE_HOME=$(echo $(pwd)/oracle/instantclient_*) # TODO: Find a better way than * to catch the name of the client folder - export LD_LIBRARY_PATH=$ORACLE_HOME:$LD_LIBRARY_PATH - export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH + export ORACLE_HOME="${oracle_install_dir}$(ls ${oracle_install_dir})" + export LD_LIBRARY_PATH="${ORACLE_HOME}/lib:${ORACLE_HOME}:${LD_LIBRARY_PATH}" curl --silent https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip --output oraclesdk.zip - unzip -q oraclesdk.zip -d oracle/ + unzip -q oraclesdk.zip -d "${oracle_install_dir}" + rm oraclesdk.zip + + local startup_script="${1}/.profile.d/oracle-client.sh" + echo "export ORACLE_HOME=${ORACLE_HOME}" >> "${startup_script}" + echo "export LD_LIBRARY_PATH=${ORACLE_HOME}/lib:${ORACLE_HOME}:\${LD_LIBRARY_PATH}" >> "${startup_script}" } function install_pecl_extension() { local extension_name="${1}" local version="${2}" - local cache_dir="${3}" + local cache_dir="${4}" if [[ $version = '*' ]]; then local version=$(curl --silent "https://pecl.php.net/rest/r/$extension_name/latest.txt") @@ -54,17 +81,20 @@ function install_pecl_extension() { curl --silent --location "https://pecl.php.net/get/${extension_name}-${version}.tgz" | tar xz pushd ${extension_name}-${version} > /dev/null - /app/vendor/php/bin/phpize > /dev/null + + /app/vendor/php/bin/phpize &> /dev/null local configure_extension_args_var_name="PHP_PECL_EXTENSION_CONFIGURE_ARGS_$extension_name" local configure_extension_args=$(printenv $configure_extension_args_var_name) local flags=$(echo $configure_extension_args | sed "s|\$BUILD_DIR|$build_dir|") if [[ $extension_name = 'oci8' ]]; then - flags="--with-oci8=instantclient,$ORACLE_HOME" + if [ -e "${3}/${apt_deps_buildpack_dir}/export" ]; then + source "${3}/${apt_deps_buildpack_dir}/export" + fi + flags="--with-oci8=instantclient,${ORACLE_HOME}" fi - echo "COMMAND ======= ./configure --with-php-config=/app/vendor/php/bin/php-config $flags > /dev/null" ./configure --with-php-config=/app/vendor/php/bin/php-config $flags > /dev/null make > /dev/null From 7a5a59c4137361b3312f5e8eafbe89d146e05e2a Mon Sep 17 00:00:00 2001 From: Quentin Escudier Date: Wed, 25 Jan 2023 10:40:28 +0100 Subject: [PATCH 12/19] fix(oci8): clean code From 2e8f674993181bb40b631d46d1171de026fc542f Mon Sep 17 00:00:00 2001 From: Quentin Escudier Date: Wed, 25 Jan 2023 11:14:13 +0100 Subject: [PATCH 13/19] fix(oci8): set -e in compile --- bin/compile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/compile b/bin/compile index 405a651e..9443bfb8 100755 --- a/bin/compile +++ b/bin/compile @@ -1,6 +1,6 @@ #!/bin/bash -set -e +# set -e set -o pipefail shopt -s dotglob From 336de5f78e27e065bb5b2882142669f5914ccb1e Mon Sep 17 00:00:00 2001 From: Soulou Date: Thu, 26 Jan 2023 18:25:57 +0100 Subject: [PATCH 14/19] Correctly export LD_LIBRARY_PATH from sub-APT buildpack when installing oci8 extensions --- bin/compile | 4 +++- lib/composer | 9 +++++++-- lib/pecl | 42 ------------------------------------------ lib/pecl_oci8 | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 45 deletions(-) create mode 100644 lib/pecl_oci8 diff --git a/bin/compile b/bin/compile index 9443bfb8..591aef3a 100755 --- a/bin/compile +++ b/bin/compile @@ -13,6 +13,7 @@ source $basedir/../lib/datadog source $basedir/../lib/scout source $basedir/../lib/newrelic source $basedir/../lib/pecl +source $basedir/../lib/pecl_oci8 if [ "$PHP_BUILDPACK_NO_NODE" != "true" ] ; then source $basedir/../lib/nodejs @@ -24,6 +25,7 @@ fi BUILD_DIR="$1" CACHE_DIR="$2" +ENV_DIR="$3" cd "$BUILD_DIR" mkdir -p "$CACHE_DIR/package" @@ -417,7 +419,7 @@ if [ "$PHP_BUILDPACK_NO_NODE" != "true" ] ; then install_node_deps "$BUILD_DIR" fi -install_composer_deps "$BUILD_DIR" +install_composer_deps "${BUILD_DIR}" "${CACHE_DIR}" "${ENV_DIR}" # Detect PHP framework # Set FRAMEWORK if not set in environment by user diff --git a/lib/composer b/lib/composer index 18c95d9b..96613f08 100644 --- a/lib/composer +++ b/lib/composer @@ -78,8 +78,13 @@ function install_composer_deps() { fetch_package "$PHP_BASE_URL" "libsodium-${sodium_version}" "/app/vendor/libsodium" | indent else if [[ $ext = 'oci8' ]]; then - install_apt_libaio "${BUILD_DIR}" "$CACHE_DIR" - install_oracle_client_extension "${BUILD_DIR}" + echo "Installing libaio for oci8" | indent + install_env_file="$(install_apt_libaio "${BUILD_DIR}" "${CACHE_DIR}" "${ENV_DIR}")" + # Source environment to export LD_LIBRARY_PATH + source "${install_env_file}" + rm "${install_env_file}" + + install_oracle_client_extension "${BUILD_DIR}" "${CACHE_DIR}" fi local ext_version=$(jq --raw-output ".require | .[\"ext-${ext}\"]" < "${BUILD_DIR}/composer.json") install_pecl_extension $ext "$ext_version" "${BUILD_DIR}" "$CACHE_DIR" | indent diff --git a/lib/pecl b/lib/pecl index 0560bab9..2e9ca436 100644 --- a/lib/pecl +++ b/lib/pecl @@ -11,48 +11,6 @@ function enable_pecl_extension() { fi } -function install_apt_libaio() { - # ---- - # Install libaio to install oci8 - echo "Installing libaio for oci8" - - local build_dir="${1}" - local cache_dir="${2}" - - echo "libaio1" > "${build_dir}/Aptfile" - - apt_deps_buildpack_dir=$(mktemp apt_buildpack_XXXX) - rm "${apt_deps_buildpack_dir}" - - readonly apt_buildpack_url="https://github.com/Scalingo/apt-buildpack.git" - git clone --depth=1 "${apt_buildpack_url}" "${build_dir}/$apt_deps_buildpack_dir" > /dev/null - - "${build_dir}/${apt_deps_buildpack_dir}/bin/compile" "${build_dir}" "${cache_dir}" "${env_dir}" > /dev/null -} - -function install_oracle_client_extension() { - # ---- - # Install oracle client - local build_dir="/app" - local oracle_install_dir="${build_dir}/vendor/oracle-client/" - mkdir -p "${oracle_install_dir}" - - curl --silent https://download.oracle.com/otn_software/linux/instantclient/instantclient-basic-linuxx64.zip --output oracleclient.zip - unzip -q oracleclient.zip -d "${oracle_install_dir}" - rm oracleclient.zip - - export ORACLE_HOME="${oracle_install_dir}$(ls ${oracle_install_dir})" - export LD_LIBRARY_PATH="${ORACLE_HOME}/lib:${ORACLE_HOME}:${LD_LIBRARY_PATH}" - - curl --silent https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip --output oraclesdk.zip - unzip -q oraclesdk.zip -d "${oracle_install_dir}" - rm oraclesdk.zip - - local startup_script="${1}/.profile.d/oracle-client.sh" - echo "export ORACLE_HOME=${ORACLE_HOME}" >> "${startup_script}" - echo "export LD_LIBRARY_PATH=${ORACLE_HOME}/lib:${ORACLE_HOME}:\${LD_LIBRARY_PATH}" >> "${startup_script}" -} - function install_pecl_extension() { local extension_name="${1}" local version="${2}" diff --git a/lib/pecl_oci8 b/lib/pecl_oci8 new file mode 100644 index 00000000..1e25a07a --- /dev/null +++ b/lib/pecl_oci8 @@ -0,0 +1,48 @@ +function install_apt_libaio() { + # ---- + # Install libaio to install oci8 + local build_dir="${1}" + local cache_dir="${2}" + local env_dir="${3}" + + echo "libaio1" > "${build_dir}/Aptfile" + + apt_deps_buildpack_dir=$(mktemp apt_buildpack_XXXX) + rm "${apt_deps_buildpack_dir}" + + readonly apt_buildpack_url="https://github.com/Scalingo/apt-buildpack.git" + git clone --quiet --depth=1 "${apt_buildpack_url}" "${build_dir}/$apt_deps_buildpack_dir" >/dev/null 2>/dev/null + + "${build_dir}/${apt_deps_buildpack_dir}/bin/compile" "${build_dir}" "${cache_dir}" "${env_dir}" > /dev/null + + # Source new libs for future buildpack (update of LD_LIBRARY_PATH) + export_file="${build_dir}/oci8_apt_export" + cp "${build_dir}/${apt_deps_buildpack_dir}/export" "${export_file}" + + echo "${export_file}" +} + +function install_oracle_client_extension() { + # ---- + # Install oracle client + local build_dir="${1}" + local cache_dir="${2}" + + local oracle_install_dir="${build_dir}/vendor/oracle-client/" + mkdir -p "${oracle_install_dir}" + + curl --silent https://download.oracle.com/otn_software/linux/instantclient/instantclient-basic-linuxx64.zip --output oracleclient.zip + unzip -q oracleclient.zip -d "${oracle_install_dir}" + rm oracleclient.zip + + export ORACLE_HOME="${oracle_install_dir}$(ls ${oracle_install_dir})" + export LD_LIBRARY_PATH="${ORACLE_HOME}/lib:${ORACLE_HOME}:${LD_LIBRARY_PATH}" + + curl --silent https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip --output oraclesdk.zip + unzip -q oraclesdk.zip -d "${oracle_install_dir}" + rm oraclesdk.zip + + local startup_script="${1}/.profile.d/oracle-client.sh" + echo "export ORACLE_HOME=${ORACLE_HOME}" >> "${startup_script}" + echo "export LD_LIBRARY_PATH=${ORACLE_HOME}/lib:${ORACLE_HOME}:\${LD_LIBRARY_PATH}" >> "${startup_script}" +} From b6b25662018912e76a4f3538c2a277a6a6ba14c8 Mon Sep 17 00:00:00 2001 From: Soulou Date: Thu, 26 Jan 2023 18:28:18 +0100 Subject: [PATCH 15/19] Rever 'set -e' --- bin/compile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/compile b/bin/compile index 591aef3a..d25d6e04 100755 --- a/bin/compile +++ b/bin/compile @@ -1,6 +1,6 @@ #!/bin/bash -# set -e +set -e set -o pipefail shopt -s dotglob From 190e8975ea74ce656f347240a50f0341674d8343 Mon Sep 17 00:00:00 2001 From: Soulou Date: Thu, 26 Jan 2023 18:31:31 +0100 Subject: [PATCH 16/19] Fix cache directory in pecl installation --- lib/pecl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pecl b/lib/pecl index 2e9ca436..ce120bf7 100644 --- a/lib/pecl +++ b/lib/pecl @@ -14,7 +14,7 @@ function enable_pecl_extension() { function install_pecl_extension() { local extension_name="${1}" local version="${2}" - local cache_dir="${4}" + local cache_dir="${3}" if [[ $version = '*' ]]; then local version=$(curl --silent "https://pecl.php.net/rest/r/$extension_name/latest.txt") From 83b3b1d7f612b69aefce53a09e86555ca95405d0 Mon Sep 17 00:00:00 2001 From: Soulou Date: Fri, 27 Jan 2023 14:57:24 +0100 Subject: [PATCH 17/19] Polish codebase, make code more generic between internal packages and PECL --- bin/compile | 44 ++-------------------------- lib/apt | 32 +++++++++++++++++++++ lib/composer | 45 ++++++++++++++++++----------- lib/package | 55 +++++++++++++++++++++++++++++++++++ lib/pecl | 80 ++++++++++++++++++++++++++++++++------------------- lib/pecl_oci8 | 32 ++++----------------- 6 files changed, 174 insertions(+), 114 deletions(-) create mode 100644 lib/apt create mode 100644 lib/package diff --git a/bin/compile b/bin/compile index d25d6e04..7de8c5f0 100755 --- a/bin/compile +++ b/bin/compile @@ -8,10 +8,12 @@ shopt -s dotglob basedir="$( cd -P "$( dirname "$0" )" && pwd )" source "$basedir/../conf/buildpack.conf" source $basedir/common.sh +source $basedir/../lib/package source $basedir/../lib/composer source $basedir/../lib/datadog source $basedir/../lib/scout source $basedir/../lib/newrelic +source $basedir/../lib/apt source $basedir/../lib/pecl source $basedir/../lib/pecl_oci8 @@ -32,48 +34,6 @@ mkdir -p "$CACHE_DIR/package" export APP_ENV=${APP_ENV:-prod} -function fetch_engine_package() { - local engine="$1" - local version="$2" - local location="$3" - - local base_url="$PHP_BASE_URL" - if [ "$engine" = "nginx" ] ; then - base_url="$NGINX_BASE_URL" - fi - - fetch_package "$base_url" "${engine}-${version}" "$location" -} - -function fetch_package() { - local base_url="$1" - local package="$2" - local location="$3" - - mkdir -p "$location" - - local checksum_url="${base_url}/package/${package}.md5" - local package_url="${base_url}/package/${package}.tgz" - local checksum=$(curl --fail --retry 3 --retry-delay 2 --connect-timeout 3 --max-time 30 "$checksum_url" 2> /dev/null) - local cache_checksum="" - - if [ -f "$CACHE_DIR/package/${package}.md5" ]; then - local cache_checksum=$(cat "$CACHE_DIR/package/${package}.md5") - fi - - mkdir -p "$CACHE_DIR/package/$(dirname "$package")" - - if [ "$cache_checksum" != "$checksum" ]; then - curl --fail --retry 3 --retry-delay 2 --connect-timeout 3 --max-time 30 "$package_url" -L -s > "$CACHE_DIR/package/${package}.tgz" - echo "$checksum" > "$CACHE_DIR/package/${package}.md5" - else - echo "Checksums match. Fetching from cache." - fi - - mkdir -p "$location" - tar xzf "$CACHE_DIR/package/${package}.tgz" -C "$location" -} - function detect_framework() { BUILD_DIR=$1 for f in "$basedir/../frameworks/"*; do diff --git a/lib/apt b/lib/apt new file mode 100644 index 00000000..eacd157f --- /dev/null +++ b/lib/apt @@ -0,0 +1,32 @@ +function apt_install() { + local apt_deps="${1}" + local build_dir="${2}" + local cache_dir="${3}" + local env_dir="${4}" + + apt_manifest="$(mktemp "${build_dir}/Aptfile.php-XXX")" + echo "${apt_deps}" | tr ' ' '\n' > "${apt_manifest}" + + apt_deps_buildpack_dir=$(mktemp /tmp/apt_buildpack_XXXX) + rm "${apt_deps_buildpack_dir}" + + readonly apt_buildpack_url="https://github.com/Scalingo/apt-buildpack.git" + git clone --quiet --depth=1 "${apt_buildpack_url}" "${apt_deps_buildpack_dir}" >/dev/null 2>/dev/null + + readonly apt_log_file=$(mktemp /tmp/apt_log_XXXX.log) + APT_FILE_MANIFEST="$(basename ${apt_manifest})" "${apt_deps_buildpack_dir}/bin/compile" "${build_dir}" "${cache_dir}" "${env_dir}" >"${apt_log_file}" 2>&1 + if [ $? -ne 0 ] ; then + tail -n 30 "${apt_log_file}" | indent + echo + warn "Fail to install apt packages" + echo + exit 1 + fi + + # Source new libs for future buildpack (update of LD_LIBRARY_PATH) + export_file="${build_dir}/oci8_apt_export" + cp "${apt_deps_buildpack_dir}/export" "${export_file}" + + rm "${apt_manifest}" + echo "${export_file}" +} diff --git a/lib/composer b/lib/composer index 96613f08..bc1cf119 100644 --- a/lib/composer +++ b/lib/composer @@ -50,7 +50,7 @@ function install_composer_deps() { chmod a+x "$CACHE_DIR/composer.phar" echo "$checksum" > $CACHE_DIR/composer.phar.md5 else - echo "Checksums match. Fetching Composer from cache." + echo "Checksums match. Fetching Composer from cache." |indent fi cp "$CACHE_DIR/composer.phar" "$target/vendor/composer/bin/" @@ -63,9 +63,27 @@ function install_composer_deps() { if [ -n "$required_extensions" ]; then status "Bundling additional extensions" for ext in $required_extensions; do - echo "$ext" | indent + local apt_deps="" + local ext_version=$(jq --raw-output ".require | .[\"ext-${ext}\"]" < "${BUILD_DIR}/composer.json") + local should_install_from_pecl="true" + # TODO: Find a better way to ignore extensions which were not found in S3 - if [ "$ext" = "memcached" ] ; then + if [ "$ext" = "oci8" ] ; then + apt_deps="libaio-dev" + fi + + if [ -n "$apt_deps" ] ; then + echo "Installing dependencies for ${ext}: ${apt_deps}" | indent + install_env_file="$(apt_install "${apt_deps}" "${BUILD_DIR}" "${CACHE_DIR}" "${ENV_DIR}")" + # Source environment to export LD_LIBRARY_PATH + source "${install_env_file}" + rm "${install_env_file}" + fi + + # Install third-party dependencies after ubuntu packages have been added + if [ "$ext" = "oci8" ] ; then + install_oracle_client_extension "${BUILD_DIR}" "${CACHE_DIR}" + elif [ "$ext" = "memcached" ] ; then fetch_package "$PHP_BASE_URL" "libmemcached-${libmemcached_version}" "/app/vendor/libmemcached" | indent elif [ "$ext" = "gmp" ] ; then fetch_package "$PHP_BASE_URL" "gmp-${gmp_version}" "/app/vendor/gmp" | indent @@ -76,21 +94,16 @@ function install_composer_deps() { sodium_version=$sodium_php72_php73_version fi fetch_package "$PHP_BASE_URL" "libsodium-${sodium_version}" "/app/vendor/libsodium" | indent + fi + + local extension_package_path="ext/$(php_api_version)/php-${ext}" + package_found="$(has_package "${PHP_BASE_URL}" "${extension_package_path}")" + if [ "${package_found}" = "true" ] ; then + echo "Installing PHP extension: ${ext}" | indent + fetch_package "${PHP_BASE_URL}" "${extension_package_path}" "/app/vendor/php" else - if [[ $ext = 'oci8' ]]; then - echo "Installing libaio for oci8" | indent - install_env_file="$(install_apt_libaio "${BUILD_DIR}" "${CACHE_DIR}" "${ENV_DIR}")" - # Source environment to export LD_LIBRARY_PATH - source "${install_env_file}" - rm "${install_env_file}" - - install_oracle_client_extension "${BUILD_DIR}" "${CACHE_DIR}" - fi - local ext_version=$(jq --raw-output ".require | .[\"ext-${ext}\"]" < "${BUILD_DIR}/composer.json") - install_pecl_extension $ext "$ext_version" "${BUILD_DIR}" "$CACHE_DIR" | indent + install_pecl_extension "${ext}" "${ext_version}" "${BUILD_DIR}" "$CACHE_DIR" fi - # TODO I don't think this instruction should be executed for all extensions - fetch_package "$PHP_BASE_URL" "ext/$(php_api_version)/php-${ext}" "/app/vendor/php" 2>/dev/null || true | indent done fi diff --git a/lib/package b/lib/package new file mode 100644 index 00000000..d450eefd --- /dev/null +++ b/lib/package @@ -0,0 +1,55 @@ +function fetch_engine_package() { + local engine="$1" + local version="$2" + local location="$3" + + local base_url="$PHP_BASE_URL" + if [ "$engine" = "nginx" ] ; then + base_url="$NGINX_BASE_URL" + fi + + fetch_package "$base_url" "${engine}-${version}" "$location" +} + +function has_package() { + local base_url="${1}" + local package="${2}" + + local package_url="${base_url}/package/${package}.tgz" + + curl --output /dev/null --silent --head --location --fail "${package_url}" + if [ $? -eq 0 ] ; then + echo "true" + else + echo "false" + fi +} + +function fetch_package() { + local base_url="$1" + local package="$2" + local location="$3" + + mkdir -p "$location" + + local checksum_url="${base_url}/package/${package}.md5" + local package_url="${base_url}/package/${package}.tgz" + local checksum=$(curl --fail --retry 3 --retry-delay 2 --connect-timeout 3 --max-time 30 "$checksum_url" 2> /dev/null) + local cache_checksum="" + + if [ -f "$CACHE_DIR/package/${package}.md5" ]; then + local cache_checksum=$(cat "$CACHE_DIR/package/${package}.md5") + fi + + mkdir -p "$CACHE_DIR/package/$(dirname "$package")" + + if [ "$cache_checksum" != "$checksum" ]; then + curl --fail --retry 3 --retry-delay 2 --connect-timeout 3 --max-time 30 "$package_url" -L -s > "$CACHE_DIR/package/${package}.tgz" + echo "$checksum" > "$CACHE_DIR/package/${package}.md5" + else + echo "Checksums match. Fetching from cache." | indent + fi + + mkdir -p "$location" + tar xzf "$CACHE_DIR/package/${package}.tgz" -C "$location" +} diff --git a/lib/pecl b/lib/pecl index ce120bf7..cc06ae73 100644 --- a/lib/pecl +++ b/lib/pecl @@ -1,16 +1,3 @@ - -function enable_pecl_extension() { - local extension_name="${1}" - local is_zend_extension_var_name="PHP_PECL_EXTENSION_IS_ZEND_$extension_name" - local is_zend_extension=$(printenv $is_zend_extension_var_name) - - if [[ $is_zend_extension = "true" ]] ; then - echo "zend_extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" - else - echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" - fi -} - function install_pecl_extension() { local extension_name="${1}" local version="${2}" @@ -23,7 +10,7 @@ function install_pecl_extension() { local cache_extension_file="${cache_dir}/${extension_name}-${version}.so" if [ -f "${cache_extension_file}" ]; then - echo "Installing PECL extension ${extension_name} version ${version} from the cache" + echo "Installing PECL extension ${extension_name} version ${version} from the cache" | indent cp "${cache_extension_file}" "${ext_dir}/${extension_name}.so" enable_pecl_extension ${extension_name} return @@ -32,30 +19,36 @@ function install_pecl_extension() { local build_dir=$(pwd) local temp_dir=$(mktmpdir "pecl-extension") - echo "Installing PECL extension ${extension_name} version ${version}" + echo "Installing PECL extension ${extension_name} version ${version}" | indent pushd "${temp_dir}" > /dev/null curl --silent --location "https://pecl.php.net/get/${extension_name}-${version}.tgz" | tar xz pushd ${extension_name}-${version} > /dev/null - - /app/vendor/php/bin/phpize &> /dev/null - - local configure_extension_args_var_name="PHP_PECL_EXTENSION_CONFIGURE_ARGS_$extension_name" - local configure_extension_args=$(printenv $configure_extension_args_var_name) - local flags=$(echo $configure_extension_args | sed "s|\$BUILD_DIR|$build_dir|") - - if [[ $extension_name = 'oci8' ]]; then - if [ -e "${3}/${apt_deps_buildpack_dir}/export" ]; then - source "${3}/${apt_deps_buildpack_dir}/export" + ( + set +e + readonly phpize_log_file=$(mktemp "/tmp/pecl-phpize-${extension_name}-XXXX.log") + /app/vendor/php/bin/phpize > "${phpize_log_file}" 2>&1 + [ $? -eq 0 ] || install_pecl_error "${extension_name}" "package" "${phpize_log_file}" + + local configure_extension_args_var_name="PHP_PECL_EXTENSION_CONFIGURE_ARGS_$extension_name" + local configure_extension_args=$(printenv $configure_extension_args_var_name) + local flags=$(echo $configure_extension_args | sed "s|\$BUILD_DIR|$build_dir|") + + if [[ $extension_name = 'oci8' ]]; then + flags="--with-oci8=instantclient,${ORACLE_HOME}" fi - flags="--with-oci8=instantclient,${ORACLE_HOME}" - fi - ./configure --with-php-config=/app/vendor/php/bin/php-config $flags > /dev/null + readonly configure_log_file=$(mktemp "/tmp/pecl-configure-${extension_name}-XXXX.log") + ./configure --with-php-config=/app/vendor/php/bin/php-config $flags > "${configure_log_file}" 2>&1 + [ $? -eq 0 ] || install_pecl_error "${extension_name}" "configure build" "${configure_log_file}" + + readonly make_log_file=$(mktemp "/tmp/pecl-make-${extension_name}-XXXX.log") + make -j 2 > "${make_log_file}" 2>&1 + [ $? -eq 0 ] || install_pecl_error "${extension_name}" "compile" "${make_log_file}" + ) - make > /dev/null cp modules/${extension_name}.so "${ext_dir}/${extension_name}.so" cp modules/${extension_name}.so "${cache_extension_file}" enable_pecl_extension ${extension_name} @@ -63,3 +56,32 @@ function install_pecl_extension() { popd > /dev/null popd > /dev/null } + +function enable_pecl_extension() { + local extension_name="${1}" + local is_zend_extension_var_name="PHP_PECL_EXTENSION_IS_ZEND_$extension_name" + local is_zend_extension=$(printenv $is_zend_extension_var_name) + + if [[ $is_zend_extension = "true" ]] ; then + echo "zend_extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" + else + echo "extension=${extension_name}.so" > "/app/vendor/php/etc/conf.d/${extension_name}.ini" + fi +} + +function install_pecl_error() { + local extension_name="${1}" + local action="${2}" + local log_file="${3}" + + echo + tail -n 30 "${log_file}" | indent + echo + # This sleep prevents from having the following lines mixed up with the output + # of the above tail. Mystery of shellscripting. + sleep 0.1 + warn "Fail to ${action} of PHP PECL extension: ${extension_name}" + echo "Read above logs to understand the source of the issue" | indent + echo + exit 1 +} diff --git a/lib/pecl_oci8 b/lib/pecl_oci8 index 1e25a07a..35c84981 100644 --- a/lib/pecl_oci8 +++ b/lib/pecl_oci8 @@ -1,27 +1,3 @@ -function install_apt_libaio() { - # ---- - # Install libaio to install oci8 - local build_dir="${1}" - local cache_dir="${2}" - local env_dir="${3}" - - echo "libaio1" > "${build_dir}/Aptfile" - - apt_deps_buildpack_dir=$(mktemp apt_buildpack_XXXX) - rm "${apt_deps_buildpack_dir}" - - readonly apt_buildpack_url="https://github.com/Scalingo/apt-buildpack.git" - git clone --quiet --depth=1 "${apt_buildpack_url}" "${build_dir}/$apt_deps_buildpack_dir" >/dev/null 2>/dev/null - - "${build_dir}/${apt_deps_buildpack_dir}/bin/compile" "${build_dir}" "${cache_dir}" "${env_dir}" > /dev/null - - # Source new libs for future buildpack (update of LD_LIBRARY_PATH) - export_file="${build_dir}/oci8_apt_export" - cp "${build_dir}/${apt_deps_buildpack_dir}/export" "${export_file}" - - echo "${export_file}" -} - function install_oracle_client_extension() { # ---- # Install oracle client @@ -42,7 +18,9 @@ function install_oracle_client_extension() { unzip -q oraclesdk.zip -d "${oracle_install_dir}" rm oraclesdk.zip - local startup_script="${1}/.profile.d/oracle-client.sh" - echo "export ORACLE_HOME=${ORACLE_HOME}" >> "${startup_script}" - echo "export LD_LIBRARY_PATH=${ORACLE_HOME}/lib:${ORACLE_HOME}:\${LD_LIBRARY_PATH}" >> "${startup_script}" + readonly startup_script="${1}/.profile.d/oracle-client.sh" + # Replacing build_dir by /app, final location of the image data. + runtime_oracle_home="$(echo "${ORACLE_HOME}" | sed -e "s+${build_dir}+/app+")" + echo "export ORACLE_HOME=${runtime_oracle_home}" >> "${startup_script}" + echo "export LD_LIBRARY_PATH=${runtime_oracle_home}/lib:${runtime_oracle_home}:\${LD_LIBRARY_PATH}" >> "${startup_script}" } From 7903a16811c2224c988ec63d9e5f16bdad86ab23 Mon Sep 17 00:00:00 2001 From: Soulou Date: Thu, 2 Feb 2023 10:11:51 +0100 Subject: [PATCH 18/19] Review + readme --- README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++- lib/apt | 10 +++------- lib/composer | 2 -- lib/package | 4 ++-- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index e0d93b35..92867a7b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ support. * Lightweight stack compared to Apache-ModPHP * Composer support * Various frameworks support out of the box (no configuration) -* Dynamic installing of [supported extensions](support/ext) listed as `ext-` requirements in `composer.json`. +* Dynamic installing of PHP extensions, listed as `ext-` requirements in `composer.json`. +* Interfacing with PECL platform to download and build extensions dynamically ## How to use it @@ -415,6 +416,58 @@ A tail on each unique log file will be run at application startup ], +### PHP Extensions + +Different types of extensions can be added to the PHP runtime, with different +levels of compatibility. All these extensions can be added in the `require` +block of the `composer.json` and this buildpack will try to install them. + +``` +{ + ... + "require": { + "ext-sodium": "*", + "ext-calendar": "*", + } +} +``` + +#### Internal PHP Extensions + +The PHP binary is not built with all modules embedded. To reduce build size and +attack surface, these extensions have to be enabled manually. The supported list +can be found here: https://github.com/Scalingo/php-buildpack/tree/master/support/ext-internal + +#### PECL PHP Extensions + +PECL extensions are registered on the https://pecl.php.net platform. This +buildpack will try to download and build them during deployments. + +Some extensions may require system dependencies absent from the stack your +application is based on. In this case you're encouraged to prepend the [APT +Buildpack](https://doc.scalingo.com/platform/deployment/buildpacks/apt) and +install the missing package according to the extension documentation. + +You may need to add extra compilation flags, in this case define them through +environment variables with the following pattern: + +``` +# replace $extension_name by the right extension name +PHP_PECL_EXTENSION_CONFIGURE_ARGS_$extension_name="--flag-to-add" +``` + +If the extension you are trying to install is a Zend extension, please define + +``` +# replace $extension_name by the right extension name +PHP_PECL_EXTENSION_IS_ZEND_$extension_name=true +``` + +#### Third Party PHP Extensions + +Some third party extensions can also be installed, list can be found here +https://github.com/Scalingo/php-buildpack/tree/master/support/ext + ## Node.js If your app contains a `package.json`, Node.js and its dependencies will be diff --git a/lib/apt b/lib/apt index eacd157f..4c642ae2 100644 --- a/lib/apt +++ b/lib/apt @@ -11,11 +11,11 @@ function apt_install() { rm "${apt_deps_buildpack_dir}" readonly apt_buildpack_url="https://github.com/Scalingo/apt-buildpack.git" - git clone --quiet --depth=1 "${apt_buildpack_url}" "${apt_deps_buildpack_dir}" >/dev/null 2>/dev/null + git clone --quiet --depth=1 "${apt_buildpack_url}" "${apt_deps_buildpack_dir}" >/dev/null 2>&1 readonly apt_log_file=$(mktemp /tmp/apt_log_XXXX.log) APT_FILE_MANIFEST="$(basename ${apt_manifest})" "${apt_deps_buildpack_dir}/bin/compile" "${build_dir}" "${cache_dir}" "${env_dir}" >"${apt_log_file}" 2>&1 - if [ $? -ne 0 ] ; then + if [ $? -ne 0 ] ; then tail -n 30 "${apt_log_file}" | indent echo warn "Fail to install apt packages" @@ -24,9 +24,5 @@ function apt_install() { fi # Source new libs for future buildpack (update of LD_LIBRARY_PATH) - export_file="${build_dir}/oci8_apt_export" - cp "${apt_deps_buildpack_dir}/export" "${export_file}" - - rm "${apt_manifest}" - echo "${export_file}" + echo "${apt_deps_buildpack_dir}/export" } diff --git a/lib/composer b/lib/composer index bc1cf119..3a39bde2 100644 --- a/lib/composer +++ b/lib/composer @@ -65,9 +65,7 @@ function install_composer_deps() { for ext in $required_extensions; do local apt_deps="" local ext_version=$(jq --raw-output ".require | .[\"ext-${ext}\"]" < "${BUILD_DIR}/composer.json") - local should_install_from_pecl="true" - # TODO: Find a better way to ignore extensions which were not found in S3 if [ "$ext" = "oci8" ] ; then apt_deps="libaio-dev" fi diff --git a/lib/package b/lib/package index d450eefd..d439336f 100644 --- a/lib/package +++ b/lib/package @@ -44,12 +44,12 @@ function fetch_package() { mkdir -p "$CACHE_DIR/package/$(dirname "$package")" if [ "$cache_checksum" != "$checksum" ]; then - curl --fail --retry 3 --retry-delay 2 --connect-timeout 3 --max-time 30 "$package_url" -L -s > "$CACHE_DIR/package/${package}.tgz" + curl --fail --retry 3 --retry-delay 2 --connect-timeout 3 --max-time 30 "$package_url" --location --silent > "$CACHE_DIR/package/${package}.tgz" echo "$checksum" > "$CACHE_DIR/package/${package}.md5" else echo "Checksums match. Fetching from cache." | indent fi mkdir -p "$location" - tar xzf "$CACHE_DIR/package/${package}.tgz" -C "$location" + tar xzf "$CACHE_DIR/package/${package}.tgz" --directory "$location" } From e49d20ab4a4acafc36febc669d008dd0ad49dbd2 Mon Sep 17 00:00:00 2001 From: Soulou <329969+Soulou@users.noreply.github.com> Date: Fri, 3 Feb 2023 14:20:06 +0100 Subject: [PATCH 19/19] Update lib/apt - better logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Étienne M. --- lib/apt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/apt b/lib/apt index 4c642ae2..3477290a 100644 --- a/lib/apt +++ b/lib/apt @@ -18,7 +18,7 @@ function apt_install() { if [ $? -ne 0 ] ; then tail -n 30 "${apt_log_file}" | indent echo - warn "Fail to install apt packages" + warn "Fail to install apt packages $apt_deps" echo exit 1 fi