range_date 0.2.4

A powerful Rust crate for handling date periods with embedded data and comprehensive date range operations.
Documentation
name: Rust CI & Release

on:
  push:
    branches: [main]
    tags: ["v*"]
  pull_request:
    branches: [main]
  schedule:
    # Weekly re-run (Monday 06:00 UTC) to catch newly disclosed advisories
    - cron: "0 6 * * 1"
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
  CARGO_TERM_COLOR: always
  RUSTFLAGS: -D warnings
  RUSTDOCFLAGS: -D warnings

jobs:
  build:
    name: Build & Test (${{ matrix.rust }})
    runs-on: ubuntu-latest
    timeout-minutes: 25
    permissions:
      contents: read
    strategy:
      fail-fast: false
      matrix:
        rust: [stable, beta, nightly]

    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Setup Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: ${{ matrix.rust }}
          components: rustfmt, clippy
          cache: false

      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2
        with:
          cache-on-failure: false

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

      - name: Run Clippy lints (lib/bin)
        continue-on-error: ${{ matrix.rust == 'nightly' }}
        run: cargo clippy --all-features -- -D clippy::expect_used -D clippy::panic -D clippy::unwrap_used -D warnings

      - name: Run Clippy lints (tests)
        continue-on-error: ${{ matrix.rust == 'nightly' }}
        run: cargo clippy --tests --all-features -- -D warnings

      - name: Build project
        continue-on-error: ${{ matrix.rust == 'nightly' }}
        run: cargo build --all --locked --verbose

      - name: Run tests
        continue-on-error: ${{ matrix.rust == 'nightly' }}
        run: cargo test --all --locked --verbose

      - name: Check documentation
        continue-on-error: ${{ matrix.rust == 'nightly' }}
        run: cargo doc --no-deps --all-features --locked

      - name: Install tarpaulin
        if: matrix.rust == 'stable'
        uses: taiki-e/install-action@v2
        with:
          tool: cargo-tarpaulin

      - name: Generate coverage report
        if: matrix.rust == 'stable'
        run: cargo tarpaulin --all-features --workspace --timeout 120 --out xml --output-dir ./coverage

      - name: Upload coverage to Codecov
        if: matrix.rust == 'stable' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
        uses: codecov/codecov-action@v6
        with:
          files: ./coverage/cobertura.xml
          fail_ci_if_error: false
          token: ${{ secrets.CODECOV_TOKEN }}
          verbose: true

  security:
    name: Security Audit
    runs-on: ubuntu-latest
    timeout-minutes: 10
    permissions:
      contents: read
    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Setup Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: stable
          cache: false

      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2
        with:
          cache-on-failure: false

      - name: Install cargo-audit
        uses: taiki-e/install-action@v2
        with:
          tool: cargo-audit

      - name: Run security audit
        run: cargo audit

  release:
    name: Release to crates.io
    needs: [build, security]
    runs-on: ubuntu-latest
    timeout-minutes: 15
    if: startsWith(github.ref, 'refs/tags/v') && github.repository == 'GuoMonth/range_date'
    environment:
      name: crates-io
      url: https://crates.io/crates/range_date
    permissions:
      contents: read

    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          persist-credentials: false

      - name: Setup Rust toolchain
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: stable
          cache: false

      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2
        with:
          cache-on-failure: false

      - name: Verify package
        run: cargo package --locked --verbose

      - name: Publish to crates.io
        run: cargo publish --locked --verbose
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}