name: Build Artifacts (macOS)
on:
  workflow_dispatch:
    inputs:
      logLevel:
        description: 'Log level'
        required: true
        default: 'warning'
        type: choice
        options:
        - info
        - warning
        - debug
      tags:
        description: 'Test scenario tags'
        required: false
        type: boolean
  pull_request:
    branches: [master, develop]
    paths-ignore:
    - '**/*.md'
    - '.circleci/**'
    - '.cirrus.yml'
  push:
    branches: [master, develop, macos]
    paths-ignore:
    - '**/*.md'
    - '.circleci/**'
    - '.cirrus.yml'
  release:
    types: [published]
  schedule:
    - cron: '0 16 * * *'
concurrency:
  group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.run_id }}
  cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
env:
  CACHE_EPOCH: 148-2
  GOPROXY: direct
jobs:
  mac-release:
    runs-on: macos-26
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - arch: x64
            build_type: Release
            xcode_version: 26.4.1
            build_options: -use-allocator=system
          - arch: arm64
            build_type: Release
            xcode_version: 26.4.1
            build_options: -use-allocator=system
    env:
      BUILD_TYPE: '${{ matrix.build_type }}'
    steps:
      - uses: actions/checkout@v5
      - name: Checkout with shallow submodules
        run: |
          # unshallow must come first otherwise submodule may be get unshallowed
          git fetch --tags --unshallow
          git submodule update --init --depth 1
      - name: Cache toolchain
        id: toolchain-cache
        uses: actions/cache@v5
        with:
          path: |
            third_party/llvm-build/Release+Asserts
          key: ${{ runner.os }}-toolchain-${{ matrix.arch }}-${{ hashFiles('CLANG_REVISION') }}-v${{ env.CACHE_EPOCH }}
      - uses: actions/setup-go@v6
        with:
          go-version: '>=1.20.0'
          cache-dependency-path: |
            tools/go.sum
            third_party/boringssl/src/go.sum
      - name: Build build tool
        run: |
          cd tools
          go build
      - name: "Install dependency: prebuilt clang and clang-tidy binaries"
        if: ${{ steps.toolchain-cache.outputs.cache-hit != 'true' }}
        run: |
          ./scripts/download-clang-prebuilt-binaries.py
          rm -f third_party/llvm-build/Release+Asserts/*.tgz
      - name: Set up Xcode version
        run: |
          sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode_version }}.app
      - name: Install the Apple certificate
        if: ${{ false && github.event_name == 'release' }}
        env:
          BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
          P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
        run: |
          # create variables
          CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
          KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db

          # import certificate and provisioning profile from secrets
          echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH

          # create temporary keychain
          security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
          security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
          security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH

          # import certificate to keychain
          security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
          security list-keychain -d user -s $KEYCHAIN_PATH

          echo "CODESIGN_IDENTITY=Developer ID Application" >> $GITHUB_ENV
          echo "KEYCHAIN_PATH=$KEYCHAIN_PATH" >> $GITHUB_ENV
      - name: Build Binary (GUI)
        run: |
          ./tools/build --arch ${{ matrix.arch }} -build-test -build-benchmark ${{ matrix.build_options }}
      - name: Clean up keychain and provisioning profile
        if: ${{ always() }}
        run: |
          if [ ! -z $KEYCHAIN_PATH ]; then
            security delete-keychain $KEYCHAIN_PATH
          fi
      - uses: actions/upload-artifact@v6
        with:
          name: darwin-release-${{ matrix.build_type }}-${{ matrix.arch }}-${{ github.run_id }}-app
          path: |
            build-darwin-${{ matrix.arch }}/yass.app
      - uses: actions/upload-artifact@v6
        with:
          name: darwin-release-${{ matrix.build_type }}-${{ matrix.arch }}-${{ github.run_id }}-dmg
          path: |
            *.dmg
          compression-level: 0 # no compression
      - uses: actions/upload-artifact@v6
        with:
          name: darwin-release-${{ matrix.build_type }}-${{ matrix.arch }}-${{ github.run_id }}-test
          path: |
            build-darwin-${{ matrix.arch }}/yass_test
            build-darwin-${{ matrix.arch }}/*.dylib
      - uses: actions/upload-artifact@v6
        with:
          name: darwin-release-${{ matrix.build_type }}-${{ matrix.arch }}-${{ github.run_id }}-benchmark
          path: |
            build-darwin-${{ matrix.arch }}/yass_benchmark
            build-darwin-${{ matrix.arch }}/*.dylib
      - uses: actions/upload-artifact@v6
        with:
          name: darwin-release-${{ matrix.build_type }}-${{ matrix.arch }}-${{ github.run_id }}-dSYM
          path: |
            build-darwin-${{ matrix.arch }}/*.dSYM
          compression-level: 9 # maximum compression
      - name: Install rosetta
        if: ${{ matrix.arch == 'x64' }}
        run: |
          /usr/sbin/softwareupdate --install-rosetta --agree-to-license
      - name: Run tests
        run: |
          ./build-darwin-${{ matrix.arch }}/yass_test
      - name: Upload dist tarball (including debuginfo)
        if: ${{ false && github.event_name == 'release' && matrix.build_type == 'Release' }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release upload ${{ github.event.release.tag_name }} *.dmg *.zip
  mac-release-native-arm64-test:
    runs-on: macos-26
    needs: mac-release
    strategy:
      fail-fast: false
      matrix:
        include:
          - arch: arm64
            build_type: Release
            gtest_repeat_times: 10
    steps:
      - name: Download built executables
        uses: actions/download-artifact@v7
        with:
          name: darwin-release-${{ matrix.build_type }}-${{ matrix.arch }}-${{ github.run_id }}-test
      - name: Run tests
        run: |
          xattr -d com.apple.quarantine yass_test || :
          chmod 755 yass_test
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks4
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks4a
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks5
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks5h
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type http
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks4a --ipv6_mode
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks5 --ipv6_mode
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks5h --ipv6_mode
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type http --ipv6_mode
  mac-release-native-intel-test:
    runs-on: macos-26-intel
    needs: mac-release
    strategy:
      fail-fast: false
      matrix:
        include:
          - arch: x64
            build_type: Release
            gtest_repeat_times: 10
    steps:
      - name: Download built executables
        uses: actions/download-artifact@v7
        with:
          name: darwin-release-${{ matrix.build_type }}-${{ matrix.arch }}-${{ github.run_id }}-test
      - name: Run tests
        run: |
          xattr -d com.apple.quarantine yass_test || :
          chmod 755 yass_test
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks4
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks4a
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks5
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks5h
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type http
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks4a --ipv6_mode
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks5 --ipv6_mode
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type socks5h --ipv6_mode
          ./yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type http --ipv6_mode
  mac-release-native-arm64-benchmark:
    runs-on: macos-26
    needs: mac-release
    strategy:
      fail-fast: false
      matrix:
        include:
          - arch: arm64
            build_type: Release
            benchmark_min_time: 1000x
    steps:
      - name: Download built executables
        uses: actions/download-artifact@v7
        with:
          name: darwin-release-${{ matrix.build_type }}-${{ matrix.arch }}-${{ github.run_id }}-benchmark
      - name: Run benchmarks
        run: |
          xattr -d com.apple.quarantine yass_benchmark || :
          chmod 755 yass_benchmark
          ./yass_benchmark --benchmark_min_time=${{ matrix.benchmark_min_time }}
