diff --git a/.github-ci.sh b/.github-ci.sh
deleted file mode 100755
index 393bff3cc9ecbd41c6708714350094d009a4a508..0000000000000000000000000000000000000000
--- a/.github-ci.sh
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/sh
-
-edo()
-{
-	printf "\\033[0;34m%s\\033[0m\\n" "$*" 1>&2
-    "$@" || exit 2
-}
-
-GHCUP_META_DOWNLOAD_URL="file://$(pwd)/.download-urls"
-export GHCUP_META_DOWNLOAD_URL
-GHCUP_META_VERSION_URL="file://$(pwd)/.available-versions"
-export GHCUP_META_VERSION_URL
-
-# install GHCs
-edo ./ghcup -v install 8.2.2
-edo ./ghcup -v install 8.4.3
-edo ./ghcup -v -c install 8.6.1
-
-# set GHC
-edo ./ghcup -v set 8.6.1
-edo ./ghcup -v set 8.4.3
-
-# rm GHC
-edo ./ghcup -v rm -f 8.6.1
-edo ./ghcup -v rm -f 8.4.3
-
-# reinstall from cached tarball
-edo ./ghcup -v -c install 8.6.1
-edo ./ghcup -v rm -f 8.6.1
-
-# set GHC
-edo ./ghcup -v set 8.2.2
-edo ./ghcup -v rm -f 8.2.2
-
-# install default GHC
-edo ./ghcup -v install
-edo ./ghcup -v set
-
-# install latest GHC
-edo ./ghcup -v install latest
-
-export PATH="$HOME/.cabal/bin:$HOME/.ghcup/bin:$HOME/.local/bin:$PATH"
-edo mkdir -p "$HOME"/.local/bin
-
-edo cp ./ghcup "$HOME"/.local/bin/ghcup
-
-# TODO: exceeds maximum time limit of travis
-# compile GHC from source
-#./ghcup -v compile 8.4.3 ghc-8.2.2
-
-# install cabal-install
-edo ghcup -v install-cabal
-
-edo cabal --version
-
-# install shellcheck
-edo wget https://storage.googleapis.com/shellcheck/shellcheck-latest.linux.x86_64.tar.xz
-edo tar -xJf shellcheck-latest.linux.x86_64.tar.xz
-edo mv shellcheck-latest/shellcheck "$HOME"/.local/bin/shellcheck
-
-# check our script for errors
-edo shellcheck ghcup
-
-edo ghcup -v debug-info
-
-edo ghcup -v list
-edo ghcup -v list -t ghc
-edo ghcup -v list -t cabal-install
-
-edo ghc --version
-
-# self update destructively
-edo ghcup -v upgrade
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 07154a426e9464c478ac2dc1ae01c2210907f7d0..11868d6ecf3628bbbd8007649cc797306a220743 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -8,20 +8,199 @@ variables:
 # CI Step
 ############################################################
 
-test:linux:
+.debian:
   image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb9:$DOCKER_REV"
-  before_script:
-    - sudo apt-get update -y && sudo apt-get install -y libnuma-dev
-  script:
-    - ./.github-ci.sh
-  dependencies: []
   tags:
     - x86_64-linux
 
-test:mac:
-  script:
-    - ./.github-ci.sh
-  dependencies: []
+.darwin:
   tags:
     - x86_64-darwin
 
+.test_ghcup_version:
+  script:
+    - ./.gitlab/script/ghcup_version.sh
+
+.test_ghcup_version:linux:
+  extends:
+    - .test_ghcup_version
+    - .debian
+  before_script:
+    - ./.gitlab/before_script/linux/install_deps.sh
+
+.test_ghcup_version:darwin:
+  extends:
+    - .test_ghcup_version
+    - .darwin
+  before_script:
+    - ./.gitlab/before_script/darwin/install_deps.sh
+
+
+######## shellcheck ########
+
+test:shellcheck:
+  extends: .debian
+  before_script:
+    - ./.gitlab/before_script/linux/install_shellcheck.sh
+  script: ./.gitlab/script/shellcheck.sh
+
+
+######## tarball caching ########
+
+test:tarball_cache:
+  extends: .debian
+  variables:
+    GHC_VERSION: "8.6.5"
+  script:
+    - ./.gitlab/script/ghcup_cached_tarball.sh
+
+
+######## linux ########
+
+test:linux:recommended:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "recommended"
+
+test:linux:latest:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "latest"
+
+test:linux:8.0.2:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.0.2"
+
+test:linux:8.2.2:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.2.2"
+
+test:linux:8.4.1:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.4.1"
+
+test:linux:8.4.2:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.4.2"
+
+test:linux:8.4.3:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.4.3"
+
+test:linux:8.4.4:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.4.4"
+
+test:linux:8.6.1:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.6.1"
+
+test:linux:8.6.2:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.6.2"
+
+test:linux:8.6.3:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.6.3"
+
+test:linux:8.6.4:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.6.4"
+
+test:linux:8.6.5:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.6.5"
+
+test:linux:8.8.1:
+  extends: .test_ghcup_version:linux
+  variables:
+    GHC_VERSION: "8.8.1"
+
+
+######## darwin ########
+
+test:mac:recommended:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "recommended"
+
+test:mac:latest:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "latest"
+
+test:mac:8.0.2:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.0.2"
+
+test:mac:8.2.2:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.2.2"
+
+test:mac:8.4.1:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.4.1"
+
+test:mac:8.4.2:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.4.2"
+
+test:mac:8.4.3:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.4.3"
+
+test:mac:8.4.4:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.4.4"
+
+test:mac:8.6.1:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.6.1"
+  # TODO: dyld: Library not loaded: /usr/local/opt/gmp/lib/libgmp.10.dylib
+  allow_failure: true
+
+test:mac:8.6.2:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.6.2"
+  # TODO: dyld: Library not loaded: /usr/local/opt/gmp/lib/libgmp.10.dylib
+  allow_failure: true
+
+test:mac:8.6.3:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.6.3"
+
+test:mac:8.6.4:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.6.4"
+
+test:mac:8.6.5:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.6.5"
+
+test:mac:8.8.1:
+  extends: .test_ghcup_version:darwin
+  variables:
+    GHC_VERSION: "8.8.1"
+
diff --git a/.gitlab/before_script/darwin/install_deps.sh b/.gitlab/before_script/darwin/install_deps.sh
new file mode 100755
index 0000000000000000000000000000000000000000..386e91ad2c646e1d392a4c62f68913018968271b
--- /dev/null
+++ b/.gitlab/before_script/darwin/install_deps.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+set -eux
+
+#sudo brew reinstall gmp
+
+exit 0
diff --git a/.gitlab/before_script/linux/install_deps.sh b/.gitlab/before_script/linux/install_deps.sh
new file mode 100755
index 0000000000000000000000000000000000000000..cc9eb69469ddb9d068b75c70e80d17c810d2ee8c
--- /dev/null
+++ b/.gitlab/before_script/linux/install_deps.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+set -eux
+
+sudo apt-get update -y
+sudo apt-get install -y libnuma-dev
diff --git a/.gitlab/before_script/linux/install_shellcheck.sh b/.gitlab/before_script/linux/install_shellcheck.sh
new file mode 100755
index 0000000000000000000000000000000000000000..21ed907835c1f307bfe94ef826e9e11944c8b1f3
--- /dev/null
+++ b/.gitlab/before_script/linux/install_shellcheck.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+set -eux
+
+# install shellcheck
+wget https://storage.googleapis.com/shellcheck/shellcheck-latest.linux.x86_64.tar.xz
+tar -xJf shellcheck-latest.linux.x86_64.tar.xz
+mkdir -p "$CI_PROJECT_DIR"/.local/bin/
+mv shellcheck-latest/shellcheck "$CI_PROJECT_DIR"/.local/bin/shellcheck
+
+
diff --git a/.gitlab/ghcup_env b/.gitlab/ghcup_env
new file mode 100644
index 0000000000000000000000000000000000000000..b4f23abb598ddb7971c9ba9150477b0c8290cdc0
--- /dev/null
+++ b/.gitlab/ghcup_env
@@ -0,0 +1,8 @@
+GHCUP_META_DOWNLOAD_URL="file://${CI_PROJECT_DIR}/.download-urls"
+export GHCUP_META_DOWNLOAD_URL
+GHCUP_META_VERSION_URL="file://${CI_PROJECT_DIR}/.available-versions"
+export GHCUP_META_VERSION_URL
+
+export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR"
+export PATH="$CI_PROJECT_DIR/.ghcup/bin:$CI_PROJECT_DIR/.local/bin:$PATH"
+
diff --git a/.gitlab/script/ghcup_cached_tarball.sh b/.gitlab/script/ghcup_cached_tarball.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9c6f91939bd1bc816f3ac39825a89775f94b2ce3
--- /dev/null
+++ b/.gitlab/script/ghcup_cached_tarball.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+set -eux
+
+. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
+
+mkdir -p "$CI_PROJECT_DIR"/.local/bin
+cp ./ghcup "$CI_PROJECT_DIR"/.local/bin/ghcup
+
+ghcup -v -c install 8.6.5
+test -f "$CI_PROJECT_DIR/.ghcup/cache/ghc-8.6.5-x86_64-deb9-linux.tar.xz"
+ghcup -v -c install 8.6.5
+
diff --git a/.gitlab/script/ghcup_version.sh b/.gitlab/script/ghcup_version.sh
new file mode 100755
index 0000000000000000000000000000000000000000..307fbb1561bfecf3b3d10d9741710c97b4d0e90a
--- /dev/null
+++ b/.gitlab/script/ghcup_version.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+set -eux
+
+. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
+
+mkdir -p "$CI_PROJECT_DIR"/.local/bin
+
+cp ./ghcup "$CI_PROJECT_DIR"/.local/bin/ghcup
+
+ghcup --version
+
+ghcup -v install ${GHC_VERSION}
+ghcup -v set ${GHC_VERSION}
+ghcup -v install-cabal
+
+cabal --version
+
+ghcup -v debug-info
+
+ghcup -v list
+ghcup -v list -t ghc
+ghcup -v list -t cabal-install
+
+ghc --version
+ghci --version
+ghc-$(ghc --numeric-version) --version
+ghci-$(ghc --numeric-version) --version
+
+ghcup -v upgrade
+
+ghcup -v rm -f ${GHC_VERSION}
+
diff --git a/.gitlab/script/shellcheck.sh b/.gitlab/script/shellcheck.sh
new file mode 100755
index 0000000000000000000000000000000000000000..aea0d94ce8f2ef4a6698106befe245c92202fcea
--- /dev/null
+++ b/.gitlab/script/shellcheck.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -eux
+
+. "$( cd "$(dirname "$0")" ; pwd -P )/../ghcup_env"
+
+shellcheck ghcup
+