diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..90ec81cf7c7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +/*/**/Dockerfile linguist-generated +/Dockerfile*.template linguist-language=Dockerfile diff --git a/.github/workflows/verify-templating.yml b/.github/workflows/verify-templating.yml new file mode 100644 index 00000000000..7e833f1c7d2 --- /dev/null +++ b/.github/workflows/verify-templating.yml @@ -0,0 +1,22 @@ +name: Verify Templating + +on: + pull_request: + push: + +defaults: + run: + shell: 'bash -Eeuo pipefail -x {0}' + +jobs: + apply-templates: + name: Check For Uncomitted Changes + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Apply Templates + run: ./apply-templates.sh + - name: Check Git Status + run: | + status="$(git status --short)" + [ -z "$status" ] diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..d548f66de02 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.jq-template.awk diff --git a/10/Dockerfile b/10/Dockerfile index 6745c2e0b9c..aded55fa51a 100644 --- a/10/Dockerfile +++ b/10/Dockerfile @@ -1,3 +1,9 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + FROM buildpack-deps:buster RUN set -ex; \ diff --git a/8/Dockerfile b/8/Dockerfile index 655a4c6064b..f30b558c95b 100644 --- a/8/Dockerfile +++ b/8/Dockerfile @@ -1,3 +1,9 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + FROM buildpack-deps:buster RUN set -ex; \ diff --git a/9/Dockerfile b/9/Dockerfile index 5e891df9ef2..aabb82c94ac 100644 --- a/9/Dockerfile +++ b/9/Dockerfile @@ -1,3 +1,9 @@ +# +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" +# +# PLEASE DO NOT EDIT IT DIRECTLY. +# + FROM buildpack-deps:buster RUN set -ex; \ diff --git a/Dockerfile.template b/Dockerfile.template index b890c7fd5c5..2fe74a57417 100644 --- a/Dockerfile.template +++ b/Dockerfile.template @@ -1,4 +1,4 @@ -FROM buildpack-deps:%%SUITE%% +FROM buildpack-deps:{{ .debian }} RUN set -ex; \ if ! command -v gpg > /dev/null; then \ @@ -39,9 +39,9 @@ ENV GCC_MIRRORS \ # only attempt the origin FTP as a mirror of last resort ftp://ftp.gnu.org/gnu/gcc -# Last Modified: placeholder -ENV GCC_VERSION placeholder -# Docker EOL: placeholder +# Last Modified: {{ .lastModified }} +ENV GCC_VERSION {{ .version }} +# Docker EOL: {{ .eol }} RUN set -ex; \ \ @@ -65,12 +65,12 @@ RUN set -ex; \ return 1; \ }; \ \ - _fetch "gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.%%TARBALL-COMPRESSION%%.sig" 'gcc.tar.%%TARBALL-COMPRESSION%%.sig'; \ - _fetch "gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.%%TARBALL-COMPRESSION%%" 'gcc.tar.%%TARBALL-COMPRESSION%%'; \ - gpg --batch --verify gcc.tar.%%TARBALL-COMPRESSION%%.sig gcc.tar.%%TARBALL-COMPRESSION%%; \ + _fetch "gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.{{ .compression }}.sig" 'gcc.tar.{{ .compression }}.sig'; \ + _fetch "gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.{{ .compression }}" 'gcc.tar.{{ .compression }}'; \ + gpg --batch --verify gcc.tar.{{ .compression }}.sig gcc.tar.{{ .compression }}; \ mkdir -p /usr/src/gcc; \ - tar -xf gcc.tar.%%TARBALL-COMPRESSION%% -C /usr/src/gcc --strip-components=1; \ - rm gcc.tar.%%TARBALL-COMPRESSION%%*; \ + tar -xf gcc.tar.{{ .compression }} -C /usr/src/gcc --strip-components=1; \ + rm gcc.tar.{{ .compression }}*; \ \ cd /usr/src/gcc; \ \ diff --git a/apply-templates.sh b/apply-templates.sh new file mode 100755 index 00000000000..de2a9c9973c --- /dev/null +++ b/apply-templates.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +[ -f versions.json ] # run "versions.sh" first + +jqt='.jq-template.awk' +if [ -n "${BASHBREW_SCRIPTS:-}" ]; then + jqt="$BASHBREW_SCRIPTS/jq-template.awk" +elif [ "$BASH_SOURCE" -nt "$jqt" ]; then + wget -qO "$jqt" 'https://github.com/docker-library/bashbrew/raw/ac3e8e9541cb362a579b05bec41dd40d1df1c6e6/scripts/jq-template.awk' +fi + +if [ "$#" -eq 0 ]; then + versions="$(jq -r 'keys | map(@sh) | join(" ")' versions.json)" + eval "set -- $versions" +fi + +generated_warning() { + cat <<-EOH + # + # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" + # + # PLEASE DO NOT EDIT IT DIRECTLY. + # + + EOH +} + +for version; do + export version + + echo "processing $version ..." + + { + generated_warning + gawk -f "$jqt" Dockerfile.template + } > "$version/Dockerfile" +done diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh index e8a551cff95..342add02688 100755 --- a/generate-stackbrew-library.sh +++ b/generate-stackbrew-library.sh @@ -1,5 +1,5 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +set -Eeuo pipefail declare -A aliases=( [10]='latest' @@ -8,11 +8,13 @@ declare -A aliases=( self="$(basename "$BASH_SOURCE")" cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" -versions=( */ ) -versions=( "${versions[@]%/}" ) +if [ "$#" -eq 0 ]; then + versions="$(jq -r 'keys | map(@sh) | join(" ")' versions.json)" + eval "set -- $versions" +fi # sort version numbers with highest first -IFS=$'\n'; versions=( $(echo "${versions[*]}" | sort -rV) ); unset IFS +IFS=$'\n'; set -- $(sort -rV <<<"$*"); unset IFS # get the most recent commit which modified any of "$@" fileCommit() { @@ -40,7 +42,7 @@ getArches() { local repo="$1"; shift local officialImagesUrl='https://github.com/docker-library/official-images/raw/master/library/' - eval "declare -A -g parentRepoToArches=( $( + eval "declare -g -A parentRepoToArches=( $( find -name 'Dockerfile' -exec awk ' toupper($1) == "FROM" && $2 !~ /^('"$repo"'|scratch|.*\/.*)(:|$)/ { print "'"$officialImagesUrl"'" $2 @@ -67,11 +69,10 @@ join() { echo "${out#$sep}" } -for version in "${versions[@]}"; do - commit="$(dirCommit "$version")" +for version; do + export version - dockerfile="$(git show "$commit":"$version/Dockerfile")" - fullVersion="$(awk '$1 == "ENV" && $2 == "GCC_VERSION" { print $3; exit }' <<<"$dockerfile")" + fullVersion="$(jq -r '.[env.version].version' versions.json)" versionAliases=() while [ "$fullVersion" != "$version" -a "${fullVersion%[.-]*}" != "$fullVersion" ]; do @@ -83,18 +84,20 @@ for version in "${versions[@]}"; do ${aliases[$version]:-} ) - parent="$(awk 'toupper($1) == "FROM" { print $2 }' <<<"$dockerfile")" + commit="$(dirCommit "$version")" + + parent="$(awk 'toupper($1) == "FROM" { print $2 }' "$version/Dockerfile")" # no i386 for now: https://github.com/docker-library/gcc/issues/38 # no mips64le for now: https://github.com/docker-library/gcc/issues/67 arches="$(echo " ${parentRepoToArches[$parent]} " | sed -r -e 's/ i386 / /g' -e 's/ mips64le / /g')" echo - grep -m1 '^# Last Modified: ' <<<"$dockerfile" + jq -r '"# Last Modified: " + .[env.version].lastModified' versions.json cat <<-EOE Tags: $(join ', ' "${versionAliases[@]}") Architectures: $(join ', ' $arches) GitCommit: $commit Directory: $version EOE - grep -m1 '^# Docker EOL: ' <<<"$dockerfile" + jq -r '"# Docker EOL: " + .[env.version].eol' versions.json done diff --git a/update.sh b/update.sh index 927bb08cddb..bac2d7581c7 100755 --- a/update.sh +++ b/update.sh @@ -1,86 +1,7 @@ -#!/bin/bash +#!/usr/bin/env bash set -Eeuo pipefail -defaultDebianSuite='buster' -declare -A debianSuites=( - #[6]='jessie' -) - cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" -versions=( "$@" ) -if [ ${#versions[@]} -eq 0 ]; then - versions=( */ ) -fi -versions=( "${versions[@]%/}" ) - -#packagesUrl='https://ftpmirror.gnu.org/gcc/' -packagesUrl='https://mirrors.kernel.org/gnu/gcc/' # the actual HTML of the page changes based on which mirror we end up hitting, so let's hit a specific one for now... :'( -packages="$(wget -qO- "$packagesUrl")" - -# our own "supported" window is 18 months from the most recent release because upstream doesn't have a good guideline, but appears to only release maintenance updates for 2-3 years after the initial release -# in addition, maintenance releases are _usually_ less than a year apart; from 4.7+ there's a handful of outliers, like 4.7.3->4.7.4 at ~14 months, 6.4->6.5 at ~15 months, etc -export TZ=UTC -eolPeriod='18 months' -today="$(date +'%s')" -eolAgo="$(date +'%s' -d "$(date -d "@$today") - $eolPeriod")" -eolAge="$(( $today - $eolAgo ))" -eols=() - -dateFormat='%Y-%m-%d' - -for version in "${versions[@]}"; do - fullVersion="$(grep -E '&2 "error: $fullVersion does not seem to even really exist" - exit 1 - fi - - echo "$version: $fullVersion ($lastModified vs $eolDate); $debianSuite, $compression" - - sed -r \ - -e 's!%%SUITE%%!'"$debianSuite"'!g' \ - -e 's!^(ENV GCC_VERSION) .*!\1 '"$fullVersion"'!' \ - -e 's!^(# Last Modified:) .*!\1 '"$lastModified"'!' \ - -e 's!^(# Docker EOL:) .*!\1 '"$eolDate"'!' \ - -e 's!%%TARBALL-COMPRESSION%%!'"$compression"'!g' \ - Dockerfile.template \ - > "$version/Dockerfile" -done - -if [ ${#eols[@]} -gt 0 ]; then - { - echo - echo - echo - echo " WARNING: the following releases are older than $eolPeriod:" - echo - for eol in "${eols[@]}"; do - echo " - $eol" - done - echo - echo - echo - } >&2 -fi +./versions.sh "$@" +./apply-templates.sh "$@" diff --git a/versions.json b/versions.json new file mode 100644 index 00000000000..c217b47732e --- /dev/null +++ b/versions.json @@ -0,0 +1,23 @@ +{ + "10": { + "compression": "xz", + "debian": "buster", + "eol": "2022-10-08", + "lastModified": "2021-04-08", + "version": "10.3.0" + }, + "8": { + "compression": "xz", + "debian": "buster", + "eol": "2021-09-04", + "lastModified": "2020-03-04", + "version": "8.4.0" + }, + "9": { + "compression": "xz", + "debian": "buster", + "eol": "2021-09-12", + "lastModified": "2020-03-12", + "version": "9.3.0" + } +} diff --git a/versions.sh b/versions.sh new file mode 100755 index 00000000000..ff071590f51 --- /dev/null +++ b/versions.sh @@ -0,0 +1,94 @@ +#!/bin/bash +set -Eeuo pipefail + +defaultDebianSuite='buster' +declare -A debianSuites=( + #[6]='jessie' +) + +cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" + +versions=( "$@" ) +if [ ${#versions[@]} -eq 0 ]; then + versions=( */ ) + json='{}' +else + json="$(< versions.json)" +fi +versions=( "${versions[@]%/}" ) + +#packagesUrl='https://ftpmirror.gnu.org/gcc/' +packagesUrl='https://mirrors.kernel.org/gnu/gcc/' # the actual HTML of the page changes based on which mirror we end up hitting, so let's hit a specific one for now... :'( +packages="$(wget -qO- "$packagesUrl")" + +# our own "supported" window is 18 months from the most recent release because upstream doesn't have a good guideline, but appears to only release maintenance updates for 2-3 years after the initial release +# in addition, maintenance releases are _usually_ less than a year apart; from 4.7+ there's a handful of outliers, like 4.7.3->4.7.4 at ~14 months, 6.4->6.5 at ~15 months, etc +export TZ=UTC +eolPeriod='18 months' +today="$(date +'%s')" +eolAgo="$(date +'%s' -d "$(date -d "@$today") - $eolPeriod")" +eolAge="$(( $today - $eolAgo ))" +eols=() + +dateFormat='%Y-%m-%d' + +for version in "${versions[@]}"; do + fullVersion="$(grep -E '&2 "error: $fullVersion does not seem to even really exist" + exit 1 + fi + + echo "$version: $fullVersion ($lastModified vs $eolDate); $debianSuite, $compression" + + export version fullVersion lastModified eolDate debianSuite compression + json="$(jq <<<"$json" -c ' + .[env.version] = { + version: env.fullVersion, + lastModified: env.lastModified, + eol: env.eolDate, + debian: env.debianSuite, + compression: env.compression, + } + ')" +done + +if [ ${#eols[@]} -gt 0 ]; then + { + echo + echo + echo + echo " WARNING: the following releases are older than $eolPeriod:" + echo + for eol in "${eols[@]}"; do + echo " - $eol" + done + echo + echo + echo + } >&2 +fi + +jq <<<"$json" -S . > versions.json