lake-pulse 0.2.0

A Rust library for analyzing data lake table health across multiple formats and storage providers.
Documentation
# Copyright 2025 Adobe. All rights reserved.
# This file is licensed to you under the Apache License,
# Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
# or the MIT license (http://opensource.org/licenses/MIT),
# at your option.
#
# Unless required by applicable law or agreed to in writing,
# this software is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
# implied. See the LICENSE-MIT and LICENSE-APACHE files for the
# specific language governing permissions and limitations under
# each license.

name: CI

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

# Concurrency strategy:
#   github.workflow: distinguish this workflow from others
#   github.ref: distinguish different branches/PRs
#   github.event_name: distinguish `push` event from `pull_request` event
#
# This ensures that only one workflow runs per PR/branch at a time,
# cancelling any in-progress runs when new commits are pushed.
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
  cancel-in-progress: true

jobs:
  # Detect what files changed to conditionally skip expensive jobs
  changes:
    name: Detect Changes
    runs-on: ubuntu-latest
    outputs:
      code: ${{ steps.filter.outputs.code }}
    steps:
      - uses: actions/checkout@v6

      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            code:
              - '**/*.rs'
              - '**/Cargo.toml'
              - '.github/workflows/**'
              - 'licenserc.yaml'

  license-header:
    name: License Header
    needs: changes
    if: needs.changes.outputs.code == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Check License Header
        uses: korandoru/hawkeye@v6

  check:
    name: Check
    needs: changes
    if: needs.changes.outputs.code == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install protobuf compiler
        run: |
          sudo apt-get update
          sudo apt-get install -y protobuf-compiler

      - name: Setup Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          components: rustfmt, clippy

      - name: Check formatting
        run: cargo fmt --all -- --check

      - name: Run clippy
        run: cargo clippy --all-targets --all-features --workspace -- -D warnings

  test:
    name: Test (${{ matrix.name }})
    needs: changes
    if: needs.changes.outputs.code == 'true'
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: "default (Delta + Iceberg)"
            features: ""
          - name: "hudi"
            features: "--features hudi"
          - name: "lance"
            features: "--features lance"
          - name: "all (hudi + lance)"
            features: "--features all"
    steps:
      - uses: actions/checkout@v6

      - name: Install protobuf compiler
        run: |
          sudo apt-get update
          sudo apt-get install -y protobuf-compiler

      - name: Setup Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1

      - name: Build
        run: cargo build ${{ matrix.features }} --workspace

      - name: Run tests
        run: cargo test ${{ matrix.features }} --workspace
        env:
          RUST_LOG: DEBUG
          RUST_BACKTRACE: full

  test-examples:
    name: Test Examples
    needs: changes
    if: needs.changes.outputs.code == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install protobuf compiler
        run: |
          sudo apt-get update
          sudo apt-get install -y protobuf-compiler

      - name: Setup Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1

      - name: Fix Iceberg metadata paths
        run: ./examples/data/iceberg_dataset/fix_paths.sh

      - name: Run examples
        run: |
          echo "Running local store examples..."
          cargo run --features all --example local_store
          cargo run --features all --example local_store_custom
          cargo run --features all --example local_store_hudi
          cargo run --features all --example local_store_iceberg
          cargo run --features all --example local_store_json
          cargo run --features all --example local_store_lance
          cargo run --features all --example local_store_synthetic_deletion_vectors

  test-platforms:
    name: Test on ${{ matrix.os }}
    needs: changes
    if: needs.changes.outputs.code == 'true'
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
    steps:
      - uses: actions/checkout@v6

      - name: Install protobuf compiler (Ubuntu)
        if: runner.os == 'Linux'
        run: |
          sudo apt-get update
          sudo apt-get install -y protobuf-compiler

      - name: Install protobuf compiler (macOS)
        if: runner.os == 'macOS'
        run: brew install protobuf

      - name: Install protobuf compiler (Windows)
        if: runner.os == 'Windows'
        run: choco install protoc

      - name: Setup Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1

      - name: Build
        run: cargo build --all-features --workspace

      - name: Run tests
        run: cargo test --all-features --workspace
        env:
          RUST_LOG: DEBUG
          RUST_BACKTRACE: full

  coverage:
    name: Code Coverage
    needs: changes
    if: needs.changes.outputs.code == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install protobuf compiler
        run: |
          sudo apt-get update
          sudo apt-get install -y protobuf-compiler

      - name: Setup Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          components: llvm-tools-preview

      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@cargo-llvm-cov

      - name: Generate code coverage
        run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v5
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: lcov.info
          fail_ci_if_error: true
          verbose: true

  required:
    name: Required
    runs-on: ubuntu-latest
    if: always()
    needs:
      - changes
      - license-header
      - check
      - test
      - test-examples
      - test-platforms
      - coverage
    steps:
      - name: Guardian
        run: |
          # If no code changes, all jobs will be skipped - that's OK
          if [[ "${{ needs.changes.outputs.code }}" != "true" ]]; then
            echo "No code changes detected. Skipping CI checks."
            exit 0
          fi

          # Code changes detected - all jobs must succeed
          results=(
            "${{ needs.license-header.result }}"
            "${{ needs.check.result }}"
            "${{ needs.test.result }}"
            "${{ needs.test-examples.result }}"
            "${{ needs.test-platforms.result }}"
            "${{ needs.coverage.result }}"
          )

          for result in "${results[@]}"; do
            if [[ "$result" != "success" ]]; then
              echo "Required jobs haven't been completed successfully."
              echo "Found result: $result"
              exit 1
            fi
          done

          echo "All required jobs passed."