diff --git a/docker-bake.hcl b/docker-bake.hcl index f66a873..e7e3250 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -14,59 +14,6 @@ variable "frankenphpMatrix" { 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.2" -} - -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 target "frankenphp" { @@ -75,8 +22,8 @@ target "frankenphp" { matrix = { "php" = frankenphpMatrix } - contexts = { - base = "target:frankenphp-upstream-${replace(substr(php, 0, 3), ".", "-")}" + args = { + "PHP_VERSION" = php } platforms = [ "linux/amd64", "linux/arm64" ] tags = imageSuffix != "" ? [ @@ -122,7 +69,7 @@ target "fpm" { "php" = phpMatrix } contexts = { - base = "target:php-fpm-alpine-${replace(substr(php, 0, 3), ".", "-")}" + base = "docker-image://docker.io/library/php:${php}-fpm-alpine" } platforms = [ "linux/amd64", "linux/arm64" ] tags = imageSuffix != "" ? [ diff --git a/frankenphp/Dockerfile b/frankenphp/Dockerfile index 0b7fb31..f79ff78 100644 --- a/frankenphp/Dockerfile +++ b/frankenphp/Dockerfile @@ -1,7 +1,8 @@ #syntax=docker/dockerfile:1.4 #check=skip=SecretsUsedInArgOrEnv -FROM base +ARG PHP_VERSION=8.4 +FROM dunglas/frankenphp:php${PHP_VERSION} RUN < versions[version].variants ?? []) - .map(variant => variant.match(/^alpine(\d+\.\d+)\/fpm$/)?.[1]) - .filter(Boolean) - .sort((a, b) => a.localeCompare(b, undefined, { numeric: true })); + const jsonData = await response.json(); + return jsonData; +} - if (alpineVersions.length === 0) { - throw new Error('No Alpine variant found'); +// Function to extract the latest patch version from the API response +function getLatestPatchVersion(apiResponse) { + if (!apiResponse || !Array.isArray(apiResponse.results)) { + throw new Error('Invalid API response'); } - return alpineVersions.at(-1); -} + for (const entry of apiResponse.results) { + // Skip RC versions + if (entry.name.includes('RC')) { + continue; + } -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}`); + // Extract version number (e.g., 8.1.33) + const versionMatch = entry.name.match(/^(\d+\.\d+\.\d+)/); + if (versionMatch) { + return versionMatch[1]; } + } - return entry.version; - }); + return null; } -function replaceVariable(hclContent, name, value) { - const regex = new RegExp(`(variable "${name}" \\{\\s*default = )(\\[[^\\]]*\\]|"[^"]*")(\\s*\\})`, 's'); +// 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; + } - if (!regex.test(hclContent)) { - throw new Error(`${name} variable not found in docker-bake.hcl`); + // 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]; + } } - return hclContent.replace(regex, `$1${value}$3`); + return null; } -async function updateBakeFile(phpVersions, phpLibraryRef, alpineVersion) { +// Function to update the phpMatrix and frankenphpMatrix in docker-bake.hcl +async function updatePhpMatrixInHcl(phpVersions, frankenphpVersions) { const hclPath = 'docker-bake.hcl'; let hclContent = await fs.readFile(hclPath, 'utf8'); - 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}"`); + // 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`); await fs.writeFile(hclPath, hclContent); - console.log('Successfully updated docker-bake.hcl'); + console.log('Successfully updated phpMatrix and frankenphpMatrix in docker-bake.hcl'); console.log('PHP versions:', phpVersions); - console.log('docker-library/php ref:', phpLibraryRef); - console.log('Alpine version:', alpineVersion); + console.log('FrankenPHP versions:', frankenphpVersions); } -const phpLibraryRef = await fetchPhpLibraryRef(); -const versions = await fetchVersions(phpLibraryRef); +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...`); + } +} -await updateBakeFile(getPhpVersions(versions), phpLibraryRef, getLatestAlpineVersion(versions)); +await updatePhpMatrixInHcl(phpVersions, frankenphpVersions);