diff --git a/.github/workflows/official-pr.yml b/.github/workflows/official-pr.yml index a9b6ef12..b57f32de 100644 --- a/.github/workflows/official-pr.yml +++ b/.github/workflows/official-pr.yml @@ -10,8 +10,7 @@ on: - "**/Dockerfile" - "**/architectures" - "**/docker-entrypoint.sh" - - "generate-stackbrew-library.sh" - - "functions.sh" + - "stackbrew.js" - "config" jobs: @@ -36,7 +35,7 @@ jobs: - name: Generate Stackbrew for diff run: | cd docker-node - ./generate-stackbrew-library.sh > ../official-images/library/node + ./stackbrew.js > ../official-images/library/node - name: Create PR in official-images id: create-pr diff --git a/10/architectures b/10/architectures deleted file mode 100644 index c178997a..00000000 --- a/10/architectures +++ /dev/null @@ -1,8 +0,0 @@ -bashbrew-arch variants -amd64 alpine3.10,alpine3.11,buster,buster-slim,stretch,stretch-slim -arm32v6 alpine3.10,alpine3.11 -arm32v7 alpine3.10,alpine3.11,buster,buster-slim,stretch,stretch-slim -arm64v8 alpine3.10,alpine3.11,buster,buster-slim,stretch,stretch-slim -i386 alpine3.10,alpine3.11 -ppc64le alpine3.10,alpine3.11,buster,buster-slim -s390x alpine3.10,alpine3.11,buster,buster-slim diff --git a/12/architectures b/12/architectures deleted file mode 100644 index e5967159..00000000 --- a/12/architectures +++ /dev/null @@ -1,7 +0,0 @@ -bashbrew-arch variants -amd64 alpine3.10,alpine3.11,alpine3.12,buster,buster-slim,stretch,stretch-slim -arm32v6 alpine3.10,alpine3.11,alpine3.12 -arm32v7 alpine3.10,alpine3.11,alpine3.12,buster,buster-slim,stretch,stretch-slim -arm64v8 alpine3.10,alpine3.11,alpine3.12,buster,buster-slim,stretch,stretch-slim -ppc64le alpine3.10,alpine3.11,alpine3.12,buster,buster-slim -s390x alpine3.10,alpine3.11,alpine3.12,buster,buster-slim diff --git a/14/architectures b/14/architectures deleted file mode 100644 index 253f4aa7..00000000 --- a/14/architectures +++ /dev/null @@ -1,7 +0,0 @@ -bashbrew-arch variants -amd64 alpine3.10,alpine3.11,alpine3.12,alpine3.13,buster,buster-slim,stretch,stretch-slim -arm32v6 alpine3.10,alpine3.11,alpine3.12,alpine3.13 -arm32v7 alpine3.10,alpine3.11,alpine3.12,alpine3.13,buster,buster-slim,stretch,stretch-slim -arm64v8 alpine3.10,alpine3.11,alpine3.12,alpine3.13,buster,buster-slim,stretch,stretch-slim -ppc64le alpine3.10,alpine3.11,alpine3.12,alpine3.13,buster,buster-slim -s390x alpine3.10,alpine3.11,alpine3.12,alpine3.13,buster,buster-slim diff --git a/15/architectures b/15/architectures deleted file mode 100644 index 253f4aa7..00000000 --- a/15/architectures +++ /dev/null @@ -1,7 +0,0 @@ -bashbrew-arch variants -amd64 alpine3.10,alpine3.11,alpine3.12,alpine3.13,buster,buster-slim,stretch,stretch-slim -arm32v6 alpine3.10,alpine3.11,alpine3.12,alpine3.13 -arm32v7 alpine3.10,alpine3.11,alpine3.12,alpine3.13,buster,buster-slim,stretch,stretch-slim -arm64v8 alpine3.10,alpine3.11,alpine3.12,alpine3.13,buster,buster-slim,stretch,stretch-slim -ppc64le alpine3.10,alpine3.11,alpine3.12,alpine3.13,buster,buster-slim -s390x alpine3.10,alpine3.11,alpine3.12,alpine3.13,buster,buster-slim diff --git a/16/architectures b/16/architectures deleted file mode 100644 index e2f96e58..00000000 --- a/16/architectures +++ /dev/null @@ -1,7 +0,0 @@ -bashbrew-arch variants -amd64 alpine3.11,alpine3.12,alpine3.13,buster,buster-slim,stretch,stretch-slim -arm32v6 alpine3.11,alpine3.12,alpine3.13 -arm32v7 alpine3.11,alpine3.12,alpine3.13,buster,buster-slim,stretch,stretch-slim -arm64v8 alpine3.11,alpine3.12,alpine3.13,buster,buster-slim,stretch,stretch-slim -ppc64le alpine3.11,alpine3.12,alpine3.13,buster,buster-slim -s390x alpine3.11,alpine3.12,alpine3.13,buster,buster-slim diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh deleted file mode 100755 index 764919fc..00000000 --- a/generate-stackbrew-library.sh +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env bash - -set -e -. functions.sh - -hash git 2> /dev/null || { echo >&2 "git not found, exiting."; } - -# Used dynamically: print "$array_" $1 -# shellcheck disable=SC2034 -array_10='10 dubnium' -# shellcheck disable=SC2034 -array_12='12 erbium' -# shellcheck disable=SC2034 -array_14='14 fermium lts' -# shellcheck disable=SC2034 -array_15='15' -# shellcheck disable=SC2034 -array_16='16 latest current' - -default_variant=$(get_config "./" "default_variant") - -default_alpine=$(get_config "./" "alpine_version") - -cd "$(cd "${0%/*}" && pwd -P)" - -self="$(basename "${BASH_SOURCE[0]}")" - -IFS=' ' read -ra versions <<< "$(get_versions)" -IFS=' ' read -ra versions <<< "$(sort_versions "${versions[@]}")" -url='https://github.com/nodejs/docker-node' - -# get the most recent commit which modified any of "$@" -fileCommit() { - git log -1 --format='format:%H' HEAD -- "$@" -} - -echo "# this file is generated via ${url}/blob/$(fileCommit "${self}")/${self}" -echo -echo "Maintainers: The Node.js Docker Team <${url}> (@nodejs)" -echo "GitRepo: ${url}.git" -echo "GitFetch: refs/heads/main" -echo - -# prints "$2$1$3$1...$N" -join() { - local sep="$1" - shift - local out - printf -v out "${sep//%/%%}%s" "$@" - echo "${out#$sep}" -} - -get_stub() { - local version="${1}" - shift - IFS='/' read -ra versionparts <<< "${version}" - local stub - eval stub="$(join '_' "${versionparts[@]}" | awk -F. '{ print "$array_" $1 }')" - echo "${stub}" -} - -for version in "${versions[@]}"; do - # Skip "docs" and other non-docker directories - [ -f "${version}/Dockerfile" ] || [ -f "${version}/${default_variant}/Dockerfile" ] || continue - - stub=$(get_stub "${version}") - commit="$(fileCommit "${version}")" - fullVersion="$(get_tag "${version}" full)" - majorMinorVersion="$(get_tag "${version}" majorminor)" - - IFS=' ' read -ra versionAliases <<< "$fullVersion $majorMinorVersion $stub" - - if [ -f "${version}/Dockerfile" ]; then - # Get supported architectures for a specific version. See details in function.sh - IFS=' ' read -ra supportedArches <<< "$(get_supported_arches "${version}" "default")" - - echo "Tags: $(join ', ' "${versionAliases[@]}")" - echo "Architectures: $(join ', ' "${supportedArches[@]}")" - echo "GitCommit: ${commit}" - echo "Directory: ${version}" - echo - fi - - # Get supported variants according to the target architecture. - # See details in function.sh - IFS=' ' read -ra variants <<< "$(get_variants "$(dirname "${version}")")" - for variant in "${variants[@]}"; do - # Skip non-docker directories - [ -f "${version}/${variant}/Dockerfile" ] || continue - - commit="$(fileCommit "${version}/${variant}")" - - slash='/' - variantAliases=("${versionAliases[@]/%/-${variant//${slash}/-}}") - if [ "${variant}" = "${default_variant}-slim" ]; then - variantAliases+=("${versionAliases[@]/%/-slim}") - elif [ "${variant}" = "alpine${default_alpine}" ]; then - variantAliases+=("${versionAliases[@]/%/-alpine}") - elif [ "${variant}" = "${default_variant}" ]; then - variantAliases+=("${versionAliases[@]}") - fi - variantAliases=("${variantAliases[@]//latest-/}") - - # Get supported architectures for a specific version and variant. - # See details in function.sh - IFS=' ' read -ra supportedArches <<< "$(get_supported_arches "${version}" "${variant}")" - - echo "Tags: $(join ', ' "${variantAliases[@]}")" - echo "Architectures: $(join ', ' "${supportedArches[@]}")" - echo "GitCommit: ${commit}" - echo "Directory: ${version}/${variant}" - echo - done -done diff --git a/stackbrew.js b/stackbrew.js new file mode 100644 index 00000000..8b6f5540 --- /dev/null +++ b/stackbrew.js @@ -0,0 +1,152 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); + +// Grab last git commit +function getCommitHasForPath(path) { + return require('child_process') + .execSync(`git log -1 --format=%H HEAD -- ${path}`) + .toString().trim() +} + +const stackbrewPath = path.basename(__filename); + +// Header +let stackbrew = `# this file is generated via https://github.com/nodejs/docker-node/blob/${getCommitHasForPath(stackbrewPath)}/${stackbrewPath} + +Maintainers: The Node.js Docker Team (@nodejs) +GitRepo: https://github.com/nodejs/docker-node.git +GitFetch: refs/heads/main\n`; + +// Loop versions + +const config = require('./versions.json'); + +const versions = Object.keys(config).reverse() + +const now = new Date().getTime() +const aplineRE = new RegExp(/alpine*/); +const slimRE = new RegExp(/\*-slim/); + +for(version of versions) { + let lts = new Date(config[version].lts).getTime(); + let maintenance = new Date(config[version].maintenance).getTime(); + let isCurrent = lts > now; + let isLTS = (maintenance > now) && (now > lts); + let codename = config[version].codename + let defaultAlpine = config[version]['alpine-default'] + let defaultDebian = config[version]['debian-default'] + let variants = config[version].variants + let fullversion; + for(variant in variants) { + let dockerfilePath = path.join(version, variant, 'Dockerfile'); + let isAlpine = aplineRE.test(variant) + let isSlim = slimRE.test(variant) + let isDefaultSlim = new RegExp(`${defaultDebian}-slim`).test(variant) + + // Get full version from the first Dockerfile + if (!fullversion) { + let dockerfile = fs.readFileSync(dockerfilePath, 'utf-8') + fullversion = dockerfile.match(/ENV NODE_VERSION (?\d+)\.(?\d+)\.(?\d+)/) + } + let tags = [ + `${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}-${variant}`, + `${fullversion.groups.major}.${fullversion.groups.minor}-${variant}`, + `${fullversion.groups.major}-${variant}`, + ] + + if (codename) { + tags.push(`${codename}-${variant}`) + } + + if (variant === defaultAlpine) { + tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}-alpine`) + tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}-alpine`) + tags.push(`${fullversion.groups.major}-alpine`) + if (codename) { + tags.push(`${codename}-alpine`) + } + } + + if (variant === defaultDebian) { + tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}`) + tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}`) + tags.push(`${fullversion.groups.major}`) + if (isSlim) { + tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}-slim`) + tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}-slim`) + tags.push(`${fullversion.groups.major}-slim`) + } + if (codename) { + tags.push(`${codename}`) + } + } + if (isDefaultSlim) { + tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}-slim`) + tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}-slim`) + tags.push(`${fullversion.groups.major}-slim`) + if (codename) { + tags.push(`${codename}-slim`) + } + } + + if (isCurrent) { + if (variant === defaultAlpine) { + tags.push(variant) + tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}.${fullversion.groups.patch}-alpine`) + tags.push(`${fullversion.groups.major}.${fullversion.groups.minor}-alpine`) + tags.push(`${fullversion.groups.major}-alpine`) + tags.push('alpine') + tags.push('current-alpine') + } + if (variant === defaultDebian) { + tags.push(variant) + tags.push('latest') + tags.push('current') + } + if (isAlpine) { + tags.push(`${variant}`) + tags.push(`current-${variant}`) + } + if (!isAlpine) { + tags.push(`${variant}`) + tags.push(`current-${variant}`) + } + if (isDefaultSlim) { + tags.push('slim') + tags.push('current-slim') + } + } + + if (isLTS) { + tags.push(`lts-${variant}`) + if (variant === defaultAlpine) { + } + if (variant === defaultDebian) { + tags.push('lts') + if (codename) { + tags.push(`lts-${codename}`) + } + } + if (isDefaultSlim) { + tags.push(`lts-slim`) + } + if (variant === defaultAlpine) { + tags.push(`lts-alpine`) + } + } + + // remove duplicates + tags = tags.filter((x, i, a) => a.indexOf(x) == i) + tags = tags.sort() + + stackbrew += `\nTags: ${tags.join(', ')}\n` + stackbrew += `Architectures: ${config[version].variants[variant].join(', ')}\n` + stackbrew += `GitCommit: ${getCommitHasForPath(dockerfilePath)}\n` + stackbrew += `Directory: ${version}/${variant}\n` + } +} + +// output +console.log(stackbrew) diff --git a/versions.json b/versions.json new file mode 100644 index 00000000..ac9a5e94 --- /dev/null +++ b/versions.json @@ -0,0 +1,305 @@ +{ + "16": { + "start": "2021-04-20", + "lts": "2021-10-26", + "maintenance": "2022-10-18", + "end": "2024-04-30", + "codename": "", + "alpine-default": "alpine3.13", + "debian-default": "buster", + "variants": { + "alpine3.11": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "alpine3.12": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "alpine3.13": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "buster": [ + "amd64", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "buster-slim": [ + "amd64", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "stretch": [ + "amd64", + "arm32v7", + "arm64v8" + ], + "stretch-slim": [ + "amd64", + "arm32v7", + "arm64v8" + ] + } + }, + "15": { + "start": "2020-10-20", + "maintenance": "2021-04-01", + "end": "2021-06-01", + "alpine-default": "alpine3.11", + "debian-default": "stretch", + "variants": { + "alpine3.10": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "alpine3.11": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "alpine3.12": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "alpine3.13": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "buster": [ + "amd64", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "buster-slim": [ + "amd64", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "stretch": [ + "amd64", + "arm32v7", + "arm64v8" + ], + "stretch-slim": [ + "amd64", + "arm32v7", + "arm64v8" + ] + } + }, + "14": { + "start": "2020-04-21", + "lts": "2020-10-27", + "maintenance": "2021-10-19", + "end": "2023-04-30", + "codename": "fermium", + "alpine-default": "alpine3.11", + "debian-default": "stretch", + "variants": { + "alpine3.10": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "alpine3.11": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "alpine3.12": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "alpine3.13": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "buster": [ + "amd64", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "buster-slim": [ + "amd64", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "stretch": [ + "amd64", + "arm32v7", + "arm64v8" + ], + "stretch-slim": [ + "amd64", + "arm32v7", + "arm64v8" + ] + } + }, + "12": { + "start": "2019-04-23", + "lts": "2019-10-21", + "maintenance": "2020-11-30", + "end": "2022-04-30", + "codename": "erbium", + "alpine-default": "alpine3.11", + "debian-default": "stretch", + "variants": { + "alpine3.10": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "alpine3.11": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "alpine3.12": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "buster": [ + "amd64", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "buster-slim": [ + "amd64", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "stretch": [ + "amd64", + "arm32v7", + "arm64v8" + ], + "stretch-slim": [ + "amd64", + "arm32v7", + "arm64v8" + ] + } + }, + "10": { + "start": "2018-04-24", + "lts": "2018-10-30", + "maintenance": "2020-05-19", + "end": "2021-04-30", + "codename": "dubnium", + "alpine-default": "alpine3.11", + "debian-default": "stretch", + "variants": { + "alpine3.10": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "i386", + "ppc64le", + "s390x" + ], + "alpine3.11": [ + "amd64", + "arm32v6", + "arm32v7", + "arm64v8", + "i386", + "ppc64le", + "s390x" + ], + "buster": [ + "amd64", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "buster-slim": [ + "amd64", + "arm32v7", + "arm64v8", + "ppc64le", + "s390x" + ], + "stretch": [ + "amd64", + "arm32v7", + "arm64v8" + ], + "stretch-slim": [ + "amd64", + "arm32v7", + "arm64v8" + ] + } + } +}