@@ -0,0 +1,170 @@
1+#!/usr/bin/env bash
2+
3+set -eu
4+cd "$(dirname "$0")"
5+
6+#
7+# Constants and defaults
8+#
9+
10+DOCKER_REPO=fpco/stack-build
11+PUSH=false
12+DRY=false
13+VARIANT=build
14+
15+#
16+# Functions
17+#
18+
19+# Print usage information and exit with failure status. First argument is an
20+# error message.
21+usage() {
22+ echo "$0: $1" >&2
23+ echo
24+ echo "Usage: $0 [--push] [--dry-run] [--small] lts-X.Y|lts-X|lts]"
25+ echo "See README.md for more information."
26+ echo
27+ exit 1
28+}
29+
30+# Print a command, and if --dry-run disabled also run it
31+dry() {
32+ echo ">>> $*"
33+ [[ $DRY = true ]] || "$@"
34+}
35+
36+# Push an image if --push is enabled (otherwise do nothing)
37+push() {
38+ [[ $PUSH = false ]] || dry docker push "$1"
39+}
40+
41+# Tag an image, and then push it if --push is enabled
42+tagpush() {
43+ dry docker tag "$1" "$2"
44+ push "$2"
45+}
46+
47+#
48+# Parse command-line
49+#
50+
51+LTS_SLUG_ARG=
52+while [[ $# -gt 0 ]]; do
53+ case "$1" in
54+ --push)
55+ PUSH=true
56+ shift
57+ ;;
58+ --dry-run)
59+ DRY=true
60+ shift
61+ ;;
62+ --small)
63+ VARIANT=small
64+ DOCKER_REPO=fpco/stack-build-small
65+ shift
66+ ;;
67+ -*)
68+ usage "Unknown option: $1"
69+ ;;
70+ *)
71+ if [[ -n "$LTS_SLUG_ARG" ]]; then
72+ usage "Cannot specify multiple snaphots: $1"
73+ fi
74+ LTS_SLUG_ARG="$1"
75+ shift
76+ ;;
77+ esac
78+done
79+
80+#
81+# Determine actual snapshot version from aliases
82+#
83+
84+SNAPSHOTS="$(mktemp "lts-snapshots.json.XXXXXX")"
85+trap "rm -f \"$SNAPSHOTS\"" EXIT
86+wget -qO- https://www.stackage.org/download/lts-snapshots.json >"$SNAPSHOTS"
87+
88+case "$LTS_SLUG_ARG" in
89+ "")
90+ usage "Missing argument: snapshot or alias"
91+ ;;
92+ lts-*.*)
93+ LTS_SLUG="$LTS_SLUG_ARG"
94+ ;;
95+ *)
96+ LTS_SLUG=$(jq -r ".[\"$LTS_SLUG_ARG\"]" "$SNAPSHOTS")
97+ if [[ -z "$LTS_SLUG" || "$LTS_SLUG" = "null" ]]; then
98+ echo "$0: Cannot find LTS version for slug: $LTS_SLUG_ARG" >&2
99+ exit 1
100+ fi
101+ ;;
102+esac
103+
104+LTS_VERSION="${LTS_SLUG#lts-}"
105+LTS_MAJOR="${LTS_VERSION%.*}"
106+LTS_MINOR="${LTS_VERSION#*.}"
107+
108+#
109+# Determine latest LTS version
110+#
111+
112+LATEST_LTS_SLUG=$(jq -r ".[\"lts\"]" $SNAPSHOTS)
113+LATEST_LTS_VERSION="${LATEST_LTS_SLUG#lts-}"
114+LATEST_LTS_MAJOR="${LATEST_LTS_VERSION%.*}"
115+LATEST_LTS_MINOR="${LATEST_LTS_VERSION#*.}"
116+
117+#
118+# Determine latest minor version of the selected major version
119+#
120+
121+MAJOR_LATEST_LTS_SLUG=$(jq -r ".[\"lts-$LTS_MAJOR\"]" $SNAPSHOTS)
122+MAJOR_LATEST_LTS_VERSION="${MAJOR_LATEST_LTS_SLUG#lts-}"
123+MAJOR_LATEST_LTS_MAJOR="${MAJOR_LATEST_LTS_VERSION%.*}"
124+MAJOR_LATEST_LTS_MINOR="${MAJOR_LATEST_LTS_VERSION#*.}"
125+
126+#
127+# Find the Dockerfile for the selected snapshot
128+#
129+
130+if [[ -s "$LTS_SLUG/Dockerfile" ]]; then
131+
132+ # If there is an exact match, build and push that image
133+
134+ sed "s/\\\$DOCKER_REPO/$(echo $DOCKER_REPO|sed 's/\//\\\//')/g" "$LTS_SLUG/Dockerfile" >"$LTS_SLUG/Dockerfile.sub"
135+ dry docker build -t "$DOCKER_REPO:$LTS_SLUG" --build-arg "DOCKER_REPO=$DOCKER_REPO" --build-arg "LTS_SLUG=$LTS_SLUG" --build-arg "VARIANT=$VARIANT" -f "$LTS_SLUG/Dockerfile.sub" "$LTS_SLUG"
136+ rm -f "$LTS_SLUG/Dockerfile.sub"
137+ push "$DOCKER_REPO:$LTS_SLUG"
138+else
139+
140+ # If no exact match, find a dockerfile for any earlier minor version of the
141+ # selected major version, and just create a new tag from version's image with the selected
142+ # minor version (assuming that nothing needs to change), and push it.
143+
144+ minor=$(( LTS_MINOR - 1 ))
145+ while [[ ! -s "lts-$LTS_MAJOR.$minor/Dockerfile" && $minor -ge 0 ]]; do
146+ minor=$(( minor - 1 ))
147+ done
148+ if [[ $minor -lt 0 ]]; then
149+ echo "$0: Cannot find any Dockerfile for LTS major version" >&2
150+ exit 1
151+ fi
152+ dry docker pull "$DOCKER_REPO:lts-$LTS_MAJOR.$minor" || true
153+ tagpush "$DOCKER_REPO:lts-$LTS_MAJOR.$minor" "$DOCKER_REPO:$LTS_SLUG"
154+fi
155+
156+#
157+# Create and push additional tags
158+#
159+
160+# If we select the latest minor version for the selected major version, then
161+# also create and push an 'lts-X' tag.
162+if [[ "$MAJOR_LATEST_LTS_VERSION" = "$LTS_VERSION" ]]; then
163+ tagpush "$DOCKER_REPO:$LTS_SLUG" "$DOCKER_REPO:lts-$LTS_MAJOR"
164+fi
165+
166+# If we selected the latest LTS snapshot, also create and push the 'lts' and 'latest' tags.
167+if [[ "$LATEST_LTS_VERSION" = "$LTS_VERSION" ]]; then
168+ tagpush "$DOCKER_REPO:$LTS_SLUG" "$DOCKER_REPO:lts"
169+ tagpush "$DOCKER_REPO:$LTS_SLUG" "$DOCKER_REPO:latest"
170+fi