waterkit 0.2.0

Kit utilities and helpers
name: CI

permissions:
  contents: read
  checks: write
  id-token: write

on:
  # Integration branches only: a topic branch that also has a pull request
  # would otherwise run the whole workflow twice for one commit, booting two
  # hosted emulators that contend for the same nested-KVM capacity.
  push:
    branches: [main, dev]
  pull_request:
    branches: ["**"]

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

env:
  CARGO_INCREMENTAL: "0"
  CARGO_PROFILE_DEV_DEBUG: "0"
  CARGO_PROFILE_TEST_DEBUG: "0"
  CARGO_TERM_COLOR: always

jobs:
  fmt:
    name: Format
    runs-on: ubuntu-latest
    # The slowest job takes about 9 minutes; a hung step must fail the
    # run instead of holding a runner until the 6-hour default.
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt
      - run: cargo fmt --all -- --check

  clippy:
    name: Clippy (${{ matrix.os }})
    runs-on: ${{ matrix.os }}
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
    steps:
      - uses: actions/checkout@v4
      # `shaderloom` compiles WGSL to DXIL on Windows and shells out to `dxc`,
      # which the runner image does not carry. WaterUI's Windows job installs it
      # the same way.
      - name: Install DirectX Shader Compiler
        if: runner.os == 'Windows'
        uses: tracel-ai/github-actions/install-dxc@295f2fdbae5271f4f8ad56d634e4ff6a95daafc8
      - name: Install Linux dependencies
        if: runner.os == 'Linux'
        uses: ./.github/actions/setup-linux-deps
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy
      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: clippy-${{ matrix.os }}
      # The root manifest is both the workspace and the `waterkit` package, so
      # without `--workspace` cargo lints only the facade and compiles every
      # member as a mere dependency. `--keep-going` makes one run report the
      # lints of every member instead of stopping at the first crate that fails.
      - run: cargo clippy --workspace --all-targets --all-features --keep-going -- -D warnings
      # A decode-only consumer takes `waterkit-codec` without its `gpu` feature
      # and must link no `wgpu`. Nothing in `--all-features` exercises that
      # shape, so check and lint it explicitly.
      - name: Check waterkit-codec without GPU output
        run: cargo check -p waterkit-codec --no-default-features --features software-encode
      - name: Clippy waterkit-codec without GPU output
        run: cargo clippy -p waterkit-codec --all-targets --no-default-features --features software-encode -- -D warnings

  cross-clippy:
    name: Clippy (${{ matrix.target }})
    runs-on: ${{ matrix.os }}
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: aarch64-apple-ios
            os: macos-latest
          - target: aarch64-linux-android
            os: ubuntu-latest
          # The `web` backends and the unsupported-platform shims sit behind
          # `cfg(target_arch = "wasm32")` or a `cfg` no other leg matches, so
          # only this leg compiles them. It lints every member but these:
          # - the crates with no browser implementation, which do not build
          #   for wasm32: `waterkit-biometric` and `waterkit-passkey` take the
          #   multi-threaded tokio runtime, `waterkit-notification` takes
          #   `uuid` without a browser random source, and `waterkit-system`
          #   rejects the target;
          # - the test harnesses, each of which drives one native platform;
          # - the facade, whose `full` default pulls in the crates above. It is
          #   linted in the next step with every feature that builds.
          - target: wasm32-unknown-unknown
            os: ubuntu-latest
            args: >-
              --locked
              --exclude waterkit
              --exclude waterkit-biometric
              --exclude waterkit-notification
              --exclude waterkit-passkey
              --exclude waterkit-system
              --exclude waterkit-test
              --exclude waterkit-test-android
              --exclude waterkit-test-ios
              --exclude waterkit-test-linux
              --exclude waterkit-test-windows
              --exclude waterkit-audio-test
              --exclude waterkit-biometric-test
              --exclude waterkit-camera-test
              --exclude waterkit-codec-bench
              --exclude waterkit-dialog-test
              --exclude waterkit-location-test
              --exclude waterkit-notification-test
              --exclude waterkit-passkey-test
              --exclude waterkit-sensor-test
              --exclude waterkit-vision-test
    steps:
      - uses: actions/checkout@v4
      # `shaderloom` compiles WGSL to DXIL on Windows and shells out to `dxc`,
      # which the runner image does not carry. WaterUI's Windows job installs it
      # the same way.
      - name: Install DirectX Shader Compiler
        if: runner.os == 'Windows'
        uses: tracel-ai/github-actions/install-dxc@295f2fdbae5271f4f8ad56d634e4ff6a95daafc8
      # Nothing in the wasm32 graph links a native library.
      - name: Install Linux dependencies
        if: runner.os == 'Linux' && matrix.target != 'wasm32-unknown-unknown'
        uses: ./.github/actions/setup-linux-deps
      - name: Setup Android NDK
        if: contains(matrix.target, 'android')
        uses: nttld/setup-ndk@v1
        id: setup-ndk
        with:
          ndk-version: r27c
          add-to-path: true
      - name: Set Android environment
        if: contains(matrix.target, 'android')
        run: |
          {
            echo "ANDROID_NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }}"
            echo "CC_aarch64-linux-android=${{ steps.setup-ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang"
            echo "CXX_aarch64-linux-android=${{ steps.setup-ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang++"
            echo "AR_aarch64-linux-android=${{ steps.setup-ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar"
            echo "CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=${{ steps.setup-ndk.outputs.ndk-path }}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang"
          } >> "$GITHUB_ENV"
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
          components: clippy
      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: cross-${{ matrix.target }}
      - run: cargo clippy --workspace ${{ matrix.args }} --target ${{ matrix.target }} --all-targets --all-features --keep-going -- -D warnings
      # Every facade feature except `biometric`, `notification`, `passkey` and
      # `system`, whose crates do not build for wasm32.
      - name: Clippy the facade on wasm32
        if: matrix.target == 'wasm32-unknown-unknown'
        run: >
          cargo clippy --locked -p waterkit --target wasm32-unknown-unknown --all-targets
          --no-default-features
          --features audio,background,bluetooth,calendar,camera,clipboard,codec,contacts,deeplink,dialog,fs,haptic,health,language,location,nfc,otp,permission,regional,screen,secret,sensor,share,speech,vaapi,video,vision,wallet
          -- -D warnings

  coverage:
    name: Coverage
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      # `shaderloom` compiles WGSL to DXIL on Windows and shells out to `dxc`,
      # which the runner image does not carry. WaterUI's Windows job installs it
      # the same way.
      - name: Install DirectX Shader Compiler
        if: runner.os == 'Windows'
        uses: tracel-ai/github-actions/install-dxc@295f2fdbae5271f4f8ad56d634e4ff6a95daafc8
      - name: Install Linux dependencies
        uses: ./.github/actions/setup-linux-deps
      - name: Start an X server for the clipboard tests
        uses: ./.github/actions/setup-x11-display
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: llvm-tools-preview
      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: ci-ubuntu
      - uses: taiki-e/install-action@cargo-llvm-cov
      - uses: taiki-e/install-action@nextest
      - run: >
          cargo llvm-cov nextest --all-features --workspace --lcov --output-path lcov.info
          --exclude waterkit-audio-test
          --exclude waterkit-biometric-test
          --exclude waterkit-camera-test
          --exclude waterkit-codec-bench
          --exclude waterkit-dialog-test
          --exclude waterkit-location-test
          --exclude waterkit-notification-test
          --exclude waterkit-sensor-test
          --exclude waterkit-vision-test
          --exclude waterkit-test-ios
          --exclude waterkit-test-android
      - uses: codecov/codecov-action@v4
        with:
          use_oidc: true
          fail_ci_if_error: false

  typos:
    name: Typos
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      - uses: crate-ci/typos@v1.49.0

  audit:
    name: Security Audit
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      - name: Generate Cargo.lock
        run: cargo generate-lockfile
      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: ci-ubuntu
      - uses: rustsec/audit-check@v2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

  unused-deps:
    name: Unused Dependencies
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: ci-ubuntu
      - uses: taiki-e/install-action@cargo-machete
      - run: cargo machete

  feature-checks:
    name: Features
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      # `shaderloom` compiles WGSL to DXIL on Windows and shells out to `dxc`,
      # which the runner image does not carry. WaterUI's Windows job installs it
      # the same way.
      - name: Install DirectX Shader Compiler
        if: runner.os == 'Windows'
        uses: tracel-ai/github-actions/install-dxc@295f2fdbae5271f4f8ad56d634e4ff6a95daafc8
      - name: Install Linux dependencies
        uses: ./.github/actions/setup-linux-deps
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
        with:
          shared-key: ci-ubuntu
      - uses: taiki-e/install-action@cargo-hack
      - run: cargo hack check --each-feature --no-dev-deps
      - run: cargo hack check --feature-powerset --no-dev-deps --depth 2
      # The root package only re-exports `waterkit-codec` with its defaults, so
      # walk that crate's own features too.
      - run: cargo hack check -p waterkit-codec --feature-powerset --no-dev-deps

  test:
    name: Test
    uses: ./.github/workflows/test.yml