Skip to content

Merge pull request #878 from IntersectMBO/jdral/ci-apt-get-fix #1275

Merge pull request #878 from IntersectMBO/jdral/ci-apt-get-fix

Merge pull request #878 from IntersectMBO/jdral/ci-apt-get-fix #1275

Workflow file for this run

name: CI
on:
push:
branches:
- "main"
pull_request:
merge_group:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
# Set the default shell on all platforms.
defaults:
run:
shell: sh
# Set the GHC and Cabal versions for linter jobs.
env:
LINT_GHC_VERSION: "9.6"
LINT_CABAL_VERSION: "3.12"
LINT_CABAL_PROJECT_FILE: "cabal.project.debug"
jobs:
################################################################################
# Setup matrix
################################################################################
setup-matrix:
name: "Build: Setup matrix"
runs-on: 'ubuntu-latest'
timeout-minutes: 5
outputs:
matrix: ${{ steps.setup-matrix.outputs.matrix }}
defaults:
run:
shell: bash
steps:
# NOTE: For caching purposes, the matrix combinations that we test on pull
# requests (PR) should be a subset of the matrix combinations we run on the
# merge queue and main (MQ, push to main).
- name: 🛠️ Setup matrix (PR)
if: ${{ github.event_name == 'pull_request' }}
run: |
{ echo 'MATRIX_COMBINATIONS<<EOF'
# Default CI: PR
echo '{"name" : "", "os": "ubuntu-latest", "ghc-version": "9.6", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "macos-latest", "ghc-version": "9.6", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "windows-latest", "ghc-version": "9.6", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo EOF
} >> "$GITHUB_ENV"
- name: 🛠️ Setup matrix (MQ, push to main)
if: ${{ github.event_name != 'pull_request' }}
run: |
{ echo 'MATRIX_COMBINATIONS<<EOF'
# Default CI: PR
echo '{"name" : "", "os": "ubuntu-latest", "ghc-version": "9.6", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "macos-latest", "ghc-version": "9.6", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "windows-latest", "ghc-version": "9.6", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
# Comprehensive CI: MQ, push to main
## Test every GHC version on Ubuntu
echo '{"name" : "", "os": "ubuntu-latest", "ghc-version": "9.2", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "ubuntu-latest", "ghc-version": "9.4", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "ubuntu-latest", "ghc-version": "9.8", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "ubuntu-latest", "ghc-version": "9.10", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "ubuntu-latest", "ghc-version": "9.12", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "ubuntu-latest", "ghc-version": "9.14", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
## Test every GHC version on MacOS
echo '{"name" : "", "os": "macos-latest", "ghc-version": "9.2", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "macos-latest", "ghc-version": "9.4", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "macos-latest", "ghc-version": "9.8", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "macos-latest", "ghc-version": "9.10", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "macos-latest", "ghc-version": "9.12", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "macos-latest", "ghc-version": "9.14", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
## Test every GHC version on Windows
echo '{"name" : "", "os": "windows-latest", "ghc-version": "9.2", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "windows-latest", "ghc-version": "9.4", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "windows-latest", "ghc-version": "9.8", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "windows-latest", "ghc-version": "9.10", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "windows-latest", "ghc-version": "9.12", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "", "os": "windows-latest", "ghc-version": "9.14", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.debug"},'
## Various special cases
echo '{"name" : "Build with +serialblockio" , "os": "ubuntu-latest", "ghc-version": "9.6", "cabal-version": "3.12", "cabal-flags": "+serialblockio", "cabal-project-file": "cabal.project.debug"},'
echo '{"name" : "Build with cabal.project.release", "os": "ubuntu-latest", "ghc-version": "9.6", "cabal-version": "3.12", "cabal-flags": "", "cabal-project-file": "cabal.project.release"},'
echo EOF
} >> "$GITHUB_ENV"
- name: 🛠️ Setup matrix
id: setup-matrix
run: |
echo $MATRIX_COMBINATIONS
MATRIX="{\"include\":[$MATRIX_COMBINATIONS]}"
echo $MATRIX
{
echo 'MATRIX<<EOF'
echo "$MATRIX"
echo EOF
} >> "$GITHUB_OUTPUT"
################################################################################
# Check success
################################################################################
check-success:
name: "Build: Check success"
runs-on: ubuntu-latest
timeout-minutes: 5
needs:
- build
defaults:
run:
shell: bash
if: ${{ !cancelled() }}
steps:
- name: 🧪 Report failure
if: ${{ needs.build.result != 'success' }}
run: |
echo "Some jobs failed"
echo "Result status: ${{ needs.build.result }}"
exit 1
- name: 🧪 Report success
if: ${{ needs.build.result == 'success' }}
run: |
echo "All jobs succeeded"
exit 0
################################################################################
# Build
################################################################################
build:
name: |
${{ matrix.name
|| format(
'Build on {0}{1}{2}',
startsWith(matrix.os, 'ubuntu-') && 'Linux' || startsWith(matrix.os, 'macOS-') && 'macOS' || startsWith(matrix.os, 'windows-') && 'Windows',
matrix.ghc-version && format(' with GHC {0}', matrix.ghc-version),
matrix.cabal-version && format(' and Cabal {0}', matrix.cabal-version)
)
}}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
needs:
- setup-matrix
strategy:
matrix: ${{ fromJSON(needs.setup-matrix.outputs.matrix) }}
fail-fast: false
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v7
- uses: ./.github/actions/fast-apt-mirror
- name: 🗄️ Print Job info
run: |
echo 'matrix.os: ${{ matrix.os }}'
echo 'matrix.ghc-version: ${{ matrix.ghc-version }}'
echo 'matrix.cabal-version: ${{ matrix.os }}'
echo 'matrix.cabal-flags: ${{ matrix.cabal-flags }}'
echo 'matrix.cabal-project-file: ${{ matrix.cabal-project-file }}'
echo 'toJSON(matrix): ${{ toJSON(matrix) }}'
- name: 🗄️ Print CPU info
uses: ./.github/actions/print-cpu-info
- name: 🛠️ Setup Haskell
id: setup-haskell
uses: haskell-actions/setup@v2
with:
ghc-version: ${{ matrix.ghc-version }}
cabal-version: ${{ matrix.cabal-version }}
- name: 🛠️ Setup system dependencies (Linux)
if: ${{ runner.os == 'Linux' }}
timeout-minutes: 10
run: sudo apt-get update && sudo apt-get -y install liburing-dev librocksdb-dev
env:
DEBIAN_FRONTEND: "noninteractive"
- name: 🛠️ Configure
run: |
cabal configure \
--project-file="${{ matrix.cabal-project-file }}" \
--enable-tests \
--enable-benchmarks \
--disable-documentation \
--ghc-options="-Werror" \
--flag="${{ matrix.cabal-flags }}"
cat "${{ matrix.cabal-project-file }}.local"
- name: 💾 Generate Cabal plan
run: |
cabal build all \
--project-file="${{ matrix.cabal-project-file }}" \
--dry-run
- name: 💾 Restore Cabal dependencies
uses: actions/cache/restore@v6
if: ${{ !env.ACT }}
id: cache-cabal
env:
key: build-${{ runner.os }}-ghc-${{ steps.setup-haskell.outputs.ghc-version }}-cabal-${{ steps.setup-haskell.outputs.cabal-version }}
with:
path: ${{ steps.setup-haskell.outputs.cabal-store }}
key: ${{ env.key }}-plan-${{ hashFiles('dist-newstyle/cache/plan.json') }}
restore-keys: ${{ env.key }}-
- name: 🛠️ Build Cabal dependencies
run: |
cabal build all \
--project-file="${{ matrix.cabal-project-file }}" \
--only-dependencies
- name: 💾 Save Cabal dependencies
uses: actions/cache/save@v6
if: ${{ !env.ACT && steps.cache-cabal.outputs.cache-hit != 'true' }}
with:
path: ${{ steps.setup-haskell.outputs.cabal-store }}
key: ${{ steps.cache-cabal.outputs.cache-primary-key }}
- name: 🏗️ Build
run: |
cabal build all \
--project-file="${{ matrix.cabal-project-file }}"
- name: 🧪 Test
id: test
run: |
cabal test all \
-j1 \
--test-show-details=direct \
--project-file="${{ matrix.cabal-project-file }}"
env:
TASTY_TIMEOUT: "5m"
# Golden test output is not printed to the screen, so if a golden test fails
# then it is not clear from the logs why the test fails. Uploading the
# directory containing the golden files after running the goldens tests
# allows us to diff the expected and actual golden file contents.
- name: 📦 Upload golden files
if: ${{ steps.test.outcome != 'success' && always() }}
uses: actions/upload-artifact@v7
with:
name: golden-files-${{ runner.os }}-ghc-${{ steps.setup-haskell.outputs.ghc-version }}-cabal-${{ steps.setup-haskell.outputs.cabal-version }}-plan-${{ hashFiles('dist-newstyle/cache/plan.json') }}
path: lsm-tree/test/golden-file-data
if-no-files-found: error
retention-days: 1
- name: 🛠️ Setup cabal-docspec (Linux)
if: ${{ runner.os == 'Linux' }}
uses: ./.github/actions/setup-cabal-docspec
- name: 🧪 Test with cabal-docspec (Linux)
if: ${{ runner.os == 'Linux' }}
run: ./scripts/test-cabal-docspec.sh
env:
SKIP_CABAL_BUILD: true
################################################################################
# Lint with actionlint
################################################################################
lint-actionlint:
name: Lint with actionlint
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v7
- name: 🛠️ Setup actionlint
uses: ./.github/actions/setup-actionlint
with:
actionlint-version: "1.7.7"
- name: 🎗️ Lint with actionlint
run: ./scripts/lint-actionlint.sh
################################################################################
# Lint with cabal-fmt
################################################################################
lint-cabal-fmt:
name: Lint with cabal-fmt
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v7
- name: 🛠️ Setup cabal-fmt
uses: ./.github/actions/setup-cabal-fmt
with:
cabal-fmt-version: "0.1.12"
ghc-version: ${{ env.LINT_GHC_VERSION }}
cabal-version: ${{ env.LINT_CABAL_VERSION }}
# The index-state is fixed to enable caching and ensure that the version
# regardless of the current state of Hackage head.
# If you want a newer version of cabal-fmt, use a more recent time.
hackage-index-state: "2025-05-22T00:00:00Z"
- name: 🎗️ Lint with cabal-fmt
run: ./scripts/format-cabal-fmt.sh && git diff --exit-code
################################################################################
# Lint with cabal
################################################################################
lint-cabal:
name: Lint with cabal
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v7
- name: 🛠️ Setup Haskell
id: setup-haskell
uses: haskell-actions/setup@v2
with:
ghc-version: ${{ env.LINT_GHC_VERSION }}
cabal-version: ${{ env.LINT_CABAL_VERSION }}
cabal-update: false
- name: 🎗️ Lint with cabal
run: ./scripts/lint-cabal.sh
################################################################################
# Lint with stylish-haskell
################################################################################
lint-stylish-haskell:
name: Lint with stylish-haskell
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v7
- name: 🛠️ Setup stylish-haskell
uses: ./.github/actions/setup-stylish-haskell
with:
stylish-haskell-version: "0.15.1.0"
ghc-version: "9.10"
cabal-version: ${{ env.LINT_CABAL_VERSION }}
# The index-state is fixed to enable caching and ensure that the version
# regardless of the current state of Hackage head.
# If you want a newer version of stylish-haskell, use a more recent time.
hackage-index-state: "2025-05-21T09:13:36Z"
- name: 🎗️ Lint with stylish-haskell
run: ./scripts/format-stylish-haskell.sh && git diff --exit-code
################################################################################
# Lint for missing IO specialisations
################################################################################
lint-io-specialisations:
name: Lint for missing IO specialisations
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v7
- name: 🎗️ Lint for missing IO specialisations
run: ./scripts/lint-io-specialisations.sh
################################################################################
# Lint with generate-readme
################################################################################
lint-generate-readme:
name: Lint with generate-readme
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v7
- name: 🛠️ Generate README.md
uses: ./.github/actions/generate-readme
with:
ghc-version: ${{ env.LINT_GHC_VERSION }}
cabal-version: ${{ env.LINT_CABAL_VERSION }}
hackage-index-state: "2025-05-22T00:00:00Z"
- name: 🎗️ Lint with generate-readme
run: git diff --exit-code
################################################################################
# Lint with HLint
################################################################################
lint-hlint:
name: Lint with HLint
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v7
- name: 🛠️ Setup HLint
uses: haskell-actions/hlint-setup@v2
with:
version: "3.10"
- name: 🎗️ Lint with HLint
run: ./scripts/lint-hlint.sh
#############################################################################
# Lint with ShellCheck
#############################################################################
lint-shellcheck:
name: "Lint with ShellCheck"
runs-on: "ubuntu-latest"
steps:
- name: 📥 Checkout repository
uses: actions/checkout@v7
- name: 🛠️ Install ShellCheck
uses: ./.github/actions/setup-shellcheck
with:
shellcheck-version: "0.10.0"
- name: 🎗️ Lint with ShellCheck
run: ./scripts/lint-shellcheck.sh