Skip to content

Add heroku/php to heroku-24 #1114

Add heroku/php to heroku-24

Add heroku/php to heroku-24 #1114

name: Build, Test, Publish
on:
pull_request:
push:
branches: ["main"]
schedule:
- cron: "0 0 * * 1-5"
workflow_dispatch:
permissions:
contents: read
defaults:
run:
# Setting an explicit bash shell ensures GitHub Actions enables pipefail mode too, rather
# than only error on exit. This is important for UX since this workflow uses pipes. See:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell
shell: bash
jobs:
create:
strategy:
fail-fast: false
matrix:
builder: ["builder-20", "builder-22", "builder-24", "salesforce-functions"]
arch: ["amd64", "arm64"]
exclude:
# Builders prior to Heroku-24 don't support ARM. We're using an exclude rather than
# an include so that the ARM jobs don't appear out of sequence in the GitHub UI.
- builder: builder-20
arch: arm64
- builder: builder-22
arch: arm64
- builder: salesforce-functions
arch: arm64
runs-on: ${{ matrix.arch == 'arm64' && 'pub-hk-ubuntu-22.04-arm-medium' || 'ubuntu-22.04' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Pack CLI
uses: buildpacks/github-actions/[email protected]
- name: Create builder image
run: pack builder create ${{ matrix.builder }} --config ${{ matrix.builder }}/builder.toml --pull-policy always
# We export the run image too (and not just the generated builder image), since it adds virtually
# no size to the archive (since the layers are mostly duplicates), and it ends up being quicker
# than docker pulling the run image in the jobs that perform the pack build.
# We manually compress the archive rather than relying upon actions/cache's compression, since
# it ends up being faster both in this job and also later when the images are consumed.
- name: Export Docker images from the Docker daemon
# Using sed rather than yq until this yq bug is fixed:
# https://github.com/mikefarah/yq/issues/1758
run: |
RUN_IMAGE_TAG=$(sed --quiet --regexp-extended --expression 's/run-image\s*=\s*"(.+)"/\1/p' ${{ matrix.builder }}/builder.toml)
docker save ${{ matrix.builder }} ${RUN_IMAGE_TAG} | zstd -T0 --long=31 -o images.tar.zst
# We use a cache here rather than artifacts because it's 4x faster and we
# don't need the builder archive outside of this workflow run anyway.
- name: Save Docker images to the cache
uses: actions/cache/save@v4
with:
key: ${{ github.run_id}}-${{ matrix.builder }}-${{ matrix.arch }}
path: images.tar.zst
test:
runs-on: ${{ matrix.arch == 'arm64' && 'pub-hk-ubuntu-22.04-arm-medium' || 'ubuntu-22.04' }}
needs: create
strategy:
fail-fast: false
matrix:
language: ["go", "gradle", "java", "node-js", "php", "python", "ruby", "scala"]
builder: ["builder-20", "builder-22", "builder-24"]
arch: ["amd64", "arm64"]
exclude:
- builder: builder-20
arch: arm64
- builder: builder-22
arch: arm64
steps:
- name: Checkout getting started guide
uses: actions/checkout@v4
with:
ref: main
repository: heroku/${{ matrix.language }}-getting-started.git
- name: Install Pack CLI
uses: buildpacks/github-actions/[email protected]
- name: Restore Docker images from the cache
uses: actions/cache/restore@v4
with:
fail-on-cache-miss: true
key: ${{ github.run_id}}-${{ matrix.builder }}-${{ matrix.arch }}
path: images.tar.zst
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
- name: Load Docker images into the Docker daemon
run: zstd -dc --long=31 images.tar.zst | docker load
- name: Build getting started guide image
run: pack build getting-started --force-color --builder ${{ matrix.builder }} --trust-builder --pull-policy never
- name: Start getting started guide image
# The `DYNO` env var is set to more accurately reflect the Heroku environment, since some of the getting
# started guides use the presence of `DYNO` to determine whether to enable production mode or not.
run: docker run --name getting-started --detach -p 8080:8080 --env PORT=8080 --env DYNO=web.1 getting-started
- name: Test getting started web server response
run: |
if curl -sSf --retry 10 --retry-delay 1 --retry-all-errors --connect-timeout 3 http://localhost:8080 -o response.txt; then
echo "Successful response from server"
else
echo "Server did not respond successfully"
docker logs getting-started
[[ -f response.txt ]] && cat response.txt
exit 1
fi
test-functions:
runs-on: ubuntu-22.04
needs: create
strategy:
fail-fast: false
matrix:
language: ["java", "javascript", "typescript"]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Pack CLI
uses: buildpacks/github-actions/[email protected]
with:
# Using an older version of Pack CLI here (that only supports Platform API <= 0.9),
# for testing parity with the Platform API version used by Kodon for Functions:
# https://github.com/buildpacks/pack/blob/v0.27.0/internal/build/lifecycle_executor.go#L30
# https://github.com/heroku/kodon/blob/functions_eol/internal/constants/constants.go#L75
pack-version: "0.27.0"
- name: Restore Docker images from the cache
uses: actions/cache/restore@v4
with:
fail-on-cache-miss: true
key: ${{ github.run_id}}-salesforce-functions-amd64
path: images.tar.zst
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
- name: Load Docker images into the Docker daemon
run: zstd -dc --long=31 images.tar.zst | docker load
- name: Build example function image
run: pack build example-function --path salesforce-functions/examples/${{ matrix.language }} --builder salesforce-functions --trust-builder --pull-policy never
- name: Start example function image
run: docker run --name example-function --detach -p 8080:8080 --env PORT=8080 --env DYNO=web.1 example-function
- name: Test example function web server response
run: |
if curl -sSf --retry 10 --retry-delay 1 --retry-all-errors --connect-timeout 3 -X POST -H 'x-health-check: true' http://localhost:8080 -o response.txt; then
echo "Successful response from function"
else
echo "Function did not respond successfully"
docker logs example-function
[[ -f response.txt ]] && cat response.txt
exit 1
fi
publish-image:
runs-on: ${{ matrix.arch == 'arm64' && 'pub-hk-ubuntu-22.04-arm-medium' || 'ubuntu-22.04' }}
if: success() && github.ref == 'refs/heads/main'
needs: ["test", "test-functions"]
strategy:
fail-fast: false
matrix:
include:
- builder: builder-20
arch: amd64
tag_public: heroku/builder:20
- builder: builder-22
arch: amd64
tag_public: heroku/builder:22
- builder: salesforce-functions
arch: amd64
tag_private: heroku-22:builder-functions
- builder: builder-24
arch: amd64
tag_public: heroku/builder:24_linux-amd64
- builder: builder-24
arch: arm64
tag_public: heroku/builder:24_linux-arm64
steps:
- name: Restore Docker images from the cache
uses: actions/cache/restore@v4
with:
fail-on-cache-miss: true
key: ${{ github.run_id}}-${{ matrix.builder }}-${{ matrix.arch }}
path: images.tar.zst
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
- name: Load Docker images into the Docker daemon
run: zstd -dc --long=31 images.tar.zst | docker load
- name: Log into Docker Hub
if: matrix.tag_public != ''
run: echo '${{ secrets.DOCKER_HUB_TOKEN }}' | docker login -u '${{ secrets.DOCKER_HUB_USER }}' --password-stdin
- name: Log into internal registry
if: matrix.tag_private != ''
run: |
REGISTRY_TOKEN=$(
curl -sSf --retry 3 --retry-delay 1 --retry-all-errors --connect-timeout 3 \
-X POST -d '{"username":"${{ secrets.SERVICE_TOKEN_USER_NAME }}", "password":"${{ secrets.SERVICE_TOKEN_PASSWORD }}"}' \
'${{ secrets.SERVICE_TOKEN_ENDPOINT }}' \
| jq --exit-status -r '.raw_id_token'
)
echo "${REGISTRY_TOKEN}" | docker login '${{ secrets.REGISTRY_HOST }}' -u '${{ secrets.REGISTRY_USER }}' --password-stdin
- name: Tag builder and push to Docker Hub
if: matrix.tag_public != ''
run: |
PUBLIC_IMAGE_URI='${{ matrix.tag_public }}'
set -x
docker tag '${{ matrix.builder }}' "${PUBLIC_IMAGE_URI}"
docker push "${PUBLIC_IMAGE_URI}"
- name: Tag builder and push to internal registry
if: matrix.tag_private != ''
run: |
PRIVATE_IMAGE_URI='${{ secrets.REGISTRY_HOST }}/s/${{ secrets.SERVICE_TOKEN_USER_NAME }}/${{ matrix.tag_private }}'
set -x
docker tag '${{ matrix.builder }}' "${PRIVATE_IMAGE_URI}"
docker push "${PRIVATE_IMAGE_URI}"
publish-manifest:
runs-on: ubuntu-22.04
needs: publish-image
strategy:
fail-fast: false
matrix:
include:
- tag_public: "heroku/builder:24"
manifests: "heroku/builder:24_linux-amd64 heroku/builder:24_linux-arm64"
steps:
- name: Log in to Docker Hub
if: matrix.tag_public != ''
run: echo '${{ secrets.DOCKER_HUB_TOKEN }}' | docker login -u '${{ secrets.DOCKER_HUB_USER }}' --password-stdin
- name: Create and push manifest lists
run: |
docker manifest create "${{ matrix.tag_public }}" ${{ matrix.manifests }}
docker manifest push "${{ matrix.tag_public }}"