# Copyright © SixtyFPS GmbH <info@slint.dev>
# SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial

name: Publish npm package to npm registry

on:
    workflow_dispatch:
        inputs:
            private:
                type: boolean
                default: true
                required: false
                description: "Private build? True means artifacts are only built. False means the package will be published to the NPM registry"
            release:
                type: boolean
                default: false
                required: false
                description: "Release? Enable options for building binaries for a release (i.e. apply a nightly tag, nightly version)"

    schedule:
        - cron: "0 5 * * *"

jobs:
    determine_version:
        runs-on: ubuntu-22.04
        outputs:
            PKG_VERSION: ${{ steps.mkversion.outputs.PKG_VERSION }}
        steps:
            - uses: actions/checkout@v4
            - uses: ./.github/actions/install-linux-dependencies
            - uses: ./.github/actions/setup-rust
            # Setup .npmrc file to publish to npm
            - uses: actions/setup-node@v4
              with:
                  node-version: "20.x"
                  registry-url: "https://registry.npmjs.org"
            - name: Determine version
              id: mkversion
              env:
                  RELEASE_INPUT: ${{ github.event.inputs.release }}
              working-directory: api/node
              run: |
                  version=`npm pkg get version | jq -r`
                  if [ "$RELEASE_INPUT" != "true" ]; then
                      nightly_version_suffix=`git log -1 --format=%cd --date="format:%Y%m%d%H"`
                      version="$version-nightly.$nightly_version_suffix"
                  fi
                  echo $version
                  echo "PKG_VERSION=$version" >> $GITHUB_OUTPUT

    build_binaries:
        env:
            PKG_VERSION: ${{ needs.determine_version.outputs.PKG_VERSION }}
            RELEASE_INPUT: ${{ github.event.inputs.release }}
            MACOSX_DEPLOYMENT_TARGET: "11.0"
        strategy:
            matrix:
                include:
                    - os: ubuntu-20.04
                      rust-target: x86_64-unknown-linux-gnu
                      napi-rs-target: linux-x64-gnu
                    - os: macos-latest
                      rust-target: x86_64-apple-darwin
                      napi-rs-target: darwin-x64
                    - os: macos-latest
                      rust-target: aarch64-apple-darwin
                      napi-rs-target: darwin-arm64
                    - os: windows-2022
                      rust-target: x86_64-pc-windows-msvc
                      napi-rs-target: win32-x64-msvc
                    - os: windows-2022
                      rust-target: i686-pc-windows-msvc
                      napi-rs-target: win32-ia32-msvc
        needs: determine_version
        runs-on: ${{ matrix.os }}
        steps:
            - uses: actions/checkout@v4
            - uses: ./.github/actions/install-linux-dependencies
              with:
                  old-ubuntu: true
            - uses: ./.github/actions/setup-rust
              with:
                  target: ${{ matrix.rust-target }}
            # Setup .npmrc file to publish to npm
            - uses: actions/setup-node@v4
              with:
                  node-version: "20.x"
                  registry-url: "https://registry.npmjs.org"
            - name: Set version
              working-directory: api/node
              shell: bash
              run: |
                  if [ "$RELEASE_INPUT" != "true" ]; then
                      npm version $PKG_VERSION
                  fi
            - name: Prepare feature config for binaries
              working-directory: api/node
              shell: bash
              run: |
                  perl -pi -e 's,^default =.*,,' Cargo.toml
                  perl -pi -e 's,# binaries:,,' Cargo.toml
                  echo "New defaults:"
                  grep "^\s*default =" Cargo.toml
            - name: Build binary
              shell: bash
              working-directory: api/node
              run: |
                  npm install --ignore-scripts
                  npm run build -- --target ${{ matrix.rust-target }}
            - name: Create package
              shell: bash
              working-directory: api/node
              run: |
                  npx napi create-npm-dir -t . -c ./binaries.json
                  mv index.${{ matrix.napi-rs-target }}.node npm/${{ matrix.napi-rs-target }}/
                  cd npm/${{ matrix.napi-rs-target }}/
                  if [ "$RELEASE_INPUT" != "true" ]; then
                    npm version $PKG_VERSION
                  fi
                  npm pack
            - name: Upload artifact
              uses: actions/upload-artifact@v4
              with:
                  name: binaries-${{ matrix.rust-target }}
                  path: "api/node/npm/${{ matrix.napi-rs-target }}/*.tgz"

    build_and_publish_npm_package:
        runs-on: ubuntu-22.04
        needs: [determine_version, build_binaries]
        env:
            PKG_VERSION: ${{ needs.determine_version.outputs.PKG_VERSION }}
            RELEASE_INPUT: ${{ github.event.inputs.release }}
        steps:
            - uses: actions/checkout@v4
            - uses: ./.github/actions/install-linux-dependencies
            - uses: ./.github/actions/setup-rust
            # Setup .npmrc file to publish to npm
            - uses: actions/setup-node@v4
              with:
                  node-version: "20.x"
                  registry-url: "https://registry.npmjs.org"
            - name: Set version
              working-directory: api/node
              run: |
                  if [ "$RELEASE_INPUT" != "true" ]; then
                      npm version $PKG_VERSION
                  fi
            - name: Select git revision
              if: github.event.inputs.release != 'true'
              run: |
                  echo "PKG_EXTRA_ARGS=--sha1=$GITHUB_SHA" >> $GITHUB_ENV
                  echo "PUBLISH_TAG=--tag nightly" >> $GITHUB_ENV
            - name: Compile index.js and index.d.ts
              working-directory: api/node
              run: |
                  npm install
                  npm run build
                  npm run compile
            - name: Prepare binary packages
              working-directory: api/node
              run: |
                  npx napi create-npm-dir -t . -c ./binaries.json
            - name: Download artifacts
              uses: actions/download-artifact@v4
              with:
                  name: binaries-x86_64-unknown-linux-gnu
                  path: api/node/
            - name: Download artifacts
              uses: actions/download-artifact@v4
              with:
                  name: binaries-x86_64-apple-darwin
                  path: api/node/
            - name: Download artifacts
              uses: actions/download-artifact@v4
              with:
                  name: binaries-aarch64-apple-darwin
                  path: api/node/
            - name: Download artifacts
              uses: actions/download-artifact@v4
              with:
                  name: binaries-x86_64-pc-windows-msvc
                  path: api/node/
            - name: Download artifacts
              uses: actions/download-artifact@v4
              with:
                  name: binaries-i686-pc-windows-msvc
                  path: api/node/
            - name: Add binary dependencies
              working-directory: api/node
              run: |
                  for package in @slint-ui/slint-ui-binary-linux-x64-gnu @slint-ui/slint-ui-binary-darwin-x64 @slint-ui/slint-ui-binary-darwin-arm64 @slint-ui/slint-ui-binary-win32-x64-msvc @slint-ui/slint-ui-binary-win32-ia32-msvc; do
                      jq --arg pkg "$package" --arg version "$PKG_VERSION" '.optionalDependencies[$pkg]=$version' package.json > new.json
                      mv new.json package.json
                  done
            - name: Build package
              run: |
                  cargo xtask node_package $PKG_EXTRA_ARGS
            - name: "Upload npm package Artifact"
              uses: actions/upload-artifact@v4
              with:
                  name: slint-ui-node-package
                  path: |
                      api/node/slint-ui-${{ env.PKG_VERSION }}.tgz
            - name: Smoke test package to see if it builds at least
              run: |
                  mkdir /tmp/nodetest
                  cd /tmp/nodetest
                  npm init -y
                  npm install --verbose $GITHUB_WORKSPACE/api/node/slint-ui-$PKG_VERSION.tgz
            - name: Build and publish packages
              if: ${{ github.event.inputs.private != 'true' && (github.ref == 'refs/heads/master' || github.event.inputs.release == 'true') }}
              run: |
                  npm publish --access public $PUBLISH_TAG api/node/slint-ui-slint-ui-binary-linux-x64-gnu-$PKG_VERSION.tgz
                  npm publish --access public $PUBLISH_TAG api/node/slint-ui-slint-ui-binary-darwin-x64-$PKG_VERSION.tgz
                  npm publish --access public $PUBLISH_TAG api/node/slint-ui-slint-ui-binary-darwin-arm64-$PKG_VERSION.tgz
                  npm publish --access public $PUBLISH_TAG api/node/slint-ui-slint-ui-binary-win32-x64-msvc-$PKG_VERSION.tgz
                  npm publish --access public $PUBLISH_TAG api/node/slint-ui-slint-ui-binary-win32-ia32-msvc-$PKG_VERSION.tgz
                  npm publish $PUBLISH_TAG api/node/slint-ui-$PKG_VERSION.tgz
              env:
                  NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
