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