Skip to content

Commit bad0f49

Browse files
authored
feat: add Python 3.14 (#51)
use MAJOR.MINOR.PATCH and MAJOR.MINOR for tagging 3.13 images
1 parent 68cf9d2 commit bad0f49

8 files changed

Lines changed: 385 additions & 10 deletions

File tree

.github/workflows/autoupdate.yml

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,31 +35,51 @@ jobs:
3535
sed -i "s/ENV PYTHON_VERSION=.*/ENV PYTHON_VERSION=$python_version/" 3.13/slim-bookworm/Dockerfile
3636
sed -i "s/3\.13\.[0-9]\+\([-a-z]*\)/$python_version\1/g" README.md
3737
38-
- name: Update requirements
38+
- name: Fetch latest Python 3.14 release
39+
if: ${{ github.event.schedule == '0 18 10 2-12/2 *' || github.event_name == 'workflow_dispatch' }}
40+
run: |
41+
python_version=$(curl -s https://www.python.org/ftp/python/ | grep -oP '3\.14\.\d+/' | uniq | sort -V | tail -n 1 | tr -d '/')
42+
43+
echo "python3.14: $python_version"
44+
45+
sed -i "s/ENV PYTHON_VERSION=.*/ENV PYTHON_VERSION=$python_version/" 3.14/bookworm/Dockerfile
46+
sed -i "s/ENV PYTHON_VERSION=.*/ENV PYTHON_VERSION=$python_version/" 3.14/slim-bookworm/Dockerfile
47+
sed -i "s/3\.14\.[0-9]\+\([-a-z]*\)/$python_version\1/g" README.md
48+
49+
- name: Update 3.12 requirements
3950
uses: coatl-dev/actions/uv-pip-compile-upgrade@v5
4051
with:
4152
path: requirements/3.12
4253
python-version: '3.12'
4354

44-
- name: Update requirements
55+
- name: Update 3.13 requirements
4556
uses: coatl-dev/actions/uv-pip-compile-upgrade@v5
4657
with:
4758
path: requirements/3.13
4859
python-version: '3.13'
4960

61+
- name: Update 3.14 requirements
62+
uses: coatl-dev/actions/uv-pip-compile-upgrade@v5
63+
with:
64+
path: requirements/3.14
65+
python-version: '3.14'
66+
5067
- name: Extract package versions and update Dockerfile
5168
run: |
5269
pip312=$(grep '^pip==' requirements/3.12/pip.txt | cut -d'=' -f3)
5370
pip313=$(grep '^pip==' requirements/3.13/pip.txt | cut -d'=' -f3)
71+
pip314=$(grep '^pip==' requirements/3.14/pip.txt | cut -d'=' -f3)
5472
5573
echo "Extracted versions:"
5674
echo "pip3.12: $pip312"
57-
echo "pip3.13: $pip313"
58-
5975
sed -i "s/ENV PYTHON_PIP_VERSION=.*/ENV PYTHON_PIP_VERSION=$pip312/" 3.12/bookworm/Dockerfile
6076
sed -i "s/ENV PYTHON_PIP_VERSION=.*/ENV PYTHON_PIP_VERSION=$pip312/" 3.12/slim-bookworm/Dockerfile
77+
echo "pip3.13: $pip313"
6178
sed -i "s/ENV PYTHON_PIP_VERSION=.*/ENV PYTHON_PIP_VERSION=$pip313/" 3.13/bookworm/Dockerfile
6279
sed -i "s/ENV PYTHON_PIP_VERSION=.*/ENV PYTHON_PIP_VERSION=$pip313/" 3.13/slim-bookworm/Dockerfile
80+
echo "pip3.14: $pip314"
81+
sed -i "s/ENV PYTHON_PIP_VERSION=.*/ENV PYTHON_PIP_VERSION=$pip314/" 3.14/bookworm/Dockerfile
82+
sed -i "s/ENV PYTHON_PIP_VERSION=.*/ENV PYTHON_PIP_VERSION=$pip314/" 3.14/slim-bookworm/Dockerfile
6383
6484
- name: Detect changes
6585
id: git-diff

.github/workflows/publish-3.13.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,11 @@ jobs:
4949
- version: '3.13'
5050
variant: bookworm
5151
tags: |
52-
${{ needs.tagger.outputs.major }}
5352
${{ needs.tagger.outputs.major-minor }}
5453
${{ needs.tagger.outputs.version }}
5554
- version: '3.13'
5655
variant: slim-bookworm
5756
tags: |
58-
${{ needs.tagger.outputs.major }}-slim
5957
${{ needs.tagger.outputs.major-minor }}-slim
6058
${{ needs.tagger.outputs.version }}-slim
6159
with:

.github/workflows/publish-3.14.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: publish-3.14
2+
3+
on:
4+
push:
5+
branches:
6+
- coatl
7+
paths:
8+
- .github/workflows/publish.yml
9+
- .github/workflows/publish-3.14.yml
10+
- 3.14/**
11+
schedule:
12+
- cron: '0 8 17 * *'
13+
14+
jobs:
15+
tagger:
16+
runs-on: ubuntu-latest
17+
outputs:
18+
major: ${{ steps.tags.outputs.major }}
19+
major-minor: ${{ steps.tags.outputs.major-minor }}
20+
version: ${{ steps.tags.outputs.version }}
21+
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v5
25+
26+
- name: Extract version number
27+
id: tags
28+
run: |
29+
# Extract the Python version from the Dockerfile
30+
VERSION=$(grep 'ENV PYTHON_VERSION' 3.14/bookworm/Dockerfile | cut -d '=' -f 2)
31+
echo "VERSION=${VERSION}"
32+
# Trim the version to the first two segments (major.minor)
33+
MAJOR_MINOR=$(echo $VERSION | cut -d'.' -f1-2)
34+
echo "MAJOR_MINOR=${MAJOR_MINOR}"
35+
# Trim the version to the first segment (major)
36+
MAJOR=$(echo $VERSION | cut -d'.' -f1-1)
37+
echo "MAJOR=${MAJOR}"
38+
# Export the extracted version to GITHUB_OUTPUT
39+
echo "major=${MAJOR}" >> $GITHUB_OUTPUT
40+
echo "major-minor=${MAJOR_MINOR}" >> $GITHUB_OUTPUT
41+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
42+
43+
publish:
44+
needs: tagger
45+
uses: ./.github/workflows/publish.yml
46+
strategy:
47+
matrix:
48+
image:
49+
- version: '3.14'
50+
variant: bookworm
51+
tags: |
52+
${{ needs.tagger.outputs.major }}
53+
${{ needs.tagger.outputs.major-minor }}
54+
${{ needs.tagger.outputs.version }}
55+
- version: '3.14'
56+
variant: slim-bookworm
57+
tags: |
58+
${{ needs.tagger.outputs.major }}-slim
59+
${{ needs.tagger.outputs.major-minor }}-slim
60+
${{ needs.tagger.outputs.version }}-slim
61+
with:
62+
image: coatldev/python
63+
version: ${{ matrix.image.version }}
64+
variant: ${{ matrix.image.variant }}
65+
tags: ${{ matrix.image.tags }}
66+
username: ${{ vars.DOCKERHUB_USERNAME }}
67+
secrets:
68+
password: ${{ secrets.DOCKERHUB_TOKEN }}

3.14/bookworm/Dockerfile

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
FROM buildpack-deps:bookworm
2+
3+
LABEL \
4+
maintainer="César Román <cesar@coatl.dev>" \
5+
repository="https://github.com/coatl-dev/docker-python" \
6+
vendor="coatl.dev"
7+
8+
ENV DEBIAN_FRONTEND=noninteractive
9+
10+
ENV PIP_NO_CACHE_DIR=1
11+
ENV PIP_ROOT_USER_ACTION=ignore
12+
13+
# ensure local python is preferred over distribution python
14+
ENV PATH=/usr/local/bin:$PATH
15+
16+
# runtime dependencies
17+
RUN set -eux; \
18+
apt-get update; \
19+
apt-get upgrade --yes; \
20+
apt-get install -y --no-install-recommends \
21+
libbluetooth-dev \
22+
tk-dev \
23+
uuid-dev \
24+
; \
25+
rm -rf /var/lib/apt/lists/*
26+
27+
ENV PYTHON_VERSION=3.14.0
28+
29+
RUN set -eux; \
30+
\
31+
wget -q -O python.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz"; \
32+
mkdir -p /usr/src/python; \
33+
tar --extract --directory /usr/src/python --strip-components=1 --file python.tar.xz; \
34+
rm python.tar.xz; \
35+
\
36+
cd /usr/src/python; \
37+
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
38+
./configure \
39+
--build="$gnuArch" \
40+
--enable-loadable-sqlite-extensions \
41+
--enable-optimizations \
42+
--enable-option-checking=fatal \
43+
--enable-shared \
44+
--with-lto \
45+
--without-ensurepip \
46+
; \
47+
nproc="$(nproc)"; \
48+
EXTRA_CFLAGS="$(dpkg-buildflags --get CFLAGS)"; \
49+
LDFLAGS="$(dpkg-buildflags --get LDFLAGS)"; \
50+
EXTRA_CFLAGS="${EXTRA_CFLAGS:-} -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"; \
51+
make -j "$nproc" \
52+
"EXTRA_CFLAGS=${EXTRA_CFLAGS:-}" \
53+
"LDFLAGS=${LDFLAGS:-}" \
54+
; \
55+
# https://github.com/docker-library/python/issues/784
56+
# prevent accidental usage of a system installed libpython of the same version
57+
rm python; \
58+
make -j "$nproc" \
59+
"EXTRA_CFLAGS=${EXTRA_CFLAGS:-}" \
60+
"LDFLAGS=${LDFLAGS:--Wl},-rpath='\$\$ORIGIN/../lib'" \
61+
python \
62+
; \
63+
make install; \
64+
\
65+
# enable GDB to load debugging data: https://github.com/docker-library/python/pull/701
66+
bin="$(readlink -ve /usr/local/bin/python3)"; \
67+
dir="$(dirname "$bin")"; \
68+
mkdir -p "/usr/share/gdb/auto-load/$dir"; \
69+
cp -vL Tools/gdb/libpython.py "/usr/share/gdb/auto-load/$bin-gdb.py"; \
70+
\
71+
cd /; \
72+
rm -rf /usr/src/python; \
73+
\
74+
find /usr/local -depth \
75+
\( \
76+
\( -type d -a \( -name test -o -name tests -o -name idle_test \) \) \
77+
-o \( -type f -a \( -name '*.pyc' -o -name '*.pyo' -o -name 'libpython*.a' \) \) \
78+
\) -exec rm -rf '{}' + \
79+
; \
80+
\
81+
ldconfig; \
82+
\
83+
export PYTHONDONTWRITEBYTECODE=1; \
84+
python3 --version
85+
86+
# make some useful symlinks that are expected to exist ("/usr/local/bin/python" and friends)
87+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
88+
RUN set -eux; \
89+
for src in idle3 pydoc3 python3 python3-config; do \
90+
dst="$(echo "$src" | tr -d 3)"; \
91+
[ -s "/usr/local/bin/$src" ]; \
92+
[ ! -e "/usr/local/bin/$dst" ]; \
93+
ln -svT "$src" "/usr/local/bin/$dst"; \
94+
done
95+
96+
# if this is called "PIP_VERSION", pip explodes with "ValueError: invalid truth value '<VERSION>'"
97+
ENV PYTHON_PIP_VERSION=25.2
98+
# https://github.com/pypa/get-pip
99+
ENV PYTHON_GET_PIP_URL=https://raw.githubusercontent.com/pypa/get-pip/HEAD/public/get-pip.py
100+
101+
RUN set -eux; \
102+
\
103+
wget -q -O get-pip.py "$PYTHON_GET_PIP_URL"; \
104+
\
105+
export PYTHONDONTWRITEBYTECODE=1; \
106+
\
107+
python get-pip.py \
108+
--disable-pip-version-check \
109+
--no-compile \
110+
"pip==$PYTHON_PIP_VERSION" \
111+
--no-setuptools \
112+
--no-wheel \
113+
; \
114+
rm -f get-pip.py; \
115+
\
116+
pip --version
117+
118+
CMD ["python3"]

0 commit comments

Comments
 (0)