rfgrep 0.5.0

Advanced recursive file grep utility with comprehensive file type classification - search, list, and analyze 153+ file formats with intelligent filtering and safety policies
Documentation
# This is the main CI workflow that runs the test suite on all pushes to main and all pull requests.
# It runs the following Jobs
name: CI/CD

on:
  push:
    branches: [main, dev, 'release/**']
    tags: ["v*", "v*-*"]  # Support prereleases
  pull_request:
    branches: [main, dev]
  workflow_dispatch:
  schedule:
    - cron: "0 0 * * 0"  # Weekly security audit

env:
  CARGO_TERM_COLOR: always
  RUSTFLAGS: "-D warnings"
  CARGO_INCREMENTAL: 0
  RUSTUP_MAX_RETRIES: 3

jobs:
  lint:
    name: Lint & Format
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0
          submodules: recursive

      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          components: clippy, rustfmt, llvm-tools-preview

      - name: Cache cargo registry
        uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-

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

      - name: Clippy (all features)
        run: cargo clippy --all-targets --all-features -- -D warnings

  test:
    name: Test Suite
    runs-on: ${{ matrix.os }}
    timeout-minutes: 15
    strategy:
      fail-fast: true
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        rust: [stable, 1.91.0]  # MSRV
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
          - os: macos-latest
            target: x86_64-apple-darwin
          - os: windows-latest
            target: x86_64-pc-windows-msvc

    steps:
      - uses: actions/checkout@v6

      - name: Install Rust (${{ matrix.rust }})
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.rust }}
          target: ${{ matrix.target }}

      - name: Cache cargo
        uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-${{ matrix.rust }}-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-${{ matrix.rust }}-

      - name: Run tests
        run: cargo test --all-features --locked --no-fail-fast

      - name: Run doctests
        run: cargo test --doc --locked

      - name: Build release
        run: cargo build --release --locked --target ${{ matrix.target }}

  security:
    name: Security Scan
    runs-on: ubuntu-latest
    needs: test
    permissions:
      contents: read
      security-events: write
    steps:
      - uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Security audit
        uses: rustsec/audit-check@v2.0.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

  build-matrix:
    name: Build Artifacts
    runs-on: ${{ matrix.os }}
    needs: [lint, test, security]
    permissions:
      actions: write
      contents: read
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            artifact_name: rfgrep-linux-x86_64
          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            artifact_name: rfgrep-linux-musl
          - os: macos-latest
            target: x86_64-apple-darwin
            artifact_name: rfgrep-macos-x86_64
          - os: macos-latest
            target: aarch64-apple-darwin
            artifact_name: rfgrep-macos-arm64
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact_name: rfgrep-windows-x86_64.exe

    steps:
      - uses: actions/checkout@v6

      - name: Install Rust + target
        uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: stable
          target: ${{ matrix.target }}

      - name: Install musl-tools
        if: matrix.target == 'x86_64-unknown-linux-musl'
        run: |
          sudo apt-get update
          sudo apt-get install -y musl-tools

      - name: Build release
        run: cargo build --release --locked --target ${{ matrix.target }}

      - name: Strip symbols (Unix)
        if: runner.os != 'Windows'
        run: |
          strip target/${{ matrix.target }}/release/rfgrep* || true

      - name: Package artifact
        run: |
          mkdir -p release
          cp target/${{ matrix.target }}/release/rfgrep* release/
          tar czf ${{ matrix.artifact_name }}.tar.gz -C release .

      - name: Upload artifacts
        uses: actions/upload-artifact@v6
        with:
          name: ${{ matrix.artifact_name }}
          path: ${{ matrix.artifact_name }}.tar.gz

  release:
    name: Create Release
    runs-on: ubuntu-latest
    needs: [ build-matrix ]
    if: startsWith(github.ref, 'refs/tags/')
    permissions:
      contents: write
      packages: write

    steps:
      - uses: actions/checkout@v6

      - name: Download all artifacts
        uses: actions/download-artifact@v7
        with:
          path: artifacts
          pattern: rfgrep-*
          merge-multiple: true


      - name: Create checksums
        run: |
          cd artifacts
          sha256sum * > SHA256SUMS

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          files: |
            artifacts/*
          generate_release_notes: true
          draft: false
          prerelease: ${{ contains(github.ref, '-') }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  publish-crates-io:
    name: Publish to Crates.io
    runs-on: ubuntu-latest
    needs: test
    if: startsWith(github.ref, 'refs/tags/')
    steps:
      - uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Publish
        run: |
          cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}

  docker:
    name: Build Docker Image
    runs-on: ubuntu-latest
    needs: build-matrix
    if: startsWith(github.ref, 'refs/tags/')
    steps:
      - uses: actions/checkout@v6

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ./Dockerfile
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            ghcr.io/${{ github.repository_owner }}/rfgrep:${{ github.ref_name }}
            ghcr.io/${{ github.repository_owner }}/rfgrep:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max

  notify:
    name: Notify Status
    runs-on: ubuntu-latest
    needs: [release, publish-crates-io, docker]
    if: always()
    steps:
      - name: Notify Slack
        if: failure()
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          channel: '#ci'
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}