plasmite 0.6.1

Persistent JSON message queues backed by plain files for local and remote IPC
Documentation
name: release

on:
  push:
    tags: ["v*"]
  workflow_dispatch:
    inputs:
      tag:
        description: "Tag to build artifacts for (format: vX.Y.Z)."
        required: true
        type: string

permissions:
  contents: read

env:
  RELEASE_RUST_TOOLCHAIN: "1.88.0"

jobs:
  release-context:
    runs-on: ubuntu-latest
    outputs:
      tag: ${{ steps.ctx.outputs.tag }}
      version: ${{ steps.ctx.outputs.version }}
    steps:
      - id: ctx
        shell: bash
        run: |
          set -euo pipefail

          if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
            tag="${{ inputs.tag }}"
          else
            tag="${GITHUB_REF_NAME}"
          fi

          if [[ -z "$tag" || "$tag" != v* ]]; then
            echo "error: release tag must use vX.Y.Z format, got '$tag'." >&2
            exit 1
          fi

          if ! git ls-remote --exit-code --tags "https://github.com/${GITHUB_REPOSITORY}.git" "refs/tags/${tag}" >/dev/null; then
            echo "error: requested tag '${tag}' does not exist on origin." >&2
            echo "hint: create/push the tag first, then rerun release build." >&2
            exit 1
          fi

          version="${tag#v}"
          echo "tag=$tag" >> "$GITHUB_OUTPUT"
          echo "version=$version" >> "$GITHUB_OUTPUT"

          mkdir -p .scratch/release-metadata
          cat > .scratch/release-metadata/metadata.json <<META
          {
            "tag": "${tag}",
            "version": "${version}",
            "source_sha": "${GITHUB_SHA}",
            "source_ref": "${GITHUB_REF}",
            "source_run_id": "${GITHUB_RUN_ID}",
            "source_workflow": "${GITHUB_WORKFLOW}"
          }
          META
      - uses: actions/upload-artifact@v4
        with:
          name: release-metadata
          path: .scratch/release-metadata/metadata.json
          if-no-files-found: error

  build-native:
    needs: [release-context]
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            platform: linux_amd64
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-gnu
            platform: linux_arm64
          - os: macos-15-intel
            target: x86_64-apple-darwin
            platform: darwin_amd64
          - os: macos-latest
            target: aarch64-apple-darwin
            platform: darwin_arm64

    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ needs.release-context.outputs.tag }}
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RELEASE_RUST_TOOLCHAIN }}
          targets: ${{ matrix.target }}
      - name: Install smoke-test tooling
        shell: bash
        run: |
          if [[ "${{ matrix.os }}" == ubuntu-* ]]; then
            sudo apt-get update
            sudo apt-get install -y pkg-config
          else
            brew install pkg-config
          fi
      - name: Build binaries
        run: cargo build --release --target ${{ matrix.target }} --bins
      - name: Build shared library with stable identity
        shell: bash
        run: |
          if [[ "${{ matrix.target }}" == *apple-darwin ]]; then
            cargo rustc --release --target ${{ matrix.target }} --lib --crate-type=cdylib -- -C link-arg=-Wl,-install_name,@rpath/libplasmite.dylib
          else
            cargo rustc --release --target ${{ matrix.target }} --lib --crate-type=cdylib -- -C link-arg=-Wl,-soname,libplasmite.so
          fi
      - name: Build static library (optional artifact)
        run: cargo rustc --release --target ${{ matrix.target }} --lib --crate-type=staticlib
      - name: Package SDK
        shell: bash
        run: ./scripts/package_release_sdk.sh "${{ matrix.target }}" "${{ matrix.platform }}" "${{ needs.release-context.outputs.version }}"
      - name: Smoke test packaged SDK
        shell: bash
        run: ./scripts/cross_artifact_smoke.sh "dist/plasmite_${{ needs.release-context.outputs.version }}_${{ matrix.platform }}.tar.gz"
      - uses: actions/upload-artifact@v4
        with:
          name: dist-${{ matrix.target }}
          path: dist/*.tar.gz
          if-no-files-found: error

  build-python-dist:
    needs: [release-context]
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            platform: linux_amd64
            upload_sdist: true
            upload_wheel: false
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-gnu
            platform: linux_arm64
            upload_sdist: false
            upload_wheel: false
          - os: macos-15-intel
            target: x86_64-apple-darwin
            platform: darwin_amd64
            upload_sdist: false
            upload_wheel: true
          - os: macos-latest
            target: aarch64-apple-darwin
            platform: darwin_arm64
            upload_sdist: false
            upload_wheel: true
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            platform: windows_amd64
            upload_sdist: false
            upload_wheel: true
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ needs.release-context.outputs.tag }}
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RELEASE_RUST_TOOLCHAIN }}
          targets: ${{ matrix.target }}
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - uses: astral-sh/setup-uv@v5
      - name: Build SDK artifacts for wheel bundling
        shell: bash
        run: |
          cargo build --release --target "${{ matrix.target }}" --bins
          if [[ "${{ matrix.target }}" == *windows-msvc ]]; then
            cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib
          elif [[ "${{ matrix.target }}" == *apple-darwin ]]; then
            cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib -- -C link-arg=-Wl,-install_name,@rpath/libplasmite.dylib
          else
            cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib -- -C link-arg=-Wl,-soname,libplasmite.so
          fi
      - name: Build and smoke-test python wheel
        shell: bash
        env:
          PLASMITE_SDK_DIR: ${{ github.workspace }}/target/${{ matrix.target }}/release
        run: ./scripts/python_wheel_smoke.sh
      - uses: actions/upload-artifact@v4
        if: matrix.upload_wheel
        with:
          name: py-dist-${{ matrix.platform }}
          path: bindings/python/dist/*.whl
          if-no-files-found: error
      - uses: actions/upload-artifact@v4
        if: matrix.upload_sdist
        with:
          name: py-sdist
          path: bindings/python/dist/*.tar.gz
          if-no-files-found: error

  build-node-native:
    needs: [release-context]
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            platform: linux-x64
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-gnu
            platform: linux-arm64
          - os: macos-15-intel
            target: x86_64-apple-darwin
            platform: darwin-x64
          - os: macos-latest
            target: aarch64-apple-darwin
            platform: darwin-arm64
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            platform: win32-x64
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ needs.release-context.outputs.tag }}
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RELEASE_RUST_TOOLCHAIN }}
          targets: ${{ matrix.target }}
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
      - run: cd bindings/node && npm ci
      - name: Build SDK artifacts for matrix platform
        shell: bash
        run: |
          cargo build --release --target "${{ matrix.target }}" --bins
          if [[ "${{ matrix.target }}" == *windows-msvc ]]; then
            cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib
          elif [[ "${{ matrix.target }}" == *apple-darwin ]]; then
            cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib -- -C link-arg=-Wl,-install_name,@rpath/libplasmite.dylib
          else
            cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib -- -C link-arg=-Wl,-soname,libplasmite.so
          fi
      - name: Build Node addon
        env:
          PLASMITE_LIB_DIR: ${{ github.workspace }}/target/${{ matrix.target }}/release
        run: cd bindings/node && npm run build
      - name: Stage node native payload
        shell: bash
        run: ./scripts/package_node_natives.sh "${{ matrix.platform }}" "${{ github.workspace }}/target/${{ matrix.target }}/release" "${{ github.workspace }}/bindings/node/index.node"
      - name: Windows node pack/install smoke
        if: matrix.platform == 'win32-x64'
        shell: bash
        env:
          PLASMITE_SDK_DIR: ${{ github.workspace }}/target/${{ matrix.target }}/release
        run: ./scripts/node_pack_smoke.sh
      - uses: actions/upload-artifact@v4
        with:
          name: node-native-${{ matrix.platform }}
          path: bindings/node/native/${{ matrix.platform }}/*
          if-no-files-found: error

  build-node-dist:
    needs: [release-context, build-node-native]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ needs.release-context.outputs.tag }}
      - uses: actions/setup-node@v4
        with:
          node-version: "20"
      - run: cd bindings/node && npm ci
      - uses: actions/download-artifact@v4
        with:
          name: node-native-linux-x64
          path: bindings/node/native/linux-x64
      - uses: actions/download-artifact@v4
        with:
          name: node-native-darwin-x64
          path: bindings/node/native/darwin-x64
      - uses: actions/download-artifact@v4
        with:
          name: node-native-darwin-arm64
          path: bindings/node/native/darwin-arm64
      - uses: actions/download-artifact@v4
        with:
          name: node-native-linux-arm64
          path: bindings/node/native/linux-arm64
        continue-on-error: true
      - uses: actions/download-artifact@v4
        with:
          name: node-native-win32-x64
          path: bindings/node/native/win32-x64
      - name: Restore native CLI execute bits
        run: find bindings/node/native -type f -name plasmite -exec chmod +x {} +
      - name: Report assembled platforms
        run: |
          echo "Assembled platforms:"
          ls -la bindings/node/native/
          for dir in bindings/node/native/*/; do
            echo "  $(basename "$dir"): $(ls "$dir" | wc -l) files"
          done
      - name: npm pack + install smoke (linux-x64 runtime)
        env:
          PLASMITE_SDK_DIR: ${{ github.workspace }}/target/x86_64-unknown-linux-gnu/release
        run: |
          tarball="$(cd bindings/node && npm pack --ignore-scripts --silent)"
          workdir="$(mktemp -d)"
          trap 'rm -rf "$workdir"; rm -f "bindings/node/${tarball}"' EXIT
          cd "$workdir"
          npm init -y >/dev/null
          npm install "${GITHUB_WORKSPACE}/bindings/node/${tarball}" >/dev/null
          node -e 'const { Client, Durability, RemoteClient } = require("plasmite"); const os = require("node:os"); const fs = require("node:fs"); const path = require("node:path"); const dir = fs.mkdtempSync(path.join(os.tmpdir(), "plasmite-node-release-")); const c = new Client(dir); const p = c.createPool("smoke", 1024*1024); p.appendJson(Buffer.from("{\"kind\":\"smoke\"}"), ["smoke"], Durability.Fast); p.close(); c.close(); const rc = new RemoteClient("http://127.0.0.1:9700"); if (!rc) throw new Error("missing remote");'
          npx plasmite --version >/dev/null
          mkdir -p "${GITHUB_WORKSPACE}/bindings/node/dist"
          cp "${GITHUB_WORKSPACE}/bindings/node/${tarball}" "${GITHUB_WORKSPACE}/bindings/node/dist/"
      - name: Build npm publish artifact
        run: ls -la bindings/node/dist
      - uses: actions/upload-artifact@v4
        with:
          name: node-dist
          path: bindings/node/dist/plasmite-*.tgz
          if-no-files-found: error