name: Turborepo Library Release

on:
  workflow_dispatch:
    inputs:
      dry_run:
        description: Do a dry run, skipping the final publish step.
        type: boolean

jobs:
  build:
    defaults:
      run:
        shell: bash -leo pipefail {0}

    strategy:
      fail-fast: false
      matrix:
        settings:
          - host: macos-latest
            target: aarch64-apple-darwin

          - host: macos-latest
            target: x86_64-apple-darwin

          - host: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            setup: |
              sudo apt update
              sudo apt install -y g++-aarch64-linux-gnu libc6-dev-arm64-cross xz-utils
              mkdir zig
              curl --show-error --location https://ziglang.org/download/0.14.0/zig-linux-x86_64-0.14.0.tar.xz | tar -J -xf - -C zig --strip-components 1
              export PATH=$PATH:$(pwd)/zig
              echo "$(pwd)/zig" >> $GITHUB_PATH

          - host: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            container: amazon/aws-lambda-nodejs:20
            install: |
              microdnf install -y gcc gcc-c++ git tar xz
              curl https://sh.rustup.rs -sSf | bash -s -- -y
              npm i -g pnpm@8.9.0
              mkdir ../zig
              curl --show-error --location https://ziglang.org/download/0.14.0/zig-linux-x86_64-0.14.0.tar.xz | tar -J -xf - -C ../zig --strip-components 1
              export PATH=$PATH:$(pwd)/../zig
              echo "$(pwd)/../zig" >> $GITHUB_PATH
            setup: |
              pnpm install

          - host: ubuntu-latest
            target: x86_64-unknown-linux-musl
            container: ghcr.io/napi-rs/napi-rs/nodejs-rust:stable-2023-09-17-alpine
            install: |
              apk update && apk upgrade
              apk add libc6-compat curl
              echo /root/.cargo/bin >> ${GITHUB_PATH}
              echo /usr/local/cargo/bin/rustup >> ${GITHUB_PATH}
            setup: |
              export PATH=/usr/local/cargo/bin/rustup:/root/.cargo/bin:${PATH}
              rustup show active-toolchain
              dirname $(rustup which cargo) >> ${GITHUB_PATH}
              pnpm install

          - host: ubuntu-latest
            target: aarch64-unknown-linux-musl
            container: ghcr.io/napi-rs/napi-rs/nodejs-rust:stable-2023-09-17-alpine
            install: |
              apk update && apk upgrade
              apk add libc6-compat curl
              echo /root/.cargo/bin >> ${GITHUB_PATH}
              echo /usr/local/cargo/bin/rustup >> ${GITHUB_PATH}
              echo /aarch64-linux-musl-cross/bin >> ${GITHUB_PATH}
            setup: |
              export PATH=/aarch64-linux-musl-cross/bin:/usr/local/cargo/bin/rustup:/root/.cargo/bin:${PATH}
              rustup show active-toolchain
              rustup target add aarch64-unknown-linux-musl
              dirname $(rustup which cargo) >> ${GITHUB_PATH}
              pnpm install
            rust_env: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc RUSTFLAGS="-Ctarget-feature=-crt-static"

          - host: windows-latest
            target: aarch64-pc-windows-msvc

          - host: windows-latest
            target: x86_64-pc-windows-msvc

    runs-on: ${{ matrix.settings.host }}
    container:
      image: ${{ matrix.settings.container }}
    steps:
      - name: Install Packages
        run: ${{ matrix.settings.install }}
        if: ${{ matrix.settings.install }}

      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Setup Rust
        uses: ./.github/actions/setup-rust
        with:
          targets: ${{ matrix.settings.target }}
          github-token: ${{ github.token }}
        if: ${{ !matrix.settings.install }}

      - name: Setup Node
        uses: ./.github/actions/setup-node
        with:
          enable-corepack: false
        if: ${{ !matrix.settings.install }}

      - name: Setup toolchain
        run: ${{ matrix.settings.setup }}
        if: ${{ matrix.settings.setup }}

      - name: Build native library
        run: |
          export PATH=/usr/local/cargo/bin/rustup:/root/.cargo/bin:${PATH}
          cd packages/turbo-repository
          ${{ matrix.settings.rust_env }} pnpm build:release --target=${{ matrix.settings.target }}

      - name: Upload Artifacts
        uses: actions/upload-artifact@v4
        with:
          name: turbo-library-${{ matrix.settings.target }}
          path: packages/turbo-repository/native

  package:
    name: Publish to NPM
    runs-on: ubuntu-latest
    needs: [build]
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Configure git
        run: |
          git config --global user.name 'Turbobot'
          git config --global user.email 'turbobot@vercel.com'

      - name: Download Artifacts
        uses: actions/download-artifact@v4
        with:
          path: native-packages

      - name: Move artifacts into place
        run: |
          mv native-packages/turbo-library-aarch64-apple-darwin/@turbo/repository.darwin-arm64.node packages/turbo-repository/npm/darwin-arm64/
          mv native-packages/turbo-library-x86_64-apple-darwin/@turbo/repository.darwin-x64.node packages/turbo-repository/npm/darwin-x64/
          mv native-packages/turbo-library-aarch64-unknown-linux-gnu/@turbo/repository.linux-arm64-gnu.node packages/turbo-repository/npm/linux-arm64-gnu/
          mv native-packages/turbo-library-aarch64-unknown-linux-musl/@turbo/repository.linux-arm64-musl.node packages/turbo-repository/npm/linux-arm64-musl/
          mv native-packages/turbo-library-x86_64-unknown-linux-gnu/@turbo/repository.linux-x64-gnu.node packages/turbo-repository/npm/linux-x64-gnu/
          mv native-packages/turbo-library-x86_64-unknown-linux-musl/@turbo/repository.linux-x64-musl.node packages/turbo-repository/npm/linux-x64-musl/
          mv native-packages/turbo-library-aarch64-pc-windows-msvc/@turbo/repository.win32-arm64-msvc.node packages/turbo-repository/npm/win32-arm64-msvc/
          mv native-packages/turbo-library-x86_64-pc-windows-msvc/@turbo/repository.win32-x64-msvc.node packages/turbo-repository/npm/win32-x64-msvc/

      - name: Build Meta Package
        run: |
          cd packages/turbo-repository/js
          npm run build

      - name: Package Artifacts
        run: |
          mkdir tarballs
          npm pack packages/turbo-repository/npm/darwin-arm64
          npm pack packages/turbo-repository/npm/darwin-x64
          npm pack packages/turbo-repository/npm/linux-arm64-gnu
          npm pack packages/turbo-repository/npm/linux-arm64-musl
          npm pack packages/turbo-repository/npm/linux-x64-gnu
          npm pack packages/turbo-repository/npm/linux-x64-musl
          npm pack packages/turbo-repository/npm/win32-arm64-msvc
          npm pack packages/turbo-repository/npm/win32-x64-msvc
          npm pack packages/turbo-repository/js
          mv *.tgz tarballs/

      - name: Upload Artifacts
        uses: actions/upload-artifact@v4
        with:
          name: Upload Tarballs
          path: tarballs

      - name: Publish Artifacts
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        if: ${{ !inputs.dry_run }}
        run: |
          npm config set --location=project "//registry.npmjs.org/:_authToken" ${NPM_TOKEN}
          VERSION=$(jq -r .version packages/turbo-repository/js/package.json)
          cd tarballs
          ls
          TAG="canary"
          npm publish -ddd --tag ${TAG} --access public turbo-repository-darwin-arm64-${VERSION}.tgz
          npm publish -ddd --tag ${TAG} --access public turbo-repository-darwin-x64-${VERSION}.tgz
          npm publish -ddd --tag ${TAG} --access public turbo-repository-linux-arm64-gnu-${VERSION}.tgz
          npm publish -ddd --tag ${TAG} --access public turbo-repository-linux-arm64-musl-${VERSION}.tgz
          npm publish -ddd --tag ${TAG} --access public turbo-repository-linux-x64-gnu-${VERSION}.tgz
          npm publish -ddd --tag ${TAG} --access public turbo-repository-linux-x64-musl-${VERSION}.tgz
          npm publish -ddd --tag ${TAG} --access public turbo-repository-win32-arm64-msvc-${VERSION}.tgz
          npm publish -ddd --tag ${TAG} --access public turbo-repository-win32-x64-msvc-${VERSION}.tgz
          npm publish -ddd --tag ${TAG} --access public turbo-repository-${VERSION}.tgz
