mikanani-cli 0.4.0

An interactive CLI to download anime torrents from Mikan Project (蜜柑计划) RSS feeds.
name: Release

# Build release binaries when a version tag is pushed, then publish a
# single GitHub Release for that tag with all archives attached.
on:
  push:
    tags: ['v*']

# Least privilege: the build matrix only needs read; the publish job
# elevates to contents:write to create the release.
permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always

jobs:
  build:
    name: ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          # Every target builds on a native runner: aws-lc-sys / ring (the
          # rustls crypto backends) compile C + assembly, which is painful to
          # cross-compile but trivial natively.
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
          - target: aarch64-unknown-linux-gnu
            os: ubuntu-24.04-arm
          - target: aarch64-apple-darwin
            os: macos-15
          - target: x86_64-pc-windows-msvc
            os: windows-latest
    steps:
      - uses: actions/checkout@v7

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

      # aws-lc-sys and ring need NASM to assemble their x86_64 code on MSVC.
      - name: Install NASM (Windows)
        if: runner.os == 'Windows'
        uses: ilammy/setup-nasm@v1

      - name: Cache cargo build
        uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}

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

      - name: Package (unix)
        if: runner.os != 'Windows'
        shell: bash
        env:
          TARGET: ${{ matrix.target }}
        run: |
          bin="target/$TARGET/release/mikan"
          strip "$bin" || true
          staging="mikan-${GITHUB_REF_NAME}-${TARGET}"
          mkdir "$staging"
          cp "$bin" README.md LICENSE "$staging/"
          tar czf "$staging.tar.gz" "$staging"
          echo "ASSET=$staging.tar.gz" >> "$GITHUB_ENV"

      - name: Package (windows)
        if: runner.os == 'Windows'
        shell: pwsh
        env:
          TARGET: ${{ matrix.target }}
        run: |
          $bin = "target/$env:TARGET/release/mikan.exe"
          $staging = "mikan-$env:GITHUB_REF_NAME-$env:TARGET"
          New-Item -ItemType Directory -Path $staging | Out-Null
          Copy-Item $bin, README.md, LICENSE $staging
          Compress-Archive -Path $staging -DestinationPath "$staging.zip"
          "ASSET=$staging.zip" >> $env:GITHUB_ENV

      - name: Upload build artifact
        uses: actions/upload-artifact@v7
        with:
          name: ${{ matrix.target }}
          path: ${{ env.ASSET }}
          retention-days: 1

  release:
    name: Publish release
    needs: build
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - name: Download all build artifacts
        uses: actions/download-artifact@v8
        with:
          path: dist

      # Runs exactly once, so the release notes (Full Changelog) are
      # generated a single time rather than once per build job.
      - name: Publish GitHub Release
        uses: softprops/action-gh-release@v3
        with:
          files: dist/**/*
          generate_release_notes: true

  # Publish the crate to crates.io. Gated behind `build` so a version that
  # fails to compile on any target never reaches the registry — a publish is
  # irreversible (you can yank, but not delete or re-upload a version).
  publish-crate:
    name: Publish to crates.io
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7

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

      - name: Cache cargo build
        uses: Swatinem/rust-cache@v2

      # The tag names the release, but `cargo publish` uploads whatever
      # version Cargo.toml declares. Fail loudly if they drift apart.
      - name: Verify tag matches Cargo.toml version
        shell: bash
        run: |
          manifest="$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version')"
          tag="${GITHUB_REF_NAME#v}"
          if [ "$manifest" != "$tag" ]; then
            echo "::error::Tag v$tag does not match Cargo.toml version $manifest"
            exit 1
          fi

      - name: Publish
        run: cargo publish --locked
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}