name: Build and Release CrossDesk

on:
  push:
    branches:
      - "**"
    tags:
      - "*"
  workflow_dispatch:

permissions:
  contents: write

env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jobs:
  # Linux amd64
  build-linux-amd64:
    name: Build on Ubuntu 22.04 amd64
    runs-on: ubuntu-22.04
    container:
      image: crossdesk/ubuntu20.04:latest
      options: --user root
    steps:
      - name: Extract version number
        id: version
        run: |
          VERSION="${GITHUB_REF##*/}"
          VERSION_NUM="${VERSION#v}"
          echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV

      - name: Set legal Debian version
        shell: bash
        id: set_deb_version
        run: |
          if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
            LEGAL_VERSION="0.0.0-${VERSION_NUM}"
          else
            LEGAL_VERSION="${VERSION_NUM}"
          fi
          echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV

      - name: Checkout code
        uses: actions/checkout@v4
        with:
          submodules: recursive

      - name: Build CrossDesk
        env:
          CUDA_PATH: /usr/local/cuda
          XMAKE_GLOBALDIR: /data
        run: |
          ls -la $XMAKE_GLOBALDIR
          xmake b -vy --root crossdesk

      - name: Decode and save certificate
        shell: bash
        run: |
          mkdir -p certs
          echo "${{ secrets.CROSSDESK_CERT_BASE64 }}" | base64 --decode > certs/crossdesk.cn_root.crt

      - name: Package
        run: |
          chmod +x ./scripts/linux/pkg_amd64.sh
          ./scripts/linux/pkg_amd64.sh ${LEGAL_VERSION}

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: crossdesk-linux-amd64-${{ env.LEGAL_VERSION }}
          path: ${{ github.workspace }}/crossdesk-linux-amd64-${{ env.LEGAL_VERSION }}.deb

  # Linux arm64
  build-linux-arm64:
    name: Build on Ubuntu 22.04 arm64
    runs-on: ubuntu-22.04-arm
    strategy:
      matrix:
        include:
          - arch: arm64
            image: crossdesk/ubuntu20.04-arm64v8:latest
            package_script: ./scripts/linux/pkg_arm64.sh
    container:
      image: ${{ matrix.image }}
      options: --user root
    steps:
      - name: Extract version number
        id: version
        run: |
          VERSION="${GITHUB_REF##*/}"
          VERSION_NUM="${VERSION#v}"
          echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV

      - name: Set legal Debian version
        shell: bash
        id: set_deb_version
        run: |
          if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
            LEGAL_VERSION="0.0.0-${VERSION_NUM}"
          else
            LEGAL_VERSION="${VERSION_NUM}"
          fi
          echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV

      - name: Checkout code
        uses: actions/checkout@v4
        with:
          submodules: recursive

      - name: Build CrossDesk
        env:
          CUDA_PATH: /usr/local/cuda
          XMAKE_GLOBALDIR: /data
        run: |
          xmake b -vy --root crossdesk

      - name: Decode and save certificate
        shell: bash
        run: |
          mkdir -p certs
          echo "${{ secrets.CROSSDESK_CERT_BASE64 }}" | base64 --decode > certs/crossdesk.cn_root.crt

      - name: Package
        run: |
          chmod +x ${{ matrix.package_script }}
          ${{ matrix.package_script }} ${LEGAL_VERSION}

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: crossdesk-linux-${{ matrix.arch }}-${{ env.LEGAL_VERSION }}
          path: ${{ github.workspace }}/crossdesk-linux-${{ matrix.arch }}-${{ env.LEGAL_VERSION }}.deb

  # macOS
  build-macos:
    name: Build on macOS
    runs-on: ${{ matrix.runner }}
    strategy:
      matrix:
        include:
          - arch: x64
            runner: macos-13
            cache-key: intel
            out-dir: ./build/macosx/x86_64/release/crossdesk
            package_script: ./scripts/macosx/pkg_x64.sh
          - arch: arm64
            runner: macos-14
            cache-key: arm
            out-dir: ./build/macosx/arm64/release/crossdesk
            package_script: ./scripts/macosx/pkg_arm64.sh

    steps:
      - name: Extract version number
        id: version
        run: |
          VERSION="${GITHUB_REF##*/}"
          VERSION_NUM="${VERSION#v}"
          echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
          echo "VERSION_NUM=${VERSION_NUM}"

      - name: Cache xmake dependencies
        uses: actions/cache@v4
        with:
          path: ~/.xmake/packages
          key: ${{ runner.os }}-xmake-deps-${{ matrix.cache-key }}-${{ hashFiles('**/xmake.lua') }}
          restore-keys: |
            ${{ runner.os }}-xmake-deps-${{ matrix.cache-key }}-

      - name: Install xmake
        run: brew install xmake

      - name: Checkout code
        uses: actions/checkout@v4

      - name: Initialize submodules
        run: git submodule update --init --recursive

      - name: Build CrossDesk
        run: xmake b -vy crossdesk

      - name: Decode and save certificate
        shell: bash
        run: |
          mkdir -p certs
          echo "${{ secrets.CROSSDESK_CERT_BASE64 }}" | base64 --decode > certs/crossdesk.cn_root.crt

      - name: Package CrossDesk app
        run: |
          chmod +x ${{ matrix.package_script }}
          ${{ matrix.package_script }} ${VERSION_NUM}

      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: crossdesk-macos-${{ matrix.arch }}-${{ env.VERSION_NUM }}
          path: crossdesk-macos-${{ matrix.arch }}-${{ env.VERSION_NUM }}.pkg

      - name: Move files to release dir
        run: |
          mkdir -p release
          cp crossdesk-macos-${{ matrix.arch }}-${{ env.VERSION_NUM }}.pkg release/

  # Windows
  build-windows-x64:
    name: Build on Windows x64
    runs-on: windows-2022
    env:
      XMAKE_GLOBALDIR: D:\xmake_global
    steps:
      - name: Extract version number
        shell: pwsh
        run: |
          $ref = $env:GITHUB_REF
          $version = $ref -replace '^refs/(tags|heads)/', ''
          $version = $version -replace '^v', ''
          $version = $version -replace '/', '-'
          echo "VERSION_NUM=$version" >> $env:GITHUB_ENV

      - name: Cache xmake dependencies
        uses: actions/cache@v4
        with:
          path: D:\xmake_global\.xmake\packages
          key: ${{ runner.os }}-xmake-deps-intel-${{ hashFiles('**/xmake.lua') }}
          restore-keys: |
            ${{ runner.os }}-xmake-deps-intel-

      - name: Install xmake
        run: |
          Invoke-Expression (Invoke-Webrequest 'https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.ps1' -UseBasicParsing).Content
          echo "C:\Users\runneradmin\xmake" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
          xmake create cuda
          Set-Location cuda
          xmake g --theme=plain
          $cudaPath = ""
          $packagesPath = "D:\xmake_global\.xmake\packages"

          if (Test-Path $packagesPath) {
              Write-Host "Packages directory exists: $packagesPath"
              try {
                  $info = xmake require --info "cuda 12.6.3" 2>$null
                  if ($null -ne $info -and $info -ne "") {
                      $cudaPath = (($info | Select-String installdir).ToString() -replace '.*installdir:\s*','').Trim()
                  }
              } catch {}
          } else {
              Write-Host "Packages directory not found: $packagesPath"
              Write-Host "Installing CUDA package..."
              xmake require -vy "cuda 12.6.3"
              $info = xmake require --info "cuda 12.6.3"
              $cudaPath = (($info | Select-String installdir).ToString() -replace '.*installdir:\s*','').Trim()
          }

          echo "CUDA_PATH=$cudaPath" >> $env:GITHUB_ENV
          Write-Host "Resolved CUDA_PATH = $cudaPath"
          Pop-Location

      - name: Download INetC plugin
        shell: powershell
        run: |
          $url = "https://github.com/DigitalMediaServer/NSIS-INetC-plugin/releases/download/v1.0.5.7/InetC.zip"
          $out = "$env:RUNNER_TEMP\InetC.zip"
          Invoke-WebRequest -Uri $url -OutFile $out
          Expand-Archive $out -DestinationPath "$env:RUNNER_TEMP\InetC" -Force

          $source = "$env:RUNNER_TEMP\InetC\x86-unicode\INetC.dll"
          $target = "C:\Program Files (x86)\NSIS\Plugins\x86-unicode\INetC.dll"

          Write-Host "Copying $source to $target"
          Copy-Item $source $target -Force

      - name: Checkout code
        uses: actions/checkout@v4

      - name: Initialize submodules
        run: git submodule update --init --recursive

      - name: Copy nsProcess plugin to NSIS folder
        run: |
          $nsisPluginDir = "C:\Program Files (x86)\NSIS\Plugins\x86-unicode"
          copy "${{ github.workspace }}\scripts\windows\nsProcess.dll" $nsisPluginDir

      - name: Build CrossDesk
        run: xmake b -vy crossdesk

      - name: Decode and save certificate
        shell: powershell
        run: |
          New-Item -ItemType Directory -Force -Path certs
          [System.IO.File]::WriteAllBytes('certs\crossdesk.cn_root.crt', [Convert]::FromBase64String('${{ secrets.CROSSDESK_CERT_BASE64 }}'))

      - name: Package
        shell: pwsh
        run: |
          cd "${{ github.workspace }}\scripts\windows"
          makensis /DVERSION=$env:VERSION_NUM nsis_script.nsi

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: crossdesk-win-x64-${{ env.VERSION_NUM }}
          path: ${{ github.workspace }}/scripts/windows/crossdesk-win-x64-${{ env.VERSION_NUM }}.exe

  release:
    name: Publish Release
    if: startsWith(github.ref, 'refs/tags/v')
    needs:
      [build-linux-amd64, build-linux-arm64, build-macos, build-windows-x64]
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          path: artifacts

      - name: Extract version number
        id: version
        run: |
          VERSION="${GITHUB_REF##*/}"
          VERSION_NUM="${VERSION#v}"
          echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_OUTPUT

      - name: Rename artifacts
        run: |
          mkdir -p release
          cp artifacts/crossdesk-macos-x64-${{ steps.version.outputs.VERSION_NUM }}/* release/crossdesk-macos-x64-${{ steps.version.outputs.VERSION_NUM }}.pkg
          cp artifacts/crossdesk-macos-arm64-${{ steps.version.outputs.VERSION_NUM }}/* release/crossdesk-macos-arm64-${{ steps.version.outputs.VERSION_NUM }}.pkg
          cp artifacts/crossdesk-linux-amd64-${{ steps.version.outputs.VERSION_NUM }}/* release/crossdesk-linux-amd64-${{ steps.version.outputs.VERSION_NUM }}.deb
          cp artifacts/crossdesk-linux-arm64-${{ steps.version.outputs.VERSION_NUM }}/* release/crossdesk-linux-arm64-${{ steps.version.outputs.VERSION_NUM }}.deb
          cp artifacts/crossdesk-win-x64-${{ steps.version.outputs.VERSION_NUM }}/* release/crossdesk-win-x64-${{ steps.version.outputs.VERSION_NUM }}.exe

      - name: List release files
        run: ls -lh release/

      - name: Upload to Versioned GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: v${{ steps.version.outputs.VERSION_NUM }}
          name: Release v${{ steps.version.outputs.VERSION_NUM }}
          draft: false
          prerelease: false
          files: release/*
          generate_release_notes: false
          body: |
            Binary release only. Source code is not included.

      - name: Create or update 'latest' tag
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git tag -f latest
          git push origin latest --force

      - name: Upload to GitHub Release (latest)
        uses: softprops/action-gh-release@v2
        with:
          tag_name: latest
          name: Latest Release
          draft: false
          prerelease: false
          files: release/*
          generate_release_notes: false

      - name: Upload artifacts to server
        uses: burnett01/rsync-deployments@5.2
        with:
          switches: -avzr --progress --delete
          path: release/*
          remote_path: /var/www/html/downloads/
          remote_host: ${{ secrets.SERVER_HOST }}
          remote_user: ${{ secrets.SERVER_USER }}
          remote_key: ${{ secrets.SERVER_KEY }}
