# Release: build the native Rust engine on each supported host, then publish ONE
# npm package `slopgate` bundling every platform's prebuilt binary under vendor/.
# bin/slopgate picks the binary matching the host at install/run time.
#
# Trigger: push a semver tag, e.g. `git tag v1.0.0 && git push origin v1.0.0`.
# Requires repository secret NPM_TOKEN (an npm automation token with publish rights
# to `slopgate`).
name: release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: read

# Force bash on every runner (Windows defaults to PowerShell, where `$VAR` env
# refs in run: steps don't expand — the staging step needs bash).
defaults:
  run:
    shell: bash

jobs:
  # One leg per host: build its target natively (no cross-compilation), stage the
  # binary into vendor/<key>/, and upload that as an artifact for the publish job.
  build:
    strategy:
      fail-fast: true
      matrix:
        include:
          - { key: linux-x64,    target: x86_64-unknown-linux-gnu,  runner: ubuntu-latest }
          - { key: linux-arm64,  target: aarch64-unknown-linux-gnu, runner: ubuntu-24.04-arm }
          # x86_64 mac built on Apple-Silicon runner via cross-compile (Intel macos-13
          # runners are being retired and queue indefinitely). Apple's toolchain
          # cross-compiles x86_64-apple-darwin from arm natively — `--target` drives it.
          - { key: darwin-x64,   target: x86_64-apple-darwin,       runner: macos-14 }
          - { key: darwin-arm64, target: aarch64-apple-darwin,      runner: macos-14 }
          - { key: win32-x64,    target: x86_64-pc-windows-msvc,    runner: windows-latest }
    runs-on: ${{ matrix.runner }}
    steps:
      - uses: actions/checkout@v6

      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Build engine
        run: cargo build --release --locked --target ${{ matrix.target }} -p slopgate-rs

      - uses: actions/setup-node@v6
        with:
          node-version: 20

      - name: Stage binary into vendor/
        run: node scripts/build-npm-packages.mjs --stage "${{ matrix.key }}"

      - name: Smoke staged native binary
        run: node scripts/build-npm-packages.mjs --smoke "${{ matrix.key }}"

      - uses: actions/upload-artifact@v7
        with:
          name: vendor-${{ matrix.key }}
          path: vendor
          if-no-files-found: error

  # After all binaries exist, collect them into vendor/ and publish one package.
  publish:
    needs: build
    runs-on: ubuntu-latest
    # id-token: write is required by `npm publish --provenance` (OIDC attestation).
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v6

      - uses: actions/setup-node@v6
        with:
          node-version: 20
          registry-url: https://registry.npmjs.org

      - name: Collect platform binaries
        uses: actions/download-artifact@v8
        with:
          pattern: vendor-*
          merge-multiple: true
          path: vendor

      # upload/download-artifact@v4 does NOT preserve the executable bit, so the
      # staged 0755 binaries arrive here as 0644 and npm packs them non-executable
      # (launcher then dies with EACCES). Restore +x before packing. The Windows
      # .exe needs no bit; only the unix `slopgate-rs` files do.
      - name: Restore executable bit on engine binaries
        run: find vendor -type f -name slopgate-rs -exec chmod 0755 {} +

      - name: Set version from tag
        env:
          REF: ${{ github.ref_name }}
        run: node scripts/build-npm-packages.mjs --set-version "${REF#v}"

      - name: Publish slopgate
        run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
