Unverified Commit a7c8c9a8 authored by Gaurav Saini's avatar Gaurav Saini Committed by GitHub

[Php] - fallback to previous version - code fix (#908)

* [php]- php fallback to prev. version - fix

* update patch version for php feature

* few changes..

* small change

* test completes successfully pointing at the new fallbacked php version

* changes acc. to review comments..
parent 55dbe138
{
"id": "php",
"version": "1.1.2",
"version": "1.1.3",
"name": "PHP",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/php",
"options": {
......
......@@ -121,6 +121,46 @@ find_version_from_git_tags() {
echo "${variable_name}=${!variable_name}"
}
# Use semver logic to decrement a version number then look for the closest match
find_prev_version_from_git_tags() {
local variable_name=$1
local current_version=${!variable_name}
local repository=$2
# Normally a "v" is used before the version number, but support alternate cases
local prefix=${3:-"tags/v"}
# Some repositories use "_" instead of "." for version number part separation, support that
local separator=${4:-"."}
# Some tools release versions that omit the last digit (e.g. go)
local last_part_optional=${5:-"false"}
# Some repositories may have tags that include a suffix (e.g. actions/node-versions)
# Try one break fix version number less if we get a failure. Use "set +e" since "set -e" can cause failures in valid scenarios.
set +e
major="$(echo "${current_version}" | grep -oE '^[0-9]+' || echo '')"
minor="$(echo "${current_version}" | grep -oP '^[0-9]+\.\K[0-9]+' || echo '')"
breakfix="$(echo "${current_version}" | grep -oP '^[0-9]+\.[0-9]+\.\K[0-9]+' 2>/dev/null || echo '')"
if [ "${minor}" = "0" ] && [ "${breakfix}" = "0" ]; then
((major=major-1))
declare -g ${variable_name}="${major}"
# Look for latest version from previous major release
find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}"
# Handle situations like Go's odd version pattern where "0" releases omit the last part
elif [ "${breakfix}" = "" ] || [ "${breakfix}" = "0" ]; then
((minor=minor-1))
declare -g ${variable_name}="${major}.${minor}"
# Look for latest version from previous minor release
find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}"
else
((breakfix=breakfix-1))
if [ "${breakfix}" = "0" ] && [ "${last_part_optional}" = "true" ]; then
declare -g ${variable_name}="${major}.${minor}"
else
declare -g ${variable_name}="${major}.${minor}.${breakfix}"
fi
fi
set -e
}
# Install PHP Composer
addcomposer() {
"${PHP_SRC}" -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
......@@ -130,8 +170,7 @@ addcomposer() {
"${PHP_SRC}" -r "unlink('composer-setup.php');"
}
install_php() {
PHP_VERSION="$1"
init_php_install() {
PHP_INSTALL_DIR="${PHP_DIR}/${PHP_VERSION}"
if [ -d "${PHP_INSTALL_DIR}" ]; then
echo "(!) PHP version ${PHP_VERSION} already exists."
......@@ -142,7 +181,6 @@ install_php() {
groupadd -r php
fi
usermod -a -G php "${USERNAME}"
PHP_URL="https://www.php.net/distributions/php-${PHP_VERSION}.tar.gz"
PHP_INI_DIR="${PHP_INSTALL_DIR}/ini"
......@@ -155,7 +193,26 @@ install_php() {
PHP_SRC_DIR="/usr/src/php"
mkdir -p $PHP_SRC_DIR
cd $PHP_SRC_DIR
wget -O php.tar.xz "$PHP_URL"
}
install_previous_version() {
PHP_VERSION=$1
if [[ "$ORIGINAL_PHP_VERSION" == "latest" ]]; then
find_prev_version_from_git_tags PHP_VERSION https://github.com/php/php-src "tags/php-"
echo -e "\nAttempting to install previous version v${PHP_VERSION}"
init_php_install
wget -O php.tar.xz "$PHP_URL"
else
echo -e "\nFailed to install v$PHP_VERSION"
fi
}
install_php() {
PHP_VERSION="$1"
init_php_install
wget -O php.tar.xz "$PHP_URL" || install_previous_version "$PHP_VERSION"
tar -xf $PHP_SRC_DIR/php.tar.xz -C "$PHP_SRC_DIR" --strip-components=1
cd $PHP_SRC_DIR;
......@@ -195,7 +252,7 @@ install_php() {
if [ "${PHP_VERSION}" != "none" ]; then
# Persistent / runtime dependencies
RUNTIME_DEPS="wget ca-certificates git build-essential xz-utils"
RUNTIME_DEPS="wget ca-certificates git build-essential xz-utils curl"
# PHP dependencies
PHP_DEPS="libssl-dev libcurl4-openssl-dev libedit-dev libsqlite3-dev libxml2-dev zlib1g-dev libsodium-dev libonig-dev"
......@@ -214,6 +271,8 @@ if [ "${PHP_VERSION}" != "none" ]; then
# Install dependencies
check_packages $RUNTIME_DEPS $PHP_DEPS $PHPIZE_DEPS
# storing value of PHP_VERSION before it changes
ORIGINAL_PHP_VERSION=$PHP_VERSION
find_version_from_git_tags PHP_VERSION https://github.com/php/php-src "tags/php-"
install_php "${PHP_VERSION}"
......
......@@ -32,5 +32,13 @@
"installComposer": true
}
}
},
"test_php_fallback": {
"image": "ubuntu:focal",
"features": {
"php": {
"version": "latest"
}
}
}
}
#!/bin/bash
echo -e "\nInstalled PHP Version by Feature: 👇 "; php -v;
USERNAME="root"
PHP_DIR="/usr/local/php"
# Figure out correct version of a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
local requested_version=${!variable_name}
if [ "${requested_version}" = "none" ]; then return; fi
local repository=$2
local prefix=${3:-"tags/v"}
local separator=${4:-"."}
local last_part_optional=${5:-"false"}
echo "${!variable_name}"
echo "$(echo "${requested_version}" | grep -o "." | wc -l)"
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
local escaped_separator=${separator//./\\.}
local last_part
if [ "${last_part_optional}" = "true" ]; then
last_part="(${escaped_separator}[0-9]+)?"
else
last_part="${escaped_separator}[0-9]+"
fi
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
else
set +e
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
set -e
fi
fi
echo "${!variable_name}"
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
exit 1
fi
echo "${variable_name}=${!variable_name}"
}
# Use semver logic to decrement a version number then look for the closest match
find_prev_version_from_git_tags() {
local variable_name=$1
local current_version=${!variable_name}
local repository=$2
# Normally a "v" is used before the version number, but support alternate cases
local prefix=${3:-"tags/v"}
# Some repositories use "_" instead of "." for version number part separation, support that
local separator=${4:-"."}
# Some tools release versions that omit the last digit (e.g. go)
local last_part_optional=${5:-"false"}
# Some repositories may have tags that include a suffix (e.g. actions/node-versions)
# Try one break fix version number less if we get a failure. Use "set +e" since "set -e" can cause failures in valid scenarios.
set +e
major="$(echo "${current_version}" | grep -oE '^[0-9]+' || echo '')"
minor="$(echo "${current_version}" | grep -oP '^[0-9]+\.\K[0-9]+' || echo '')"
breakfix="$(echo "${current_version}" | grep -oP '^[0-9]+\.[0-9]+\.\K[0-9]+' 2>/dev/null || echo '')"
if [ "${minor}" = "0" ] && [ "${breakfix}" = "0" ]; then
((major=major-1))
declare -g ${variable_name}="${major}"
# Look for latest version from previous major release
find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}"
# Handle situations like Go's odd version pattern where "0" releases omit the last part
elif [ "${breakfix}" = "" ] || [ "${breakfix}" = "0" ]; then
((minor=minor-1))
declare -g ${variable_name}="${major}.${minor}"
# Look for latest version from previous minor release
find_version_from_git_tags "${variable_name}" "${repository}" "${prefix}" "${separator}" "${last_part_optional}"
else
((breakfix=breakfix-1))
if [ "${breakfix}" = "0" ] && [ "${last_part_optional}" = "true" ]; then
declare -g ${variable_name}="${major}.${minor}"
else
declare -g ${variable_name}="${major}.${minor}.${breakfix}"
fi
fi
set -e
}
init_php_install() {
PHP_INSTALL_DIR="${PHP_DIR}/${PHP_VERSION}"
if [ -d "${PHP_INSTALL_DIR}" ]; then
echo "(!) PHP version ${PHP_VERSION} already exists."
exit 1
fi
if ! cat /etc/group | grep -e "^php:" > /dev/null 2>&1; then
groupadd -r php
fi
usermod -a -G php "${USERNAME}"
PHP_URL="https://www.php.net/distributions/php-${PHP_VERSION}.tar.gz"
PHP_INI_DIR="${PHP_INSTALL_DIR}/ini"
CONF_DIR="${PHP_INI_DIR}/conf.d"
mkdir -p "${CONF_DIR}";
PHP_EXT_DIR="${PHP_INSTALL_DIR}/extensions"
mkdir -p "${PHP_EXT_DIR}"
PHP_SRC_DIR="/usr/src/php"
mkdir -p $PHP_SRC_DIR
cd $PHP_SRC_DIR
}
install_previous_version() {
echo -e "\nInstalling Previous Version..."
find_prev_version_from_git_tags PHP_VERSION https://github.com/php/php-src "tags/php-"
echo -e "\nNow installing this version as a fallback previous version: ${PHP_VERSION} 🤞🏻"
init_php_install
wget -O php.tar.xz "$PHP_URL"
}
install_php() {
# trying to install with a possible new tag not having a released source binary yet
PHP_VERSION="8.3.xyz"
init_php_install
wget -O php.tar.xz "$PHP_URL" || install_previous_version
tar -xf $PHP_SRC_DIR/php.tar.xz -C "$PHP_SRC_DIR" --strip-components=1
cd $PHP_SRC_DIR;
# PHP 7.4+, the pecl/pear installers are officially deprecated and are removed in PHP 8+
# Thus, requiring an explicit "--with-pear"
IFS="."
read -a versions <<< "${PHP_VERSION}"
PHP_MAJOR_VERSION=${versions[0]}
PHP_MINOR_VERSION=${versions[1]}
VERSION_CONFIG=""
if (( $(($PHP_MAJOR_VERSION)) >= 8 )) || (( $(($PHP_MAJOR_VERSION)) == 7 && $(($PHP_MINOR_VERSION)) >= 4 )); then
VERSION_CONFIG="--with-pear"
fi
./configure --prefix="${PHP_INSTALL_DIR}" --with-config-file-path="$PHP_INI_DIR" --with-config-file-scan-dir="$CONF_DIR" --enable-option-checking=fatal --with-curl --with-libedit --enable-mbstring --with-openssl --with-zlib --with-password-argon2 --with-sodium=shared "$VERSION_CONFIG" EXTENSION_DIR="$PHP_EXT_DIR";
make -j "$(nproc)"
find -type f -name '*.a' -delete
make install
find "${PHP_INSTALL_DIR}" -type f -executable -exec strip --strip-all '{}' + || true
make clean
cp -v $PHP_SRC_DIR/php.ini-* "$PHP_INI_DIR/";
cp "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# Install xdebug
"${PHP_INSTALL_DIR}/bin/pecl" install xdebug
XDEBUG_INI="${CONF_DIR}/xdebug.ini"
echo "zend_extension=${PHP_EXT_DIR}/xdebug.so" > "${XDEBUG_INI}"
echo "xdebug.mode = debug" >> "${XDEBUG_INI}"
echo "xdebug.start_with_request = yes" >> "${XDEBUG_INI}"
echo "xdebug.client_port = 9003" >> "${XDEBUG_INI}"
}
apt-get purge php.*
PHP_DIR="/usr/local/php"
PHP_INSTALL_DIR="${PHP_DIR}/${PHP_VERSION}"
PHP_SRC_DIR="/usr/src/php"
install_php
PHP_SRC="${PHP_INSTALL_DIR}/bin/php"
updaterc() {
echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..."
if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then
echo -e "$1" >> /etc/bash.bashrc
fi
if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then
echo -e "$1" >> /etc/zsh/zshrc
fi
}
if [ "${PHP_VERSION}" != "none" ]; then
CURRENT_DIR="${PHP_DIR}/current"
if [[ ! -d "${CURRENT_DIR}" ]]; then
ln -s -r "${PHP_INSTALL_DIR}" ${CURRENT_DIR}
fi
if [[ $(ls -l ${CURRENT_DIR}) != *"-> ${PHP_INSTALL_DIR}"* ]] ; then
rm "${CURRENT_DIR}"
ln -s -r "${PHP_INSTALL_DIR}" "${CURRENT_DIR}"
fi
rm -rf "${PHP_SRC_DIR}"
updaterc "if [[ \"\${PATH}\" != *\"${CURRENT_DIR}\"* ]]; then export PATH=\"${CURRENT_DIR}/bin:\${PATH}\"; fi"
chown -R "${USERNAME}:php" "${PHP_DIR}"
chmod -R g+r+w "${PHP_DIR}"
find "${PHP_DIR}" -type d -print0 | xargs -n 1 -0 chmod g+s
fi
echo -e "\nInstalled PHP Version by Test: 👇 "; php -v;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment