name: Windows Release Build

permissions:
  contents: read

on:
  workflow_call:
    inputs:
      generate-gpo:
        required: true
        type: boolean
        default: false
      build-version:
        description: "The version to build"
        required: true
        type: string
      profile-data-path-archive:
        description: "The path to the zip archive containing the profile data"
        type: string
      release-branch:
        description: "The branch to build"
        required: true
        type: string
      MOZ_BUILD_DATE:
        type: string
        required: true
        default: ""
      use-sccache:
        description: "Use sccache"
        required: true
        type: boolean
        default: false

jobs:
  windows-build:
    name: Build Windows - ${{ matrix.arch }}
    # aarch64 does not need full 16x, and we also dont use full LTO when generating GPO
    runs-on: ${{ (inputs.release-branch == 'release' && !inputs.generate-gpo && matrix.arch == 'x86_64') && 'self-hosted' || 'blacksmith-8vcpu-ubuntu-2404' }}
    env:
      SCCACHE_GHA_ENABLED: ${{ inputs.use-sccache && 'true' || 'false' }}
      CARGO_TERM_COLOR: always
      CARGO_INCREMENTAL: 0
    strategy:
      fail-fast: false
      matrix:
        arch: [x86_64, aarch64]

    steps:
      - name: Free Disk Space (Ubuntu)
        uses: jlumbroso/free-disk-space@main
        if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
        with:
          tool-cache: false

      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          submodules: recursive
          token: ${{ secrets.DEPLOY_KEY }}

      - name: Setup Node.js
        uses: useblacksmith/setup-node@v5
        with:
          node-version-file: ".nvmrc"

      - name: Run sccache-cache
        uses: mozilla-actions/sccache-action@main
        if: ${{ inputs.use-sccache }}
        with:
          disable_annotations: true

      - name: Expose actions cache variables
        uses: actions/github-script@v6
        with:
          script: |
            core.exportVariable('ACTIONS_CACHE_URL', process.env['ACTIONS_CACHE_URL'])
            core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN'])

      - name: Setup Git
        run: |
          git config --global user.name "github-actions[bot]"
          git config --global user.email "github-actions[bot]@users.noreply.github.com"

      - name: Install dependencies
        run: |
          npm ci
          sudo apt-get update
          sudo apt-get install -y python3 python3-pip dos2unix yasm nasm build-essential libgtk2.0-dev libpython3-dev m4 uuid libasound2-dev libcurl4-openssl-dev libdbus-1-dev libdrm-dev libdbus-glib-1-dev libgtk-3-dev libpulse-dev libx11-xcb-dev libxt-dev xvfb lld llvm --fix-missing

      - name: Load Surfer CI setup
        run: npm run surfer -- ci --brand ${{ inputs.release-branch }} --display-version ${{ inputs.build-version }}

      - name: Download Firefox and dependencies
        if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
        run: npm run download

      - name: win-cross Cache
        env:
          SEGMENT_DOWNLOAD_TIMEOUT_MINS: 5
        id: cache-win-cross
        uses: useblacksmith/cache@v5
        with:
          path: ${HOME}/win-cross
          key: win-cross

      - name: Setup for Windows
        if: steps.cache-win-cross.outputs.cache-hit != 'true' && !(inputs.generate-gpo && matrix.arch == 'aarch64')
        run: |
          set -x
          mkdir -p ~/win-cross
          cd engine/
          sudo apt-get install python3-launchpadlib
          sudo add-apt-repository ppa:savoury1/backports
          sudo apt-get update
          sudo apt-get install -y python3-pip autoconf \
            autoconf2.13 \
            automake \
            bison \
            build-essential \
            cabextract \
            curl \
            cmake \
            flex \
            gawk \
            gcc-multilib \
            git \
            gnupg \
            jq \
            libbz2-dev \
            libexpat1-dev \
            libffi-dev \
            libncursesw5-dev \
            libsqlite3-dev \
            libssl-dev \
            libtool \
            libucl-dev \
            libxml2-dev \
            msitools \
            ninja-build \
            openssh-client \
            p7zip-full \
            pkg-config \
            procps \
            python3-requests \
            python3-toml \
            scons \
            subversion \
            tar \
            unzip \
            uuid \
            uuid-dev \
            wget \
            zip \
            zlib1g-dev \
            aria2
          echo Setup wine
          aria2c "https://firefox-ci-tc.services.mozilla.com/api/queue/v1/task/dQz_aHy8Rl-Lt0xf2WlrMw/artifacts/public/build/wine.tar.zst" -o wine.tar.zst
          tar --zstd -xf wine.tar.zst -C ~/win-cross
          rm wine.tar.zst
          echo Setup Visual Studio
          ./mach python --virtualenv build taskcluster/scripts/misc/get_vs.py build/vs/vs2026.yaml ~/win-cross/vs2026

      - name: Import
        if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
        env:
          SURFER_COMPAT: ${{ matrix.arch }}
          SURFER_CERT_PATCH_ISSUER: ${{ secrets.SURFER_CERT_PATCH_ISSUER }}
          SURFER_CERT_PATCH_NAME: ${{ secrets.SURFER_CERT_PATCH_NAME }}
        run: |
          . "$HOME/.cargo/env"
          npm run import -- --verbose

      - name: Bootstrap
        if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
        run: |
          set -x
          cd engine/
          chmod -R +x "$(echo ~)/win-cross/vs2026" || true
          cd ..
          export SURFER_PLATFORM="win32"
          npm run bootstrap
          cd engine/
          ls ~/.mozbuild/clang/lib/clang/
          echo "export LIB=\"$(cd ~/.mozbuild/clang/lib/clang/* && cd lib/windows && pwd)\"" >> ../configs/common/mozconfig
          cat ../configs/common/mozconfig
          sudo apt-get update
          sudo apt-get install dos2unix
          ls ~/win-cross/wine || true
          ls ~/win-cross/vs2026 || true

      - name: Setup Rust
        if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
        run: |
          curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain $(cat .rust-toolchain)
          source $HOME/.cargo/env
          if test "${{ matrix.arch }}" = "aarch64"; then
            rustup target add aarch64-pc-windows-msvc
          else
            rustup target add x86_64-pc-windows-msvc
          fi
          # Stored in build/windows/.windows-rs-version
          WINDOWS_RS_VERSION=$(cat build/windows/.windows-rs-version)
          cd engine/
          cargo install cargo-download --locked
          cargo download -x windows=$WINDOWS_RS_VERSION
          export CARGO_INCREMENTAL=0
          echo "" >> ../configs/common/mozconfig
          echo "export MOZ_WINDOWS_RS_DIR=$(pwd)/windows-$WINDOWS_RS_VERSION" >> ../configs/common/mozconfig

      - name: Build language packs
        if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
        run: sh scripts/download-language-packs.sh

      - name: Download artifact (if use profdata)
        uses: actions/download-artifact@v4
        if: ${{ !inputs.generate-gpo && matrix.arch == 'x86_64' }}
        with:
          path: ~/artifact
          name: windows-profdata-${{ matrix.arch == 'aarch64' && 'arm64' || matrix.arch }}

      - name: Show artifact info
        if: ${{ !inputs.generate-gpo && matrix.arch == 'x86_64' }}
        run: |
          ls ~/artifact
          ls ~/artifact/en-US.log
          ls ~/artifact/merged.profdata
          chmod +x ~/artifact/en-US.log
          chmod +x ~/artifact/merged.profdata

      - name: Build
        if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
        env:
          SURFER_COMPAT: ${{ matrix.arch }}
          ZEN_RELEASE_BRANCH: ${{ inputs.release-branch }}
          ZEN_SAFEBROWSING_API_KEY: ${{ secrets.ZEN_SAFEBROWSING_API_KEY }}
          ZEN_MOZILLA_API_KEY: ${{ secrets.ZEN_MOZILLA_API_KEY }}
          # Firefox doesn't support location service for Windows
          # ZEN_GOOGLE_LOCATION_SERVICE_API_KEY: ${{ secrets.ZEN_GOOGLE_LOCATION_SERVICE_API_KEY }}
        run: |
          set -x
          dos2unix configs/windows/mozconfig
          export SURFER_PLATFORM="win32"
          export ZEN_CROSS_COMPILING=1
          if test ${{ inputs.generate-gpo }} = true; then
            export ZEN_GA_GENERATE_PROFILE=1
          fi
          if [[ -n ${{ inputs.MOZ_BUILD_DATE }} ]];then
            export MOZ_BUILD_DATE=${{ inputs.MOZ_BUILD_DATE }}
          fi
          bash .github/workflows/src/release-build.sh

      - name: Package
        if: ${{ !(inputs.generate-gpo && matrix.arch == 'aarch64') }}
        env:
          SURFER_COMPAT: ${{ matrix.arch }}
          ZEN_GA_DISABLE_PGO: true
        run: |
          set -x
          export SURFER_PLATFORM="win32"
          export ZEN_CROSS_COMPILING=1
          export ZEN_RELEASE=1
          npm run package
          ls ./dist
          mv ./dist/zen-$(npm run --silent surfer -- get version | xargs).en-US.win64${{ matrix.arch == 'aarch64' && '-aarch64' || '' }}.zip zen.win64.zip
          ls .

      - name: Move package for PGO upload
        if: ${{ inputs.generate-gpo && matrix.arch == 'x86_64' }}
        run: |
          set -x
          mv ./zen.win64.zip ./zen.win64-pgo-stage-1.zip

      - name: Rename artifacts
        if: ${{ !inputs.generate-gpo }}
        run: |
          mv ./zen.win64.zip zen.win-${{ matrix.arch == 'aarch64' && 'arm64' || matrix.arch }}.zip
          mv ./dist/output.mar windows${{ matrix.arch == 'aarch64' && '-arm64' || '' }}.mar
          mv ./dist/zen.installer.exe ./zen.installer${{ matrix.arch == 'aarch64' && '-arm64' || '' }}.exe

      - name: Upload artifact (PGO)
        uses: actions/upload-artifact@v4
        if: ${{ inputs.generate-gpo && matrix.arch == 'x86_64' }}
        with:
          retention-days: 2
          name: ${{ matrix.arch == 'aarch64' && 'arm64' || matrix.arch }}-${{ inputs.profile-data-path-archive }}
          path: ./zen.win64-pgo-stage-1.zip

      - name: Remove unnecessary files from obj
        if: ${{ !inputs.generate-gpo }}
        run: |
          set -x
          mkdir obj-${{ matrix.arch }}-pc-windows-msvc/

          rm -rf engine/obj-${{ matrix.arch }}-pc-windows-msvc/_tests
          rm -rf engine/obj-${{ matrix.arch }}-pc-windows-msvc/config/autoconf.mk
          rm -rf engine/obj-${{ matrix.arch }}-pc-windows-msvc/config.statusd/substs/
          rm -rf engine/obj-${{ matrix.arch }}-pc-windows-msvc/dist/install

          find engine/obj-${{ matrix.arch }}-pc-windows-msvc/dist -maxdepth 1 -type f -name "*.zip" -delete

          cp -r --no-dereference engine/obj-${{ matrix.arch }}-pc-windows-msvc/* obj-${{ matrix.arch }}-pc-windows-msvc/ || true

      - name: Upload dist object
        if: ${{ !inputs.generate-gpo }}
        uses: actions/upload-artifact@v4
        with:
          retention-days: 2
          name: windows-x64-obj-${{ matrix.arch == 'aarch64' && 'arm64' || matrix.arch }}
          path: obj-${{ matrix.arch }}-pc-windows-msvc

      - name: Upload artifact (if Twilight branch, installer)
        if: ${{ inputs.release-branch == 'twilight' && !inputs.generate-gpo }}
        uses: actions/upload-artifact@v4
        with:
          retention-days: 5
          name: zen.installer${{ matrix.arch == 'aarch64' && '-arm64' ||  '' }}.exe
          path: ./zen.installer${{ matrix.arch == 'aarch64' && '-arm64' || '' }}.exe

      - name: Upload artifact (if Twilight branch, .mar)
        if: ${{ inputs.release-branch == 'twilight' && !inputs.generate-gpo }}
        uses: actions/upload-artifact@v4
        with:
          retention-days: 5
          name: windows${{ matrix.arch == 'aarch64' && '-arm64' || '' }}.mar
          path: ./windows${{ matrix.arch == 'aarch64' && '-arm64' || '' }}.mar

      - name: Upload artifact (if Twilight branch, update manifests)
        if: ${{ inputs.release-branch == 'twilight' && !inputs.generate-gpo }}
        uses: actions/upload-artifact@v4
        with:
          retention-days: 5
          name: windows_update_manifest_${{ matrix.arch == 'aarch64' && 'arm64' || matrix.arch }}
          path: ./dist/update
