name: Build and Release to R2

on:
  push:
    tags:
      - 'v*' # Trigger when pushing tags starting with v, e.g., v1.0.0

jobs:
  build-and-upload:
    runs-on: ${{ matrix.target.runner }}
    strategy:
      fail-fast: true # if it is set to true, then one job failed the other jobs will be cancelled  together.
      matrix:
        component: [libra]
        target:
          - { rust: x86_64-unknown-linux-gnu, os: linux, arch: amd64, runner: ubuntu-latest }
          - { rust: aarch64-unknown-linux-gnu, os: linux, arch: arm64, runner: ubuntu-24.04-arm }
          - { rust: aarch64-apple-darwin, os: darwin, arch: arm64, runner: macos-latest }
          - { rust: x86_64-pc-windows-msvc, os: windows, arch: amd64, runner: windows-latest }

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

      - name: Set up Rust
        uses: actions-rust-lang/setup-rust-toolchain@v1
        with:
          toolchain: stable
          target: ${{ matrix.target.rust }}

      - name: Setup Node.js
        uses: actions/setup-node@v5
        with:
          node-version: "22"

      - name: Enable pnpm
        run: |
          corepack enable
          corepack prepare pnpm@11.1.0 --activate

      - name: Install web dependencies
        run: pnpm --dir web install --frozen-lockfile

      - name: Install Linux dependencies
        if: matrix.target.os == 'linux'
        run: |
          sudo apt-get update

      - name: Cache cargo registry
        uses: actions/cache@v5
        with:
          path: ~/.cargo/registry
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}

      - name: Cache cargo index
        uses: actions/cache@v5
        with:
          path: ~/.cargo/git
          key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}

      - name: Cache cargo build
        uses: actions/cache@v5
        with:
          path: target
          key: ${{ runner.os }}-cargo-build-target-${{ matrix.target.rust }}-${{ hashFiles('**/Cargo.lock') }}

      - name: Build Binary (Unix)
        if: matrix.target.os != 'windows'
        shell: bash
        run: |
          VERSION=${GITHUB_REF_NAME}
          BINARY_NAME="${{ matrix.component }}-${{ matrix.target.os }}-${{ matrix.target.arch }}"

          echo "Building $BINARY_NAME for target ${{ matrix.target.rust }}..."

          RUSTFLAGS="-C strip=symbols" cargo build --locked --release --target ${{ matrix.target.rust }}

          # Create build directory and copy binary
          mkdir -p build
          cp target/${{ matrix.target.rust }}/release/${{ matrix.component }} build/$BINARY_NAME

          # Make binary executable
          chmod +x build/$BINARY_NAME

          echo "Built binary: $BINARY_NAME"

      - name: Build Binary (Windows)
        if: matrix.target.os == 'windows'
        shell: pwsh
        run: |
          $version = $env:GITHUB_REF_NAME
          $binaryName = "${{ matrix.component }}-${{ matrix.target.os }}-${{ matrix.target.arch }}"

          Write-Output "Building $binaryName for target ${{ matrix.target.rust }}..."

          $env:RUSTFLAGS = "-C strip=symbols -C link-args=/STACK:0x1000000" 
          cargo build --locked --release --target ${{ matrix.target.rust }}

          # Create build directory and copy binary
          New-Item -ItemType Directory -Force -Path "build" | Out-Null
          Copy-Item "target\${{ matrix.target.rust }}\release\${{ matrix.component }}.exe" "build\$binaryName.exe"

          Write-Output "Built binary: $binaryName"

      - name: Upload to Cloudflare R2 (Unix)
        if: matrix.target.os != 'windows'
        shell: bash
        env:
          RCLONE_CONFIG_R2_TYPE: s3
          RCLONE_CONFIG_R2_PROVIDER: Cloudflare
          RCLONE_CONFIG_R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
          RCLONE_CONFIG_R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
          RCLONE_CONFIG_R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }}
          RCLONE_CONFIG_R2_ACL: private
        run: |
          # Install rclone
          if [[ "${{ matrix.target.os }}" == "darwin" ]]; then
            brew install rclone
          else
            curl https://rclone.org/install.sh | sudo bash
          fi

          # Upload binaries to R2
          rclone copy ./build/ r2:${{ secrets.R2_BUCKET_NAME }}/libra/releases/${{ github.ref_name }}/ -v

          echo "Upload completed for ${{ matrix.component }}-${{ matrix.target.os }}-${{ matrix.target.arch }}"

      - name: Upload to Cloudflare R2 (Windows)
        if: matrix.target.os == 'windows'
        shell: pwsh
        env:
          RCLONE_CONFIG_R2_TYPE: s3
          RCLONE_CONFIG_R2_PROVIDER: Cloudflare
          RCLONE_CONFIG_R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
          RCLONE_CONFIG_R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
          RCLONE_CONFIG_R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }}
          RCLONE_CONFIG_R2_ACL: private
        run: |
          # Install rclone via choco
          choco install rclone -y

          # Upload binaries to R2
          rclone copy ./build/ r2:${{ secrets.R2_BUCKET_NAME }}/libra/releases/${{ github.ref_name }}/ -v

          Write-Output "Upload completed for ${{ matrix.component }}-${{ matrix.target.os }}-${{ matrix.target.arch }}"
