c2pa-html 0.1.0

C2PA manifest embedding, referencing, and hard binding for HTML documents
Documentation
name: Release

# Cut a release by pushing a version tag that matches the crate version:
#   git tag v0.1.0 && git push origin v0.1.0
#
# crates.io publishing is gated on a repository secret; the job is skipped
# cleanly if it is absent, so a tag can drive a partial release:
#   CARGO_REGISTRY_TOKEN  — crates.io API token
#
# PyPI publishing uses Trusted Publishing (OIDC), not a secret. Register the
# publisher on PyPI for project `c2pa-html`, owner `writerslogic`, repository
# `c2pa-html`, workflow `release.yml`, environment `pypi`.

on:
  push:
    tags: ['v*.*.*']
  # Manual re-run for the current Cargo.toml version (e.g. to complete a partial
  # release). The version is read from Cargo.toml, not the ref, and every
  # publish job is idempotent, so this is safe to run repeatedly.
  workflow_dispatch:

permissions:
  contents: write

env:
  CARGO_TERM_COLOR: always

jobs:
  verify:
    name: Verify
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy
      - uses: actions/setup-python@v5
        with:
          python-version: '3.x'
      - name: Tag matches crate version
        if: github.ref_type == 'tag'
        run: |
          tag_version="${GITHUB_REF_NAME#v}"
          if ! grep -q "^version = \"${tag_version}\"$" Cargo.toml; then
            echo "::error::tag ${tag_version} does not match the version in Cargo.toml"
            exit 1
          fi
      - run: cargo fmt --all -- --check
      # Not --all-features: pyo3's `extension-module` leaves Python symbols to
      # be supplied by the interpreter, so a test binary linked with it fails.
      - run: cargo clippy --all-targets -- -D warnings
      - run: cargo clippy --features python -- -D warnings
      - run: cargo test

  crates-io:
    name: Publish to crates.io
    needs: verify
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: dtolnay/rust-toolchain@stable
      - name: cargo publish
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: |
          if [ -z "$CARGO_REGISTRY_TOKEN" ]; then
            echo "::warning::CARGO_REGISTRY_TOKEN not set; skipping crates.io publish"
            exit 0
          fi
          ver="$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2)"
          if cargo search c2pa-html --limit 1 | grep -q "^c2pa-html = \"${ver}\""; then
            echo "crates.io already has c2pa-html ${ver}; skipping"
            exit 0
          fi
          cargo publish

  wheels:
    name: Build wheels (${{ matrix.platform.os }} ${{ matrix.platform.target }})
    needs: verify
    runs-on: ${{ matrix.platform.os }}
    strategy:
      fail-fast: false
      matrix:
        platform:
          - { os: ubuntu-latest, target: x86_64 }
          - { os: ubuntu-latest, target: aarch64 }
          - { os: macos-latest, target: aarch64 }
          # Cross-compile the Intel-mac wheel on the fast arm64 runner; the
          # macos-13 (Intel) runner is scarce and times out.
          - { os: macos-latest, target: x86_64 }
          - { os: windows-latest, target: x64 }
    steps:
      - uses: actions/checkout@v7
      - uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist --features python
          manylinux: auto
      - uses: actions/upload-artifact@v4
        with:
          name: wheels-${{ matrix.platform.os }}-${{ matrix.platform.target }}
          path: dist

  sdist:
    name: Build sdist
    needs: verify
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: PyO3/maturin-action@v1
        with:
          command: sdist
          args: --out dist
      - uses: actions/upload-artifact@v4
        with:
          name: wheels-sdist
          path: dist

  pypi:
    name: Publish to PyPI
    needs: [wheels, sdist]
    runs-on: ubuntu-latest
    environment: pypi
    permissions:
      id-token: write # Trusted Publishing (OIDC); no PyPI token needed
    steps:
      - uses: actions/download-artifact@v4
        with:
          pattern: wheels-*
          merge-multiple: true
          path: dist
      - uses: pypa/gh-action-pypi-publish@release/v1
        with:
          packages-dir: dist
          skip-existing: true

  github-release:
    name: GitHub release
    needs: verify
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
        with:
          fetch-depth: 0
      - name: Create release
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          ver="$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2)"
          tag="v${ver}"
          if gh release view "$tag" >/dev/null 2>&1; then
            echo "release $tag already exists; skipping"
            exit 0
          fi
          gh release create "$tag" --title "$tag" --generate-notes