magic-wormhole 0.8.1

Get things from one computer to another, safely
Documentation
name: Rust

on:
  push:
    branches: [main, "v*"]
    tags: ["[0-9]+.[0-9]+.[0-9]+"]
  pull_request:
    branches: [main, "v*"]

jobs:
  read_msrv:
    name: Read MSRV
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install Rust (stable)
        uses: actions-rust-lang/setup-rust-toolchain@v1
      - name: Read MSRV from workspace manifest
        id: read_msrv
        run: |
          cargo metadata --no-deps --format-version=1 \
          | jq -r 'first(.packages[]).rust_version' \
          | sed -E 's/^1\.([0-9]{2})$/1\.\1\.0/' \
          | xargs -0 printf "msrv=%s" \
          | tee /dev/stderr \
          >> "$GITHUB_OUTPUT"
    outputs:
      msrv: ${{ steps.read_msrv.outputs.msrv }}

  formatting:
    name: Cargo Format
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # Ensure rustfmt is installed and setup problem matcher
      - uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          components: rustfmt
          toolchain: nightly
      - name: Rustfmt Check
        uses: actions-rust-lang/rustfmt@v1

  clippy:
    name: Clippy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Cache ~/.cargo
        uses: actions/cache@v4
        with:
          path: ~/.cargo
          key: ${{ runner.os }}-clippy-dotcargo
      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-clippy-cargo-build-target
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: stable
          components: clippy
      - name: cargo clippy
        run: cargo clippy --all-features

  test:
    name: "Test (${{ matrix.os }} ${{ matrix.channel }})"
    needs:
      - read_msrv
    runs-on: ${{ matrix.image }}
    strategy:
      fail-fast: false
      matrix:
        channel:
          - MSRV
          - stable
        os:
          - Linux
          - Windows
          - macOS
          - WASM
        include:
          - os: Linux
            image: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            features: all,native-tls,experimental
          - os: Windows
            image: windows-latest
            target: x86_64-pc-windows-msvc
            features: all,native-tls,experimental
          - os: macOS
            image: macos-latest
            target: aarch64-apple-darwin
            features: all,native-tls,experimental
          - os: WASM
            image: ubuntu-latest
            target: wasm32-unknown-unknown
            features: transit,transfer
          - channel: msrv
            rust: ${{ needs.read_msrv.outputs.msrv }}
          - channel: stable
            rust: stable
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ matrix.rust }}
          target: wasm32-unknown-unknown
      - name: Cache ~/.cargo
        uses: actions/cache@v4
        with:
          path: ~/.cargo
          key: ${{ runner.os }}-test-dotcargo-${{ matrix.rust }}
      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-test-build-target-${{ matrix.rust }}
      - name: build library (no default features)
        run: cargo build -p magic-wormhole --target ${{ matrix.target }} --no-default-features
      - name: build library (features=transit)
        run: cargo build -p magic-wormhole --target ${{ matrix.target }} --no-default-features --features=transit
      - name: build library (features=transfer)
        run: cargo build -p magic-wormhole --target ${{ matrix.target }} --no-default-features --features=transfer
      - name: build library (features=forwarding)
        if: ${{ matrix.os != 'WASM' }}
        run: cargo build -p magic-wormhole --target ${{ matrix.target }} --no-default-features --features=forwarding
      - name: build CLI
        if: ${{ matrix.os != 'WASM' }}
        run: cargo build -p magic-wormhole-cli --target ${{ matrix.target }} --features=all
      - name: build WASM
        if: ${{ matrix.os == 'WASM' }}
        run: cargo build -p magic-wormhole --target wasm32-unknown-unknown --no-default-features --features ${{ matrix.features }}
      - name: test
        uses: nick-fields/retry@v3
        with:
          max_attempts: 3
          polling_interval_seconds: 30
          timeout_minutes: 30
          retry_on_exit_code: 101
          command: cargo test --verbose --workspace --features ${{ matrix.features }}

  dist:
    name: "Dist (${{ matrix.os }})"
    runs-on: ${{ matrix.image }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - Linux
          - Windows
          - macOS
        include:
          - os: Linux
            image: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            ext: ""
          - os: Windows
            image: windows-latest
            target: x86_64-pc-windows-gnu
            ext: ".exe"
          - os: macOS
            image: macos-latest
            target: aarch64-apple-darwin
            ext: ""
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: stable
          target: ${{ matrix.target }}
      - name: Cache ~/.cargo
        uses: actions/cache@v4
        with:
          path: ~/.cargo
          key: ${{ runner.os }}-test-dotcargo-stable
      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-test-build-target-stable
      - name: Build
        run: cargo build -p magic-wormhole-cli --target ${{ matrix.target }} --bins --locked --release
      - name: Tar binaries
        run: |
          pushd "target/${{ matrix.target }}/release/"
          tar -cvzf "magic-wormhole-cli-${{ matrix.target }}.tgz" "wormhole-rs${{ matrix.ext }}"
          popd
      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: magic-wormhole-cli-${{ matrix.target }}
          path: target/${{ matrix.target }}/release/magic-wormhole-cli-${{ matrix.target }}.tgz
          if-no-files-found: error

  coverage:
    name: Coverage
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: nightly
      - uses: taiki-e/cache-cargo-install-action@v2
        with:
          tool: cargo-tarpaulin
      - name: Cache ~/.cargo
        uses: actions/cache@v4
        with:
          path: ~/.cargo
          key: ${{ runner.os }}-coverage-dotcargo
      - name: Cache cargo build
        uses: actions/cache@v4
        with:
          path: target
          key: ${{ runner.os }}-coverage-cargo-build-target
      - name: Run tarpaulin
        run: cargo tarpaulin --workspace --out Xml
      - name: upload coverage
        uses: codecov/codecov-action@v4
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

  cargo-deny:
    name: Cargo deny
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: nightly
      - name: Checkout Rust toolcnain
        uses: actions/checkout@v4
      - uses: EmbarkStudios/cargo-deny-action@v2
        with:
          rust-version: ${{ needs.read_msrv.outputs.msrv }}

  semver:
    name: SemVer
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: nightly
      - name: Check semver
        uses: obi1kenobi/cargo-semver-checks-action@v2
        with:
          feature-group: default-features
          features: "all"
      - name: Extract Changelog
        uses: release-flow/keep-a-changelog-action@v3
        with:
          command: query
          version: unreleased

  release:
    name: Release
    runs-on: ubuntu-latest
    needs:
      - dist
    steps:
      - uses: actions/checkout@v4
      - name: Get Cargo Version
        id: query-version
        run: |
          cargo metadata --no-deps --format-version=1 \
          | jq -r 'first(.packages[]).version' \
          | xargs -0 printf "version=%s" \
          >> "$GITHUB_OUTPUT"
      - name: Check Tag
        id: check-tag
        run: |
          if git show-ref --tags --verify --quiet "refs/tags/${{ steps.query-version.outputs.version }}"; then
            echo "tag=1" >> "$GITHUB_OUTPUT"
          else
            echo "tag=0" >> "$GITHUB_OUTPUT"
          fi
      - name: Extract changelog for ${{ steps.query-version.outputs.version }}
        id: query-changelog
        continue-on-error: true
        uses: release-flow/keep-a-changelog-action@v3
        with:
          command: query
          version: ${{ steps.query-version.outputs.version }}
      - name: "Fallback: Extract changelog for unreleased"
        if: ${{ steps.query-changelog.outcome != 'success' }}
        id: query-changelog-unreleased
        uses: release-flow/keep-a-changelog-action@v3
        with:
          command: query
          version: unreleased
      - uses: actions/download-artifact@v4
        with:
          path: "./dist"
          pattern: "magic-wormhole-cli-*"
      - name: Update Release
        uses: softprops/action-gh-release@v2
        if: ${{ startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/main') }}
        with:
          name: "Version ${{ steps.query-version.outputs.version }}"
          body: ${{ steps.query-changelog.outputs.release-notes || steps.query-changelog-unreleased.outputs.release-notes }}
          files: "./dist/**/magic-wormhole-cli-*"
          fail_on_unmatched_files: true
          prerelease: ${{ contains(steps.query-version.outputs.version, '-') }}
          draft: ${{ (steps.check-tag.outputs.tag == 0 && !startsWith(github.ref, 'refs/tags/')) || steps.query-changelog.outcome != 'success' }}
          make_latest: ${{ !contains(steps.query-version.outputs.version, '-') && startsWith(github.ref, 'refs/tags/') }}