Skip to content

Commit 009880b

Browse files
authored
Remove Python 3.8 support + deprecate Python 3.9 (#1732)
Python 3.8 reached upstream EOL on 7th October 2024: https://devguide.python.org/versions/#supported-versions The Python version support policy is that supported versions follows the upstream EOL lifecycle: https://devcenter.heroku.com/articles/python-support#python-version-support-policy As such, the buildpack has been showing a deprecation warning with a scheduled removal date since December 2023: - #1515 - #1721 - https://devcenter.heroku.com/changelog-items/2768 (Plus Python 3.8 binaries have never been available for Heroku-22 or Heroku-24, meaning it was only ever supported on Heroku-20 and older.) Dropping support for Python 3.8 also unblocks upgrading to Poetry v2 (which has already dropped 3.8 support). Apps using Python 3.8 that aren't able to upgrade immediately will need to pin to an older buildpack version temporarily (which will work until Heroku-20 EOLs). A deprecation warning has now also been added for Python 3.9. GUS-W-17472311. GUS-W-14846945.
1 parent 9a649bc commit 009880b

File tree

20 files changed

+173
-199
lines changed

20 files changed

+173
-199
lines changed

.github/workflows/build_python_runtime.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ jobs:
5858
run: aws s3 sync ./upload "s3://${S3_BUCKET}"
5959

6060
heroku-22:
61-
# On Heroku-22 we only support Python 3.9+.
62-
if: inputs.stack == 'heroku-22' || (inputs.stack == 'auto' && !startsWith(inputs.python_version,'3.8.'))
61+
if: inputs.stack == 'heroku-22' || inputs.stack == 'auto'
6362
runs-on: pub-hk-ubuntu-24.04-xlarge
6463
env:
6564
STACK_VERSION: "22"
@@ -80,8 +79,7 @@ jobs:
8079
run: aws s3 sync ./upload "s3://${S3_BUCKET}"
8180

8281
heroku-24:
83-
# On Heroku-24 we only support Python 3.9+.
84-
if: inputs.stack == 'heroku-24' || (inputs.stack == 'auto' && !startsWith(inputs.python_version,'3.8.'))
82+
if: inputs.stack == 'heroku-24' || inputs.stack == 'auto'
8583
strategy:
8684
fail-fast: false
8785
matrix:

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## [Unreleased]
44

5+
- Added a deprecation warning for Python 3.9. ([#1732](https://github.com/heroku/heroku-buildpack-python/pull/1732))
6+
- Removed support for Python 3.8. ([#1732](https://github.com/heroku/heroku-buildpack-python/pull/1732))
7+
- Improved the error messages shown for EOL or unrecognised major Python versions. ([#1732](https://github.com/heroku/heroku-buildpack-python/pull/1732))
58

69
## [v273] - 2025-01-03
710

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ The supported Python versions are:
4949
These Python versions are deprecated on Heroku:
5050

5151
- Python 3.9
52-
- Python 3.8 (only available on the [Heroku-20](https://devcenter.heroku.com/articles/heroku-20-stack) stack)
5352

5453
Python versions older than those listed above are no longer supported, since they have reached
5554
end-of-life [upstream](https://devguide.python.org/versions/#supported-versions).

bin/compile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ meta_time "package_manager_install_duration" "${package_manager_install_start_ti
194194
# Installs the sqlite3 dev headers and sqlite3 binary but not the
195195
# libsqlite3-0 library since that exists in the base image.
196196
# We skip this step on Python 3.13 or when using Poetry, as a first step towards removing this feature.
197-
if [[ "${python_major_version}" == +(3.8|3.9|3.10|3.11|3.12) && "${package_manager}" != "poetry" ]]; then
197+
if [[ "${python_major_version}" == +(3.9|3.10|3.11|3.12) && "${package_manager}" != "poetry" ]]; then
198198
install_sqlite_start_time=$(nowms)
199199
source "${BUILDPACK_DIR}/bin/steps/sqlite3"
200200
buildpack_sqlite3_install

bin/steps/python

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ PYTHON_URL="${S3_BASE_URL}/python-${python_full_version}-ubuntu-${UBUNTU_VERSION
1414
# 1. It's a Python major version we've deprecated and so is only available on older stacks (i.e: Python 3.8).
1515
# 2. If an exact Python version was requested and the patch version doesn't exist (e.g. 3.12.999).
1616
# 3. The user has pinned to an older buildpack version and the S3 bucket location or layout has changed since.
17-
# TODO: Update this message to be more specific once Python 3.8 support is dropped.
17+
# TODO: Update this message to be more specific now that Python 3.8 support has been removed, and so (1) can no longer occur.
1818
if ! curl --output /dev/null --silent --head --fail --retry 3 --retry-connrefused --connect-timeout 10 "${PYTHON_URL}"; then
1919
output::error <<-EOF
2020
Error: Python ${python_full_version} isn't available for this stack (${STACK}).
@@ -74,18 +74,22 @@ function warn_if_patch_update_available() {
7474
# We wait until now to display outdated Python version warnings, since we only want to show them
7575
# if there weren't any errors with the version to avoid adding noise to the error messages.
7676
# TODO: Move this into lib/ as part of the warnings refactor.
77-
if [[ "${python_major_version}" == "3.8" ]]; then
78-
output::warning <<-'EOF'
79-
Warning: Support for Python 3.8 is ending soon!
77+
if [[ "${python_major_version}" == "3.9" ]]; then
78+
output::warning <<-EOF
79+
Warning: Support for Python 3.9 is ending soon!
8080
81-
Python 3.8 reached its upstream end-of-life on 7th October 2024, and so
82-
no longer receives security updates:
81+
Python 3.9 will reach its upstream end-of-life in October 2025,
82+
at which point it will no longer receive security updates:
8383
https://devguide.python.org/versions/#supported-versions
8484
85-
Support for Python 3.8 will be removed from this buildpack on 7th January 2025.
85+
As such, support for Python 3.9 will be removed from this
86+
buildpack on 7th January 2026.
8687
87-
Upgrade to a newer Python version as soon as possible to keep your app secure.
88-
See: https://devcenter.heroku.com/articles/python-runtimes
88+
Upgrade to a newer Python version as soon as possible, by
89+
changing the version in your ${python_version_origin} file.
90+
91+
For more information, see:
92+
https://devcenter.heroku.com/articles/python-support#supported-python-versions
8993
EOF
9094
fi
9195

builds/build_python_runtime.sh

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function abort() {
2121
}
2222

2323
case "${STACK:?}" in
24-
heroku-22 | heroku-24)
24+
heroku-20 | heroku-22 | heroku-24)
2525
SUPPORTED_PYTHON_VERSIONS=(
2626
"3.9"
2727
"3.10"
@@ -30,16 +30,6 @@ case "${STACK:?}" in
3030
"3.13"
3131
)
3232
;;
33-
heroku-20)
34-
SUPPORTED_PYTHON_VERSIONS=(
35-
"3.8"
36-
"3.9"
37-
"3.10"
38-
"3.11"
39-
"3.12"
40-
"3.13"
41-
)
42-
;;
4333
*)
4434
abort "Unsupported stack '${STACK}'!"
4535
;;
@@ -63,7 +53,7 @@ case "${PYTHON_MAJOR_VERSION}" in
6353
# https://keybase.io/pablogsal/
6454
GPG_KEY_FINGERPRINT='A035C8C19219BA821ECEA86B64E628F8D684696D'
6555
;;
66-
3.8 | 3.9)
56+
3.9)
6757
# https://keybase.io/ambv/
6858
GPG_KEY_FINGERPRINT='E3FF2839C048B25C084DEBE9B26995E310250568'
6959
;;
@@ -122,7 +112,7 @@ CONFIGURE_OPTS=(
122112
"--with-system-expat"
123113
)
124114

125-
if [[ "${PYTHON_MAJOR_VERSION}" != +(3.8|3.9) ]]; then
115+
if [[ "${PYTHON_MAJOR_VERSION}" != +(3.9) ]]; then
126116
CONFIGURE_OPTS+=(
127117
# Shared builds are beneficial for a number of reasons:
128118
# - Reduces the size of the build, since it avoids the duplication between
@@ -147,7 +137,7 @@ if [[ "${PYTHON_MAJOR_VERSION}" != +(3.8|3.9) ]]; then
147137
)
148138
fi
149139

150-
if [[ "${PYTHON_MAJOR_VERSION}" != +(3.8|3.9|3.10) ]]; then
140+
if [[ "${PYTHON_MAJOR_VERSION}" != +(3.9|3.10) ]]; then
151141
CONFIGURE_OPTS+=(
152142
# Skip building the test modules, since we remove them after the build anyway.
153143
# This feature was added in Python 3.10+, however it wasn't until Python 3.11
@@ -170,7 +160,7 @@ fi
170160
# - https://github.com/docker-library/python/issues/810
171161
# We only use `dpkg-buildflags` for Python versions where we build in shared mode (Python 3.9+),
172162
# since some of the options it enables interferes with the stripping of static libraries.
173-
if [[ "${PYTHON_MAJOR_VERSION}" == +(3.8|3.9) ]]; then
163+
if [[ "${PYTHON_MAJOR_VERSION}" == +(3.9) ]]; then
174164
EXTRA_CFLAGS=''
175165
LDFLAGS='-Wl,--strip-all'
176166
else
@@ -182,7 +172,7 @@ CPU_COUNT="$(nproc)"
182172
make -j "${CPU_COUNT}" "EXTRA_CFLAGS=${EXTRA_CFLAGS}" "LDFLAGS=${LDFLAGS}"
183173
make install
184174

185-
if [[ "${PYTHON_MAJOR_VERSION}" == +(3.8|3.9) ]]; then
175+
if [[ "${PYTHON_MAJOR_VERSION}" == +(3.9) ]]; then
186176
# On older versions of Python we're still building the static library, which has to be
187177
# manually stripped since the linker stripping enabled in LDFLAGS doesn't cover them.
188178
# We're using `--strip-unneeded` since `--strip-all` would remove the `.symtab` section
@@ -233,7 +223,7 @@ LD_LIBRARY_PATH="${SRC_DIR}" "${SRC_DIR}/python" -m compileall -f --invalidation
233223
# (e.g. `python -m pydoc`) if needed.
234224
rm "${INSTALL_DIR}"/bin/{idle,pydoc}*
235225
# The 2to3 module and entrypoint was removed from the stdlib in Python 3.13.
236-
if [[ "${PYTHON_MAJOR_VERSION}" == +(3.8|3.9|3.10|3.11|3.12) ]]; then
226+
if [[ "${PYTHON_MAJOR_VERSION}" == +(3.9|3.10|3.11|3.12) ]]; then
237227
rm "${INSTALL_DIR}"/bin/2to3*
238228
fi
239229

lib/pip.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function pip::install_pip_setuptools_wheel() {
3131
# them installed.
3232
# - Most of the Python ecosystem has stopped installing them for Python 3.12+ already.
3333
# See the Python CNB's removal for more details: https://github.com/heroku/buildpacks-python/pull/243
34-
if [[ "${python_major_version}" == +(3.8|3.9|3.10|3.11|3.12) ]]; then
34+
if [[ "${python_major_version}" == +(3.9|3.10|3.11|3.12) ]]; then
3535
meta_set "setuptools_version" "${SETUPTOOLS_VERSION}"
3636
meta_set "wheel_version" "${WHEEL_VERSION}"
3737
packages_to_install+=(

lib/python_version.sh

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
# however, it helps Shellcheck realise the options under which these functions will run.
55
set -euo pipefail
66

7-
LATEST_PYTHON_3_8="3.8.20"
87
LATEST_PYTHON_3_9="3.9.21"
98
LATEST_PYTHON_3_10="3.10.16"
109
LATEST_PYTHON_3_11="3.11.11"
1110
LATEST_PYTHON_3_12="3.12.8"
1211
LATEST_PYTHON_3_13="3.13.1"
1312

13+
OLDEST_SUPPORTED_PYTHON_3_MINOR_VERSION=9
14+
NEWEST_SUPPORTED_PYTHON_3_MINOR_VERSION=13
15+
1416
DEFAULT_PYTHON_FULL_VERSION="${LATEST_PYTHON_3_13}"
1517
DEFAULT_PYTHON_MAJOR_VERSION="${DEFAULT_PYTHON_FULL_VERSION%.*}"
1618

@@ -280,7 +282,7 @@ function python_version::resolve_python_version() {
280282
local major="${BASH_REMATCH[1]}"
281283
local minor="${BASH_REMATCH[2]}"
282284

283-
if ((major < 3 || (major == 3 && minor < 8))); then
285+
if ((major < 3 || (major == 3 && minor < OLDEST_SUPPORTED_PYTHON_3_MINOR_VERSION))); then
284286
if [[ "${python_version_origin}" == "cached" ]]; then
285287
output::error <<-EOF
286288
Error: The cached Python version has reached end-of-life.
@@ -292,14 +294,13 @@ function python_version::resolve_python_version() {
292294
and is therefore no longer receiving security updates:
293295
https://devguide.python.org/versions/#supported-versions
294296
295-
As such, it is no longer supported by this buildpack.
296-
297-
Please upgrade to a newer Python version by creating a
298-
'.python-version' file that contains a Python version like:
299-
${DEFAULT_PYTHON_MAJOR_VERSION}
300-
301-
For a list of the supported Python versions, see:
297+
As such, it's no longer supported by this buildpack:
302298
https://devcenter.heroku.com/articles/python-support#supported-python-versions
299+
300+
Please upgrade to at least Python 3.${OLDEST_SUPPORTED_PYTHON_3_MINOR_VERSION} by creating a
301+
.python-version file in the root directory of your app,
302+
that contains a Python version like:
303+
3.${OLDEST_SUPPORTED_PYTHON_3_MINOR_VERSION}
303304
EOF
304305
else
305306
output::error <<-EOF
@@ -309,20 +310,18 @@ function python_version::resolve_python_version() {
309310
therefore no longer receiving security updates:
310311
https://devguide.python.org/versions/#supported-versions
311312
312-
As such, it is no longer supported by this buildpack.
313-
314-
Please upgrade to a newer Python version by updating the
315-
version configured via the '${python_version_origin}' file.
316-
317-
For a list of the supported Python versions, see:
313+
As such, it's no longer supported by this buildpack:
318314
https://devcenter.heroku.com/articles/python-support#supported-python-versions
315+
316+
Please upgrade to at least Python 3.${OLDEST_SUPPORTED_PYTHON_3_MINOR_VERSION} by changing the
317+
version in your ${python_version_origin} file.
319318
EOF
320319
fi
321320
meta_set "failure_reason" "python-version::eol"
322321
exit 1
323322
fi
324323

325-
if (((major == 3 && minor > 13) || major >= 4)); then
324+
if (((major == 3 && minor > NEWEST_SUPPORTED_PYTHON_3_MINOR_VERSION) || major >= 4)); then
326325
if [[ "${python_version_origin}" == "cached" ]]; then
327326
output::error <<-EOF
328327
Error: The cached Python version isn't recognised.
@@ -336,7 +335,14 @@ function python_version::resolve_python_version() {
336335
This can occur if you have downgraded the version of the
337336
buildpack to an older version.
338337
339-
Please switch back to a newer version of this buildpack.
338+
Please switch back to a newer version of this buildpack:
339+
https://devcenter.heroku.com/articles/managing-buildpacks#view-your-buildpacks
340+
https://devcenter.heroku.com/articles/managing-buildpacks#classic-buildpacks-references
341+
342+
Alternatively, request an older Python version by creating
343+
a .python-version file in the root directory of your app,
344+
that contains a Python version like:
345+
3.${NEWEST_SUPPORTED_PYTHON_3_MINOR_VERSION}
340346
EOF
341347
else
342348
output::error <<-EOF
@@ -350,12 +356,12 @@ function python_version::resolve_python_version() {
350356
https://devcenter.heroku.com/articles/python-support#supported-python-versions
351357
352358
If it has, make sure that you are using the latest version
353-
of this buildpack, and have not pinned to an older release:
359+
of this buildpack, and haven't pinned to an older release:
354360
https://devcenter.heroku.com/articles/managing-buildpacks#view-your-buildpacks
355361
https://devcenter.heroku.com/articles/managing-buildpacks#classic-buildpacks-references
356362
357-
Otherwise, switch to a supported version (such as Python ${DEFAULT_PYTHON_MAJOR_VERSION})
358-
by updating the version configured via the '${python_version_origin}' file.
363+
Otherwise, switch to a supported version (such as Python 3.${NEWEST_SUPPORTED_PYTHON_3_MINOR_VERSION})
364+
by changing the version in your ${python_version_origin} file.
359365
EOF
360366
fi
361367
meta_set "failure_reason" "python-version::unknown-major"
@@ -366,7 +372,6 @@ function python_version::resolve_python_version() {
366372
# Otherwise map major version specifiers to the latest patch release.
367373
case "${requested_python_version}" in
368374
*.*.*) echo "${requested_python_version}" ;;
369-
3.8) echo "${LATEST_PYTHON_3_8}" ;;
370375
3.9) echo "${LATEST_PYTHON_3_9}" ;;
371376
3.10) echo "${LATEST_PYTHON_3_10}" ;;
372377
3.11) echo "${LATEST_PYTHON_3_11}" ;;

spec/fixtures/pipenv_python_version_eol/Pipfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ typing-extensions = "*"
99
[dev-packages]
1010

1111
[requires]
12-
python_version = "3.7"
12+
python_version = "3.8"

spec/fixtures/pipenv_python_version_eol/Pipfile.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)