name: Release
on:
push:
tags: ['v*.*.*']
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
targets: wasm32-unknown-unknown
- 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
- run: cargo clippy --all-targets -- -D warnings
- run: cargo clippy --target wasm32-unknown-unknown -- -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
# Ask cargo rather than guessing from `cargo search`: the index can
# lag a publish by minutes, so a search-based guard reports "not
# published" for something that is, and the re-run then fails.
if out=$(cargo publish 2>&1); then
printf '%s\n' "$out"
elif printf '%s' "$out" | grep -q 'already exists'; then
echo "crates.io already has this version; skipping"
else
printf '%s\n' "$out"
exit 1
fi
npm:
name: Publish to npm
needs: verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
- uses: jetli/wasm-pack-action@v0.4.0
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
- name: Build and publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
if [ -z "$NODE_AUTH_TOKEN" ]; then
echo "::warning::NPM_TOKEN not set; skipping npm publish"
exit 0
fi
ver="$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2)"
if npm view "c2pa-html@${ver}" version >/dev/null 2>&1; then
echo "npm already has c2pa-html@${ver}; skipping"
exit 0
fi
wasm-pack build --target bundler --out-dir pkg
# The leading ./ stops npm resolving "pkg" as a registry package spec.
npm publish ./pkg --access public
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 }
- { 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 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