name: Publish bolt-cli packages
on:
  release:
    types: [ published ]
  push:
    branches:
      - 'release/v*'
  workflow_dispatch:
    inputs:
      release_version:
        description: 'The release version'
        required: true
        default: '0.0.1'

jobs:
  publish-npm-binaries:
    name: Publish NPM packages
    runs-on: ${{ matrix.build.os }}
    strategy:
      fail-fast: false
      matrix:
        build:
          - {
            NAME: linux-x64-glibc,
            OS: ubuntu-20.04,
            TOOLCHAIN: stable,
            TARGET: x86_64-unknown-linux-gnu,
          }
          - {
            NAME: linux-x86-glibc,
            OS: ubuntu-22.04,
            TOOLCHAIN: stable,
            TARGET: i686-unknown-linux-gnu,
          }
          - {
            NAME: linux-arm64-glibc,
            OS: ubuntu-20.04,
            TOOLCHAIN: stable,
            TARGET: aarch64-unknown-linux-gnu,
          }
          - {
            NAME: win32-x64-msvc,
            OS: windows-2022,
            TOOLCHAIN: stable,
            TARGET: x86_64-pc-windows-msvc,
          }
          - {
            NAME: win32-x86-msvc,
            OS: windows-2022,
            TOOLCHAIN: stable,
            TARGET: i686-pc-windows-msvc,
          }
          - {
            NAME: darwin-x64,
            OS: macos-11,
            TOOLCHAIN: stable,
            TARGET: x86_64-apple-darwin,
          }
          - {
            NAME: darwin-arm64,
            OS: macos-11,
            TOOLCHAIN: stable,
            TARGET: aarch64-apple-darwin,
          }
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set DRY_RUN based on trigger
        shell: bash
        run: echo "DRY_RUN=true" >> $GITHUB_ENV
        if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release/v')

      - name: Set the release version
        shell: bash
        run: |
          if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
            echo "RELEASE_VERSION=${{ github.event.inputs.release_version }}" >> $GITHUB_ENV
          elif [[ "${{ github.event_name }}" == "push" ]]; then
            VERSION=$(echo "${GITHUB_REF}" | sed -E 's|refs/heads/release/v||')
            echo "RELEASE_VERSION=${VERSION}" >> $GITHUB_ENV
          elif [[ "${{ github.event_name }}" == "release" ]]; then
            VERSION=$(echo "${GITHUB_REF}" | sed -E 's|refs/tags/v||')
            echo "RELEASE_VERSION=${VERSION}" >> $GITHUB_ENV
          fi

      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: ${{ matrix.build.TOOLCHAIN }}
          target: ${{ matrix.build.TARGET }}
          override: true

      - name: Build (linux/macos)
        if: matrix.build.OS != 'windows-2022'
        uses: actions-rs/cargo@v1
        with:
          use-cross: true
          command: build
          args: --manifest-path=cli/Cargo.toml --release --locked --target ${{ matrix.build.TARGET }}

      - name: Build (windows)
        if: matrix.build.OS == 'windows-2022'
        uses: actions-rs/cargo@v1
        with:
          command: build
          args: --manifest-path=cli/Cargo.toml --no-default-features --release --locked --target ${{ matrix.build.TARGET }}

      - name: Check versions are aligned
        run: |
          # Fails if versions are not aligned
          cargo install git-cliff
          ./version-align.sh --check

      - name: Build the NPM package
        shell: bash
        run: |
          # set the binary name
          bin="bolt"
          # derive the OS and architecture from the build matrix name
          # note: when split by a hyphen, first part is the OS and the second is the architecture
          node_os=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f1)
          export node_os
          node_arch=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f2)
          export node_arch
          # set the version
          export node_version="${{ env.RELEASE_VERSION }}"
          # set the package name
          # note: use 'windows' as OS name instead of 'win32'
          if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
            export node_pkg="${bin}-cli-windows-${node_arch}"
          else
            export node_pkg="${bin}-cli-${node_os}-${node_arch}"
          fi
          echo "node_pkg=${node_pkg}" >> $GITHUB_ENV
          # create the package directory
          mkdir -p "${node_pkg}/bin"
          # generate package.json from the template
          envsubst < cli/npm-package/package.json.tmpl > "${node_pkg}/package.json"
          cat "${node_pkg}/package.json"
          # copy the binary into the package
          # note: windows binaries has '.exe' extension
          if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
            bin="${bin}.exe"
          fi
          echo "bin_name=${bin}" >> $GITHUB_ENV
          cp "target/${{ matrix.build.TARGET }}/release/${bin}" "${node_pkg}/bin"
          cp "target/${{ matrix.build.TARGET }}/release/${bin}" "${node_pkg}/bin"
          
          # Create the release bin file
          release_name="bolt-cli-${{ matrix.build.NAME }}"
          if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
            release_name="${release_name}.exe"
          fi
          echo "release_name=${release_name}" >> $GITHUB_ENV
          mv "target/${{ matrix.build.TARGET }}/release/${bin}" "target/${{ matrix.build.TARGET }}/release/${release_name}"

      - name: Publish binary to GitHub release
        if: ${{ env.DRY_RUN != 'true' }}
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: target/${{ matrix.build.TARGET }}/release/${{ env.release_name }}
          overwrite: true
          tag: "v${{ env.RELEASE_VERSION }}"
          release_name: "v${{ env.RELEASE_VERSION }}"
          asset_name: "${{ env.release_name }}"

      - name: Publish the NPM package
        run: |
          echo "DRY_RUN=${{ env.DRY_RUN }}"
          cd ${{ env.node_pkg }}
          echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
          npm set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
          if [ "${{ env.DRY_RUN }}" = "true" ]; then
            echo "Running npm publish in dry-run mode"
            npm publish --access public --dry-run
          else
            npm publish --access public
          fi
        shell: bash
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
  publish-wrapper-npm-package:
    name: Publish wrapper NPM packages
    runs-on: ubuntu-20.04
    needs: publish-npm-binaries
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Set DRY_RUN based on trigger
        run: echo "DRY_RUN=true" >> $GITHUB_ENV
        if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release/v')
      - name: Publish the NPM package
        shell: bash
        run: |
          cd cli/npm-package
          npm install
          npm run build
          cd lib
          echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
          npm set //registry.npmjs.org/:_authToken ${{ secrets.NPM_TOKEN }}
          if [ "${DRY_RUN}" = "true" ]; then
            echo "Running npm publish in dry-run mode"
            npm publish --access public --dry-run
          else
            npm publish --access public
          fi
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}