name: Release on: push: tags: ["v*"] workflow_dispatch: env: CARGO_TERM_COLOR: always jobs: # -------------------------------------------------------------------------- # crates.io: three crates in dependency order # -------------------------------------------------------------------------- cargo-publish: name: Publish to crates.io runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 # Idempotent publishing: if the version is already on crates.io we # treat that as success so re-runs of the workflow don't fail. - name: Publish wickra-core (idempotent) run: | out=$(cargo publish -p wickra-core --token "$CARGO_REGISTRY_TOKEN" 2>&1) && echo "$out" \ || (echo "$out" | grep -q "already uploaded\|already exists" && echo "skip: already published" \ || (echo "$out"; exit 1)) env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - name: Wait for crates.io index to refresh run: sleep 45 - name: Publish wickra-data (idempotent) run: | out=$(cargo publish -p wickra-data --token "$CARGO_REGISTRY_TOKEN" 2>&1) && echo "$out" \ || (echo "$out" | grep -q "already uploaded\|already exists" && echo "skip: already published" \ || (echo "$out"; exit 1)) env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - name: Wait for crates.io index to refresh run: sleep 45 - name: Publish wickra (idempotent) run: | out=$(cargo publish -p wickra --token "$CARGO_REGISTRY_TOKEN" 2>&1) && echo "$out" \ || (echo "$out" | grep -q "already uploaded\|already exists" && echo "skip: already published" \ || (echo "$out"; exit 1)) env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} # -------------------------------------------------------------------------- # PyPI: cross-platform wheels + sdist # -------------------------------------------------------------------------- python-wheels: name: Build wheels (${{ matrix.target }} on ${{ matrix.os }}) strategy: fail-fast: false matrix: include: - { os: ubuntu-latest, target: x86_64, manylinux: auto } - { os: ubuntu-latest, target: aarch64, manylinux: auto } - { os: macos-latest, target: x86_64, manylinux: auto } - { os: macos-latest, target: aarch64, manylinux: auto } - { os: windows-latest, target: x64, manylinux: auto } runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.11" - uses: PyO3/maturin-action@v1 with: working-directory: bindings/python target: ${{ matrix.target }} args: --release --strip --out dist manylinux: ${{ matrix.manylinux }} - uses: actions/upload-artifact@v4 with: name: wheels-${{ matrix.os }}-${{ matrix.target }} path: bindings/python/dist/* python-sdist: name: Build Python sdist runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: PyO3/maturin-action@v1 with: working-directory: bindings/python command: sdist args: --out dist - uses: actions/upload-artifact@v4 with: name: wheels-sdist path: bindings/python/dist/* python-publish: name: Publish to PyPI needs: [python-wheels, python-sdist] runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v4 with: path: dist pattern: wheels-* merge-multiple: true - name: Upload to PyPI uses: PyO3/maturin-action@v1 with: command: upload args: --skip-existing dist/* env: MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }} # -------------------------------------------------------------------------- # npm: per-platform native binaries + main meta-package # -------------------------------------------------------------------------- node-build: name: Node build (${{ matrix.target }}) strategy: fail-fast: false matrix: include: - { host: ubuntu-latest, target: x86_64-unknown-linux-gnu } - { host: macos-latest, target: x86_64-apple-darwin } - { host: macos-latest, target: aarch64-apple-darwin } - { host: windows-latest, target: x86_64-pc-windows-msvc } runs-on: ${{ matrix.host }} steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" - uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} - uses: Swatinem/rust-cache@v2 - name: Install Node deps working-directory: bindings/node run: npm install - name: Build native module working-directory: bindings/node run: npx napi build --platform --release --target ${{ matrix.target }} - name: Upload artifact uses: actions/upload-artifact@v4 with: name: bindings-${{ matrix.target }} path: bindings/node/wickra.*.node if-no-files-found: error node-publish: name: Publish to npm needs: node-build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" registry-url: "https://registry.npmjs.org" - name: Install Node deps working-directory: bindings/node run: npm install - name: Download all platform binaries uses: actions/download-artifact@v4 with: path: bindings/node/artifacts pattern: bindings-* - name: Create npm// scaffolding (one per target) working-directory: bindings/node run: | for t in x86_64-unknown-linux-gnu x86_64-apple-darwin aarch64-apple-darwin x86_64-pc-windows-msvc; do npx napi create-npm-dir -t "$t" . done - name: Move binaries into platform package layout working-directory: bindings/node run: npx napi artifacts --dir artifacts - name: Prepublish platform packages to npm working-directory: bindings/node run: npx napi prepublish -t npm --skip-gh-release env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Publish main package to npm working-directory: bindings/node run: npm publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # -------------------------------------------------------------------------- # WASM: wasm-pack build + npm publish (as `wickra-wasm`) # -------------------------------------------------------------------------- wasm-publish: name: Publish wickra-wasm to npm runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" registry-url: "https://registry.npmjs.org" - uses: dtolnay/rust-toolchain@stable with: targets: wasm32-unknown-unknown - uses: jetli/wasm-pack-action@v0.4.0 - name: Build WASM package (bundler target) run: wasm-pack build bindings/wasm --target bundler --release --features panic-hook - name: Enrich generated package.json with author + repo metadata working-directory: bindings/wasm/pkg run: | node -e " const fs = require('fs'); const pkg = JSON.parse(fs.readFileSync('package.json')); pkg.author = 'kingchenc '; pkg.repository = { type: 'git', url: 'https://github.com/kingchenc/wickra' }; pkg.homepage = 'https://github.com/kingchenc/wickra'; pkg.bugs = { url: 'https://github.com/kingchenc/wickra/issues' }; pkg.license = 'SEE LICENSE IN LICENSE'; fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2)); " - name: Publish wickra-wasm to npm (idempotent) working-directory: bindings/wasm/pkg run: | out=$(npm publish --access public 2>&1) && echo "$out" \ || (echo "$out" | grep -q "You cannot publish over" && echo "skip: version already on npm" \ || (echo "$out"; exit 1)) env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}