name: CI

on:
  push:
    branches: [master]
  pull_request:
  workflow_dispatch:

# cancel running jobs on new commit to PR
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

jobs:
  rustfmt:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: 1.70.0
          override: true
          components: rustfmt
      - run: cargo fmt -- --check
      - run: cd sys && cargo fmt -- --check

  clippy:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v2
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: nightly
          override: true
          components: clippy

      - name: Install dependencies
        run: |
          sudo apt update
          sudo apt install -y libgeos-dev
      - run: cargo clippy -- -D warnings
      - run: cd sys && cargo clippy -- -D warnings

  check_static:
    name: Check static feature
    runs-on: ubuntu-24.04
    env:
      LD_LIBRARY_PATH: /usr/local/lib

    steps:
      - uses: actions/checkout@v2
        with:
          submodules: "true"

      - name: Install toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: 1.70.0
          override: true

      - name: Build static geos crate
        run: cargo build --features static

  check:
    name: Check ${{ matrix.toolchain }} / ${{ matrix.geos.version }}
    runs-on: ubuntu-24.04
    env:
      LD_LIBRARY_PATH: /usr/local/lib
      GEOS_LIB_DIR: "/usr/lib/x86_64-linux-gnu"
      GEOS_VERSION: ${{ matrix.geos.version }}
      RUSTFLAGS: ${{ matrix.toolchain == 'nightly' && '-Zlinker-features=-lld' || '' }}
      RUSTDOCFLAGS: ${{ matrix.toolchain == 'nightly' && '-Zlinker-features=-lld' || '' }}

    strategy:
      fail-fast: false
      matrix:
        toolchain:
          - 1.70.0
          # - nightly
        geos:
          - version: "3.6.5"
            version_feature: ""
          - version: "3.7.5"
            version_feature: "v3_7_0"
          - version: "3.8.4"
            version_feature: "v3_8_0"
          - version: "3.9.6"
            version_feature: "v3_9_0"
          - version: "3.10.7"
            version_feature: "v3_10_0"
          - version: "3.11.5"
            version_feature: "v3_11_0"
          - version: "3.12.3"
            version_feature: "v3_12_0"
          - version: "3.13.1"
            version_feature: "v3_13_0"
          - version: "3.14.1"
            version_feature: "v3_14_0"
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: "true"

      - name: Install toolchain
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.toolchain }}
          override: true

      - name: Install dependencies
        run: |
          sudo apt update
          sudo apt install build-essential ccache ninja-build pkg-config valgrind
          sudo /usr/sbin/update-ccache-symlinks

      - name: Prepare ccache
        run: ccache --clear --set-config cache_dir=~/.ccache

      - name: Cache ccache
        uses: actions/cache@v4
        env:
          cache-name: ccache-v1
        with:
          path: ~/.ccache
          key: ${{ env.cache-name }}-${{ matrix.os }}-${{ github.job }}-${{ github.ref }}-${{ github.sha }}-${{ github.head_ref }}
          restore-keys: |
            ${{ env.cache-name }}-${{ matrix.os }}-${{ github.job }}-${{ github.ref }}-${{ github.sha }}
            ${{ env.cache-name }}-${{ matrix.os }}-${{ github.job }}-${{ github.ref }}
            ${{ env.cache-name }}-${{ matrix.os }}-${{ github.job }}

      - name: Clear ccache statistics
        run: |
          ccache --zero-stats --set-config cache_dir=~/.ccache
          ccache --max-size=2G --set-config cache_dir=~/.ccache
          ccache --show-stats --set-config cache_dir=~/.ccache

      - name: Install GEOS
        run: |
          cd sys/geos-src/source
          git fetch --unshallow --tags origin
          git checkout "tags/${{ matrix.geos.version }}"
          mkdir build
          cd build
          cmake -G Ninja -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_BUILD_TYPE=Release ..
          sudo ninja install

      - name: Build geos crate
        run: |
          cargo build --features '${{ matrix.geos.version_feature }}'
          cargo build --features '${{ matrix.geos.version_feature }},geo,json'

      - name: Run geos tests
        run: |
          cargo test --features '${{ matrix.geos.version_feature }},tests'
          cargo test --features '${{ matrix.geos.version_feature }},tests,geo,json'

      - name: Check doc generation
        run: |
          cargo doc --features dox
          cargo doc

      - name: Run examples
        run: |
          cargo run --example verbose_example
          cargo run --example prepared_geom
          cargo run --features geo --example prepared_geom
          cargo run --example from_geo
          cargo run --features geo --example from_geo

      - name: Check memory leaks
        # run valgrind to check that there are no memoryleaks
        # Note: cargo seems to randomly name the executable, so we use find to find all the tests
        #
        # As long as leaks come from "geos::geom::GeometryFactory::getDefaultInstance", then
        # it's fine (singleton).
        run: |
          find ./target/debug/deps -name "geos*"  -type f -executable | xargs -n 1 valgrind --leak-check=full --error-exitcode=42 --show-leak-kinds=all
          valgrind --leak-check=full --error-exitcode=42 ./target/debug/examples/from_geo
          valgrind --leak-check=full --error-exitcode=42 ./target/debug/examples/verbose_example
          valgrind --leak-check=full --error-exitcode=42 ./target/debug/examples/prepared_geom
