From 9ac33adba482414ae8168cb233cc7ee06dd47b54 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Thu, 24 Sep 2026 06:20:30 +0200 Subject: [PATCH] Migrate the CI from haskell-ci to haskell-gha haskell-ci made a long workflow that ran each job in a container. The new workflow comes from haskell-gha. It is shorter and runs on the runner image. The tested-with field now lists each GHC series instead of exact versions, so each job uses the newest release of its series. The fourmolu and HLint checks are now jobs of the same workflow, with fourmolu 0.20.1.0 and HLint 3.10. HLint now fails on every hint, not only on warnings. The Postgres service now uses version 18. Without a job container, the Postgres service is at localhost, so the tests and the example connect there. The new workflow runs the test suite and the example at the same time, and both create and drop the table table_versions of hpqtypes-extras. So each one now uses its own database on GitHub. The test suite also exited with code 0 when a test failed, so a failed test did not fail CI. Now it fails the test suite. The package descriptions also no longer give warnings in cabal check, apart from the missing upper bounds. --- .github/haskell-gha.conf.yml | 25 ++ .github/workflows/fourmolu.yaml | 10 - .github/workflows/haskell-ci.yml | 262 ------------------ .github/workflows/haskell-gha.yml | 212 ++++++++++++++ .github/workflows/hlint.yaml | 19 -- cabal.haskell-ci | 5 - consumers-metrics-prometheus/README.md | 2 +- .../consumers-metrics-prometheus.cabal | 4 +- consumers/README.md | 2 +- consumers/consumers.cabal | 6 +- consumers/example/Example.hs | 2 +- consumers/test/Test.hs | 4 +- 12 files changed, 247 insertions(+), 306 deletions(-) create mode 100644 .github/haskell-gha.conf.yml delete mode 100644 .github/workflows/fourmolu.yaml delete mode 100644 .github/workflows/haskell-ci.yml create mode 100644 .github/workflows/haskell-gha.yml delete mode 100644 .github/workflows/hlint.yaml delete mode 100644 cabal.haskell-ci diff --git a/.github/haskell-gha.conf.yml b/.github/haskell-gha.conf.yml new file mode 100644 index 0000000..b8b03bc --- /dev/null +++ b/.github/haskell-gha.conf.yml @@ -0,0 +1,25 @@ +apt: [libpq-dev] +services: + postgres: + image: postgres:18 + env: + POSTGRES_PASSWORD: postgres + ports: ['5432:5432'] + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 +hooks: + after-setup: + # cabal runs the test suite and the example at the same time, and both + # create and drop the table table_versions of hpqtypes-extras. + - name: Create the test databases + run: | + for db in consumers_test consumers_example; do + docker exec ${{ job.services.postgres.id }} psql -U postgres -c "CREATE DATABASE $db" + done +fourmolu: + version: '0.20.1.0' +hlint: + version: '3.10' diff --git a/.github/workflows/fourmolu.yaml b/.github/workflows/fourmolu.yaml deleted file mode 100644 index 4730c86..0000000 --- a/.github/workflows/fourmolu.yaml +++ /dev/null @@ -1,10 +0,0 @@ -name: Fourmolu -on: push -jobs: - format: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: haskell-actions/run-fourmolu@v10 - with: - version: "0.15.0.0" diff --git a/.github/workflows/haskell-ci.yml b/.github/workflows/haskell-ci.yml deleted file mode 100644 index 862fa02..0000000 --- a/.github/workflows/haskell-ci.yml +++ /dev/null @@ -1,262 +0,0 @@ -# This GitHub workflow config has been generated by a script via -# -# haskell-ci 'github' 'cabal.project' '--config=cabal.haskell-ci' -# -# To regenerate the script (for example after adjusting tested-with) run -# -# haskell-ci regenerate -# -# For more information, see https://github.com/haskell-CI/haskell-ci -# -# version: 0.19.20260104 -# -# REGENDATA ("0.19.20260104",["github","cabal.project","--config=cabal.haskell-ci"]) -# -name: Haskell-CI -on: - push: - branches: - - master - pull_request: - branches: - - master - merge_group: - branches: - - master -jobs: - linux: - name: Haskell-CI - Linux - ${{ matrix.compiler }} - runs-on: ubuntu-24.04 - timeout-minutes: - 60 - container: - image: buildpack-deps:jammy - services: - postgres: - image: postgres:14 - env: - POSTGRES_PASSWORD: postgres - options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 - continue-on-error: ${{ matrix.allow-failure }} - strategy: - matrix: - include: - - compiler: ghc-9.14.1 - compilerKind: ghc - compilerVersion: 9.14.1 - setup-method: ghcup - allow-failure: false - - 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 - - compiler: ghc-9.2.8 - compilerKind: ghc - compilerVersion: 9.2.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 "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 "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 <> $CABAL_CONFIG < 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@v5 - with: - path: source - - name: initial cabal.project for sdist - run: | - touch cabal.project - echo "packages: $GITHUB_WORKSPACE/source/consumers" >> cabal.project - echo "packages: $GITHUB_WORKSPACE/source/consumers-metrics-prometheus" >> 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_consumers="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/consumers-[0-9.]*')" - echo "PKGDIR_consumers=${PKGDIR_consumers}" >> "$GITHUB_ENV" - PKGDIR_consumers_metrics_prometheus="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/consumers-metrics-prometheus-[0-9.]*')" - echo "PKGDIR_consumers_metrics_prometheus=${PKGDIR_consumers_metrics_prometheus}" >> "$GITHUB_ENV" - rm -f cabal.project cabal.project.local - touch cabal.project - touch cabal.project.local - echo "packages: ${PKGDIR_consumers}" >> cabal.project - echo "packages: ${PKGDIR_consumers_metrics_prometheus}" >> cabal.project - echo "package consumers" >> cabal.project - echo " ghc-options: -Werror=missing-methods -Werror=missing-fields" >> cabal.project - echo "package consumers-metrics-prometheus" >> cabal.project - echo " ghc-options: -Werror=missing-methods -Werror=missing-fields" >> cabal.project - if [ $((HCNUMVER >= 90400)) -ne 0 ] ; then echo "package consumers" >> cabal.project ; fi - if [ $((HCNUMVER >= 90400)) -ne 0 ] ; then echo " ghc-options: -Werror=unused-packages" >> cabal.project ; fi - if [ $((HCNUMVER >= 90400)) -ne 0 ] ; then echo "package consumers-metrics-prometheus" >> cabal.project ; fi - if [ $((HCNUMVER >= 90400)) -ne 0 ] ; then echo " ghc-options: -Werror=unused-packages" >> cabal.project ; fi - echo "package consumers" >> cabal.project - echo " ghc-options: -Werror=incomplete-patterns -Werror=incomplete-uni-patterns" >> cabal.project - echo "package consumers-metrics-prometheus" >> cabal.project - echo " ghc-options: -Werror=incomplete-patterns -Werror=incomplete-uni-patterns" >> cabal.project - cat >> cabal.project <- + --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + strategy: + fail-fast: false + matrix: + ghc: + - '9.2' + - '9.4' + - '9.6' + - '9.8' + - '9.10' + - '9.12' + - '9.14' + steps: + - uses: actions/checkout@v7 + + - name: Install the system packages + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends libpq-dev + + - name: Install the gold linker + if: contains(fromJSON('["9.2","9.4"]'), matrix.ghc) + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends binutils-gold + + - uses: haskell-actions/setup@v2 + id: setup + with: + ghc-version: ${{ matrix.ghc }} + cabal-version: '3.16.1.0' + + - name: Show the versions + id: versions + run: | + ghc --version + cabal --version + echo "GHC ${{ steps.setup.outputs.ghc-version }}, cabal ${{ steps.setup.outputs.cabal-version }}, image $ImageOS $ImageVersion" >> "$GITHUB_STEP_SUMMARY" + echo "image=$ImageOS" >> "$GITHUB_OUTPUT" + + - name: Create the test databases + run: | + for db in consumers_test consumers_example; do + docker exec ${{ job.services.postgres.id }} psql -U postgres -c "CREATE DATABASE $db" + done + + - name: Unpack the source tarballs + run: | + shopt -s extglob + cabal sdist all --output-directory="$RUNNER_TEMP"/haskell-gha-sdist + mkdir "$RUNNER_TEMP"/haskell-gha + for f in cabal.project cabal.project.freeze cabal.project.local; do + if [ -f "$f" ]; then cp "$f" "$RUNNER_TEMP"/haskell-gha; fi + done + mkdir -p "$RUNNER_TEMP"/haskell-gha/consumers + tar -xzf "$RUNNER_TEMP"/haskell-gha-sdist/consumers-+([0-9.]).tar.gz --strip-components=1 -C "$RUNNER_TEMP"/haskell-gha/consumers + mkdir -p "$RUNNER_TEMP"/haskell-gha/consumers-metrics-prometheus + tar -xzf "$RUNNER_TEMP"/haskell-gha-sdist/consumers-metrics-prometheus-+([0-9.]).tar.gz --strip-components=1 -C "$RUNNER_TEMP"/haskell-gha/consumers-metrics-prometheus + + - name: Configure the project + working-directory: ${{ runner.temp }}/haskell-gha + run: | + cat >> cabal.project.local <<'EOF' + jobs: 4 + tests: True + benchmarks: True + + package consumers + ghc-options: -Werror + + package consumers-metrics-prometheus + ghc-options: -Werror + EOF + + - name: Enable parallel module builds for the local packages + if: contains(fromJSON('["9.2","9.4","9.6"]'), matrix.ghc) + working-directory: ${{ runner.temp }}/haskell-gha + run: | + cat >> cabal.project.local <<'EOF' + package consumers + ghc-options: -j4 + + package consumers-metrics-prometheus + ghc-options: -j4 + EOF + + - name: Enable the GHC job semaphore + if: contains(fromJSON('["9.8","9.10","9.12","9.14"]'), matrix.ghc) + working-directory: ${{ runner.temp }}/haskell-gha + run: | + echo 'semaphore: True' >> cabal.project.local + + - name: Make the build plan + id: plan + working-directory: ${{ runner.temp }}/haskell-gha + run: | + cabal build all --dry-run + echo "hash=$(sha256sum dist-newstyle/cache/plan.json | cut -d ' ' -f 1)" >> "$GITHUB_OUTPUT" + + - uses: actions/cache/restore@v6 + id: cache + with: + path: ${{ steps.setup.outputs.cabal-store }} + key: ${{ runner.os }}-${{ steps.versions.outputs.image }}-ghc-${{ steps.setup.outputs.ghc-version }}-${{ steps.plan.outputs.hash }} + restore-keys: ${{ runner.os }}-${{ steps.versions.outputs.image }}-ghc-${{ steps.setup.outputs.ghc-version }}- + + - name: Build the dependencies + working-directory: ${{ runner.temp }}/haskell-gha + run: | + cabal build all --only-dependencies + + - uses: actions/cache/save@v6 + if: steps.cache.outputs.cache-hit != 'true' + with: + path: ${{ steps.setup.outputs.cabal-store }} + key: ${{ steps.cache.outputs.cache-primary-key }} + + - name: Build + working-directory: ${{ runner.temp }}/haskell-gha + run: | + cabal build all + + - name: Run the tests + working-directory: ${{ runner.temp }}/haskell-gha + run: | + cabal test all --test-show-details=direct + + - name: Check the packages + working-directory: ${{ runner.temp }}/haskell-gha + run: | + failed=0 + check() { + echo "Checking the package $1" + (cd "$2" && cabal check) || { echo "::error::cabal check failed for the package $1"; failed=1; } + } + check consumers consumers + check consumers-metrics-prometheus consumers-metrics-prometheus + exit "$failed" + + - name: Build the documentation + working-directory: ${{ runner.temp }}/haskell-gha + run: | + cabal haddock all --disable-documentation --haddock-all --haddock-for-hackage diff --git a/.github/workflows/hlint.yaml b/.github/workflows/hlint.yaml deleted file mode 100644 index c286ab9..0000000 --- a/.github/workflows/hlint.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: HLint -on: push - -jobs: - 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: . - fail-on: warning diff --git a/cabal.haskell-ci b/cabal.haskell-ci deleted file mode 100644 index 4dada4a..0000000 --- a/cabal.haskell-ci +++ /dev/null @@ -1,5 +0,0 @@ -branches: master -doctest: False -tests: True -postgresql: True -installed: -all diff --git a/consumers-metrics-prometheus/README.md b/consumers-metrics-prometheus/README.md index 2d8996d..4f76142 100644 --- a/consumers-metrics-prometheus/README.md +++ b/consumers-metrics-prometheus/README.md @@ -1,7 +1,7 @@ # consumers-metrics-prometheus [![Hackage version](https://img.shields.io/hackage/v/consumers-metrics-prometheus.svg?label=Hackage)](https://hackage.haskell.org/package/consumers-metrics-prometheus) -[![Haskell-CI](https://github.com/scrive/consumers/actions/workflows/haskell-ci.yml/badge.svg?branch=master)](https://github.com/scrive/consumers/actions/workflows/haskell-ci.yml) +[![CI](https://github.com/scrive/consumers/actions/workflows/haskell-gha.yml/badge.svg?branch=master)](https://github.com/scrive/consumers/actions/workflows/haskell-gha.yml) Provides seamless instrumentation of your existing `consumers` using Prometheus. diff --git a/consumers-metrics-prometheus/consumers-metrics-prometheus.cabal b/consumers-metrics-prometheus/consumers-metrics-prometheus.cabal index e023d87..60100a7 100644 --- a/consumers-metrics-prometheus/consumers-metrics-prometheus.cabal +++ b/consumers-metrics-prometheus/consumers-metrics-prometheus.cabal @@ -9,14 +9,14 @@ description: Provides seamless instrumentation of your existing homepage: https://github.com/scrive/consumers license: BSD-3-Clause license-file: LICENSE -extra-source-files: CHANGELOG.md, README.md +extra-doc-files: CHANGELOG.md, README.md author: Scrive AB maintainer: Andrzej Rybczak , Jonathan Jouty copyright: Scrive AB category: Concurrency, Database build-type: Simple -tested-with: GHC == { 9.2.8, 9.4.8, 9.6.7, 9.8.4, 9.10.3, 9.12.2, 9.14.1 } +tested-with: GHC ^>= { 9.2, 9.4, 9.6, 9.8, 9.10, 9.12, 9.14 } bug-reports: https://github.com/scrive/consumers/issues source-repository head diff --git a/consumers/README.md b/consumers/README.md index 7e0f62e..2bdf639 100644 --- a/consumers/README.md +++ b/consumers/README.md @@ -1,6 +1,6 @@ # consumers -[![Haskell-CI](https://github.com/scrive/consumers/actions/workflows/haskell-ci.yml/badge.svg?branch=master)](https://github.com/scrive/consumers/actions/workflows/haskell-ci.yml) +[![CI](https://github.com/scrive/consumers/actions/workflows/haskell-gha.yml/badge.svg?branch=master)](https://github.com/scrive/consumers/actions/workflows/haskell-gha.yml) [![Hackage version](https://img.shields.io/hackage/v/consumers.svg?label=Hackage)](https://hackage.haskell.org/package/consumers) Library for setting up concurrent consumers of data stored inside diff --git a/consumers/consumers.cabal b/consumers/consumers.cabal index b9a3e96..c67003c 100644 --- a/consumers/consumers.cabal +++ b/consumers/consumers.cabal @@ -10,14 +10,14 @@ description: Library for setting up concurrent consumers of data homepage: https://github.com/scrive/consumers license: BSD-3-Clause license-file: LICENSE -extra-source-files: CHANGELOG.md, README.md +extra-doc-files: CHANGELOG.md, README.md author: Scrive AB maintainer: Andrzej Rybczak , Jonathan Jouty copyright: Scrive AB category: Concurrency, Database build-type: Simple -tested-with: GHC == { 9.2.8, 9.4.8, 9.6.7, 9.8.4, 9.10.3, 9.12.2, 9.14.1 } +tested-with: GHC ^>= { 9.2, 9.4, 9.6, 9.8, 9.10, 9.12, 9.14 } bug-reports: https://github.com/scrive/consumers/issues source-repository head @@ -97,7 +97,7 @@ test-suite consumers-test build-depends: base, consumers, exceptions, - HUnit, + HUnit >= 1.6, hpqtypes, hpqtypes-extras >= 1.19.0.0, log-base, diff --git a/consumers/example/Example.hs b/consumers/example/Example.hs index 47f563a..c25af82 100644 --- a/consumers/example/Example.hs +++ b/consumers/example/Example.hs @@ -33,7 +33,7 @@ main = do connString : _args -> pure $ T.pack connString [] -> lookupEnv "GITHUB_ACTIONS" >>= \case - Just "true" -> pure "host=postgres user=postgres password=postgres" + Just "true" -> pure "host=localhost user=postgres password=postgres dbname=consumers_example" _ -> printUsage >> exitFailure let connSettings = diff --git a/consumers/test/Test.hs b/consumers/test/Test.hs index fd2b61d..1c619ac 100644 --- a/consumers/test/Test.hs +++ b/consumers/test/Test.hs @@ -52,7 +52,7 @@ runTestEnv connSource logger = . unTestEnv main :: IO () -main = void . T.runTestTT $ T.TestCase test +main = T.runTestTTAndExit $ T.TestCase test test :: IO () test = do @@ -61,7 +61,7 @@ test = do connString : _args -> pure $ T.pack connString [] -> lookupEnv "GITHUB_ACTIONS" >>= \case - Just "true" -> pure "host=postgres user=postgres password=postgres" + Just "true" -> pure "host=localhost user=postgres password=postgres dbname=consumers_test" _ -> printUsage >> exitFailure let connSettings =