name: npm release

on:
  workflow_dispatch:
    inputs:
      version:
        description: "npm version to publish, e.g. 0.1.0-beta.0. Empty uses 0.1.0-beta.<run_number>."
        required: false
        type: string
      tag:
        description: "npm dist-tag"
        required: true
        default: "beta"
        type: choice
        options:
          - beta
          - next
          - latest
      dry_run:
        description: "Run build and npm pack without publishing"
        required: true
        default: true
        type: boolean

permissions:
  contents: read
  id-token: write

jobs:
  platform:
    name: Build ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: linux-x64
            os: ubuntu-24.04
            arch: x64
          - target: linux-arm64
            os: ubuntu-24.04-arm
            arch: arm64
          - target: darwin-x64
            os: macos-15-intel
            arch: x64
          - target: darwin-arm64
            os: macos-15
            arch: arm64
          - target: win32-x64
            os: windows-2025
            arch: x64
          - target: win32-arm64
            os: windows-11-arm
            arch: arm64

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 24
          registry-url: "https://registry.npmjs.org"

      - name: Use npm CLI with trusted publishing support
        run: |
          npm install -g npm@^11.10.0
          node --version
          npm --version

      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: 21
          cache: maven

      - uses: actions/setup-python@v5
        id: setup-python
        with:
          python-version: "3.12"
          architecture: ${{ matrix.arch }}

      - name: Install OpenSSL for Windows ARM64 Python builds
        if: ${{ matrix.target == 'win32-arm64' }}
        shell: pwsh
        run: |
          $triplet = "arm64-windows-static-md"
          $vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT
          if (-not $vcpkgRoot) {
            $vcpkgRoot = Join-Path $env:RUNNER_TEMP "vcpkg"
          }

          if (-not (Test-Path (Join-Path $vcpkgRoot "vcpkg.exe"))) {
            git clone https://github.com/microsoft/vcpkg.git $vcpkgRoot
            & (Join-Path $vcpkgRoot "bootstrap-vcpkg.bat") -disableMetrics
          }

          & (Join-Path $vcpkgRoot "vcpkg.exe") install "openssl:$triplet" --clean-after-build
          $opensslDir = Join-Path $vcpkgRoot "installed\$triplet"

          Add-Content -Path $env:GITHUB_ENV -Value "VCPKG_ROOT=$vcpkgRoot"
          Add-Content -Path $env:GITHUB_ENV -Value "VCPKGRS_TRIPLET=$triplet"
          Add-Content -Path $env:GITHUB_ENV -Value "OPENSSL_DIR=$opensslDir"
          Add-Content -Path $env:GITHUB_ENV -Value "OPENSSL_STATIC=1"

      - name: Resolve release version
        shell: bash
        run: |
          version="${{ inputs.version }}"
          if [ -z "$version" ]; then
            version="0.1.0-beta.${{ github.run_number }}"
          fi
          echo "MUSIO_RELEASE_VERSION=$version" >> "$GITHUB_ENV"

      - name: Sync npm package versions
        run: node packaging/scripts/set-npm-version.js "$MUSIO_RELEASE_VERSION"
        shell: bash

      - name: Install frontend dependencies
        run: npm ci
        working-directory: frontend

      - name: Build platform vendor
        run: npm run build:vendor
        working-directory: packaging/platforms/${{ matrix.target }}
        env:
          MUSIO_PYTHON_EXE: ${{ steps.setup-python.outputs.python-path }}

      - name: Verify package
        run: npm pack --dry-run
        working-directory: packaging/platforms/${{ matrix.target }}

      - name: Publish platform package
        if: ${{ !inputs.dry_run }}
        shell: bash
        run: |
          package_name="$(node -p "require('./package.json').name")"
          package_version="$(node -p "require('./package.json').version")"
          if npm view "${package_name}@${package_version}" version --registry=https://registry.npmjs.org/ >/dev/null 2>&1; then
            echo "${package_name}@${package_version} is already published; skipping."
            exit 0
          fi
          npm publish --access public --tag "${{ inputs.tag }}"
        working-directory: packaging/platforms/${{ matrix.target }}

  launcher:
    name: Publish launcher
    runs-on: ubuntu-24.04
    needs: platform
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 24
          registry-url: "https://registry.npmjs.org"

      - name: Use npm CLI with trusted publishing support
        run: |
          npm install -g npm@^11.10.0
          node --version
          npm --version

      - name: Resolve release version
        shell: bash
        run: |
          version="${{ inputs.version }}"
          if [ -z "$version" ]; then
            version="0.1.0-beta.${{ github.run_number }}"
          fi
          echo "MUSIO_RELEASE_VERSION=$version" >> "$GITHUB_ENV"

      - name: Sync npm package versions
        run: node packaging/scripts/set-npm-version.js "$MUSIO_RELEASE_VERSION"

      - name: Verify launcher package
        run: npm pack --dry-run
        working-directory: packaging/npm

      - name: Publish launcher package
        if: ${{ !inputs.dry_run }}
        shell: bash
        run: |
          package_name="$(node -p "require('./package.json').name")"
          package_version="$(node -p "require('./package.json').version")"
          if npm view "${package_name}@${package_version}" version --registry=https://registry.npmjs.org/ >/dev/null 2>&1; then
            echo "${package_name}@${package_version} is already published; skipping."
            exit 0
          fi
          npm publish --access public --tag "${{ inputs.tag }}"
        working-directory: packaging/npm
