From 2d20ca5a8291b7350bb253a359fead2f492cb101 Mon Sep 17 00:00:00 2001 From: Kevin Rudde Date: Wed, 21 Oct 2026 16:38:36 +0200 Subject: [PATCH] feat: update php versions and build from source --- docker-bake.hcl | 63 +++++++++++++++++-- frankenphp/Dockerfile | 3 +- update-php-matrix.mjs | 143 +++++++++++++----------------------------- 3 files changed, 104 insertions(+), 105 deletions(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index 8ed2d8a..88e200e 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -7,11 +7,64 @@ variable "tagPrefix" { } variable "phpMatrix" { - default = [ "8.2.34", "8.3.35", "8.4.26", "8.5.11" ] + default = [ "8.2.35", "8.3.36", "8.4.27", "8.5.12" ] } variable "frankenphpMatrix" { - default = [ "8.2.34", "8.3.35", "8.4.26", "8.5.11" ] + default = [ "8.2.35", "8.3.36", "8.4.27", "8.5.12" ] +} + +variable "phpLibraryRef" { + default = "e3eaff845f7a9f7259c31da54dce0320b47a3bbd" +} + +variable "alpineVersion" { + default = "3.24" +} + +variable "frankenphpRef" { + default = "v1.13.1" +} + +variable "goVersion" { + default = "1.27" +} + +# PHP built from source with the upstream docker-library/php Dockerfiles + +target "php-fpm-alpine" { + name = "php-fpm-alpine-${replace(substr(php, 0, 3), ".", "-")}" + context = "https://github.com/docker-library/php.git#${phpLibraryRef}:${substr(php, 0, 3)}/alpine${alpineVersion}/fpm" + matrix = { + "php" = phpMatrix + } + platforms = [ "linux/amd64", "linux/arm64" ] +} + +target "php-zts-trixie" { + name = "php-zts-trixie-${replace(substr(php, 0, 3), ".", "-")}" + context = "https://github.com/docker-library/php.git#${phpLibraryRef}:${substr(php, 0, 3)}/trixie/zts" + matrix = { + "php" = frankenphpMatrix + } + platforms = [ "linux/amd64", "linux/arm64" ] +} + +target "frankenphp-upstream" { + name = "frankenphp-upstream-${replace(substr(php, 0, 3), ".", "-")}" + context = "https://github.com/php/frankenphp.git#${frankenphpRef}" + target = "runner" + matrix = { + "php" = frankenphpMatrix + } + contexts = { + php-base = "target:php-zts-trixie-${replace(substr(php, 0, 3), ".", "-")}" + golang-base = "docker-image://docker.io/library/golang:${goVersion}-trixie" + } + args = { + "FRANKENPHP_VERSION" = frankenphpRef + } + platforms = [ "linux/amd64", "linux/arm64" ] } # Frankenphp @@ -22,8 +75,8 @@ target "frankenphp" { matrix = { "php" = frankenphpMatrix } - args = { - "PHP_VERSION" = php + contexts = { + base = "target:frankenphp-upstream-${replace(substr(php, 0, 3), ".", "-")}" } platforms = [ "linux/amd64", "linux/arm64" ] tags = imageSuffix != "" ? [ @@ -69,7 +122,7 @@ target "fpm" { "php" = phpMatrix } contexts = { - base = "docker-image://docker.io/library/php:${php}-fpm-alpine" + base = "target:php-fpm-alpine-${replace(substr(php, 0, 3), ".", "-")}" } platforms = [ "linux/amd64", "linux/arm64" ] tags = imageSuffix != "" ? [ diff --git a/frankenphp/Dockerfile b/frankenphp/Dockerfile index f79ff78..0b7fb31 100644 --- a/frankenphp/Dockerfile +++ b/frankenphp/Dockerfile @@ -1,8 +1,7 @@ #syntax=docker/dockerfile:1.4 #check=skip=SecretsUsedInArgOrEnv -ARG PHP_VERSION=8.4 -FROM dunglas/frankenphp:php${PHP_VERSION} +FROM base RUN < versions[version].variants ?? []) + .map(variant => variant.match(/^alpine(\d+\.\d+)\/fpm$/)?.[1]) + .filter(Boolean) + .sort((a, b) => a.localeCompare(b, undefined, { numeric: true })); + + if (alpineVersions.length === 0) { + throw new Error('No Alpine variant found'); } - for (const entry of apiResponse.results) { - // Skip RC versions - if (entry.name.includes('RC')) { - continue; - } + return alpineVersions.at(-1); +} - // Extract version number (e.g., 8.1.33) - const versionMatch = entry.name.match(/^(\d+\.\d+\.\d+)/); - if (versionMatch) { - return versionMatch[1]; +function getPhpVersions(versions) { + return supportedVersions.map(version => { + const entry = versions[version]; + if (!entry || !/^\d+\.\d+\.\d+$/.test(entry.version)) { + throw new Error(`No valid version found for PHP ${version}`); } - } - return null; + return entry.version; + }); } -// Function to extract the latest PHP patch version from FrankenPHP API response -function getLatestFrankenphpPatchVersion(apiResponse) { - if (!apiResponse || !Array.isArray(apiResponse.results)) { - throw new Error('Invalid API response'); - } - - for (const entry of apiResponse.results) { - // Skip RC versions - if (entry.name.includes('RC')) { - continue; - } +function replaceVariable(hclContent, name, value) { + const regex = new RegExp(`(variable "${name}" \\{\\s*default = )(\\[[^\\]]*\\]|"[^"]*")(\\s*\\})`, 's'); - // Extract PHP version number from FrankenPHP tag (e.g., 1.9.1-php8.2.29 -> 8.2.29) - const versionMatch = entry.name.match(/-php(\d+\.\d+\.\d+)$/); - if (versionMatch) { - return versionMatch[1]; - } + if (!regex.test(hclContent)) { + throw new Error(`${name} variable not found in docker-bake.hcl`); } - return null; + return hclContent.replace(regex, `$1${value}$3`); } -// Function to update the phpMatrix and frankenphpMatrix in docker-bake.hcl -async function updatePhpMatrixInHcl(phpVersions, frankenphpVersions) { +async function updateBakeFile(phpVersions, phpLibraryRef, alpineVersion) { const hclPath = 'docker-bake.hcl'; let hclContent = await fs.readFile(hclPath, 'utf8'); - // Find the phpMatrix variable and replace its value - const phpMatrixRegex = /(variable "phpMatrix" \{\s*default = )(\[[^\]]*\])(\s*\})/s; - const newPhpMatrix = `[ ${phpVersions.map(v => `"${v}"`).join(', ')} ]`; - - if (!phpMatrixRegex.test(hclContent)) { - throw new Error('phpMatrix variable not found in docker-bake.hcl'); - } - - hclContent = hclContent.replace(phpMatrixRegex, `$1${newPhpMatrix}$3`); - - // Find the frankenphpMatrix variable and replace its value - const frankenphpMatrixRegex = /(variable "frankenphpMatrix" \{\s*default = )(\[[^\]]*\])(\s*\})/s; - const newFrankenphpMatrix = `[ ${frankenphpVersions.map(v => `"${v}"`).join(', ')} ]`; - - if (!frankenphpMatrixRegex.test(hclContent)) { - throw new Error('frankenphpMatrix variable not found in docker-bake.hcl'); - } - - hclContent = hclContent.replace(frankenphpMatrixRegex, `$1${newFrankenphpMatrix}$3`); + const matrix = `[ ${phpVersions.map(v => `"${v}"`).join(', ')} ]`; + hclContent = replaceVariable(hclContent, 'phpMatrix', matrix); + hclContent = replaceVariable(hclContent, 'frankenphpMatrix', matrix); + hclContent = replaceVariable(hclContent, 'phpLibraryRef', `"${phpLibraryRef}"`); + hclContent = replaceVariable(hclContent, 'alpineVersion', `"${alpineVersion}"`); await fs.writeFile(hclPath, hclContent); - console.log('Successfully updated phpMatrix and frankenphpMatrix in docker-bake.hcl'); + console.log('Successfully updated docker-bake.hcl'); console.log('PHP versions:', phpVersions); - console.log('FrankenPHP versions:', frankenphpVersions); + console.log('docker-library/php ref:', phpLibraryRef); + console.log('Alpine version:', alpineVersion); } -const phpVersions = []; -const frankenphpVersions = []; - -for (const version of supportedVersions) { - console.log(`Fetching latest patch version for PHP ${version}...`); - const apiResponse = await fetchPhpTags(version); - const latestVersion = getLatestPatchVersion(apiResponse); - - if (latestVersion) { - phpVersions.push(latestVersion); - console.log(`Found latest version for PHP ${version}: ${latestVersion}`); - } else { - throw new Error(`No valid version found for PHP ${version}`); - } - - console.log(`Fetching FrankenPHP version for PHP ${version}...`); - const frankenphpApiResponse = await fetchFrankenPhpTags(version); - const frankenphpLatestVersion = getLatestFrankenphpPatchVersion(frankenphpApiResponse); - - if (frankenphpLatestVersion) { - frankenphpVersions.push(frankenphpLatestVersion); - console.log(`Found FrankenPHP version for PHP ${version}: ${frankenphpLatestVersion}`); - } else { - console.log(`No FrankenPHP version found for PHP ${version}, skipping...`); - } -} +const phpLibraryRef = await fetchPhpLibraryRef(); +const versions = await fetchVersions(phpLibraryRef); -await updatePhpMatrixInHcl(phpVersions, frankenphpVersions); +await updateBakeFile(getPhpVersions(versions), phpLibraryRef, getLatestAlpineVersion(versions));