Skip to content

Commit

Permalink
Add Python binary build support for Heroku-24
Browse files Browse the repository at this point in the history
This adds support for building Python binaries for Heroku-24
using GitHub Actions. Since the Heroku-24 base image supports
both `amd64` and `arm64` (to allow for multi-arch CNBs), for
Heroku-24 (only) we now also build binaries for both architectures.

A later PR will add support for Heroku-24 to the buildpack itself,
however, that depends on (a) the Python binaries already having
been built, (b) the Heroku build system for Heroku-24 being ready,
so those changes are not being made here.

GUS-W-15571102.
  • Loading branch information
edmorley committed Apr 22, 2024
1 parent 151fb27 commit d4b40b2
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 4 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/build_python_runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ on:
- auto
- heroku-20
- heroku-22
- heroku-24
default: auto
required: false
dry_run:
Expand Down Expand Up @@ -67,3 +68,36 @@ jobs:
- name: Upload Python runtime archive to S3
if: (!inputs.dry_run)
run: aws s3 sync ./upload "s3://${S3_BUCKET}"

heroku-24:
# On Heroku-24 we only support Python 3.12+.
if: inputs.stack == 'heroku-24' || (inputs.stack == 'auto' && startsWith(inputs.python_version,'3.12.'))
strategy:
fail-fast: false
matrix:
architecture: ["amd64", "arm64"]
runs-on: ${{ matrix.architecture == 'arm64' && 'pub-hk-ubuntu-22.04-arm-large' || 'pub-hk-ubuntu-22.04-xlarge' }}
env:
STACK_VERSION: "24"
steps:
- name: Checkout
uses: actions/checkout@v4
# The beta Arm64 runners don't yet ship with the normal installed tools.
- name: Install Docker and AWS CLI (ARM64 only)
if: matrix.architecture == 'arm64'
run: |
sudo apt-get update --error-on=any
sudo apt-get install -y --no-install-recommends acl docker.io docker-buildx unzip
sudo usermod -aG docker $USER
sudo setfacl --modify user:$USER:rw /var/run/docker.sock
curl https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip -o awscliv2.zip
unzip awscliv2.zip
sudo ./aws/install
rm -rf awscliv2.zip ./aws/
- name: Build Docker image
run: docker build --platform="linux/${{ matrix.architecture }}" --pull --tag buildenv --build-arg=STACK_VERSION builds/
- name: Build and package Python runtime
run: docker run --rm --volume="${PWD}/upload:/tmp/upload" buildenv ./build_python_runtime.sh "${{ inputs.python_version }}"
- name: Upload Python runtime archive to S3
if: (!inputs.dry_run)
run: aws s3 sync ./upload "s3://${S3_BUCKET}"
5 changes: 4 additions & 1 deletion builds/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
ARG STACK_VERSION="22"
ARG STACK_VERSION="24"
FROM heroku/heroku:${STACK_VERSION}-build

ARG STACK_VERSION
ENV STACK="heroku-${STACK_VERSION}"

# For Heroku-24 and newer, the build image sets a non-root default `USER`.
USER root

RUN apt-get update --error-on=any \
&& apt-get install -y --no-install-recommends \
libsqlite3-dev \
Expand Down
12 changes: 9 additions & 3 deletions builds/build_python_runtime.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ set -euo pipefail
PYTHON_VERSION="${1:?"Error: The Python version to build must be specified as the first argument."}"
PYTHON_MAJOR_VERSION="${PYTHON_VERSION%.*}"

ARCH=$(dpkg --print-architecture)

# Python is relocated to different locations by the classic buildpack and CNB (which works since we
# set `LD_LIBRARY_PATH` and `PYTHONHOME` appropriately at build/run-time), so for packaging purposes
# we install Python into an arbitrary location that intentionally matches neither location.
Expand All @@ -18,6 +20,11 @@ function error() {
}

case "${STACK}" in
heroku-24)
SUPPORTED_PYTHON_VERSIONS=(
"3.12"
)
;;
heroku-22)
SUPPORTED_PYTHON_VERSIONS=(
"3.9"
Expand Down Expand Up @@ -63,7 +70,7 @@ case "${PYTHON_MAJOR_VERSION}" in
;;
esac

echo "Building Python ${PYTHON_VERSION} for ${STACK}..."
echo "Building Python ${PYTHON_VERSION} for ${STACK} (${ARCH})..."

SOURCE_URL="https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz"
SIGNATURE_URL="${SOURCE_URL}.asc"
Expand Down Expand Up @@ -214,9 +221,8 @@ LD_LIBRARY_PATH="${SRC_DIR}" "${SRC_DIR}/python" -m compileall -f --invalidation
ln -srvT "${INSTALL_DIR}/bin/python3" "${INSTALL_DIR}/bin/python"

# Results in a compressed archive filename of form: 'python-X.Y.Z-ubuntu-22.04-amd64.tar.zst'
# TODO: Switch to dynamically calculating the architecture when adding support for Heroku-24.
UBUNTU_VERSION=$(lsb_release --short --release 2>/dev/null)
TAR_FILEPATH="${UPLOAD_DIR}/python-${PYTHON_VERSION}-ubuntu-${UBUNTU_VERSION}-amd64.tar"
TAR_FILEPATH="${UPLOAD_DIR}/python-${PYTHON_VERSION}-ubuntu-${UBUNTU_VERSION}-${ARCH}.tar"
tar --create --format=pax --sort=name --file "${TAR_FILEPATH}" --directory="${INSTALL_DIR}" .
zstd -T0 -22 --ultra --long --no-progress --rm "${TAR_FILEPATH}"

Expand Down

0 comments on commit d4b40b2

Please sign in to comment.