diff --git a/README.md b/README.md index ebf667cd2..5f308304c 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,7 @@ PHP extensions can be set up using the `extensions` input. It accepts a `string` - These extensions have custom support: - `cubrid` and `pdo_cubrid` on `Ubuntu`. - - `gearman`, `geos` and `event` on `Ubuntu` and `macOS`. + - `event`, `gearman`, `geos` and `relay` on `Ubuntu` and `macOS`. - `blackfire`, `couchbase`, `ioncube`, `oci8`, `pdo_firebird`, `pdo_oci`, `pecl_http`, `phalcon3`, `phalcon4` and `phalcon5` on all supported OS. - By default, extensions which cannot be added or disabled gracefully leave an error message in the logs, the execution is not interrupted. To change this behaviour you can set `fail-fast` flag to `true`. diff --git a/__tests__/extensions.test.ts b/__tests__/extensions.test.ts index f2c3beb33..7800bf5b7 100644 --- a/__tests__/extensions.test.ts +++ b/__tests__/extensions.test.ts @@ -59,6 +59,8 @@ describe('Extension tests', () => { ${'pdo_sqlsrv'} | ${'7.4'} | ${'add_sqlsrv pdo_sqlsrv'} ${'pecl_http'} | ${'7.3'} | ${'add_http'} ${'phalcon3'} | ${'7.3'} | ${'add_phalcon phalcon3'} + ${'relay'} | ${'7.4'} | ${'add_relay relay'} + ${'relay-v1.2.3'} | ${'7.4'} | ${'add_relay relay-v1.2.3'} ${'sqlite'} | ${'7.4'} | ${'add_extension sqlite3'} ${'sqlsrv-1.2.3-beta1'} | ${'7.4'} | ${'add_pecl_extension sqlsrv 1.2.3beta1 extension'} ${'Xdebug'} | ${'7.4'} | ${'add_extension xdebug'} @@ -92,6 +94,7 @@ describe('Extension tests', () => { ${'pcov'} | ${'5.6'} | ${'add_log "$cross" "pcov" "pcov is not supported on PHP 5.6"'} ${'pdo_oci'} | ${'7.3'} | ${'add_oci pdo_oci'} ${'pecl_http'} | ${'7.3'} | ${'add_http'} + ${'relay-1.2.3'} | ${'7.4'} | ${'add_relay relay-1.2.3'} ${'sqlite'} | ${'7.2'} | ${'add_extension sqlite3'} `( 'checking addExtensionOnDarwin for extension $extension on version $version', diff --git a/dist/index.js b/dist/index.js index 849787481..71ad512b6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -244,6 +244,7 @@ async function addExtensionDarwin(extension_csv, version) { case /.+-.+\/.+@.+/.test(extension): add_script += await utils.parseExtensionSource(extension, ext_prefix); return; + case /^(7\.4|8\.[0-2])relay(-v?\d+\.\d+\.\d+)?$/.test(version_extension): case /^(5\.[3-6]|7\.[0-4]|8\.[0-2])blackfire(-\d+\.\d+\.\d+)?$/.test(version_extension): case /^couchbase|^event|^gearman$|^geos$|^pdo_oci$|^oci8$|^(pecl_)?http|^pdo_firebird$/.test(extension): case /^(5\.[3-6]|7\.[0-4])ioncube$/.test(version_extension): @@ -358,6 +359,7 @@ async function addExtensionLinux(extension_csv, version) { case /.+-.+\/.+@.+/.test(extension): add_script += await utils.parseExtensionSource(extension, ext_prefix); return; + case /^(7\.4|8\.[0-2])relay(-v?\d+\.\d+\.\d+)?$/.test(version_extension): case /^(5\.[3-6]|7\.[0-4]|8\.[0-2])blackfire(-\d+\.\d+\.\d+)?$/.test(version_extension): case /^((5\.[3-6])|(7\.[0-2]))pdo_cubrid$|^((5\.[3-6])|(7\.[0-4]))cubrid$/.test(version_extension): case /^couchbase|^event|^gearman$|^geos$|^pdo_oci$|^oci8$|^(pecl_)?http|^pdo_firebird$/.test(extension): diff --git a/src/extensions.ts b/src/extensions.ts index c83b96ce9..ea56352df 100644 --- a/src/extensions.ts +++ b/src/extensions.ts @@ -31,11 +31,13 @@ export async function addExtensionDarwin( case /.+-.+\/.+@.+/.test(extension): add_script += await utils.parseExtensionSource(extension, ext_prefix); return; + // match 7.4relay...8.2relay // match 5.3blackfire...8.2blackfire // match 5.3blackfire-(semver)...8.1blackfire-(semver) // match couchbase, event, geos, pdo_oci, oci8, http, pecl_http // match 5.3ioncube...7.4ioncube // match 7.0phalcon3...7.3phalcon3, 7.2phalcon4...7.4phalcon4, and 7.4phalcon5...8.2phalcon5 + case /^(7\.4|8\.[0-2])relay(-v?\d+\.\d+\.\d+)?$/.test(version_extension): case /^(5\.[3-6]|7\.[0-4]|8\.[0-2])blackfire(-\d+\.\d+\.\d+)?$/.test( version_extension ): @@ -252,12 +254,14 @@ export async function addExtensionLinux( case /.+-.+\/.+@.+/.test(extension): add_script += await utils.parseExtensionSource(extension, ext_prefix); return; + // match 7.4relay...8.2relay // match 5.3blackfire...8.2blackfire // match 5.3blackfire-(semver)...8.1blackfire-(semver) // match 5.3pdo_cubrid...7.2php_cubrid, 5.3cubrid...7.4cubrid // match couchbase, geos, pdo_oci, oci8, http, pecl_http // match 5.3ioncube...7.4ioncube // match 7.0phalcon3...7.3phalcon3, 7.2phalcon4...7.4phalcon4, 7.4phalcon5...8.2phalcon5 + case /^(7\.4|8\.[0-2])relay(-v?\d+\.\d+\.\d+)?$/.test(version_extension): case /^(5\.[3-6]|7\.[0-4]|8\.[0-2])blackfire(-\d+\.\d+\.\d+)?$/.test( version_extension ): diff --git a/src/scripts/extensions/relay.sh b/src/scripts/extensions/relay.sh new file mode 100644 index 000000000..ea6c2f0cf --- /dev/null +++ b/src/scripts/extensions/relay.sh @@ -0,0 +1,143 @@ +# Get relay version +get_relay_version() { + local ext=$1 + if [[ "$ext" =~ ^relay$ ]]; then + get -s -n "" "${relay_releases:?}"/latest 2<&1 | grep -m 1 -Eo "tag/(v[0-9]+(\.[0-9]+)?(\.[0-9]+)?)" | head -n 1 | cut -d '/' -f 2 + else + relay_version="${ext##*-}" + echo "v${relay_version/v//}" + fi +} + +# Get OS suffix in relay artifact URL. +get_os_suffix() { + if [ "$os" = "Linux" ]; then + if [[ "$ID" =~ ubuntu|debian ]]; then + echo debian + elif [ "$ID" = "centos" ]; then + echo centos"$VERSION_ID" + else + echo "$ID" + fi + else + echo darwin + fi +} + +# Get openssl suffix in relay artifact URL. +get_openssl_suffix() { + openssl_3=$(php -r "echo strpos(OPENSSL_VERSION_TEXT, 'SSL 3') !== false;") + [ "$openssl_3" = "1" ] && echo '.libssl3' || echo '' +} + +# Change library paths in relay binary. +change_library_paths() { + if [ "$os" = "Darwin" ]; then + otool -L "${ext_dir:?}"/relay.so | grep -q 'ssl.1' && openssl_version='1.1' || openssl_version='3' + [ -e "${brew_prefix:?}"/opt/openssl@"$openssl_version" ] || brew install openssl@"$openssl_version" + dylibs="$(otool -L "${ext_dir:?}"/relay.so | grep -Eo '.*\.dylib' | cut -f1 -d ' ')" + install_name_tool -change "$(echo "${dylibs}" | grep -E "libzstd.*dylib" | xargs)" "$brew_prefix"/opt/zstd/lib/libzstd.dylib "$ext_dir"/relay.so + install_name_tool -change "$(echo "${dylibs}" | grep -E "liblz4.*dylib" | xargs)" "$brew_prefix"/opt/lz4/lib/liblz4.dylib "$ext_dir"/relay.so + install_name_tool -change "$(echo "${dylibs}" | grep -E "libssl.*dylib" | xargs)" "$brew_prefix"/opt/openssl@"$openssl_version"/lib/libssl.dylib "$ext_dir"/relay.so + install_name_tool -change "$(echo "${dylibs}" | grep -E "libcrypto.*dylib" | xargs)" "$brew_prefix"/opt/openssl@"$openssl_version"/lib/libcrypto.dylib "$ext_dir"/relay.so + fi +} + +# Add relay dependencies +add_relay_dependencies() { + add_extension json + add_extension msgpack + add_extension igbinary + if [ "$os" = "Darwin" ]; then + . "${0%/*}"/tools/brew.sh + configure_brew + brew install hiredis lz4 zstd + fi +} + +# Initialize relay extension ini configuration +init_relay_ini() { + relay_ini=$1 + if [ -e "$relay_ini" ]; then + if [[ -n "$RELAY_KEY" ]]; then + sudo sed -i.bak "s/^; relay.key =.*/relay.key = $RELAY_KEY/" "$relay_ini" + fi + if [[ -n "$RELAY_ENVIRONMENT" ]]; then + sudo sed -i.bak "s/^; relay.environment =.*/relay.environment = $RELAY_ENVIRONMENT/" "$relay_ini" + fi + if [[ -n "$RELAY_EVICTION_POLICY" ]]; then + sudo sed -i.bak "s/^; relay.eviction_policy =.*/relay.eviction_policy = $RELAY_EVICTION_POLICY/" "$relay_ini" + fi + if [[ -n "$RELAY_MAX_MEMORY" ]]; then + sudo sed -i.bak "s/^; relay.maxmemory =.*/relay.maxmemory = $RELAY_MAX_MEMORY/" "$relay_ini" + fi + sudo rm -rf "$relay_ini".bak + fi +} + +# Enable relay extension +enable_relay() { + relay_ini=$1 + if [ -e "$relay_ini" ]; then + init_relay_ini "$relay_ini" + if [ "$os" = "Linux" ]; then + sudo mv "$relay_ini" "${ini_dir:?}"/../mods-available/relay.ini + sudo phpenmod -v "${version:?}" relay + else + sudo mv "${relay_ini}" "${scan_dir:?}"/60-relay.ini + fi + fi +} + +# Patch binary id in relay extension +init_relay_binary_id() { + if [ -e "${ext_dir:?}"/relay.so ]; then + grep -aq 00000000 "${ext_dir:?}"/relay.so && \ + sudo LC_ALL=C sed -i.bak "s/00000000-0000-0000-0000-000000000000/$(uuidgen)/" "$ext_dir"/relay.so + fi +} + +# Configure relay extension +configure_relay() { + change_library_paths + init_relay_binary_id + enable_relay "${ext_dir}"/relay.ini +} + +# Helper function to add relay extension +add_relay_helper() { + arch="$(uname -m | sed 's/_/-/')" + os_suffix="$(get_os_suffix)" + openssl_suffix="$(get_openssl_suffix)" + artifact_file_name="relay-$relay_version-php${version:?}-$os_suffix-$arch$openssl_suffix.tar.gz" + url="$relay_releases"/download/"$relay_version"/"$artifact_file_name" + fallback_url="$relay_trunk"/"$artifact_file_name" + get -q -n /tmp/relay.tar.gz "$url" "$fallback_url" + if [ "$openssl_suffix" = '.libssl3' ] && (! [ -e /tmp/relay.tar.gz ] || ! file /tmp/relay.tar.gz | grep -q 'gzip'); then + get -q -n /tmp/relay.tar.gz "${url/.libssl3/}" "${fallback_url/.libssl3/}" + fi + if [ -e /tmp/relay.tar.gz ] && file /tmp/relay.tar.gz | grep -q 'gzip'; then + sudo tar --strip-components=1 -xzf /tmp/relay.tar.gz -C "${ext_dir:?}" + sudo mv "${ext_dir:?}"/relay-pkg.so "${ext_dir:?}"/relay.so + fi +} + +# Add relay extension +add_relay() { + local ext=$1 + local arch + local url + os=$(uname -s) + relay_releases=https://github.com/cachewerk/relay/releases + relay_trunk=https://builds.r2.relay.so + relay_version=$(get_relay_version "$ext") + add_relay_dependencies >/dev/null 2>&1 + if shared_extension relay; then + message="Enabled" + else + add_relay_helper >/dev/null 2>&1 + message="Installed and enabled" + fi + configure_relay >/dev/null 2>&1 + add_extension_log relay "$message" +}