docker-wrapper 0.11.1

A Docker CLI wrapper for Rust
Documentation
name: CI

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

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  test:
    name: Test Suite
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        rust: [stable, beta]
        exclude:
          # Reduce CI load by excluding some combinations
          - os: macos-latest
            rust: beta
          - os: windows-latest
            rust: beta

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install Rust
        uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9
        with:
          toolchain: ${{ matrix.rust }}
          components: rustfmt, clippy

      - name: Cache Rust dependencies
        uses: swatinem/rust-cache@v2
        with:
          shared-key: "ci-${{ matrix.os }}-${{ matrix.rust }}"
          cache-all-crates: true

      - name: Check formatting
        if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest'
        run: cargo fmt -- --check

      - name: Check for executor.execute_command antipattern
        if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest'
        run: |
          # Commands should use self.execute_command(args) not self.executor.execute_command("docker", args)
          # The latter causes "docker docker <cmd>" double-command bug (issue #233)
          if grep -rE 'executor\.execute_command\("docker"|execute_command\("docker",' src/command.rs src/command/; then
            echo "ERROR: Found execute_command(\"docker\", ...) antipattern!"
            echo "Use self.execute_command(args) instead to avoid 'docker docker' bug."
            echo "For compose commands, pass 'compose' as command name, not 'docker'."
            exit 1
          fi

      - name: Run Clippy
        if: matrix.rust == 'stable'
        run: cargo clippy --all-targets --all-features -- -D warnings

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

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

      - name: Check individual template features compile
        shell: bash
        run: |
          for feature in template-redis template-redis-cluster template-redis-enterprise template-postgres template-mysql template-mongodb template-nginx; do
            echo "Checking feature: $feature"
            cargo check --features "$feature"
          done

      - name: Run tests
        run: cargo test --lib --all-features && cargo test --doc --all-features

  docker-tests:
    name: Docker Integration Tests
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

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

      - name: Cache Rust dependencies
        uses: swatinem/rust-cache@v2
        with:
          shared-key: "ci-docker"
          cache-all-crates: true

      - name: Start Docker
        run: |
          sudo systemctl start docker
          docker --version

      - name: Pull test images in parallel
        run: |
          docker pull alpine:latest &
          docker pull redis:7.2-alpine &
          docker pull redis:7-alpine &
          docker pull redis:6-alpine &
          docker pull redis/redis-stack:latest &
          docker pull nginx:alpine &
          docker pull postgres:15-alpine &
          docker pull mysql:8 &
          docker pull mongo:latest &
          wait

      - name: Run integration tests
        run: cargo test --test '*' --all-features
        env:
          DOCKER_HOST: unix:///var/run/docker.sock

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

  security:
    name: Security Audit
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

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

      - name: Cache Rust dependencies
        uses: swatinem/rust-cache@v2
        with:
          shared-key: "ci-security"
          cache-all-crates: true

      - name: Cache cargo-audit
        id: cache-cargo-audit
        uses: actions/cache@v5
        with:
          path: ~/.cargo/bin/cargo-audit
          key: cargo-audit-${{ runner.os }}

      - name: Install cargo-audit if not cached
        if: steps.cache-cargo-audit.outputs.cache-hit != 'true'
        run: cargo install cargo-audit --locked

      - name: Run security audit
        run: cargo audit

  # TODO: Re-enable and fix coverage job - currently has flaky integration tests
  # coverage:
  #   name: Code Coverage
  #   runs-on: ubuntu-latest
  #
  #   steps:
  #     - name: Checkout code
  #       uses: actions/checkout@v6
  #
  #     - name: Install Rust
  #       uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9
  #       with:
  #         toolchain: stable
  #
  #     - name: Cache Rust dependencies
  #       uses: swatinem/rust-cache@v2
  #       with:
  #         shared-key: "ci-coverage"
  #         cache-all-crates: true
  #
  #     - name: Cache cargo-tarpaulin
  #       id: cache-cargo-tarpaulin
  #       uses: actions/cache@v5
  #       with:
  #         path: ~/.cargo/bin/cargo-tarpaulin
  #         key: cargo-tarpaulin-${{ runner.os }}
  #
  #     - name: Install cargo-tarpaulin if not cached
  #       if: steps.cache-cargo-tarpaulin.outputs.cache-hit != 'true'
  #       run: cargo install cargo-tarpaulin --locked
  #
  #     - name: Start Docker
  #       run: |
  #         sudo systemctl start docker
  #         docker --version
  #
  #     - name: Pull test images for coverage
  #       run: |
  #         docker pull alpine:latest &
  #         docker pull redis:7.2-alpine &
  #         docker pull redis:7-alpine &
  #         docker pull redis/redis-stack:latest &
  #         docker pull nginx:alpine &
  #         docker pull postgres:15-alpine &
  #         wait
  #
  #     - name: Create redis-dev config directory
  #       run: mkdir -p ~/.config/redis-dev
  #
  #     - name: Generate code coverage
  #       run: cargo tarpaulin --all-features --workspace --timeout 120 --out xml --skip-clean
  #
  #     - name: Upload coverage to Codecov
  #       uses: codecov/codecov-action@v5
  #       with:
  #         file: cobertura.xml
  #         fail_ci_if_error: false

  msrv:
    name: Minimum Supported Rust Version
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install Rust 1.89.0
        uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9
        with:
          toolchain: 1.89.0

      - name: Cache Rust dependencies
        uses: swatinem/rust-cache@v2
        with:
          shared-key: "ci-msrv"
          cache-all-crates: true

      - name: Build with MSRV
        run: cargo build --all-features

      - name: Test with MSRV
        run: cargo test --lib --all-features

  docs:
    name: Documentation
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

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

      - name: Cache Rust dependencies
        uses: swatinem/rust-cache@v2
        with:
          shared-key: "ci-docs"
          cache-all-crates: true

      - name: Build documentation
        run: cargo doc --all-features --no-deps
        env:
          RUSTDOCFLAGS: -D warnings

  dependency-check:
    name: Dependency Management
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

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

      - name: Cache Rust dependencies and tools
        uses: swatinem/rust-cache@v2
        with:
          shared-key: "ci-deps"
          cache-all-crates: true
          cache-directories: |
            ~/.cargo/bin/

      - name: Cache cargo-machete
        id: cache-cargo-machete
        uses: actions/cache@v5
        with:
          path: ~/.cargo/bin/cargo-machete
          key: cargo-machete-${{ runner.os }}

      - name: Install cargo-machete if not cached
        if: steps.cache-cargo-machete.outputs.cache-hit != 'true'
        run: cargo install cargo-machete --locked

      - name: Check for unused dependencies
        run: cargo machete
        continue-on-error: true

      - name: Cache cargo-outdated
        id: cache-cargo-outdated
        uses: actions/cache@v5
        with:
          path: ~/.cargo/bin/cargo-outdated
          key: cargo-outdated-${{ runner.os }}

      - name: Install cargo-outdated if not cached
        if: steps.cache-cargo-outdated.outputs.cache-hit != 'true'
        run: cargo install cargo-outdated --locked

      - name: Check for outdated dependencies
        run: cargo outdated --exit-code 1 || true
        continue-on-error: true