diff --git a/.github/scripts/brew.sh b/.github/scripts/brew.sh new file mode 100644 index 0000000..d59922e --- /dev/null +++ b/.github/scripts/brew.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +set -eux + +. .github/scripts/env.sh + +if [ -e "$HOME/.brew" ] ; then + ( + cd "$HOME/.brew" + git fetch --depth 1 + git reset --hard origin/master + ) +else + git clone --depth=1 https://github.com/Homebrew/brew "$HOME/.brew" +fi +export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH" + +mkdir -p $CI_PROJECT_DIR/.brew_cache +export HOMEBREW_CACHE=$CI_PROJECT_DIR/.brew_cache +mkdir -p $CI_PROJECT_DIR/.brew_logs +export HOMEBREW_LOGS=$CI_PROJECT_DIR/.brew_logs +mkdir -p /private/tmp/.brew_tmp +export HOMEBREW_TEMP=/private/tmp/.brew_tmp + +brew update +brew install ${1+"$@"} + + +set -eux + +. .github/scripts/env.sh + +if [ -e "$HOME/.brew" ] ; then + ( + cd "$HOME/.brew" + git fetch --depth 1 + git reset --hard origin/master + ) +else + git clone --depth=1 https://github.com/Homebrew/brew "$HOME/.brew" +fi +export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$PATH" + +mkdir -p $CI_PROJECT_DIR/.brew_cache +export HOMEBREW_CACHE=$CI_PROJECT_DIR/.brew_cache +mkdir -p $CI_PROJECT_DIR/.brew_logs +export HOMEBREW_LOGS=$CI_PROJECT_DIR/.brew_logs +mkdir -p /private/tmp/.brew_tmp +export HOMEBREW_TEMP=/private/tmp/.brew_tmp + +brew update +brew install ${1+"$@"} + diff --git a/.github/scripts/env.sh b/.github/scripts/env.sh new file mode 100644 index 0000000..088b4c8 --- /dev/null +++ b/.github/scripts/env.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +if [ "${RUNNER_OS}" = "Windows" ] ; then + ext=".exe" +else + ext='' +fi + +export DEBIAN_FRONTEND=noninteractive +export TZ=Asia/Singapore + +export OS="$RUNNER_OS" +export PATH="$HOME/.local/bin:$PATH" + +if [ "${RUNNER_OS}" = "Windows" ] ; then + # on windows use pwd to get unix style path + CI_PROJECT_DIR="$(pwd)" + export CI_PROJECT_DIR + export GHCUP_INSTALL_BASE_PREFIX="/c" + export GHCUP_BIN="$GHCUP_INSTALL_BASE_PREFIX/ghcup/bin" + export PATH="$GHCUP_BIN:$PATH" + export CABAL_DIR="C:\\Users\\runneradmin\\AppData\\Roaming\\cabal" +else + export CI_PROJECT_DIR="${GITHUB_WORKSPACE}" + export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR" + export GHCUP_BIN="$GHCUP_INSTALL_BASE_PREFIX/.ghcup/bin" + export PATH="$GHCUP_BIN:$PATH" + export CABAL_DIR="$CI_PROJECT_DIR/cabal" + export CABAL_CACHE="$CI_PROJECT_DIR/cabal-cache" +fi diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..592c067 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,141 @@ +name: Haskell CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + ghc: ['8.0', '8.2', '8.4', '8.6', '8.8', '8.10', '9.0', '9.2', '9.4', '9.6', '9.8'] + cabal: ['3.8.1.0'] + include: + - os: macOS-latest + ghc: '9.4' + cabal: '3.8.1.0' + - os: macOS-latest + ghc: '9.6' + cabal: '3.8.1.0' + - os: windows-latest + ghc: '9.4' + cabal: '3.8.1.0' + - os: windows-latest + ghc: '9.6' + cabal: '3.8.1.0' + steps: + - uses: actions/checkout@v3 + + - name: Install dependencies (Ubuntu) + if: runner.os == 'Linux' + run: | + sudo apt-get -y update + sudo apt-get -y install libtinfo5 libtinfo6 libncurses5 libncurses6 + + - name: Install ghc/cabal + run: | + set -eux + ghcup install ghc --set ${{ matrix.ghc }} + ghcup install cabal ${{ matrix.cabal }} + shell: bash + + - name: Build + run: | + set -eux + [ "$(ghc --numeric-version)" = "${{ matrix.ghc }}" ] + cabal update + cabal build --enable-tests --enable-benchmarks + cabal test + cabal bench + cabal haddock + cabal check + cabal sdist + shell: bash + + i386: + runs-on: ubuntu-latest + container: + image: i386/ubuntu:bionic + steps: + - name: Install + run: | + apt-get update -y + apt-get install -y autoconf build-essential zlib1g-dev libgmp-dev curl libncurses5 libtinfo5 libncurses5-dev libtinfo-dev + curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_INSTALL_NO_STACK=1 sh + - uses: actions/checkout@v1 + - name: Test + run: | + . ~/.ghcup/env + cabal update + cabal test + cabal bench + + # We use github.com/haskell self-hosted runners for ARM testing. + # If they become unavailable in future, put ['armv7', 'aarch64'] + # back to emulation jobs above. + arm: + runs-on: [self-hosted, Linux, ARM64] + strategy: + fail-fast: true + matrix: + arch: [arm32v7, arm64v8] + steps: + - uses: docker://hasufell/arm64v8-ubuntu-haskell:focal + name: Cleanup + with: + args: "find . -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +" + + - name: Checkout code + uses: actions/checkout@v3 + + - if: matrix.arch == 'arm32v7' + uses: docker://hasufell/arm32v7-ubuntu-haskell:focal + name: Run build (arm32v7 linux) + with: + args: sh -c "cabal update && ghcup install ghc --isolate=/usr --force 9.2.2 && cabal test -w ghc-9.2.2 && cabal bench -w ghc-9.2.2" + + - if: matrix.arch == 'arm64v8' + uses: docker://hasufell/arm64v8-ubuntu-haskell:focal + name: Run build (arm64v8 linux) + with: + args: sh -c "cabal update && ghcup install ghc --isolate=/usr --force 9.2.2 && cabal test -w ghc-9.2.2 && cabal bench -w ghc-9.2.2" + + darwin_arm: + runs-on: ${{ matrix.os }} + env: + MACOSX_DEPLOYMENT_TARGET: 10.13 + strategy: + fail-fast: false + matrix: + include: + - os: [self-hosted, macOS, ARM64] + ghc: 8.10.7 + - os: [self-hosted, macOS, ARM64] + ghc: 9.2.8 + - os: [self-hosted, macOS, ARM64] + ghc: 9.4.7 + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Run build + run: | + bash .github/scripts/brew.sh git coreutils llvm@11 autoconf automake + export PATH="$HOME/.brew/bin:$HOME/.brew/sbin:$HOME/.brew/opt/llvm@11/bin:$PATH" + export CC="$HOME/.brew/opt/llvm@11/bin/clang" + export CXX="$HOME/.brew/opt/llvm@11/bin/clang++" + export LD=ld + export AR="$HOME/.brew/opt/llvm@11/bin/llvm-ar" + export RANLIB="$HOME/.brew/opt/llvm@11/bin/llvm-ranlib" + . .github/scripts/env.sh + curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_INSTALL_NO_STACK=1 BOOTSTRAP_HASKELL_GHC_VERSION=${{ matrix.ghc }} BOOTSTRAP_HASKELL_ADJUST_BASHRC=yes sh + cabal test + cabal bench + env: + HOMEBREW_CHANGE_ARCH_TO_ARM: 1