Skip to content

Build and upload Python 3.13.0 #282

Build and upload Python 3.13.0

Build and upload Python 3.13.0 #282

name: Build and upload Python runtime
run-name: "Build and upload Python ${{ inputs.python_version }}${{ inputs.dry_run && ' (dry run)' || '' }}"
on:
workflow_dispatch:
inputs:
python_version:
description: "Python version (eg: 3.12.0)"
type: string
required: true
stack:
description: "Stack(s)"
type: choice
options:
- auto
- heroku-20
- heroku-22
- heroku-24
default: auto
required: false
dry_run:
description: "Skip uploading to S3 (dry run)"
type: boolean
default: false
required: false
permissions:
contents: read
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: "us-east-1"
S3_BUCKET: "heroku-buildpack-python"
# Unfortunately these jobs cannot be easily written as a matrix since `matrix.exclude` does not
# support expression syntax, and the `matrix` context is not available inside the job `if` key.
jobs:
heroku-20:
if: inputs.stack == 'heroku-20' || inputs.stack == 'auto'
runs-on: pub-hk-ubuntu-24.04-xlarge
env:
STACK_VERSION: "20"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Docker image
run: docker build --platform="linux/amd64" --pull --tag buildenv --build-arg=STACK_VERSION builds/
- name: Compile and package Python runtime
run: docker run --rm --volume="${PWD}/upload:/tmp/upload" buildenv ./build_python_runtime.sh "${{ inputs.python_version }}"
- name: Test Python runtime
run: |
RUN_IMAGE='heroku/heroku:${{ env.STACK_VERSION }}'
ARCHIVE_FILENAME='python-${{ inputs.python_version }}-ubuntu-${{ env.STACK_VERSION }}.04-amd64.tar.zst'
docker run --rm --volume="${PWD}/upload:/upload:ro" --volume="${PWD}/builds:/builds:ro" "${RUN_IMAGE}" /builds/test_python_runtime.sh "/upload/${ARCHIVE_FILENAME}"
- name: Upload Python runtime archive to S3
if: (!inputs.dry_run)
run: aws s3 sync ./upload "s3://${S3_BUCKET}"
heroku-22:
# On Heroku-22 we only support Python 3.9+.
if: inputs.stack == 'heroku-22' || (inputs.stack == 'auto' && !startsWith(inputs.python_version,'3.8.'))
runs-on: pub-hk-ubuntu-24.04-xlarge
env:
STACK_VERSION: "22"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Docker image
run: docker build --platform="linux/amd64" --pull --tag buildenv --build-arg=STACK_VERSION builds/
- name: Compile and package Python runtime
run: docker run --rm --volume="${PWD}/upload:/tmp/upload" buildenv ./build_python_runtime.sh "${{ inputs.python_version }}"
- name: Test Python runtime
run: |
RUN_IMAGE='heroku/heroku:${{ env.STACK_VERSION }}'
ARCHIVE_FILENAME='python-${{ inputs.python_version }}-ubuntu-${{ env.STACK_VERSION }}.04-amd64.tar.zst'
docker run --rm --volume="${PWD}/upload:/upload:ro" --volume="${PWD}/builds:/builds:ro" "${RUN_IMAGE}" /builds/test_python_runtime.sh "/upload/${ARCHIVE_FILENAME}"
- 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.9+.
if: inputs.stack == 'heroku-24' || (inputs.stack == 'auto' && !startsWith(inputs.python_version,'3.8.'))
strategy:
fail-fast: false
matrix:
arch: ["amd64", "arm64"]
runs-on: ${{ matrix.arch == 'arm64' && 'pub-hk-ubuntu-24.04-arm-xlarge' || 'pub-hk-ubuntu-24.04-xlarge' }}
env:
STACK_VERSION: "24"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Docker image
run: docker build --platform="linux/${{ matrix.arch }}" --pull --tag buildenv --build-arg=STACK_VERSION builds/
- name: Compile and package Python runtime
run: docker run --rm --volume="${PWD}/upload:/tmp/upload" buildenv ./build_python_runtime.sh "${{ inputs.python_version }}"
- name: Test Python runtime
run: |
RUN_IMAGE='heroku/heroku:${{ env.STACK_VERSION }}'
ARCHIVE_FILENAME='python-${{ inputs.python_version }}-ubuntu-${{ env.STACK_VERSION }}.04-${{ matrix.arch }}.tar.zst'
docker run --rm --volume="${PWD}/upload:/upload:ro" --volume="${PWD}/builds:/builds:ro" "${RUN_IMAGE}" /builds/test_python_runtime.sh "/upload/${ARCHIVE_FILENAME}"
- name: Upload Python runtime archive to S3
if: (!inputs.dry_run)
run: aws s3 sync ./upload "s3://${S3_BUCKET}"