Skip to content

Commit

Permalink
Add initial jq-based templating engine
Browse files Browse the repository at this point in the history
  • Loading branch information
tianon committed Mar 24, 2022
1 parent 6916e7b commit c4e3208
Show file tree
Hide file tree
Showing 189 changed files with 2,939 additions and 935 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Dockerfile* linguist-language=Dockerfile
3 changes: 1 addition & 2 deletions .github/workflows/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ done
jq -c . <<<"$strategy" > /dev/null # sanity check

# now that we have a list of legit images with generate scripts, look for dangling Dockerfiles
strategyDockerfiles="$(jq -c '[ .matrix.include[].meta.dockerfiles[], "cygwin/Dockerfile" ]' <<<"$strategy")"
allDockerfiles="$(git ls-files '*/Dockerfile' | jq -Rsc 'rtrimstr("\n") | split("\n")')"
danglingDockerfiles="$(jq -cn "$allDockerfiles - $strategyDockerfiles")"
danglingDockerfiles="$(jq <<<"$strategy" -c --argjson allDockerfiles "$allDockerfiles" '$allDockerfiles - [ .matrix.include[].meta.dockerfiles[] ]')"

strategy="$(jq -c --argjson danglingDockerfiles "$danglingDockerfiles" '.matrix.include[0] as $first | .matrix.include += [
$danglingDockerfiles[]
Expand Down
25 changes: 25 additions & 0 deletions .github/workflows/verify-templating.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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: ./parallel.sh apply-templates.sh
- name: Git Diff (informational)
run: |
git diff || :
- name: Check Git Status
run: |
status="$(git status --short)"
[ -z "$status" ]
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/.jq-template.awk
54 changes: 54 additions & 0 deletions .libs/deb-repo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env bash
set -Eeuo pipefail

deb-repo() {
[ -n "$uri" ]
[ -n "$suite" ]
#[ -n "$component" ] # if suite ends with /, this is optional
: "${arch:=amd64}"
[ -n "$package" ]

_deb-repo_packages() {
local packages
if [[ "$suite" == */ ]]; then
[ -z "${component:-}" ]
packages="$uri/${suite}Packages"
else
[ -n "$component" ]
packages="$uri/dists/$suite/$component/binary-$arch/Packages"
fi
{ wget -qO- "$packages.xz" | xz -d 2>/dev/null; } \
|| { wget -qO- "$packages.bz2" | bunzip2 2>/dev/null; } \
|| { wget -qO- "$packages.gz" | gunzip 2>/dev/null; } \
|| { wget -qO- "$packages.zstd" | zstd -d 2>/dev/null; } \
|| wget -qO- "$packages"
}

local versions version
versions="$(
_deb-repo_packages | gawk -F ':[[:space:]]+' -v package="$package" '
function do_the_thing() { if (pkg == package) { printf "%s %s\n", ver, sha256 }; pkg = ver = sha256 = "" }
$1 == "Package" { do_the_thing(); pkg = $2; ver = sha256 = "" }
$1 == "Version" { ver = $2 }
$1 == "SHA256" { sha256 = $2 }
END { do_the_thing() }
' | sort -rV
)"
version="$(head -1 <<<"$versions")" # TODO some way to get *not* the latest version?
if [ -z "$version" ]; then
echo >&2 "error: failed to find a version for '$package' in '$uri' (suite '$suite', comp '$component', arch '$arch')"
return 1
fi
local sha256="${version##* }"
version="${version% $sha256}"
[ "$sha256" != "$version" ] || sha256=

echo >&2 "deb $package: $version"
# TODO gather "supported arches" list

jq -nS --arg version "$version" --arg sha256 "$sha256" '
{
version: $version,
} | if $sha256 then .sha256 = $sha256 else . end
'
}
59 changes: 59 additions & 0 deletions .libs/git.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env bash
set -Eeuo pipefail

git-tags() {
local repo="$1"; shift
[ -n "$repo" ]

local tag
tag="$(
git ls-remote --tags "$repo" \
| cut -d/ -f3 \
| cut -d^ -f1 \
| grep -vE -- '-(rc|alpha|beta)' \
| sort -Vu \
| tail -1
)"
local version="${tag#v}"

local base; base="$(basename "$repo")"
echo >&2 "git $base: $version"

jq -nc --arg tag "$tag" --arg version "$version" '
{
version: $version,
tag: $tag,
}
'
}

git-ref-commit() {
local repo="$1"; shift
local ref="$1"; shift

local commit
commit="$(git ls-remote "$repo" "$ref" | cut -d$'\t' -f1)"

local base; base="$(basename "$repo")"
echo >&2 "git $base - $ref: $commit"

jq -nc --arg commit "$commit" '{ version: $commit }'
}

github-file-commit() {
local repo="$1"; shift
local branch="$1"; shift
local file="$1"; shift
[ -n "$repo" ]
[ -n "$branch" ]
[ -n "$file" ]

local atom
atom="$(wget -qO- "https://github.com/$repo/commits/$branch/$file.atom")"
local commit
commit="$(awk <<<"$atom" -F ' *[<>/]+' '$2 == "id" && $3 ~ /Commit/ { print $4; exit }')"

echo >&2 "github $repo - $file: $commit"

jq -nc --arg commit "$commit" '{ version: $commit }'
}
32 changes: 32 additions & 0 deletions .libs/pypi.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
set -Eeuo pipefail

pypi() {
local package="$1"; shift
[ -n "$package" ]

local json version
json="$(wget -qO- "https://pypi.org/pypi/$package/json")"
version="$(jq <<<"$json" -r '.info.version')" # TODO some way to only get versions matching a particular string? ("1.14.x" etc. instead of just latest)

echo >&2 "pip $package: $version"

jq <<<"$json" -c '
.info
| (
.classifiers
| map(
match("^(?:Programming Language :: )?Python :: ([0-9]+[.][0-9]+)$")
| .captures[0].string
| split(".")
| map(tonumber)
)
| sort[-1]
| join(".")
) as $python
| {
version: .version,
python: { version: $python },
}
'
}
67 changes: 67 additions & 0 deletions apply-templates.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/env bash
set -Eeuo pipefail

jqt="$(dirname "$BASH_SOURCE")"
jqt="$jqt/.jq-template.awk"
if [ -n "${BASHBREW_SCRIPTS:-}" ]; then
jqt="$BASHBREW_SCRIPTS/jq-template.awk"
elif [ "$BASH_SOURCE" -nt "$jqt" ]; then
# https://github.com/docker-library/bashbrew/blob/master/scripts/jq-template.awk
jqtNew="$jqt.new.$$" # using a (unique) ".new" file so this is safe to run concurrently
wget -qO "$jqtNew" 'https://github.com/docker-library/bashbrew/raw/1da7341a79651d28fbcc3d14b9176593c4231942/scripts/jq-template.awk'
mv -f "$jqtNew" "$jqt"
fi
jqt="$(readlink -ve "$jqt")"

dirs="$(find "$@" -type f -name versions.json -exec bash -Eeuo pipefail -c 'for d; do dir="$(dirname "${d#./}")"; printf " %q" "$dir"; done' -- '{}' +)"
eval "set -- $dirs"

if [ "$#" -eq 0 ]; then
echo >&2 "error: failed to find any 'versions.json' files!"
exit 1
fi

generated_warning() {
cat <<-EOH
#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#
EOH
}

for dir; do
export dir

template="$dir"
while [ ! -s "$template/Dockerfile.template" ]; do
if [ "$template" = '.' ]; then
echo >&2 "error: failed to find template for '$dir'!"
exit 1
fi
template="$(dirname "$template")"
done

variants="$(jq -r '.variants // [""] | map(@sh) | join(" ")' "$dir/versions.json")"
eval "variants=( $variants )"

text="$dir"
if [ "$dir" != "$template" ]; then
text+=" ($template)"
fi
template="$template/Dockerfile.template"

for variant in "${variants[@]}"; do
export variant

echo "processing $text${variant:+" variant '$variant'"} ..."

(
cd "$dir"
generated_warning
gawk -f "$jqt"
) < "$template" > "$dir/Dockerfile${variant:+".$variant"}"
done
done
11 changes: 9 additions & 2 deletions backblaze-b2/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
FROM python:3.9-alpine3.14
#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#

FROM python:3.10-alpine3.15

# https://pypi.org/project/b2/
ENV BACKBLAZE_B2_VERSION 3.2.1

RUN set -eux; \
pip install --no-cache-dir "b2 == $BACKBLAZE_B2_VERSION"
pip install --no-cache-dir "b2 == $BACKBLAZE_B2_VERSION"; \
b2 version

CMD ["b2", "--help"]
10 changes: 10 additions & 0 deletions backblaze-b2/Dockerfile.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM python:{{ .python.version }}-alpine3.15

# https://pypi.org/project/b2/
ENV BACKBLAZE_B2_VERSION {{ .version }}

RUN set -eux; \
pip install --no-cache-dir "b2 == $BACKBLAZE_B2_VERSION"; \
b2 version

CMD ["b2", "--help"]
9 changes: 0 additions & 9 deletions backblaze-b2/update.sh

This file was deleted.

6 changes: 6 additions & 0 deletions backblaze-b2/versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"python": {
"version": "3.10"
},
"version": "3.2.1"
}
12 changes: 12 additions & 0 deletions backblaze-b2/versions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -Eeuo pipefail

[ -e versions.json ]

dir="$(readlink -ve "$BASH_SOURCE")"
dir="$(dirname "$dir")"
source "$dir/../.libs/pypi.sh"

json="$(pypi 'b2')"

jq <<<"$json" -S . > versions.json
12 changes: 10 additions & 2 deletions beets/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
FROM python:3.9-alpine3.14
#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#

FROM python:3.9-alpine3.15

ENV BEETS_VERSION 1.6.0

RUN pip install --no-cache-dir beets==$BEETS_VERSION
RUN set -eux; \
pip install --no-cache-dir "beets == $BEETS_VERSION"; \
beet --version

CMD ["beet"]
9 changes: 9 additions & 0 deletions beets/Dockerfile.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM python:{{ .python.version }}-alpine3.15

ENV BEETS_VERSION {{ .version }}

RUN set -eux; \
pip install --no-cache-dir "beets == $BEETS_VERSION"; \
beet --version

CMD ["beet"]
9 changes: 0 additions & 9 deletions beets/update.sh

This file was deleted.

6 changes: 6 additions & 0 deletions beets/versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"python": {
"version": "3.9"
},
"version": "1.6.0"
}
12 changes: 12 additions & 0 deletions beets/versions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -Eeuo pipefail

[ -e versions.json ]

dir="$(readlink -ve "$BASH_SOURCE")"
dir="$(dirname "$dir")"
source "$dir/../.libs/pypi.sh"

json="$(pypi 'beets')"

jq <<<"$json" -S . > versions.json
Loading

0 comments on commit c4e3208

Please sign in to comment.