From 724f5667db6f48e25a6c1171119d65b505bb71b5 Mon Sep 17 00:00:00 2001 From: Andrei Dziahel Date: Mon, 16 Jun 2025 14:13:44 +0200 Subject: [PATCH] add: Dockerfile generator initial draft --- .github/workflows/debian.yml | 11 +- .gitignore | 7 +- 9.10/_globals.yaml | 9 ++ 9.10/bookworm.yaml | 21 ++++ 9.10/bookworm/Dockerfile | 144 +++++++++++++++++++++++++ 9.10/bullseye.yaml | 17 +++ 9.10/bullseye/Dockerfile | 193 +++++++++++++++++---------------- 9.10/slim-bookworm.yaml | 21 ++++ 9.10/slim-bookworm/Dockerfile | 144 +++++++++++++++++++++++++ 9.10/slim-bullseye.yaml | 17 +++ 9.12/_globals.yaml | 9 ++ 9.12/bookworm.yaml | 16 +++ 9.12/bookworm/Dockerfile | 197 ++++++++++++++++++---------------- 9.12/bullseye.yaml | 22 ++++ 9.12/bullseye/Dockerfile | 144 +++++++++++++++++++++++++ 9.12/slim-bookworm.yaml | 16 +++ 9.12/slim-bookworm/Dockerfile | 197 ++++++++++++++++++---------------- 9.12/slim-bullseye.yaml | 22 ++++ 9.12/slim-bullseye/Dockerfile | 144 +++++++++++++++++++++++++ README.md | 36 ++++++- generator/.gitignore | 3 + generator/CHANGELOG.md | 5 + generator/app/Main.hs | 117 ++++++++++++++++++++ generator/app/Options.hs | 70 ++++++++++++ generator/generator.cabal | 84 +++++++++++++++ generator/hie.yaml | 2 + generator/stack.yaml | 68 ++++++++++++ generator/stack.yaml.lock | 12 +++ template/Dockerfile.jinja | 146 +++++++++++++++++++++++++ 29 files changed, 1605 insertions(+), 289 deletions(-) create mode 100644 9.10/_globals.yaml create mode 100644 9.10/bookworm.yaml create mode 100644 9.10/bookworm/Dockerfile create mode 100644 9.10/bullseye.yaml create mode 100644 9.10/slim-bookworm.yaml create mode 100644 9.10/slim-bookworm/Dockerfile create mode 100644 9.10/slim-bullseye.yaml create mode 100644 9.12/_globals.yaml create mode 100644 9.12/bookworm.yaml create mode 100644 9.12/bullseye.yaml create mode 100644 9.12/bullseye/Dockerfile create mode 100644 9.12/slim-bookworm.yaml create mode 100644 9.12/slim-bullseye.yaml create mode 100644 9.12/slim-bullseye/Dockerfile create mode 100644 generator/.gitignore create mode 100644 generator/CHANGELOG.md create mode 100644 generator/app/Main.hs create mode 100644 generator/app/Options.hs create mode 100644 generator/generator.cabal create mode 100644 generator/hie.yaml create mode 100644 generator/stack.yaml create mode 100644 generator/stack.yaml.lock create mode 100644 template/Dockerfile.jinja diff --git a/.github/workflows/debian.yml b/.github/workflows/debian.yml index 4b808850..18216887 100644 --- a/.github/workflows/debian.yml +++ b/.github/workflows/debian.yml @@ -35,17 +35,18 @@ jobs: - ghc: '9.12.2' ghc_minor: '9.12' deb: 'slim-bookworm' + - ghc: '9.12.2' + ghc_minor: '9.12' + deb: 'bullseye' + - ghc: '9.12.2' + ghc_minor: '9.12' + deb: 'slim-bullseye' - ghc: '9.10.2' ghc_minor: '9.10' - ghc: '9.8.4' ghc_minor: '9.8' - ghc: '9.6.7' ghc_minor: '9.6' - exclude: - - ghc: '9.12.2' - deb: 'bullseye' - - ghc: '9.12.2' - deb: 'slim-bullseye' steps: - uses: actions/checkout@v4 - name: build + smoke test [${{ matrix.ghc }}] diff --git a/.gitignore b/.gitignore index caf38adc..ea95de4d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +generator/.stack-work +generator/dist-newstyle +/.idea + keys/* ### https://raw.github.com/github/gitignore/2399ff1c7957fa3b4eeecefa7354bbe50776063b/Global/Emacs.gitignore @@ -55,7 +59,8 @@ tramp .LSOverride # Icon must end with two \r -Icon +Icon + # Thumbnails ._* diff --git a/9.10/_globals.yaml b/9.10/_globals.yaml new file mode 100644 index 00000000..a6d67e60 --- /dev/null +++ b/9.10/_globals.yaml @@ -0,0 +1,9 @@ +stack: + version: "3.3.1" + release_key: "C5705533DA4F78D8664B5DC0575159689BEFB442" + sha256sum: + "aarch64": 'bdd618ea5a9c921417727011f2ecd78987dffa5cee5e741108baf65a9b5b58ab' + "x86_64": '88d7e517342c125b0a098d9d578fe53e590618ae4b2427283a27408a1ebd06d8' +cabal_install: + version: "3.14.1.1" + release_key: "EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF" diff --git a/9.10/bookworm.yaml b/9.10/bookworm.yaml new file mode 100644 index 00000000..e3979825 --- /dev/null +++ b/9.10/bookworm.yaml @@ -0,0 +1,21 @@ +--- +distro: + codename: 'bookworm' + abbr: 'deb12' + image: 'debian:bookworm' +ghc: + version: "9.10.2" + release_key: "88B57FCF7DB53B4DB3BFA4B1588764FBE22D19C4" + sha256sum: + "aarch64": '0188ca098abdaf71eb0804d0f35311f405da489137d8d438bfaa43b8d1e3f1b0' + "x86_64": '71d025743f2eb4d3af95d4dd94a22c093c2814d78ab95dd0e12bb6751b1c7d4e' +cabal_install: + sha256sum: + "aarch64": 'f763fb2af2bc1ff174b7361a7d51109a585954f87a0e14f86d144f3bce28f7a9' + "x86_64": '73a463306c771e18ca22c0a9469176ffab0138ec5925adb5364ef47174e1adc5' +overrides: + ghc: + "aarch64": + # GHC 9.10.2 doesn't have a deb12 bindist for aarch64 for some reason, so we're using the bullseye one instead + url: "https://downloads.haskell.org/~ghc/9.10.2/ghc-9.10.2-aarch64-deb11-linux.tar.xz" +_globals: !include '_globals.yaml' diff --git a/9.10/bookworm/Dockerfile b/9.10/bookworm/Dockerfile new file mode 100644 index 00000000..6b9a52e4 --- /dev/null +++ b/9.10/bookworm/Dockerfile @@ -0,0 +1,144 @@ +FROM debian:bookworm + +ENV LANG=C.UTF-8 + +# common haskell + stack dependencies +RUN <&2 "error: unsupported architecture '$ARCH'" exit 1 ; + esac + curl -sSL "$STACK_URL" -o stack.tar.gz + echo "$STACK_SHA256 stack.tar.gz" | sha256sum --strict --check + + curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc + GNUPGHOME="$(mktemp -d)" + export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY" + gpg --batch --verify stack.tar.gz.asc stack.tar.gz + gpgconf --kill all + + tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack" + stack config set system-ghc --global true + stack config set install-ghc --global false + + rm -rf /tmp/* + + stack --version; +EOT + +ARG CABAL_INSTALL=3.14.1.1 +ARG CABAL_INSTALL_RELEASE_KEY=EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF + +RUN <&2 "error: unsupported architecture '$ARCH'"; exit 1 ;; + esac + curl -fSL "$CABAL_INSTALL_URL" -o cabal-install.tar.gz + echo "$CABAL_INSTALL_SHA256 cabal-install.tar.gz" | sha256sum --strict --check + + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL" + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL.sig" + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$CABAL_INSTALL_RELEASE_KEY" + gpg --batch --verify SHA256SUMS.sig SHA256SUMS + # confirm we are verifying SHA256SUMS that matches the release + sha256 + grep "$CABAL_INSTALL_SHA256 $CABAL_INSTALL_TAR" SHA256SUMS + gpgconf --kill all; + + tar -xf cabal-install.tar.gz -C /usr/local/bin + + rm -rf /tmp/* + + cabal --version +EOT + +ARG GHC='9.10.2' +ARG GHC_RELEASE_KEY='88B57FCF7DB53B4DB3BFA4B1588764FBE22D19C4' + +RUN <&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; + esac + curl -sSL "$GHC_URL" -o ghc.tar.xz + echo "$GHC_SHA256 ghc.tar.xz" | sha256sum --strict --check + + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + curl -sSL "$GHC_URL.sig" -o ghc.tar.xz.sig + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$GHC_RELEASE_KEY" + gpg --batch --verify ghc.tar.xz.sig ghc.tar.xz + gpgconf --kill all + + tar xf ghc.tar.xz + cd "ghc-$GHC-$ARCH-unknown-linux" + ./configure --prefix "/opt/ghc/$GHC" + make install + + rm -rf /tmp/* + + "/opt/ghc/$GHC/bin/ghc" --version +EOT + +ENV PATH=/root/.cabal/bin:/root/.local/bin:/opt/ghc/${GHC}/bin:$PATH + +CMD ["ghci"] diff --git a/9.10/bullseye.yaml b/9.10/bullseye.yaml new file mode 100644 index 00000000..020d0ba8 --- /dev/null +++ b/9.10/bullseye.yaml @@ -0,0 +1,17 @@ +--- +distro: + codename: 'bullseye' + abbr: 'deb11' + image: 'debian:bullseye' +ghc: + version: "9.10.2" + release_key: "88B57FCF7DB53B4DB3BFA4B1588764FBE22D19C4" + sha256sum: + "aarch64": '0188ca098abdaf71eb0804d0f35311f405da489137d8d438bfaa43b8d1e3f1b0' + "x86_64": '2fe2c3e0a07e4782530e8bf83eeda8ff6935e40d5450c1809abcdc6182c9c848' +cabal_install: + sha256sum: + "aarch64": '5e8c47a055d5b744741039a7061ee43ec7d080d1251784e7a4cd836403e42523' + "x86_64": '41b85bb25fa654e4b79169014b9142fe696ff35e002e043caa0e52d65204ba8a' +_globals: !include '_globals.yaml' + diff --git a/9.10/bullseye/Dockerfile b/9.10/bullseye/Dockerfile index 91e6bfcb..01d43a04 100644 --- a/9.10/bullseye/Dockerfile +++ b/9.10/bullseye/Dockerfile @@ -3,7 +3,8 @@ FROM debian:bullseye ENV LANG=C.UTF-8 # common haskell + stack dependencies -RUN apt-get update && \ +RUN <&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; \ - esac; \ - curl -sSL "$STACK_URL" -o stack.tar.gz; \ - echo "$STACK_SHA256 stack.tar.gz" | sha256sum --strict --check; \ - \ - curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc; \ - GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \ - gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY"; \ - gpg --batch --verify stack.tar.gz.asc stack.tar.gz; \ - gpgconf --kill all; \ - \ - tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack"; \ - stack config set system-ghc --global true; \ - stack config set install-ghc --global false; \ - \ - rm -rf /tmp/*; \ - \ + case "$ARCH" in + 'aarch64') + STACK_SHA256='bdd618ea5a9c921417727011f2ecd78987dffa5cee5e741108baf65a9b5b58ab' + ;; + 'x86_64') + STACK_SHA256='88d7e517342c125b0a098d9d578fe53e590618ae4b2427283a27408a1ebd06d8' + ;; + *) echo >&2 "error: unsupported architecture '$ARCH'" exit 1 ; + esac + curl -sSL "$STACK_URL" -o stack.tar.gz + echo "$STACK_SHA256 stack.tar.gz" | sha256sum --strict --check + + curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc + GNUPGHOME="$(mktemp -d)" + export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY" + gpg --batch --verify stack.tar.gz.asc stack.tar.gz + gpgconf --kill all + + tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack" + stack config set system-ghc --global true + stack config set install-ghc --global false + + rm -rf /tmp/* + stack --version; +EOT -ARG CABAL_INSTALL=3.12.1.0 -ARG CABAL_INSTALL_RELEASE_KEY=1E07C9A1A3088BAD47F74A3E227EE1942B0BDB95 +ARG CABAL_INSTALL=3.14.1.1 +ARG CABAL_INSTALL_RELEASE_KEY=EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF -RUN set -eux; \ - cd /tmp; \ - ARCH="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)"; \ - CABAL_INSTALL_TAR="cabal-install-$CABAL_INSTALL-$ARCH-linux-deb11.tar.xz"; \ - CABAL_INSTALL_URL="https://downloads.haskell.org/~cabal/cabal-install-$CABAL_INSTALL/$CABAL_INSTALL_TAR"; \ - CABAL_INSTALL_SHA256SUMS_URL="https://downloads.haskell.org/~cabal/cabal-install-$CABAL_INSTALL/SHA256SUMS"; \ +RUN <&2 "error: unsupported architecture '$ARCH'"; exit 1 ;; \ - esac; \ - curl -fSL "$CABAL_INSTALL_URL" -o cabal-install.tar.gz; \ - echo "$CABAL_INSTALL_SHA256 cabal-install.tar.gz" | sha256sum --strict --check; \ - \ - curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL"; \ - curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL.sig"; \ - GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \ - gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$CABAL_INSTALL_RELEASE_KEY"; \ - gpg --batch --verify SHA256SUMS.sig SHA256SUMS; \ + case "$ARCH" in + 'aarch64') + CABAL_INSTALL_SHA256='5e8c47a055d5b744741039a7061ee43ec7d080d1251784e7a4cd836403e42523' + ;; + 'x86_64') + CABAL_INSTALL_SHA256='41b85bb25fa654e4b79169014b9142fe696ff35e002e043caa0e52d65204ba8a' + ;; + *) echo >&2 "error: unsupported architecture '$ARCH'"; exit 1 ;; + esac + curl -fSL "$CABAL_INSTALL_URL" -o cabal-install.tar.gz + echo "$CABAL_INSTALL_SHA256 cabal-install.tar.gz" | sha256sum --strict --check + + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL" + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL.sig" + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$CABAL_INSTALL_RELEASE_KEY" + gpg --batch --verify SHA256SUMS.sig SHA256SUMS # confirm we are verifying SHA256SUMS that matches the release + sha256 - grep "$CABAL_INSTALL_SHA256 $CABAL_INSTALL_TAR" SHA256SUMS; \ - gpgconf --kill all; \ - \ - tar -xf cabal-install.tar.gz -C /usr/local/bin; \ - \ - rm -rf /tmp/*; \ - \ + grep "$CABAL_INSTALL_SHA256 $CABAL_INSTALL_TAR" SHA256SUMS + gpgconf --kill all; + + tar -xf cabal-install.tar.gz -C /usr/local/bin + + rm -rf /tmp/* + cabal --version +EOT -ARG GHC=9.10.2 -ARG GHC_RELEASE_KEY=88B57FCF7DB53B4DB3BFA4B1588764FBE22D19C4 +ARG GHC='9.10.2' +ARG GHC_RELEASE_KEY='88B57FCF7DB53B4DB3BFA4B1588764FBE22D19C4' -RUN set -eux; \ - cd /tmp; \ - ARCH="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)"; \ - GHC_URL="https://downloads.haskell.org/~ghc/$GHC/ghc-$GHC-$ARCH-deb11-linux.tar.xz"; \ +RUN <&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; \ - esac; \ - curl -sSL "$GHC_URL" -o ghc.tar.xz; \ - echo "$GHC_SHA256 ghc.tar.xz" | sha256sum --strict --check; \ - \ - GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \ - curl -sSL "$GHC_URL.sig" -o ghc.tar.xz.sig; \ - gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$GHC_RELEASE_KEY"; \ - gpg --batch --verify ghc.tar.xz.sig ghc.tar.xz; \ - gpgconf --kill all; \ - \ - tar xf ghc.tar.xz; \ - cd "ghc-$GHC-$ARCH-unknown-linux"; \ - ./configure --prefix "/opt/ghc/$GHC"; \ - make install; \ - \ - rm -rf /tmp/*; \ - \ + case "$ARCH" in + 'aarch64') + GHC_SHA256='0188ca098abdaf71eb0804d0f35311f405da489137d8d438bfaa43b8d1e3f1b0' + ;; + 'x86_64') + GHC_SHA256='2fe2c3e0a07e4782530e8bf83eeda8ff6935e40d5450c1809abcdc6182c9c848' + ;; + *) echo >&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; + esac + curl -sSL "$GHC_URL" -o ghc.tar.xz + echo "$GHC_SHA256 ghc.tar.xz" | sha256sum --strict --check + + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + curl -sSL "$GHC_URL.sig" -o ghc.tar.xz.sig + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$GHC_RELEASE_KEY" + gpg --batch --verify ghc.tar.xz.sig ghc.tar.xz + gpgconf --kill all + + tar xf ghc.tar.xz + cd "ghc-$GHC-$ARCH-unknown-linux" + ./configure --prefix "/opt/ghc/$GHC" + make install + + rm -rf /tmp/* + "/opt/ghc/$GHC/bin/ghc" --version +EOT ENV PATH=/root/.cabal/bin:/root/.local/bin:/opt/ghc/${GHC}/bin:$PATH diff --git a/9.10/slim-bookworm.yaml b/9.10/slim-bookworm.yaml new file mode 100644 index 00000000..c90b809e --- /dev/null +++ b/9.10/slim-bookworm.yaml @@ -0,0 +1,21 @@ +--- +distro: + codename: 'bookworm' + abbr: 'deb12' + image: 'debian:bookworm-slim' +ghc: + version: "9.10.2" + release_key: "88B57FCF7DB53B4DB3BFA4B1588764FBE22D19C4" + sha256sum: + "aarch64": '0188ca098abdaf71eb0804d0f35311f405da489137d8d438bfaa43b8d1e3f1b0' + "x86_64": '71d025743f2eb4d3af95d4dd94a22c093c2814d78ab95dd0e12bb6751b1c7d4e' +cabal_install: + sha256sum: + "aarch64": 'f763fb2af2bc1ff174b7361a7d51109a585954f87a0e14f86d144f3bce28f7a9' + "x86_64": '73a463306c771e18ca22c0a9469176ffab0138ec5925adb5364ef47174e1adc5' +overrides: + ghc: + "aarch64": + # GHC 9.10.2 doesn't have a deb12 bindist for aarch64 for some reason, so we're using the bullseye one instead + url: "https://downloads.haskell.org/~ghc/9.10.2/ghc-9.10.2-aarch64-deb11-linux.tar.xz" +_globals: !include '_globals.yaml' diff --git a/9.10/slim-bookworm/Dockerfile b/9.10/slim-bookworm/Dockerfile new file mode 100644 index 00000000..696100d5 --- /dev/null +++ b/9.10/slim-bookworm/Dockerfile @@ -0,0 +1,144 @@ +FROM debian:bookworm-slim + +ENV LANG=C.UTF-8 + +# common haskell + stack dependencies +RUN <&2 "error: unsupported architecture '$ARCH'" exit 1 ; + esac + curl -sSL "$STACK_URL" -o stack.tar.gz + echo "$STACK_SHA256 stack.tar.gz" | sha256sum --strict --check + + curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc + GNUPGHOME="$(mktemp -d)" + export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY" + gpg --batch --verify stack.tar.gz.asc stack.tar.gz + gpgconf --kill all + + tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack" + stack config set system-ghc --global true + stack config set install-ghc --global false + + rm -rf /tmp/* + + stack --version; +EOT + +ARG CABAL_INSTALL=3.14.1.1 +ARG CABAL_INSTALL_RELEASE_KEY=EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF + +RUN <&2 "error: unsupported architecture '$ARCH'"; exit 1 ;; + esac + curl -fSL "$CABAL_INSTALL_URL" -o cabal-install.tar.gz + echo "$CABAL_INSTALL_SHA256 cabal-install.tar.gz" | sha256sum --strict --check + + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL" + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL.sig" + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$CABAL_INSTALL_RELEASE_KEY" + gpg --batch --verify SHA256SUMS.sig SHA256SUMS + # confirm we are verifying SHA256SUMS that matches the release + sha256 + grep "$CABAL_INSTALL_SHA256 $CABAL_INSTALL_TAR" SHA256SUMS + gpgconf --kill all; + + tar -xf cabal-install.tar.gz -C /usr/local/bin + + rm -rf /tmp/* + + cabal --version +EOT + +ARG GHC='9.10.2' +ARG GHC_RELEASE_KEY='88B57FCF7DB53B4DB3BFA4B1588764FBE22D19C4' + +RUN <&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; + esac + curl -sSL "$GHC_URL" -o ghc.tar.xz + echo "$GHC_SHA256 ghc.tar.xz" | sha256sum --strict --check + + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + curl -sSL "$GHC_URL.sig" -o ghc.tar.xz.sig + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$GHC_RELEASE_KEY" + gpg --batch --verify ghc.tar.xz.sig ghc.tar.xz + gpgconf --kill all + + tar xf ghc.tar.xz + cd "ghc-$GHC-$ARCH-unknown-linux" + ./configure --prefix "/opt/ghc/$GHC" + make install + + rm -rf /tmp/* + + "/opt/ghc/$GHC/bin/ghc" --version +EOT + +ENV PATH=/root/.cabal/bin:/root/.local/bin:/opt/ghc/${GHC}/bin:$PATH + +CMD ["ghci"] diff --git a/9.10/slim-bullseye.yaml b/9.10/slim-bullseye.yaml new file mode 100644 index 00000000..b307ee1a --- /dev/null +++ b/9.10/slim-bullseye.yaml @@ -0,0 +1,17 @@ +--- +distro: + codename: 'bullseye' + abbr: 'deb11' + image: 'debian:bullseye-slim' +ghc: + version: "9.10.2" + release_key: "88B57FCF7DB53B4DB3BFA4B1588764FBE22D19C4" + sha256sum: + "aarch64": '0188ca098abdaf71eb0804d0f35311f405da489137d8d438bfaa43b8d1e3f1b0' + "x86_64": '2fe2c3e0a07e4782530e8bf83eeda8ff6935e40d5450c1809abcdc6182c9c848' +cabal_install: + sha256sum: + "aarch64": '5e8c47a055d5b744741039a7061ee43ec7d080d1251784e7a4cd836403e42523' + "x86_64": '41b85bb25fa654e4b79169014b9142fe696ff35e002e043caa0e52d65204ba8a' +_globals: !include '_globals.yaml' + diff --git a/9.12/_globals.yaml b/9.12/_globals.yaml new file mode 100644 index 00000000..a6d67e60 --- /dev/null +++ b/9.12/_globals.yaml @@ -0,0 +1,9 @@ +stack: + version: "3.3.1" + release_key: "C5705533DA4F78D8664B5DC0575159689BEFB442" + sha256sum: + "aarch64": 'bdd618ea5a9c921417727011f2ecd78987dffa5cee5e741108baf65a9b5b58ab' + "x86_64": '88d7e517342c125b0a098d9d578fe53e590618ae4b2427283a27408a1ebd06d8' +cabal_install: + version: "3.14.1.1" + release_key: "EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF" diff --git a/9.12/bookworm.yaml b/9.12/bookworm.yaml new file mode 100644 index 00000000..b778dde9 --- /dev/null +++ b/9.12/bookworm.yaml @@ -0,0 +1,16 @@ +--- +distro: + codename: 'bookworm' + abbr: 'deb12' + image: 'debian:bookworm' +ghc: + version: "9.12.2" + release_key: "FFEB7CE81E16A36B3E2DED6F2DE04D4E97DB64AD" + sha256sum: + "aarch64": 'bee95bc91a621d8a2e9a9d86dac28ff839605e87316518dae12c779709bd58f1' + "x86_64": '447ec2fcc773ae9ebc3f39766c719641631274f9b765d7426a8cbe9241677c9f' +cabal_install: + sha256sum: + "aarch64": 'f763fb2af2bc1ff174b7361a7d51109a585954f87a0e14f86d144f3bce28f7a9' + "x86_64": '73a463306c771e18ca22c0a9469176ffab0138ec5925adb5364ef47174e1adc5' +_globals: !include '_globals.yaml' diff --git a/9.12/bookworm/Dockerfile b/9.12/bookworm/Dockerfile index 79784595..9d39f295 100644 --- a/9.12/bookworm/Dockerfile +++ b/9.12/bookworm/Dockerfile @@ -3,7 +3,8 @@ FROM debian:bookworm ENV LANG=C.UTF-8 # common haskell + stack dependencies -RUN apt-get update && \ +RUN <&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; \ - esac; \ - curl -sSL "$STACK_URL" -o stack.tar.gz; \ - echo "$STACK_SHA256 stack.tar.gz" | sha256sum --strict --check; \ - \ - curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc; \ - GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \ - gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY"; \ - gpg --batch --verify stack.tar.gz.asc stack.tar.gz; \ - gpgconf --kill all; \ - \ - tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack"; \ - stack config set system-ghc --global true; \ - stack config set install-ghc --global false; \ - \ - rm -rf /tmp/*; \ - \ + case "$ARCH" in + 'aarch64') + STACK_SHA256='bdd618ea5a9c921417727011f2ecd78987dffa5cee5e741108baf65a9b5b58ab' + ;; + 'x86_64') + STACK_SHA256='88d7e517342c125b0a098d9d578fe53e590618ae4b2427283a27408a1ebd06d8' + ;; + *) echo >&2 "error: unsupported architecture '$ARCH'" exit 1 ; + esac + curl -sSL "$STACK_URL" -o stack.tar.gz + echo "$STACK_SHA256 stack.tar.gz" | sha256sum --strict --check + + curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc + GNUPGHOME="$(mktemp -d)" + export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY" + gpg --batch --verify stack.tar.gz.asc stack.tar.gz + gpgconf --kill all + + tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack" + stack config set system-ghc --global true + stack config set install-ghc --global false + + rm -rf /tmp/* + stack --version; +EOT -ARG CABAL_INSTALL=3.14.1.1 -ARG CABAL_INSTALL_RELEASE_KEY=EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF +ARG CABAL_INSTALL='3.14.1.1' +ARG CABAL_INSTALL_RELEASE_KEY='EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF' -RUN set -eux; \ - cd /tmp; \ - ARCH="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)"; \ - CABAL_INSTALL_TAR="cabal-install-$CABAL_INSTALL-$ARCH-linux-deb12.tar.xz"; \ - CABAL_INSTALL_URL="https://downloads.haskell.org/~cabal/cabal-install-$CABAL_INSTALL/$CABAL_INSTALL_TAR"; \ - CABAL_INSTALL_SHA256SUMS_URL="https://downloads.haskell.org/~cabal/cabal-install-$CABAL_INSTALL/SHA256SUMS"; \ +RUN <&2 "error: unsupported architecture '$ARCH'"; exit 1 ;; \ - esac; \ - curl -fSL "$CABAL_INSTALL_URL" -o cabal-install.tar.gz; \ - echo "$CABAL_INSTALL_SHA256 cabal-install.tar.gz" | sha256sum --strict --check; \ - \ - curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL"; \ - curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL.sig"; \ - GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \ - gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$CABAL_INSTALL_RELEASE_KEY"; \ - gpg --batch --verify SHA256SUMS.sig SHA256SUMS; \ + case "$ARCH" in + 'aarch64') + CABAL_INSTALL_SHA256='f763fb2af2bc1ff174b7361a7d51109a585954f87a0e14f86d144f3bce28f7a9' + ;; + 'x86_64') + CABAL_INSTALL_SHA256='73a463306c771e18ca22c0a9469176ffab0138ec5925adb5364ef47174e1adc5' + ;; + *) echo >&2 "error: unsupported architecture '$ARCH'"; exit 1 ;; + esac + curl -fSL "$CABAL_INSTALL_URL" -o cabal-install.tar.gz + echo "$CABAL_INSTALL_SHA256 cabal-install.tar.gz" | sha256sum --strict --check + + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL" + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL.sig" + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$CABAL_INSTALL_RELEASE_KEY" + gpg --batch --verify SHA256SUMS.sig SHA256SUMS # confirm we are verifying SHA256SUMS that matches the release + sha256 - grep "$CABAL_INSTALL_SHA256 $CABAL_INSTALL_TAR" SHA256SUMS; \ - gpgconf --kill all; \ - \ - tar -xf cabal-install.tar.gz -C /usr/local/bin; \ - \ - rm -rf /tmp/*; \ - \ + grep "$CABAL_INSTALL_SHA256 $CABAL_INSTALL_TAR" SHA256SUMS + gpgconf --kill all; + + tar -xf cabal-install.tar.gz -C /usr/local/bin + + rm -rf /tmp/* + cabal --version +EOT -ARG GHC=9.12.2 -ARG GHC_RELEASE_KEY=FFEB7CE81E16A36B3E2DED6F2DE04D4E97DB64AD +ARG GHC='9.12.2' +ARG GHC_RELEASE_KEY='FFEB7CE81E16A36B3E2DED6F2DE04D4E97DB64AD' -RUN set -eux; \ - cd /tmp; \ - ARCH="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)"; \ - GHC_URL="https://downloads.haskell.org/~ghc/$GHC/ghc-$GHC-$ARCH-deb12-linux.tar.xz"; \ +RUN <&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; \ - esac; \ - curl -sSL "$GHC_URL" -o ghc.tar.xz; \ - echo "$GHC_SHA256 ghc.tar.xz" | sha256sum --strict --check; \ - \ - GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \ - curl -sSL "$GHC_URL.sig" -o ghc.tar.xz.sig; \ - gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$GHC_RELEASE_KEY"; \ - gpg --batch --verify ghc.tar.xz.sig ghc.tar.xz; \ - gpgconf --kill all; \ - \ - tar xf ghc.tar.xz; \ - cd "ghc-$GHC-$ARCH-unknown-linux"; \ - ./configure --prefix "/opt/ghc/$GHC"; \ - make install; \ - \ - rm -rf /tmp/*; \ - \ + case "$ARCH" in + 'aarch64') + GHC_SHA256='bee95bc91a621d8a2e9a9d86dac28ff839605e87316518dae12c779709bd58f1' + ;; + 'x86_64') + GHC_SHA256='447ec2fcc773ae9ebc3f39766c719641631274f9b765d7426a8cbe9241677c9f' + ;; + *) echo >&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; + esac + curl -sSL "$GHC_URL" -o ghc.tar.xz + echo "$GHC_SHA256 ghc.tar.xz" | sha256sum --strict --check + + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + curl -sSL "$GHC_URL.sig" -o ghc.tar.xz.sig + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$GHC_RELEASE_KEY" + gpg --batch --verify ghc.tar.xz.sig ghc.tar.xz + gpgconf --kill all + + tar xf ghc.tar.xz + cd "ghc-$GHC-$ARCH-unknown-linux" + ./configure --prefix "/opt/ghc/$GHC" + make install + + rm -rf /tmp/* + "/opt/ghc/$GHC/bin/ghc" --version +EOT ENV PATH=/root/.cabal/bin:/root/.local/bin:/opt/ghc/${GHC}/bin:$PATH diff --git a/9.12/bullseye.yaml b/9.12/bullseye.yaml new file mode 100644 index 00000000..72ec3349 --- /dev/null +++ b/9.12/bullseye.yaml @@ -0,0 +1,22 @@ +--- +distro: + codename: 'bullseye' + abbr: 'deb11' + image: 'debian:bullseye' +ghc: + version: "9.12.2" + release_key: "FFEB7CE81E16A36B3E2DED6F2DE04D4E97DB64AD" + sha256sum: + "aarch64": '6048eae62ede069459398fa6f2e92ab9719e1b83e93a9014e6a410c54ed2755f' # hash from deb10 bindist + "x86_64": '47d5faba492545b49b8dd49a79e64b4ef8eb4b1632d4ddc64355ce4e812eec75' +cabal_install: + sha256sum: + "aarch64": '5e8c47a055d5b744741039a7061ee43ec7d080d1251784e7a4cd836403e42523' + "x86_64": '41b85bb25fa654e4b79169014b9142fe696ff35e002e043caa0e52d65204ba8a' +overrides: + ghc: + "aarch64": + # GHC 9.12.2 doesn't have a deb11 bindist for aarch64 for some reason, so we're using the deb10 one instead + url: "https://downloads.haskell.org/~ghc/9.12.2/ghc-9.12.2-aarch64-deb10-linux.tar.xz" +_globals: !include '_globals.yaml' + diff --git a/9.12/bullseye/Dockerfile b/9.12/bullseye/Dockerfile new file mode 100644 index 00000000..e8095031 --- /dev/null +++ b/9.12/bullseye/Dockerfile @@ -0,0 +1,144 @@ +FROM debian:bullseye + +ENV LANG=C.UTF-8 + +# common haskell + stack dependencies +RUN <&2 "error: unsupported architecture '$ARCH'" exit 1 ; + esac + curl -sSL "$STACK_URL" -o stack.tar.gz + echo "$STACK_SHA256 stack.tar.gz" | sha256sum --strict --check + + curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc + GNUPGHOME="$(mktemp -d)" + export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY" + gpg --batch --verify stack.tar.gz.asc stack.tar.gz + gpgconf --kill all + + tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack" + stack config set system-ghc --global true + stack config set install-ghc --global false + + rm -rf /tmp/* + + stack --version; +EOT + +ARG CABAL_INSTALL='3.14.1.1' +ARG CABAL_INSTALL_RELEASE_KEY='EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF' + +RUN <&2 "error: unsupported architecture '$ARCH'"; exit 1 ;; + esac + curl -fSL "$CABAL_INSTALL_URL" -o cabal-install.tar.gz + echo "$CABAL_INSTALL_SHA256 cabal-install.tar.gz" | sha256sum --strict --check + + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL" + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL.sig" + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$CABAL_INSTALL_RELEASE_KEY" + gpg --batch --verify SHA256SUMS.sig SHA256SUMS + # confirm we are verifying SHA256SUMS that matches the release + sha256 + grep "$CABAL_INSTALL_SHA256 $CABAL_INSTALL_TAR" SHA256SUMS + gpgconf --kill all; + + tar -xf cabal-install.tar.gz -C /usr/local/bin + + rm -rf /tmp/* + + cabal --version +EOT + +ARG GHC='9.12.2' +ARG GHC_RELEASE_KEY='FFEB7CE81E16A36B3E2DED6F2DE04D4E97DB64AD' + +RUN <&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; + esac + curl -sSL "$GHC_URL" -o ghc.tar.xz + echo "$GHC_SHA256 ghc.tar.xz" | sha256sum --strict --check + + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + curl -sSL "$GHC_URL.sig" -o ghc.tar.xz.sig + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$GHC_RELEASE_KEY" + gpg --batch --verify ghc.tar.xz.sig ghc.tar.xz + gpgconf --kill all + + tar xf ghc.tar.xz + cd "ghc-$GHC-$ARCH-unknown-linux" + ./configure --prefix "/opt/ghc/$GHC" + make install + + rm -rf /tmp/* + + "/opt/ghc/$GHC/bin/ghc" --version +EOT + +ENV PATH=/root/.cabal/bin:/root/.local/bin:/opt/ghc/${GHC}/bin:$PATH + +CMD ["ghci"] diff --git a/9.12/slim-bookworm.yaml b/9.12/slim-bookworm.yaml new file mode 100644 index 00000000..257b055b --- /dev/null +++ b/9.12/slim-bookworm.yaml @@ -0,0 +1,16 @@ +--- +distro: + codename: 'bookworm' + abbr: 'deb12' + image: 'debian:bookworm-slim' +ghc: + version: "9.12.2" + release_key: "FFEB7CE81E16A36B3E2DED6F2DE04D4E97DB64AD" + sha256sum: + "aarch64": 'bee95bc91a621d8a2e9a9d86dac28ff839605e87316518dae12c779709bd58f1' + "x86_64": '447ec2fcc773ae9ebc3f39766c719641631274f9b765d7426a8cbe9241677c9f' +cabal_install: + sha256sum: + "aarch64": 'f763fb2af2bc1ff174b7361a7d51109a585954f87a0e14f86d144f3bce28f7a9' + "x86_64": '73a463306c771e18ca22c0a9469176ffab0138ec5925adb5364ef47174e1adc5' +_globals: !include '_globals.yaml' diff --git a/9.12/slim-bookworm/Dockerfile b/9.12/slim-bookworm/Dockerfile index 0a3e2dca..3a660ba2 100644 --- a/9.12/slim-bookworm/Dockerfile +++ b/9.12/slim-bookworm/Dockerfile @@ -3,7 +3,8 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 # common haskell + stack dependencies -RUN apt-get update && \ +RUN <&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; \ - esac; \ - curl -sSL "$STACK_URL" -o stack.tar.gz; \ - echo "$STACK_SHA256 stack.tar.gz" | sha256sum --strict --check; \ - \ - curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc; \ - GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \ - gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY"; \ - gpg --batch --verify stack.tar.gz.asc stack.tar.gz; \ - gpgconf --kill all; \ - \ - tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack"; \ - stack config set system-ghc --global true; \ - stack config set install-ghc --global false; \ - \ - rm -rf /tmp/*; \ - \ + case "$ARCH" in + 'aarch64') + STACK_SHA256='bdd618ea5a9c921417727011f2ecd78987dffa5cee5e741108baf65a9b5b58ab' + ;; + 'x86_64') + STACK_SHA256='88d7e517342c125b0a098d9d578fe53e590618ae4b2427283a27408a1ebd06d8' + ;; + *) echo >&2 "error: unsupported architecture '$ARCH'" exit 1 ; + esac + curl -sSL "$STACK_URL" -o stack.tar.gz + echo "$STACK_SHA256 stack.tar.gz" | sha256sum --strict --check + + curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc + GNUPGHOME="$(mktemp -d)" + export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY" + gpg --batch --verify stack.tar.gz.asc stack.tar.gz + gpgconf --kill all + + tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack" + stack config set system-ghc --global true + stack config set install-ghc --global false + + rm -rf /tmp/* + stack --version; +EOT -ARG CABAL_INSTALL=3.14.1.1 -ARG CABAL_INSTALL_RELEASE_KEY=EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF +ARG CABAL_INSTALL='3.14.1.1' +ARG CABAL_INSTALL_RELEASE_KEY='EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF' -RUN set -eux; \ - cd /tmp; \ - ARCH="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)"; \ - CABAL_INSTALL_TAR="cabal-install-$CABAL_INSTALL-$ARCH-linux-deb12.tar.xz"; \ - CABAL_INSTALL_URL="https://downloads.haskell.org/~cabal/cabal-install-$CABAL_INSTALL/$CABAL_INSTALL_TAR"; \ - CABAL_INSTALL_SHA256SUMS_URL="https://downloads.haskell.org/~cabal/cabal-install-$CABAL_INSTALL/SHA256SUMS"; \ +RUN <&2 "error: unsupported architecture '$ARCH'"; exit 1 ;; \ - esac; \ - curl -fSL "$CABAL_INSTALL_URL" -o cabal-install.tar.gz; \ - echo "$CABAL_INSTALL_SHA256 cabal-install.tar.gz" | sha256sum --strict --check; \ - \ - curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL"; \ - curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL.sig"; \ - GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \ - gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$CABAL_INSTALL_RELEASE_KEY"; \ - gpg --batch --verify SHA256SUMS.sig SHA256SUMS; \ + case "$ARCH" in + 'aarch64') + CABAL_INSTALL_SHA256='f763fb2af2bc1ff174b7361a7d51109a585954f87a0e14f86d144f3bce28f7a9' + ;; + 'x86_64') + CABAL_INSTALL_SHA256='73a463306c771e18ca22c0a9469176ffab0138ec5925adb5364ef47174e1adc5' + ;; + *) echo >&2 "error: unsupported architecture '$ARCH'"; exit 1 ;; + esac + curl -fSL "$CABAL_INSTALL_URL" -o cabal-install.tar.gz + echo "$CABAL_INSTALL_SHA256 cabal-install.tar.gz" | sha256sum --strict --check + + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL" + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL.sig" + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$CABAL_INSTALL_RELEASE_KEY" + gpg --batch --verify SHA256SUMS.sig SHA256SUMS # confirm we are verifying SHA256SUMS that matches the release + sha256 - grep "$CABAL_INSTALL_SHA256 $CABAL_INSTALL_TAR" SHA256SUMS; \ - gpgconf --kill all; \ - \ - tar -xf cabal-install.tar.gz -C /usr/local/bin; \ - \ - rm -rf /tmp/*; \ - \ + grep "$CABAL_INSTALL_SHA256 $CABAL_INSTALL_TAR" SHA256SUMS + gpgconf --kill all; + + tar -xf cabal-install.tar.gz -C /usr/local/bin + + rm -rf /tmp/* + cabal --version +EOT -ARG GHC=9.12.2 -ARG GHC_RELEASE_KEY=FFEB7CE81E16A36B3E2DED6F2DE04D4E97DB64AD +ARG GHC='9.12.2' +ARG GHC_RELEASE_KEY='FFEB7CE81E16A36B3E2DED6F2DE04D4E97DB64AD' -RUN set -eux; \ - cd /tmp; \ - ARCH="$(dpkg-architecture --query DEB_BUILD_GNU_CPU)"; \ - GHC_URL="https://downloads.haskell.org/~ghc/$GHC/ghc-$GHC-$ARCH-deb12-linux.tar.xz"; \ +RUN <&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; \ - esac; \ - curl -sSL "$GHC_URL" -o ghc.tar.xz; \ - echo "$GHC_SHA256 ghc.tar.xz" | sha256sum --strict --check; \ - \ - GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \ - curl -sSL "$GHC_URL.sig" -o ghc.tar.xz.sig; \ - gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$GHC_RELEASE_KEY"; \ - gpg --batch --verify ghc.tar.xz.sig ghc.tar.xz; \ - gpgconf --kill all; \ - \ - tar xf ghc.tar.xz; \ - cd "ghc-$GHC-$ARCH-unknown-linux"; \ - ./configure --prefix "/opt/ghc/$GHC"; \ - make install; \ - \ - rm -rf /tmp/*; \ - \ + case "$ARCH" in + 'aarch64') + GHC_SHA256='bee95bc91a621d8a2e9a9d86dac28ff839605e87316518dae12c779709bd58f1' + ;; + 'x86_64') + GHC_SHA256='447ec2fcc773ae9ebc3f39766c719641631274f9b765d7426a8cbe9241677c9f' + ;; + *) echo >&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; + esac + curl -sSL "$GHC_URL" -o ghc.tar.xz + echo "$GHC_SHA256 ghc.tar.xz" | sha256sum --strict --check + + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + curl -sSL "$GHC_URL.sig" -o ghc.tar.xz.sig + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$GHC_RELEASE_KEY" + gpg --batch --verify ghc.tar.xz.sig ghc.tar.xz + gpgconf --kill all + + tar xf ghc.tar.xz + cd "ghc-$GHC-$ARCH-unknown-linux" + ./configure --prefix "/opt/ghc/$GHC" + make install + + rm -rf /tmp/* + "/opt/ghc/$GHC/bin/ghc" --version +EOT ENV PATH=/root/.cabal/bin:/root/.local/bin:/opt/ghc/${GHC}/bin:$PATH diff --git a/9.12/slim-bullseye.yaml b/9.12/slim-bullseye.yaml new file mode 100644 index 00000000..f1486944 --- /dev/null +++ b/9.12/slim-bullseye.yaml @@ -0,0 +1,22 @@ +--- +distro: + codename: 'bullseye' + abbr: 'deb11' + image: 'debian:bullseye-slim' +ghc: + version: "9.12.2" + release_key: "FFEB7CE81E16A36B3E2DED6F2DE04D4E97DB64AD" + sha256sum: + "aarch64": '6048eae62ede069459398fa6f2e92ab9719e1b83e93a9014e6a410c54ed2755f' # hash from deb10 bindist + "x86_64": '47d5faba492545b49b8dd49a79e64b4ef8eb4b1632d4ddc64355ce4e812eec75' +cabal_install: + sha256sum: + "aarch64": '5e8c47a055d5b744741039a7061ee43ec7d080d1251784e7a4cd836403e42523' + "x86_64": '41b85bb25fa654e4b79169014b9142fe696ff35e002e043caa0e52d65204ba8a' +overrides: + ghc: + "aarch64": + # GHC 9.12.2 doesn't have a deb11 bindist for aarch64 for some reason, so we're using the deb10 one instead + url: "https://downloads.haskell.org/~ghc/9.12.2/ghc-9.12.2-aarch64-deb10-linux.tar.xz" +_globals: !include '_globals.yaml' + diff --git a/9.12/slim-bullseye/Dockerfile b/9.12/slim-bullseye/Dockerfile new file mode 100644 index 00000000..660374b3 --- /dev/null +++ b/9.12/slim-bullseye/Dockerfile @@ -0,0 +1,144 @@ +FROM debian:bullseye-slim + +ENV LANG=C.UTF-8 + +# common haskell + stack dependencies +RUN <&2 "error: unsupported architecture '$ARCH'" exit 1 ; + esac + curl -sSL "$STACK_URL" -o stack.tar.gz + echo "$STACK_SHA256 stack.tar.gz" | sha256sum --strict --check + + curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc + GNUPGHOME="$(mktemp -d)" + export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY" + gpg --batch --verify stack.tar.gz.asc stack.tar.gz + gpgconf --kill all + + tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack" + stack config set system-ghc --global true + stack config set install-ghc --global false + + rm -rf /tmp/* + + stack --version; +EOT + +ARG CABAL_INSTALL='3.14.1.1' +ARG CABAL_INSTALL_RELEASE_KEY='EAF2A9A722C0C96F2B431CA511AAD8CEDEE0CAEF' + +RUN <&2 "error: unsupported architecture '$ARCH'"; exit 1 ;; + esac + curl -fSL "$CABAL_INSTALL_URL" -o cabal-install.tar.gz + echo "$CABAL_INSTALL_SHA256 cabal-install.tar.gz" | sha256sum --strict --check + + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL" + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL.sig" + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$CABAL_INSTALL_RELEASE_KEY" + gpg --batch --verify SHA256SUMS.sig SHA256SUMS + # confirm we are verifying SHA256SUMS that matches the release + sha256 + grep "$CABAL_INSTALL_SHA256 $CABAL_INSTALL_TAR" SHA256SUMS + gpgconf --kill all; + + tar -xf cabal-install.tar.gz -C /usr/local/bin + + rm -rf /tmp/* + + cabal --version +EOT + +ARG GHC='9.12.2' +ARG GHC_RELEASE_KEY='FFEB7CE81E16A36B3E2DED6F2DE04D4E97DB64AD' + +RUN <&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; + esac + curl -sSL "$GHC_URL" -o ghc.tar.xz + echo "$GHC_SHA256 ghc.tar.xz" | sha256sum --strict --check + + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + curl -sSL "$GHC_URL.sig" -o ghc.tar.xz.sig + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$GHC_RELEASE_KEY" + gpg --batch --verify ghc.tar.xz.sig ghc.tar.xz + gpgconf --kill all + + tar xf ghc.tar.xz + cd "ghc-$GHC-$ARCH-unknown-linux" + ./configure --prefix "/opt/ghc/$GHC" + make install + + rm -rf /tmp/* + + "/opt/ghc/$GHC/bin/ghc" --version +EOT + +ENV PATH=/root/.cabal/bin:/root/.local/bin:/opt/ghc/${GHC}/bin:$PATH + +CMD ["ghci"] diff --git a/README.md b/README.md index ef2a1e44..f4a1a979 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,40 @@ Additionally, only the latest patch version of each major version of GHC will re #### Cabal + Stack -For actively supported GHC versions, Cabal and Stack should be updated when new versions are relesaed. +For actively supported GHC versions, Cabal and Stack should be updated when new versions are released. ## Maintenance +### Generating Dockerfiles + +The tool at ./generator is created to generate the `Dockerfile`s from templates. +This is done to reduce duplication and make it easier to add new GHC & tools. + +Having Haskell toolchain & stack installed, you want to build the generator first: + +```bash +$ cd generator +$ stack build +``` + +Then you can (re)generate the desired Dockerfile by running: + +```bash +$ stack run -- -t ../template/Dockerfile.jinja --data-file ../9.12/bookworm.yaml > ../9.12/bookworm/Dockerfile +``` + +The general file layout looks the following way: + +* `/.yaml` - the data file with versions and sha256s. +* `//_globals.yaml` - the global-ish data file with versions and sha256s (Stack binary distribution is not distro specific, like GHC or cabal-install, so we're avoiding copy&pasting it that way). It's explicitly included by the distro-specific YAML files. +* `//Dockerfile` - the generated Dockerfile. + +There might be a handful of `RuntimeError`s printed to stderr by the generator; +those that mention `IndexError` are probably safe to ignore: it's about data not found in `override` section, when there's nothing to override. +Raise an issue if you have ideas on how reporting them could be improved. + +Now, check the created/updated `Dockerfile` and commit it to the VCS. + ### Building + Running Locally You can build and run the images locally with something like: @@ -131,8 +161,8 @@ Images are built and released by the central docker official images system. Spec 1. Determine which docker haskell image GHC versions have been impacted by the unreleased changes (stack + cabal bumps impacts all versions, GHC just impacts specific versions). 2. Update the `GitCommit` in the [`haskell`](https://github.com/docker-library/official-images/blob/master/library/haskell) file. 3. Update the `Tags` if these have changed. -3. Create a PR, including info on what has changed. The official images people will review the actual Dockerfile changes as they want official images to maintain a high level of quality. -4. Once merged, their build system will run and the image updates will eventually be released. +4. Create a PR, including info on what has changed. The official images people will review the actual Dockerfile changes as they want official images to maintain a high level of quality. +5. Once merged, their build system will run and the image updates will eventually be released. This [doc](https://github.com/docker-library/faq#an-images-source-changed-in-git-now-what) describes the process in more detail. diff --git a/generator/.gitignore b/generator/.gitignore new file mode 100644 index 00000000..857a4d7f --- /dev/null +++ b/generator/.gitignore @@ -0,0 +1,3 @@ +/.stack-work + +/.idea diff --git a/generator/CHANGELOG.md b/generator/CHANGELOG.md new file mode 100644 index 00000000..94167225 --- /dev/null +++ b/generator/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for generator + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/generator/app/Main.hs b/generator/app/Main.hs new file mode 100644 index 00000000..c6a03311 --- /dev/null +++ b/generator/app/Main.hs @@ -0,0 +1,117 @@ +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} + +-- | An example Ginger CLI application. +-- +-- Takes two optional arguments; the first one is a template file, the second +-- one a file containing some context data in JSON format. +module Main where + +import qualified Data.Aeson as JSON +import qualified Data.ByteString as BS +import qualified Data.ByteString.UTF8 as UTF8 +import Data.HashMap.Strict (HashMap) +import qualified Data.HashMap.Strict as HashMap +import Data.Text (Text) +import qualified Data.Text as Text +import qualified Data.Yaml as YAML hiding (decodeFile) +import qualified Data.Yaml.Include as YAML (decodeFile) +import Options (DataSource (..), Options (..), TemplateSource (..), parseOptions) +import System.Environment (getArgs) +import System.Exit +import System.IO +import System.IO.Error +import Text.Ginger + +main :: IO () +main = do + args <- getArgs + options <- parseOptions args + case options of + RunOptions tpl dat -> + run tpl dat + +loadData :: DataSource -> IO (Maybe (HashMap Text JSON.Value)) +loadData (DataFromFile fn) = YAML.decodeFile fn +loadData DataFromStdin = decodeStdin +loadData (DataLiteral str) = decodeString str + +loadTemplate :: TemplateSource -> IO (Template SourcePos) +loadTemplate tplSrc = do + let resolve = loadFileMay + (tpl, src) <- case tplSrc of + TemplateFromFile fn -> (,) <$> parseGingerFile resolve fn <*> return Nothing + TemplateFromStdin -> getContents >>= \s -> (,) <$> parseGinger resolve Nothing s <*> return (Just s) + + case tpl of + Left err -> do + tplSource <- + case src of + Just s -> + return (Just s) + Nothing -> do + let s = sourceName <$> peSourcePosition err + case s of + Nothing -> return Nothing + Just sn -> Just <$> loadFile sn + printParserError tplSource err + exitFailure + Right t -> do + return t + +run :: TemplateSource -> DataSource -> IO () +run tplSrc dataSrc = do + scope <- loadData dataSrc + let contextLookup :: Text -> Run p IO Text (GVal (Run p IO Text)) + contextLookup key = return $ toGVal (scope >>= HashMap.lookup key) + let context = + makeContextTextExM + contextLookup + (putStr . Text.unpack) + (hPutStrLn stderr . show) + + tpl <- loadTemplate tplSrc + runGingerT context tpl >>= either (hPutStrLn stderr . show) showOutput + where + showOutput value + | isNull value = return () + | otherwise = putStrLn . show $ value + +printParserError :: Maybe String -> ParserError -> IO () +printParserError srcMay = putStrLn . formatParserError srcMay + +displayParserError :: String -> ParserError -> IO () +displayParserError src pe = do + case peSourcePosition pe of + Just pos -> do + let ln = Prelude.take 1 . Prelude.drop (sourceLine pos - 1) . Prelude.lines $ src + case ln of + [] -> return () + x : _ -> do + putStrLn x + putStrLn $ Prelude.replicate (sourceColumn pos - 1) ' ' ++ "^" + _ -> return () + +loadFile :: FilePath -> IO String +loadFile fn = openFile fn ReadMode >>= hGetContents + +loadFileMay :: FilePath -> IO (Maybe String) +loadFileMay fn = + tryIOError (loadFile fn) >>= \case + Right contents -> return (Just contents) + Left err -> do + print err + return Nothing + +decodeString :: (JSON.FromJSON v) => String -> IO (Maybe v) +decodeString = return . YAML.decode . UTF8.fromString + +decodeStdin :: (JSON.FromJSON v) => IO (Maybe v) +decodeStdin = YAML.decode <$> BS.getContents + +gAsStr :: GVal m -> String +gAsStr = Text.unpack . asText + +strToGVal :: String -> GVal m +strToGVal = toGVal . Text.pack diff --git a/generator/app/Options.hs b/generator/app/Options.hs new file mode 100644 index 00000000..41d88197 --- /dev/null +++ b/generator/app/Options.hs @@ -0,0 +1,70 @@ +module Options +where + +import Data.Semigroup ( (<>) ) -- needed for GHC 8.0 and 8.2 +import Options.Applicative + + +data TemplateSource + = TemplateFromFile FilePath + | TemplateFromStdin + +data DataSource + = DataFromFile FilePath + | DataLiteral String + | DataFromStdin + +data Options + = RunOptions TemplateSource DataSource + +parseOptions :: [String] -> IO Options +parseOptions args = + execParser $ info (options <**> helper) + ( fullDesc + <> header "ginger - A command-line interface for the Ginger template language" + ) + +options :: Parser Options +options = runOptions + +runOptions :: Parser Options +runOptions = + RunOptions <$> templateSource <*> dataSource + +templateSource :: Parser TemplateSource +templateSource = + convert <$> option str + ( long "template" + <> short 't' + <> metavar "TEMPLATE" + <> help "Load ginger template from this file" + <> value "-" + ) + where + convert "-" = TemplateFromStdin + convert f = TemplateFromFile f + +dataSource :: Parser DataSource +dataSource = + dataFromFile <|> dataLiteral + +dataFromFile :: Parser DataSource +dataFromFile = + convert <$> option str + ( long "data-file" + <> metavar "DATAFILE" + <> help "Load JSON or YAML data from this file (`-' to read from stdin)" + ) + where + convert "-" = DataFromStdin + convert f = DataFromFile f + +dataLiteral :: Parser DataSource +dataLiteral = + DataLiteral <$> option str + ( long "data" + <> short 'd' + <> metavar "DATA" + <> help "Use specified (JSON or YAML) DATA" + <> value "{}" + ) diff --git a/generator/generator.cabal b/generator/generator.cabal new file mode 100644 index 00000000..a2117cd9 --- /dev/null +++ b/generator/generator.cabal @@ -0,0 +1,84 @@ +cabal-version: 3.8 +-- The cabal-version field refers to the version of the .cabal specification, +-- and can be different from the cabal-install (the tool) version and the +-- Cabal (the library) version you are using. As such, the Cabal (the library) +-- version used must be equal or greater than the version stated in this field. +-- Starting from the specification version 2.2, the cabal-version field must be +-- the first thing in the cabal file. + +-- Initial package description 'generator' generated by +-- 'cabal init'. For further documentation, see: +-- http://haskell.org/cabal/users-guide/ +-- +-- The name of the package. +name: generator + +-- The package version. +-- See the Haskell package versioning policy (PVP) for standards +-- guiding when and how versions should be incremented. +-- https://pvp.haskell.org +-- PVP summary: +-+------- breaking API changes +-- | | +----- non-breaking API additions +-- | | | +--- code changes with no API change +version: 0.1.0.0 + +-- A short (one-line) description of the package. +-- synopsis: + +-- A longer description of the package. +-- description: + +-- The license under which the package is released. +license: NONE + +-- The package author(s). +author: Andrei Dziahel + +-- An email address to which users can send suggestions, bug reports, and patches. +maintainer: develop7@develop7.info + +-- A copyright notice. +-- copyright: +build-type: Simple + +-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README. +extra-doc-files: CHANGELOG.md + +-- Extra source files to be distributed with the package, such as examples, or a tutorial module. +-- extra-source-files: + +common warnings + ghc-options: -Wall + +executable generator + -- Import common warning flags. + import: warnings + + -- .hs or .lhs file containing the Main module. + main-is: Main.hs + + -- Modules included in this executable, other than Main. + other-modules: Options + + -- LANGUAGE extensions used by modules in this package. + -- other-extensions: + + -- Other library packages from which modules are imported. + build-depends: base + , aeson + , bytestring + , data-default + , ginger + , optparse-applicative + , text + , process + , transformers + , unordered-containers + , utf8-string + , yaml + + -- Directories containing source files. + hs-source-dirs: app + + -- Base language which the package is written in. + default-language: Haskell2010 diff --git a/generator/hie.yaml b/generator/hie.yaml new file mode 100644 index 00000000..4ef275e0 --- /dev/null +++ b/generator/hie.yaml @@ -0,0 +1,2 @@ +cradle: + stack: diff --git a/generator/stack.yaml b/generator/stack.yaml new file mode 100644 index 00000000..71570403 --- /dev/null +++ b/generator/stack.yaml @@ -0,0 +1,68 @@ +# This file was automatically generated by 'stack init' +# +# Some commonly used options have been documented as comments in this file. +# For advanced use and comprehensive documentation of the format, please see: +# https://docs.haskellstack.org/en/stable/configure/yaml/ + +# A 'specific' Stackage snapshot or a compiler version. +# A snapshot resolver dictates the compiler version and the set of packages +# to be used for project dependencies. For example: +# +# snapshot: lts-23.14 +# snapshot: nightly-2025-02-15 +# snapshot: ghc-9.8.4 +# +# The location of a snapshot can be provided as a file or url. Stack assumes +# a snapshot provided as a file might change, whereas a url resource does not. +# +# snapshot: ./custom-snapshot.yaml +# snapshot: https://example.com/snapshots/2024-01-01.yaml +resolver: lts-24.13 + +# User packages to be built. +# Various formats can be used as shown in the example below. +# +# packages: +# - some-directory +# - https://example.com/foo/bar/baz-0.0.2.tar.gz +# subdirs: +# - auto-update +# - wai +packages: +- . +# Dependency packages to be pulled from upstream that are not in the snapshot. +# These entries can reference officially published versions as well as +# forks / in-progress versions pinned to a git hash. For example: +# +# extra-deps: +# - acme-missiles-0.3 +# - git: https://github.com/commercialhaskell/stack.git +# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a +# +# extra-deps: [] +#extra-deps: +# - ginger-0.10.6.0 + +# Override default flag values for project packages and extra-deps +# flags: {} + +# Extra package databases containing global packages +# extra-package-dbs: [] + +# Control whether we use the GHC we find on the path +# system-ghc: true +# +# Require a specific version of Stack, using version ranges +# require-stack-version: -any # Default +# require-stack-version: ">=3.5" +# +# Override the architecture used by Stack, especially useful on Windows +# arch: i386 +# arch: x86_64 +# +# Extra directories used by Stack for building +# extra-include-dirs: [/path/to/dir] +# extra-lib-dirs: [/path/to/dir] +# +# Allow a newer minor version of GHC than the snapshot specifies +# compiler-check: newer-minor diff --git a/generator/stack.yaml.lock b/generator/stack.yaml.lock new file mode 100644 index 00000000..24decbb7 --- /dev/null +++ b/generator/stack.yaml.lock @@ -0,0 +1,12 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/topics/lock_files + +packages: [] +snapshots: +- completed: + sha256: 95817c7fe8ae8ca6e8f4ecfd3e876b3edc4e5fbba9f8d8f757e87b484f9bfe6b + size: 726101 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/24/13.yaml + original: lts-24.13 diff --git a/template/Dockerfile.jinja b/template/Dockerfile.jinja new file mode 100644 index 00000000..bc76ec74 --- /dev/null +++ b/template/Dockerfile.jinja @@ -0,0 +1,146 @@ +FROM {{ distro.image }} + +ENV LANG=C.UTF-8 + +# common haskell + stack dependencies +RUN <&2 "error: unsupported architecture '$ARCH'" exit 1 ; + esac + curl -sSL "$STACK_URL" -o stack.tar.gz + echo "$STACK_SHA256 stack.tar.gz" | sha256sum --strict --check + + curl -sSL "$STACK_URL.asc" -o stack.tar.gz.asc + GNUPGHOME="$(mktemp -d)" + export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$STACK_RELEASE_KEY" + gpg --batch --verify stack.tar.gz.asc stack.tar.gz + gpgconf --kill all + + tar -xf stack.tar.gz -C /usr/local/bin --strip-components=1 "stack-$STACK-linux-$ARCH/stack" + stack config set system-ghc --global true + stack config set install-ghc --global false + + rm -rf /tmp/* + + stack --version; +EOT + +ARG CABAL_INSTALL='{{ _globals.cabal_install.version }}' +ARG CABAL_INSTALL_RELEASE_KEY='{{ _globals.cabal_install.release_key }}' + +RUN <&2 "error: unsupported architecture '$ARCH'"; exit 1 ;; + esac + curl -fSL "$CABAL_INSTALL_URL" -o cabal-install.tar.gz + echo "$CABAL_INSTALL_SHA256 cabal-install.tar.gz" | sha256sum --strict --check + + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL" + curl -sSLO "$CABAL_INSTALL_SHA256SUMS_URL.sig" + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$CABAL_INSTALL_RELEASE_KEY" + gpg --batch --verify SHA256SUMS.sig SHA256SUMS + # confirm we are verifying SHA256SUMS that matches the release + sha256 + grep "$CABAL_INSTALL_SHA256 $CABAL_INSTALL_TAR" SHA256SUMS + gpgconf --kill all; + + tar -xf cabal-install.tar.gz -C /usr/local/bin + + rm -rf /tmp/* + + cabal --version +EOT + +ARG GHC='{{ ghc.version }}' +ARG GHC_RELEASE_KEY='{{ ghc.release_key }}' + +RUN <&2 "error: unsupported architecture '$ARCH'" ; exit 1 ;; + esac + curl -sSL "$GHC_URL" -o ghc.tar.xz + echo "$GHC_SHA256 ghc.tar.xz" | sha256sum --strict --check + + GNUPGHOME="$(mktemp -d)"; export GNUPGHOME + curl -sSL "$GHC_URL.sig" -o ghc.tar.xz.sig + gpg --batch --keyserver keyserver.ubuntu.com --receive-keys "$GHC_RELEASE_KEY" + gpg --batch --verify ghc.tar.xz.sig ghc.tar.xz + gpgconf --kill all + + tar xf ghc.tar.xz + cd "ghc-$GHC-$ARCH-unknown-linux" + ./configure --prefix "/opt/ghc/$GHC" + make install + + rm -rf /tmp/* + + "/opt/ghc/$GHC/bin/ghc" --version +EOT + +ENV PATH=/root/.cabal/bin:/root/.local/bin:/opt/ghc/${GHC}/bin:$PATH + +CMD ["ghci"]