ytdown 0.4.0

A Rust library mirroring yt-dlp's core: extract, select, and download media. Ships with a companion CLI (ytdown-cli).
Documentation
name: release-please

on:
  push:
    branches: [main, master]
  # Manual dispatch re-publishes the current master version to PyPI
  # (e.g. when a wheel build failed during the release run).
  workflow_dispatch:

permissions:
  contents: write
  pull-requests: write

jobs:
  release-please:
    runs-on: ubuntu-latest
    outputs:
      release_created: ${{ steps.rp.outputs.release_created }}
      releases_created: ${{ steps.rp.outputs.releases_created }}
      lib_release_created: ${{ steps.rp.outputs.release_created }}
      cli_release_created: ${{ steps.rp.outputs['cli--release_created'] }}
    steps:
      - uses: googleapis/release-please-action@v5
        id: rp
        with:
          config-file: release-please-config.json
          manifest-file: .release-please-manifest.json

  publish:
    needs: release-please
    if: needs.release-please.outputs.releases_created == 'true'
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - name: Publish ytdown
        if: needs.release-please.outputs.lib_release_created == 'true'
        run: cargo publish -p ytdown
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
      - name: Publish ytdown-cli
        if: needs.release-please.outputs.cli_release_created == 'true'
        run: cargo publish -p ytdown-cli
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

  # --- Python bindings (ytdown-py) ----------------------------------------
  # The PyPI publish chains off this workflow (like the crates.io publish)
  # because tags created by release-please's GITHUB_TOKEN do not trigger
  # `on: push: tags` workflows.

  pypi-wheels:
    needs: release-please
    if: needs.release-please.outputs.release_created == 'true' || github.event_name == 'workflow_dispatch'
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      matrix:
        platform:
          - runner: ubuntu-latest
            target: x86_64
          - runner: macos-latest
            target: aarch64
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v6
      - name: Build wheel
        uses: PyO3/maturin-action@v1
        with:
          working-directory: ytdown-py
          target: ${{ matrix.platform.target }}
          args: --release --out dist
          manylinux: auto
      - uses: actions/upload-artifact@v7
        with:
          name: wheels-${{ runner.os }}-${{ matrix.platform.target }}
          path: ytdown-py/dist

  # No sdist: maturin cannot vendor the `path = ".."` dependency without file
  # collisions (both crates ship a README.md). Source installs work from git:
  #   pip install "git+https://github.com/4thel00z/ytdown#subdirectory=ytdown-py"

  publish-pypi:
    needs: [release-please, pypi-wheels]
    if: needs.release-please.outputs.release_created == 'true' || github.event_name == 'workflow_dispatch'
    runs-on: ubuntu-latest
    permissions:
      # Trusted Publishing (OIDC) — no API token needed.
      id-token: write
      # Artifact attestation.
      attestations: write
      contents: read
    steps:
      - uses: actions/download-artifact@v8
      - name: Generate artifact attestation
        uses: actions/attest-build-provenance@v4
        with:
          subject-path: wheels-*/*
      - name: Collect distributions
        run: |
          mkdir -p dist
          cp wheels-*/* dist/
      - name: Publish to PyPI (Trusted Publishing)
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          packages-dir: dist