feat: validate cached futility-rejection replay against a state seal #127
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Adapted from haskell-ci for the Sabela project. | |
| # To regenerate, see https://github.com/haskell-CI/haskell-ci | |
| name: Haskell-CI | |
| on: | |
| - push | |
| - pull_request | |
| - merge_group | |
| jobs: | |
| fourmolu: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: haskell-actions/run-fourmolu@v11 | |
| with: | |
| version: "0.17.0.0" | |
| hlint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: 'Set up HLint' | |
| uses: haskell-actions/hlint-setup@v2 | |
| with: | |
| version: '3.8' | |
| - name: Run HLint | |
| uses: haskell-actions/hlint-run@v2 | |
| with: | |
| path: '["src/", "app/", "test/", "sabela-hub/src/", "sabela-hub/test/"]' | |
| fail-on: warning | |
| frontend: | |
| # The served pages (static/*.html) are generated from static/src/ by | |
| # tools/build-frontend.mjs and embedded into the binary at compile time. | |
| # This job fails a PR that forgot to rebuild them, left a partial | |
| # unformatted, or grew a JS module past the size cap. | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Prettier check (frontend sources) | |
| run: npx --yes --package=prettier@3.3.3 -- prettier --check 'static/src/**/*.{html,js,css}' 'tools/*.mjs' | |
| - name: Bundled pages up to date | |
| run: node tools/build-frontend.mjs --check | |
| - name: Module size cap | |
| run: ./scripts/check-module-size.sh | |
| - name: Comment style (changed lines) | |
| run: | | |
| BASE_REF="${{ github.base_ref || 'main' }}" | |
| git fetch --no-tags origin "$BASE_REF" || true | |
| BASE="origin/$BASE_REF" ./scripts/check-comments.sh | |
| linux: | |
| name: Haskell-CI - Linux - ${{ matrix.compiler }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: | |
| 60 | |
| container: | |
| image: buildpack-deps:jammy | |
| continue-on-error: ${{ matrix.allow-failure }} | |
| strategy: | |
| matrix: | |
| include: | |
| - compiler: ghc-9.12.2 | |
| compilerKind: ghc | |
| compilerVersion: 9.12.2 | |
| setup-method: ghcup | |
| allow-failure: false | |
| - compiler: ghc-9.10.3 | |
| compilerKind: ghc | |
| compilerVersion: 9.10.3 | |
| setup-method: ghcup | |
| allow-failure: false | |
| - compiler: ghc-9.8.4 | |
| compilerKind: ghc | |
| compilerVersion: 9.8.4 | |
| setup-method: ghcup | |
| allow-failure: false | |
| - compiler: ghc-9.6.7 | |
| compilerKind: ghc | |
| compilerVersion: 9.6.7 | |
| setup-method: ghcup | |
| allow-failure: false | |
| - compiler: ghc-9.4.8 | |
| compilerKind: ghc | |
| compilerVersion: 9.4.8 | |
| setup-method: ghcup | |
| allow-failure: false | |
| fail-fast: false | |
| steps: | |
| - name: apt-get install | |
| run: | | |
| apt-get update | |
| apt-get install -y --no-install-recommends gnupg ca-certificates dirmngr curl git software-properties-common libtinfo5 | |
| - name: Install GHCup | |
| run: | | |
| mkdir -p "$HOME/.ghcup/bin" | |
| curl -sL https://downloads.haskell.org/ghcup/0.1.50.1/x86_64-linux-ghcup-0.1.50.1 > "$HOME/.ghcup/bin/ghcup" | |
| chmod a+x "$HOME/.ghcup/bin/ghcup" | |
| - name: Install cabal-install | |
| run: | | |
| "$HOME/.ghcup/bin/ghcup" install cabal 3.16.0.0 || (cat "$HOME"/.ghcup/logs/*.* && false) | |
| echo "CABAL=$HOME/.ghcup/bin/cabal-3.16.0.0 -vnormal+nowrap" >> "$GITHUB_ENV" | |
| - name: Install GHC (GHCup) | |
| if: matrix.setup-method == 'ghcup' | |
| run: | | |
| "$HOME/.ghcup/bin/ghcup" install ghc "$HCVER" || (cat "$HOME"/.ghcup/logs/*.* && false) | |
| HC=$("$HOME/.ghcup/bin/ghcup" whereis ghc "$HCVER") | |
| HCPKG=$(echo "$HC" | sed 's#ghc$#ghc-pkg#') | |
| HADDOCK=$(echo "$HC" | sed 's#ghc$#haddock#') | |
| echo "HC=$HC" >> "$GITHUB_ENV" | |
| echo "HCPKG=$HCPKG" >> "$GITHUB_ENV" | |
| echo "HADDOCK=$HADDOCK" >> "$GITHUB_ENV" | |
| env: | |
| HCKIND: ${{ matrix.compilerKind }} | |
| HCNAME: ${{ matrix.compiler }} | |
| HCVER: ${{ matrix.compilerVersion }} | |
| - name: Set PATH and environment variables | |
| run: | | |
| echo "$HOME/.cabal/bin" >> $GITHUB_PATH | |
| echo "$HOME/.ghcup/bin" >> $GITHUB_PATH | |
| echo "LANG=C.UTF-8" >> "$GITHUB_ENV" | |
| echo "CABAL_DIR=$HOME/.cabal" >> "$GITHUB_ENV" | |
| echo "CABAL_CONFIG=$HOME/.cabal/config" >> "$GITHUB_ENV" | |
| HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\d+)\.(\d+)\.(\d+)(\.(\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))') | |
| echo "HCNUMVER=$HCNUMVER" >> "$GITHUB_ENV" | |
| echo "ARG_TESTS=--enable-tests" >> "$GITHUB_ENV" | |
| echo "ARG_BENCH=--enable-benchmarks" >> "$GITHUB_ENV" | |
| echo "HEADHACKAGE=false" >> "$GITHUB_ENV" | |
| echo "GHC=$HC" >> "$GITHUB_ENV" | |
| echo "ARG_COMPILER=--$HCKIND --with-compiler=$HC" >> "$GITHUB_ENV" | |
| env: | |
| HCKIND: ${{ matrix.compilerKind }} | |
| HCNAME: ${{ matrix.compiler }} | |
| HCVER: ${{ matrix.compilerVersion }} | |
| - name: env | |
| run: | | |
| env | |
| - name: write cabal config | |
| run: | | |
| mkdir -p $CABAL_DIR | |
| cat >> $CABAL_CONFIG <<EOF | |
| remote-build-reporting: anonymous | |
| write-ghc-environment-files: never | |
| remote-repo-cache: $CABAL_DIR/packages | |
| logs-dir: $CABAL_DIR/logs | |
| world-file: $CABAL_DIR/world | |
| extra-prog-path: $CABAL_DIR/bin | |
| symlink-bindir: $CABAL_DIR/bin | |
| installdir: $CABAL_DIR/bin | |
| build-summary: $CABAL_DIR/logs/build.log | |
| store-dir: $CABAL_DIR/store | |
| install-dirs user | |
| prefix: $CABAL_DIR | |
| repository hackage.haskell.org | |
| url: http://hackage.haskell.org/ | |
| EOF | |
| cat >> $CABAL_CONFIG <<EOF | |
| program-default-options | |
| ghc-options: $GHCJOBS +RTS -M3G -RTS | |
| EOF | |
| cat $CABAL_CONFIG | |
| - name: versions | |
| run: | | |
| $HC --version || true | |
| $HC --print-project-git-commit-id || true | |
| $CABAL --version || true | |
| - name: update cabal index | |
| run: | | |
| $CABAL v2-update -v | |
| - name: install cabal-plan | |
| run: | | |
| mkdir -p $HOME/.cabal/bin | |
| curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.7.3.0/cabal-plan-0.7.3.0-x86_64-linux.xz > cabal-plan.xz | |
| echo 'f62ccb2971567a5f638f2005ad3173dba14693a45154c1508645c52289714cb2 cabal-plan.xz' | sha256sum -c - | |
| xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan | |
| rm -f cabal-plan.xz | |
| chmod a+x $HOME/.cabal/bin/cabal-plan | |
| cabal-plan --version | |
| - name: checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| path: source | |
| - name: initial cabal.project for sdist | |
| run: | | |
| touch cabal.project | |
| echo "packages: $GITHUB_WORKSPACE/source/." >> cabal.project | |
| echo "packages: $GITHUB_WORKSPACE/source/siza-client/" >> cabal.project | |
| echo "packages: $GITHUB_WORKSPACE/source/sabela-notebook/" >> cabal.project | |
| cat cabal.project | |
| - name: sdist | |
| run: | | |
| mkdir -p sdist | |
| $CABAL sdist all --output-dir $GITHUB_WORKSPACE/sdist | |
| - name: unpack | |
| run: | | |
| mkdir -p unpacked | |
| find sdist -maxdepth 1 -type f -name '*.tar.gz' -exec tar -C $GITHUB_WORKSPACE/unpacked -xzvf {} \; | |
| - name: generate cabal.project | |
| run: | | |
| PKGDIR_sabela="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/sabela-[0-9.]*')" | |
| test -n "$PKGDIR_sabela" || { echo "sdist unpack produced no sabela-<version> directory"; exit 1; } | |
| echo "PKGDIR_sabela=${PKGDIR_sabela}" >> "$GITHUB_ENV" | |
| PKGDIR_siza_client="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/siza-client-[0-9.]*')" | |
| test -n "$PKGDIR_siza_client" || { echo "sdist unpack produced no siza-client-<version> directory"; exit 1; } | |
| echo "PKGDIR_siza_client=${PKGDIR_siza_client}" >> "$GITHUB_ENV" | |
| PKGDIR_sabela_notebook="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/sabela-notebook-[0-9.]*')" | |
| test -n "$PKGDIR_sabela_notebook" || { echo "sdist unpack produced no sabela-notebook-<version> directory"; exit 1; } | |
| echo "PKGDIR_sabela_notebook=${PKGDIR_sabela_notebook}" >> "$GITHUB_ENV" | |
| rm -f cabal.project cabal.project.local | |
| touch cabal.project | |
| touch cabal.project.local | |
| echo "packages: ${PKGDIR_sabela}" >> cabal.project | |
| echo "packages: ${PKGDIR_siza_client}" >> cabal.project | |
| echo "packages: ${PKGDIR_sabela_notebook}" >> cabal.project | |
| echo "package sabela" >> cabal.project | |
| echo " ghc-options: -Werror=missing-methods -Werror=missing-fields" >> cabal.project | |
| echo "package sabela" >> cabal.project | |
| echo " ghc-options: -Werror=unused-packages" >> cabal.project | |
| echo "package sabela" >> cabal.project | |
| # -Werror=incomplete-uni-patterns is deliberately NOT here: the | |
| # promotion is package-wide, src is already clean, and the suite binds | |
| # refutable patterns on purpose (`let Right plan = ...`). | |
| echo " ghc-options: -Werror=incomplete-patterns" >> cabal.project | |
| cat >> cabal.project <<EOF | |
| EOF | |
| $HCPKG list --simple-output --names-only | perl -ne 'for (split /\s+/) { print "constraints: any.$_ installed\n" unless /^(sabela|siza-client|sabela-notebook)$/; }' >> cabal.project.local | |
| cat cabal.project | |
| cat cabal.project.local | |
| - name: dump install plan | |
| run: | | |
| $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all | |
| cabal-plan | |
| - name: restore cache | |
| uses: actions/cache/restore@v4 | |
| with: | |
| key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }} | |
| path: ~/.cabal/store | |
| restore-keys: ${{ runner.os }}-${{ matrix.compiler }}- | |
| - name: install dependencies | |
| run: | | |
| $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --dependencies-only -j2 all | |
| $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dependencies-only -j2 all | |
| - name: build w/o tests | |
| run: | | |
| $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all | |
| - name: build | |
| run: | | |
| $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --write-ghc-environment-files=always | |
| - name: tests | |
| run: | | |
| $CABAL v2-test $ARG_COMPILER $ARG_TESTS $ARG_BENCH sabela:sabela-test --test-show-details=direct | |
| $CABAL v2-test $ARG_COMPILER $ARG_TESTS $ARG_BENCH siza-client:siza-client-test --test-show-details=direct | |
| - name: cabal check | |
| run: | | |
| cd ${PKGDIR_sabela} || false | |
| ${CABAL} -vnormal check | |
| - name: haddock | |
| run: | | |
| $CABAL v2-haddock --disable-documentation --haddock-all $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all | |
| - name: unconstrained build | |
| run: | | |
| rm -f cabal.project.local | |
| $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all | |
| - name: save cache | |
| if: always() | |
| uses: actions/cache/save@v4 | |
| with: | |
| key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }} | |
| path: ~/.cabal/store |