name: Build

on:
  workflow_call:
    secrets:
      CACHIX_AUTH_TOKEN:
        required: false
  pull_request:
    branches:
      - main
      - v[0-9]+
    paths:
      - .github/workflows/build.yaml
      - .github/actions/**
      - .github/scripts/**
      - .github/*
      - '*.nix'
      - nix/**
      - .cirrus.yml
      - cabal.project*
      - postgrest.cabal
      - stack.yaml*
      - '**.hs'
      - '!**.md'

concurrency:
  # Terminate all previous runs of the same workflow for pull requests
  group: build-${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

jobs:
  static:
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: Linux aarch64
            runs-on: ubuntu-24.04-arm
            artifact: aarch64
          - name: Linux x86-64
            runs-on: ubuntu-24.04
            artifact: x86-64
    name: Nix - ${{ matrix.name }} static
    runs-on: ${{ matrix.runs-on }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Setup Nix Environment
        uses: ./.github/actions/setup-nix
        with:
          authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'

      - name: Build static executable
        run: nix-build -A postgrestStatic -A postgrestStatic.tests
      - name: Save built executable as artifact
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: postgrest-linux-static-${{ matrix.artifact }}
          path: result/bin/postgrest
          if-no-files-found: error

      - name: Build Docker image
        run: nix-build -A docker.image --out-link postgrest-docker-${{ matrix.artifact }}.tar.gz
      - name: Save built Docker image as artifact
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: postgrest-docker-${{ matrix.artifact }}
          path: postgrest-docker-${{ matrix.artifact }}.tar.gz
          if-no-files-found: error


  macos:
    name: Nix - MacOS
    runs-on: macos-15
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - name: Setup Nix Environment
        uses: ./.github/actions/setup-nix
        with:
          authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
      - name: Install gnu sed
        run: brew install gnu-sed

      - name: Build everything
        run: |
          # The --dry-run will give us a list of derivations to download from cachix and
          # derivations to build. We only take those that would have to be built and then build
          # those explicitly. This has the advantage that pure verification will not include
          # a download anymore, making it much faster. If something needs to be built, only
          # the dependencies required to do so will be downloaded, but not everything.
          nix-build --dry-run 2>&1 \
            | gsed -e '1,/derivations will be built:$/d' -e '/paths will be fetched/Q' \
            | xargs nix-build


  stack:
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: MacOS aarch64
            runs-on: macos-14
            cache: |
              ~/.stack/pantry
              ~/.stack/snapshots
              ~/.stack/stack.sqlite3
            artifact: postgrest-macos-aarch64
            deps: brew link --force libpq

          - name: MacOS x86-64
            runs-on: macos-15-intel
            cache: |
              ~/.stack/pantry
              ~/.stack/snapshots
              ~/.stack/stack.sqlite3
            artifact: postgrest-macos-x86-64
            deps: brew link --force libpq

          - name: Windows
            runs-on: windows-2022
            cache: |
              C:\sr\pantry
              C:\sr\snapshots
              C:\sr\stack.sqlite3
            deps: Add-Content $env:GITHUB_PATH $env:PGBIN
            artifact: postgrest-windows-x86-64

    name: Stack - ${{ matrix.name }}
    runs-on: ${{ matrix.runs-on }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: haskell-actions/setup@cd0d9bdd65b20557f41bea4dbe43d0b5fbbfe553 # v2.11.0
        with:
          # This must match the version in stack.yaml's resolver
          ghc-version: 9.8.4
          enable-stack: true
          stack-no-global: true
          stack-setup-ghc: true
      - name: Cache ~/.stack
        uses: ./.github/actions/cache-on-main
        with:
          path: ${{ matrix.cache }}
          prefix: stack
          suffix: ${{ hashFiles('postgrest.cabal', 'stack.yaml.lock') }}
      - name: Cache .stack-work
        uses: ./.github/actions/cache-on-main
        with:
          path: .stack-work
          save-prs: true
          prefix: stack-work-${{ hashFiles('postgrest.cabal', 'stack.yaml.lock') }}
          suffix: ${{ hashFiles('main/**/*.hs', 'src/**/*.hs') }}
      - name: Install dependencies
        if: matrix.deps
        run: ${{ matrix.deps }}
      - name: Build with Stack
        run: stack build --lock-file error-on-write --local-bin-path result --copy-bins
      - name: Strip Executable
        run: strip result/postgrest*
      - name: Save built executable as artifact
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
        with:
          name: ${{ matrix.artifact }}
          path: |
            result/postgrest
            result/postgrest.exe
          if-no-files-found: error


  freebsd:
    name: Stack - FreeBSD from CirrusCI
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: ./.github/actions/artifact-from-cirrus
        with:
          token: ${{ github.token }}
          task: Build FreeBSD (Stack)
          download: bin
          upload: postgrest-freebsd-x86-64


  cabal:
    strategy:
      matrix:
        ghc: ['9.10.3', '9.12.3']
      fail-fast: false
    name: Cabal - Linux x86-64 - GHC ${{ matrix.ghc }}
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      - uses: haskell-actions/setup@cd0d9bdd65b20557f41bea4dbe43d0b5fbbfe553 # v2.11.0
        with:
          ghc-version: ${{ matrix.ghc }}
      - name: Cache .cabal
        uses: ./.github/actions/cache-on-main
        with:
          path: |
            ~/.cabal/packages
            ~/.cabal/store
          prefix: cabal-${{ matrix.ghc }}-${{ hashFiles('cabal.project.freeze') }}
          suffix: ${{ hashFiles('postgrest.cabal', 'cabal.project') }}
      - name: Cache dist-newstyle
        uses: ./.github/actions/cache-on-main
        with:
          path: dist-newstyle
          save-prs: true
          prefix: cabal-${{ matrix.ghc }}-dist-newstyle-${{ hashFiles('postgrest.cabal', 'cabal.project', 'cabal.project.freeze') }}
          suffix: ${{ hashFiles('**/*.hs') }}
      - name: Install dependencies
        run: cabal build --only-dependencies --enable-tests --enable-benchmarks
      - name: Build
        run: cabal build --enable-tests --enable-benchmarks all
