Unverified Commit 5ad3f6fb authored by Gaurav Saini's avatar Gaurav Saini Committed by GitHub

[python] - cpython - prev. version fallback - fix (#907)

* [python] - cpython - prev. version fallback - fix

* according to comments
parent a674273c
{ {
"id": "python", "id": "python",
"version": "1.4.1", "version": "1.4.2",
"name": "Python", "name": "Python",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/python", "documentationURL": "https://github.com/devcontainers/features/tree/main/src/python",
"description": "Installs the provided version of Python, as well as PIPX, and other common Python utilities. JupyterLab is conditionally installed with the python feature. Note: May require source code compilation.", "description": "Installs the provided version of Python, as well as PIPX, and other common Python utilities. JupyterLab is conditionally installed with the python feature. Note: May require source code compilation.",
......
...@@ -248,6 +248,48 @@ find_version_from_git_tags() { ...@@ -248,6 +248,48 @@ find_version_from_git_tags() {
echo "${variable_name}=${!variable_name}" 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)
local version_suffix_regex=$6
# 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
}
# Use Oryx to install something using a partial version match # Use Oryx to install something using a partial version match
oryx_install() { oryx_install() {
local platform=$1 local platform=$1
...@@ -368,6 +410,29 @@ install_openssl3() { ...@@ -368,6 +410,29 @@ install_openssl3() {
rm -rf /tmp/openssl3 rm -rf /tmp/openssl3
} }
install_prev_vers_cpython() {
VERSION=$1
echo -e "\n(!) Failed to fetch the latest artifacts for cpython ${VERSION}..."
find_prev_version_from_git_tags VERSION https://github.com/python/cpython
echo -e "\nAttempting to install ${VERSION}"
install_cpython "${VERSION}"
}
install_cpython() {
VERSION=$1
INSTALL_PATH="${PYTHON_INSTALL_PATH}/${VERSION}"
if [ -d "${INSTALL_PATH}" ]; then
echo "(!) Python version ${VERSION} already exists."
exit 1
fi
mkdir -p /tmp/python-src ${INSTALL_PATH}
cd /tmp/python-src
cpython_tgz_filename="Python-${VERSION}.tgz"
cpython_tgz_url="https://www.python.org/ftp/python/${VERSION}/${cpython_tgz_filename}"
echo "Downloading ${cpython_tgz_filename}..."
curl -sSL -o "/tmp/python-src/${cpython_tgz_filename}" "${cpython_tgz_url}"
}
install_from_source() { install_from_source() {
VERSION=$1 VERSION=$1
echo "(*) Building Python ${VERSION} from source..." echo "(*) Building Python ${VERSION} from source..."
...@@ -378,13 +443,6 @@ install_from_source() { ...@@ -378,13 +443,6 @@ install_from_source() {
# Find version using soft match # Find version using soft match
find_version_from_git_tags VERSION "https://github.com/python/cpython" find_version_from_git_tags VERSION "https://github.com/python/cpython"
INSTALL_PATH="${PYTHON_INSTALL_PATH}/${VERSION}"
if [ -d "${INSTALL_PATH}" ]; then
echo "(!) Python version ${VERSION} already exists."
exit 1
fi
# Some platforms/os versions need modern versions of openssl installed # Some platforms/os versions need modern versions of openssl installed
# via common package repositories, for now rhel-7 family, use case statement to # via common package repositories, for now rhel-7 family, use case statement to
# make it easy to expand # make it easy to expand
...@@ -396,23 +454,21 @@ install_from_source() { ...@@ -396,23 +454,21 @@ install_from_source() {
;; ;;
esac esac
# Download tgz of source install_cpython "${VERSION}"
mkdir -p /tmp/python-src ${INSTALL_PATH} if [ -f "/tmp/python-src/${cpython_tgz_filename}" ]; then
cd /tmp/python-src if grep -q "404 Not Found" "/tmp/python-src/${cpython_tgz_filename}"; then
local tgz_filename="Python-${VERSION}.tgz" install_prev_vers_cpython "${VERSION}"
local tgz_url="https://www.python.org/ftp/python/${VERSION}/${tgz_filename}" fi
echo "Downloading ${tgz_filename}..." fi;
curl -sSL -o "/tmp/python-src/${tgz_filename}" "${tgz_url}"
# Verify signature # Verify signature
if [[ ${VERSION_CODENAME} = "centos7" ]] || [[ ${VERSION_CODENAME} = "rhel7" ]]; then if [[ ${VERSION_CODENAME} = "centos7" ]] || [[ ${VERSION_CODENAME} = "rhel7" ]]; then
receive_gpg_keys_centos7 PYTHON_SOURCE_GPG_KEYS receive_gpg_keys_centos7 PYTHON_SOURCE_GPG_KEYS
else else
receive_gpg_keys PYTHON_SOURCE_GPG_KEYS receive_gpg_keys PYTHON_SOURCE_GPG_KEYS
fi fi
echo "Downloading ${tgz_filename}.asc..." echo "Downloading ${cpython_tgz_filename}.asc..."
curl -sSL -o "/tmp/python-src/${tgz_filename}.asc" "${tgz_url}.asc" curl -sSL -o "/tmp/python-src/${cpython_tgz_filename}.asc" "${cpython_tgz_url}.asc"
gpg --verify "${tgz_filename}.asc" gpg --verify "${cpython_tgz_filename}.asc"
# Update min protocol for testing only - https://bugs.python.org/issue41561 # Update min protocol for testing only - https://bugs.python.org/issue41561
if [ -f /etc/pki/tls/openssl.cnf ]; then if [ -f /etc/pki/tls/openssl.cnf ]; then
...@@ -424,7 +480,7 @@ install_from_source() { ...@@ -424,7 +480,7 @@ install_from_source() {
export OPENSSL_CONF=/tmp/python-src/openssl.cnf export OPENSSL_CONF=/tmp/python-src/openssl.cnf
# Untar and build # Untar and build
tar -xzf "/tmp/python-src/${tgz_filename}" -C "/tmp/python-src" --strip-components=1 tar -xzf "/tmp/python-src/${cpython_tgz_filename}" -C "/tmp/python-src" --strip-components=1
local config_args="" local config_args=""
if [ "${OPTIMIZE_BUILD_FROM_SOURCE}" = "true" ]; then if [ "${OPTIMIZE_BUILD_FROM_SOURCE}" = "true" ]; then
config_args="${config_args} --enable-optimizations" config_args="${config_args} --enable-optimizations"
......
This diff is collapsed.
{ {
"install_cpython_fallback_prev_version_test": {
"image": "python:3.12",
"features": {
"python": {
"version": "3.12",
"installTools": false,
"skipVulnerabilityPatching": true
}
}
},
"install_python310_skipVulnerabilityPatching_true": { "install_python310_skipVulnerabilityPatching_true": {
"image": "python:3.10", "image": "python:3.10",
"features": { "features": {
......
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