From f8198432f1072a3deb6f6fc4628f1ac6a83d8102 Mon Sep 17 00:00:00 2001 From: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> Date: Thu, 15 Jan 2026 01:25:40 +0700 Subject: [PATCH 1/6] attempt to split alpine version checking for builds Signed-off-by: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> --- build-automation.mjs | 71 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/build-automation.mjs b/build-automation.mjs index ba296d1ed4..8c734ad199 100644 --- a/build-automation.mjs +++ b/build-automation.mjs @@ -17,12 +17,22 @@ const checkIfThereAreNewVersions = async (github) => { for (let supportedVersion of supportedVersions) { const { stdout } = await exec(`ls ${supportedVersion}`); - - const { stdout: fullVersionOutput } = await exec(`. ./functions.sh && get_full_version ./${supportedVersion}/${stdout.trim().split("\n")[0]}`, { shell: "bash" }); - - console.log(fullVersionOutput); - - latestSupportedVersions[supportedVersion] = { fullVersion: fullVersionOutput.trim() }; + const baseVersions = stdout.trim().split("\n"); + + const debianVersion = baseVersions.find(v => !v.startsWith("alpine")); + const { stdout: debianVersionOutput } = await exec(`. ./functions.sh && get_full_version ./${supportedVersion}/${debianVersion}`, { shell: "bash" }); + + const alpineVersion = baseVersions.find(v => v.startsWith("alpine")); + const { stdout: alpineVersionOutput } = await exec(`. ./functions.sh && get_full_version ./${supportedVersion}/${alpineVersion}`, { shell: "bash" }); + + const fullVersion = { debian : debianVersionOutput.trim(), alpine: alpineVersionOutput.trim() }; + console.log(`${supportedVersion}: debian=${fullVersion.debian}, alpine=${fullVersion.alpine}`); + + latestSupportedVersions[supportedVersion] = { + fullVersion: fullVersion.debian, + alpineVersion: fullVersion.alpine, + alpineIsBehind: fullVersion.debian !== fullVersion.alpine + }; } const { data: availableVersionsJson } = await github.request('https://nodejs.org/download/release/index.json'); @@ -39,9 +49,25 @@ const checkIfThereAreNewVersions = async (github) => { if (latestSupportedVersions[availableMajor] == null) { continue; } - const [_latestMajor, latestMinor, latestPatch] = latestSupportedVersions[availableMajor].fullVersion.split("."); - if (latestSupportedVersions[availableMajor] && (Number(availableMinor) > Number(latestMinor) || (availableMinor === latestMinor && Number(availablePatch) > Number(latestPatch)))) { - filteredNewerVersions[availableMajor] = { fullVersion: `${availableMajor}.${availableMinor}.${availablePatch}` }; + + const supported = latestSupportedVersions[availableMajor]; + const [_latestMajor, latestMinor, latestPatch] = supported.fullVersion.split("."); + const [_alpineMajor, alpineMinor, alpinePatch] = supported.alpineVersion.split("."); + + const availableFullVersion = `${availableMajor}.${availableMinor}.${availablePatch}`; + + const newDebian = Number(availableMinor) > Number(latestMinor) || (availableMinor === latestMinor && Number(availablePatch) > Number(latestPatch)); + const newAlpine = Number(availableMinor) > Number(alpineMinor) || (availableMinor === alpineMinor && Number(availablePatch) > Number(alpinePatch)); + + const isCatchup = supported.alpineIsBehind && newAlpine && availableFullVersion === supported.fullVersion; + + // Alpine will be always behind or equal to Debian + // So if Debian is new version, then alpineOnly is always false. And vice versa + if (newDebian || isCatchup) { + filteredNewerVersions[availableMajor] = { + fullVersion: availableFullVersion, + alpineOnly: !newDebian + }; } } @@ -88,13 +114,30 @@ export default async function(github) { const newVersions = await checkForMuslVersionsAndSecurityReleases(github, versions); let updatedVersions = []; for (const [version, newVersion] of Object.entries(newVersions)) { - if (newVersion.muslBuildExists) { - const { stdout } = await exec(`./update.sh ${newVersion.isSecurityRelease ? "-s " : ""}${version}`); + if (newVersion.alpineOnly) { + if (newVersion.muslBuildExists) { + console.log(`Catch-up Alpine build for version ${newVersion.fullVersion}`); + const { stdout } = await exec(`./update.sh ${version} alpine`); + console.log(stdout); + updatedVersions.push(`${newVersion.fullVersion} (alpine)`); + } else { + console.log(`There's no musl build for version ${newVersion.fullVersion} yet. Skipping Alpine catch-up.`); + } + } else if (newVersion.isSecurityRelease) { + console.log(`Processing security release ${newVersion.fullVersion}`); + const { stdout } = await exec(`./update.sh -s ${version}`); + console.log(stdout); + updatedVersions.push(newVersion.fullVersion); + } else if (newVersion.muslBuildExists) { + const { stdout } = await exec(`./update.sh ${version}`); console.log(stdout); updatedVersions.push(newVersion.fullVersion); } else { - console.log(`There's no musl build for version ${newVersion.fullVersion} yet.`); - process.exit(0); + // No musl build - update non-alpine only + console.log(`There's no musl build for version ${newVersion.fullVersion} yet. Updating non-alpine only.`); + const { stdout } = await exec(`./update.sh ${version} bookworm,bookworm-slim,bullseye,bullseye-slim,trixie,trixie-slim`); + console.log(stdout); + updatedVersions.push(`${newVersion.fullVersion} (non-alpine)`); } } const { stdout } = (await exec(`git diff`)); @@ -102,4 +145,4 @@ export default async function(github) { return updatedVersions.join(', '); } -} +} \ No newline at end of file From 3dbbef0b93765b2d6a2bce9e7f139d620a555961 Mon Sep 17 00:00:00 2001 From: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> Date: Thu, 15 Jan 2026 18:04:03 +0700 Subject: [PATCH 2/6] improve logic Signed-off-by: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> --- build-automation.mjs | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/build-automation.mjs b/build-automation.mjs index 8c734ad199..7320f8ec37 100644 --- a/build-automation.mjs +++ b/build-automation.mjs @@ -113,33 +113,31 @@ export default async function(github) { } else { const newVersions = await checkForMuslVersionsAndSecurityReleases(github, versions); let updatedVersions = []; + for (const [version, newVersion] of Object.entries(newVersions)) { - if (newVersion.alpineOnly) { - if (newVersion.muslBuildExists) { - console.log(`Catch-up Alpine build for version ${newVersion.fullVersion}`); - const { stdout } = await exec(`./update.sh ${version} alpine`); - console.log(stdout); - updatedVersions.push(`${newVersion.fullVersion} (alpine)`); + const { fullVersion, muslBuildExists, isSecurityRelease, alpineOnly } = newVersion; + // If MUSL is available: build everything (new versions) or alpine only (catch-up) + if (muslBuildExists) { + const updateScope = alpineOnly ? "alpine" : ""; + + console.log(`MUSL available. Updating ${fullVersion} ${updateScope}.`.trim()); + const { stdout } = await exec(`./update.sh ${version} ${updateScope}`.trim()); + console.log(stdout); + + updatedVersions.push(`${fullVersion} ${updateScope}`.trim()); + // Security release: no MUSL build + } else if (isSecurityRelease && !alpineOnly) { + console.log(`Updating ${fullVersion} for non-alpine.`); + + const { stdout } = await exec(`./update.sh -s ${version}`); + console.log(stdout); + + updatedVersions.push(`${fullVersion} (non-alpine)`); } else { - console.log(`There's no musl build for version ${newVersion.fullVersion} yet. Skipping Alpine catch-up.`); + console.log(`No MUSL build for ${fullVersion} yet.`); } - } else if (newVersion.isSecurityRelease) { - console.log(`Processing security release ${newVersion.fullVersion}`); - const { stdout } = await exec(`./update.sh -s ${version}`); - console.log(stdout); - updatedVersions.push(newVersion.fullVersion); - } else if (newVersion.muslBuildExists) { - const { stdout } = await exec(`./update.sh ${version}`); - console.log(stdout); - updatedVersions.push(newVersion.fullVersion); - } else { - // No musl build - update non-alpine only - console.log(`There's no musl build for version ${newVersion.fullVersion} yet. Updating non-alpine only.`); - const { stdout } = await exec(`./update.sh ${version} bookworm,bookworm-slim,bullseye,bullseye-slim,trixie,trixie-slim`); - console.log(stdout); - updatedVersions.push(`${newVersion.fullVersion} (non-alpine)`); - } } + const { stdout } = (await exec(`git diff`)); console.log(stdout); From 2bd4f4f3fbd2d90e59ad5ae162e909d2841b1a10 Mon Sep 17 00:00:00 2001 From: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> Date: Thu, 15 Jan 2026 18:12:39 +0700 Subject: [PATCH 3/6] update variable names Signed-off-by: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> --- build-automation.mjs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/build-automation.mjs b/build-automation.mjs index 7320f8ec37..3cb3bdd266 100644 --- a/build-automation.mjs +++ b/build-automation.mjs @@ -19,19 +19,19 @@ const checkIfThereAreNewVersions = async (github) => { const { stdout } = await exec(`ls ${supportedVersion}`); const baseVersions = stdout.trim().split("\n"); - const debianVersion = baseVersions.find(v => !v.startsWith("alpine")); - const { stdout: debianVersionOutput } = await exec(`. ./functions.sh && get_full_version ./${supportedVersion}/${debianVersion}`, { shell: "bash" }); + const standardVersion = baseVersions.find(v => !v.startsWith("alpine")); + const { stdout: standardVersionOutput } = await exec(`. ./functions.sh && get_full_version ./${supportedVersion}/${standardVersion}`, { shell: "bash" }); const alpineVersion = baseVersions.find(v => v.startsWith("alpine")); const { stdout: alpineVersionOutput } = await exec(`. ./functions.sh && get_full_version ./${supportedVersion}/${alpineVersion}`, { shell: "bash" }); - const fullVersion = { debian : debianVersionOutput.trim(), alpine: alpineVersionOutput.trim() }; - console.log(`${supportedVersion}: debian=${fullVersion.debian}, alpine=${fullVersion.alpine}`); + const fullVersion = { main : standardVersionOutput.trim(), alpine: alpineVersionOutput.trim() }; + console.log(`${supportedVersion}: main=${fullVersion.main}, alpine=${fullVersion.alpine}`); latestSupportedVersions[supportedVersion] = { - fullVersion: fullVersion.debian, + fullVersion: fullVersion.main, alpineVersion: fullVersion.alpine, - alpineIsBehind: fullVersion.debian !== fullVersion.alpine + alpineIsBehind: fullVersion.main !== fullVersion.alpine }; } @@ -56,17 +56,17 @@ const checkIfThereAreNewVersions = async (github) => { const availableFullVersion = `${availableMajor}.${availableMinor}.${availablePatch}`; - const newDebian = Number(availableMinor) > Number(latestMinor) || (availableMinor === latestMinor && Number(availablePatch) > Number(latestPatch)); + const newMainline = Number(availableMinor) > Number(latestMinor) || (availableMinor === latestMinor && Number(availablePatch) > Number(latestPatch)); const newAlpine = Number(availableMinor) > Number(alpineMinor) || (availableMinor === alpineMinor && Number(availablePatch) > Number(alpinePatch)); const isCatchup = supported.alpineIsBehind && newAlpine && availableFullVersion === supported.fullVersion; - // Alpine will be always behind or equal to Debian - // So if Debian is new version, then alpineOnly is always false. And vice versa - if (newDebian || isCatchup) { + // Alpine will be always behind or equal to main + // So if main is new version, then alpineOnly is always false. And vice versa + if (newMainline || isCatchup) { filteredNewerVersions[availableMajor] = { fullVersion: availableFullVersion, - alpineOnly: !newDebian + alpineOnly: !newMainline }; } } From faebb3d7113ec80b7dc70758f5f40168b63d7999 Mon Sep 17 00:00:00 2001 From: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> Date: Thu, 15 Jan 2026 22:49:13 +0700 Subject: [PATCH 4/6] trim whitespaces Signed-off-by: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> --- build-automation.mjs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/build-automation.mjs b/build-automation.mjs index 3cb3bdd266..a1d25522e9 100644 --- a/build-automation.mjs +++ b/build-automation.mjs @@ -24,7 +24,7 @@ const checkIfThereAreNewVersions = async (github) => { const alpineVersion = baseVersions.find(v => v.startsWith("alpine")); const { stdout: alpineVersionOutput } = await exec(`. ./functions.sh && get_full_version ./${supportedVersion}/${alpineVersion}`, { shell: "bash" }); - + const fullVersion = { main : standardVersionOutput.trim(), alpine: alpineVersionOutput.trim() }; console.log(`${supportedVersion}: main=${fullVersion.main}, alpine=${fullVersion.alpine}`); @@ -64,9 +64,9 @@ const checkIfThereAreNewVersions = async (github) => { // Alpine will be always behind or equal to main // So if main is new version, then alpineOnly is always false. And vice versa if (newMainline || isCatchup) { - filteredNewerVersions[availableMajor] = { - fullVersion: availableFullVersion, - alpineOnly: !newMainline + filteredNewerVersions[availableMajor] = { + fullVersion: availableFullVersion, + alpineOnly: !newMainline }; } } @@ -119,19 +119,19 @@ export default async function(github) { // If MUSL is available: build everything (new versions) or alpine only (catch-up) if (muslBuildExists) { const updateScope = alpineOnly ? "alpine" : ""; - + console.log(`MUSL available. Updating ${fullVersion} ${updateScope}.`.trim()); const { stdout } = await exec(`./update.sh ${version} ${updateScope}`.trim()); console.log(stdout); - + updatedVersions.push(`${fullVersion} ${updateScope}`.trim()); // Security release: no MUSL build } else if (isSecurityRelease && !alpineOnly) { console.log(`Updating ${fullVersion} for non-alpine.`); - + const { stdout } = await exec(`./update.sh -s ${version}`); console.log(stdout); - + updatedVersions.push(`${fullVersion} (non-alpine)`); } else { console.log(`No MUSL build for ${fullVersion} yet.`); @@ -143,4 +143,4 @@ export default async function(github) { return updatedVersions.join(', '); } -} \ No newline at end of file +} From b687765488b0db8335797bbfe0123943cbc10fe3 Mon Sep 17 00:00:00 2001 From: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> Date: Fri, 16 Jan 2026 01:12:57 +0700 Subject: [PATCH 5/6] fix incorrect behavior for -s and [variants] parameter Signed-off-by: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> --- functions.sh | 4 ++-- update.sh | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/functions.sh b/functions.sh index 444dc2f679..056477801f 100755 --- a/functions.sh +++ b/functions.sh @@ -69,7 +69,7 @@ function get_variants() { if [ ${#variantsfilter[@]} -gt 0 ]; then for variant1 in "${availablevariants[@]}"; do for variant2 in "${variantsfilter[@]}"; do - if [ "${variant1}" = "${variant2}" ]; then + if [[ "${variant1}" =~ ^"${variant2}" ]]; then variants+=("${variant1}") fi done @@ -365,4 +365,4 @@ function tests_updated() { return 1 fi return 0 -} +} \ No newline at end of file diff --git a/update.sh b/update.sh index c30b6b3088..e99cf4b19f 100755 --- a/update.sh +++ b/update.sh @@ -130,6 +130,14 @@ function update_node_version() { fi nodeVersion="${version}.${fullVersion:-0}" + + # preserve the existing YARN_VERSION + if [ "${SKIP}" = true ] && [ -f "${dockerfile}" ]; then + existing_yarn_version=$(grep -m1 'ENV YARN_VERSION=' "${dockerfile}" | cut -d'=' -f2 || echo "") + if [ -n "${existing_yarn_version}" ]; then + sed -Ei -e 's/^(ENV YARN_VERSION)=.*/\1='"${existing_yarn_version}"'/' "${dockerfile}-tmp" + fi + fi sed -Ei -e 's/^FROM (.*)/FROM '"$fromprefix"'\1/' "${dockerfile}-tmp" sed -Ei -e 's/^(ENV NODE_VERSION)=.*/\1='"${nodeVersion}"'/' "${dockerfile}-tmp" @@ -208,6 +216,11 @@ for version in "${versions[@]}"; do # Skip non-docker directories [ -f "${version}/${variant}/Dockerfile" ] || continue + # Skip alpine variants when SKIP is true + if [ "${SKIP}" = true ] && is_alpine "${variant}"; then + continue + fi + update_variant=$(in_variants_to_update "${variant}") template_file="${parentpath}/Dockerfile-${variant}.template" From dd0693d7e5e1a4b7cb06758c02db02497c4edd62 Mon Sep 17 00:00:00 2001 From: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> Date: Fri, 16 Jan 2026 01:18:25 +0700 Subject: [PATCH 6/6] trim whitespaces Signed-off-by: Harta Angkasa <24356946+ItsHarta@users.noreply.github.com> --- functions.sh | 2 +- update.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/functions.sh b/functions.sh index 056477801f..c223854342 100755 --- a/functions.sh +++ b/functions.sh @@ -365,4 +365,4 @@ function tests_updated() { return 1 fi return 0 -} \ No newline at end of file +} diff --git a/update.sh b/update.sh index e99cf4b19f..63a57f6348 100755 --- a/update.sh +++ b/update.sh @@ -130,7 +130,7 @@ function update_node_version() { fi nodeVersion="${version}.${fullVersion:-0}" - + # preserve the existing YARN_VERSION if [ "${SKIP}" = true ] && [ -f "${dockerfile}" ]; then existing_yarn_version=$(grep -m1 'ENV YARN_VERSION=' "${dockerfile}" | cut -d'=' -f2 || echo "")