name: 📦🚀 Build Installers - MacOS

on:
  workflow_dispatch:
    inputs:
      release_type:
        description: "Tagged release testing scenario"
        required: false
        type: choice
        default: ""
        options:
          - ""
          - 9.9.9-b1
          - 9.9.9-rc1
          - 9.9.9
  push:
    paths-ignore:
      - "**.md"
    branches:
      - "long_lived/**"
      - main
      - "release/**"
  release:
    types: [published]
  pull_request:
    paths-ignore:
      - "**.md"
    branches:
      - "**"

concurrency:
  # SHA is added to the end if on `main` to let all main workflows run
  group: ${{ github.ref }}-${{ github.workflow }}-${{ github.event_name }}-${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.ref, 'refs/heads/long_lived/')) && github.sha || '' }}
  cancel-in-progress: true

permissions:
  id-token: write
  contents: write

jobs:
  version:
    uses: ./.github/workflows/reflow-version.yml

  build:
    name: Build ${{ matrix.os.name }} DMG
    runs-on: ${{ matrix.os.runs-on }}
    needs:
      - version
    timeout-minutes: 90
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.10"]
        os:
          - runs-on: macos-12
            name: intel
            bladebit-suffix: macos-x86-64.tar.gz
            arch-artifact-name: intel
          - runs-on: macos-13-arm64
            name: m1
            bladebit-suffix: macos-arm64.tar.gz
            arch-artifact-name: arm

    env:
      CHIA_INSTALLER_VERSION: ${{ needs.version.outputs.chia-installer-version }}
      SETUPTOOLS_SCM_PRETEND_VERSION_FOR_CHIA_BLOCKCHAIN: ${{ needs.version.outputs.chia-installer-version }}
      TAG_TYPE: ${{ needs.version.outputs.tag-type }}

    steps:
      - uses: Chia-Network/actions/clean-workspace@main

      - name: Checkout Code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          submodules: recursive

      - uses: Chia-Network/actions/git-ssh-to-https@main

      - name: Cleanup any leftovers that exist from previous runs
        run: bash build_scripts/clean-runner.sh || true

      - name: Set Env
        uses: Chia-Network/actions/setjobenv@main
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          MACOSX_DEPLOYMENT_TARGET: 12

      - name: Test for secrets access
        id: check_secrets
        shell: bash
        run: |
          unset HAS_APPLE_SECRET

          if [ -n "$APPLE_SECRET" ]; then HAS_APPLE_SECRET='true' ; fi
          echo HAS_APPLE_SECRET=${HAS_APPLE_SECRET} >> "$GITHUB_OUTPUT"
        env:
          APPLE_SECRET: "${{ secrets.APPLE_DEV_ID_APP }}"

      - name: Setup Python environment
        uses: Chia-Network/actions/setup-python@main
        with:
          python-version: ${{ matrix.python-version }}

      # This will be recreated in the next step
      # Done now and at the end of the workflow in case the last workflow fails, and this is still around
      - name: Delete keychain if it already exists
        run: security delete-keychain signing_temp.keychain || true

      - name: Import Apple app signing certificate
        if: steps.check_secrets.outputs.HAS_APPLE_SECRET
        uses: Apple-Actions/import-codesign-certs@v3
        with:
          p12-file-base64: ${{ secrets.APPLE_DEV_ID_APP }}
          p12-password: ${{ secrets.APPLE_DEV_ID_APP_PASS }}

      - name: Get latest madmax plotter
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          LATEST_MADMAX=$(gh api repos/Chia-Network/chia-plotter-madmax/releases/latest --jq 'select(.prerelease == false) | .tag_name')
          mkdir "$GITHUB_WORKSPACE"/madmax
          gh release download -R Chia-Network/chia-plotter-madmax "$LATEST_MADMAX" -p 'chia_plot-'$LATEST_MADMAX'-macos-${{ matrix.os.name }}'
          mv chia_plot-$LATEST_MADMAX-macos-${{ matrix.os.name }} "$GITHUB_WORKSPACE"/madmax/chia_plot
          gh release download -R Chia-Network/chia-plotter-madmax "$LATEST_MADMAX" -p 'chia_plot_k34-'$LATEST_MADMAX'-macos-${{ matrix.os.name }}'
          mv chia_plot_k34-$LATEST_MADMAX-macos-${{ matrix.os.name }} "$GITHUB_WORKSPACE"/madmax/chia_plot_k34
          chmod +x "$GITHUB_WORKSPACE"/madmax/chia_plot
          chmod +x "$GITHUB_WORKSPACE"/madmax/chia_plot_k34

      - name: Fetch bladebit versions
        shell: bash
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Fetch the latest version of each type
          LATEST_RELEASE=$(gh api repos/Chia-Network/bladebit/releases/latest --jq 'select(.prerelease == false) | .tag_name')
          LATEST_BETA=$(gh api repos/Chia-Network/bladebit/releases --jq 'map(select(.prerelease) | select(.tag_name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+-beta[0-9]+$"))) | first | .tag_name')
          LATEST_RC=$(gh api repos/Chia-Network/bladebit/releases --jq 'map(select(.prerelease) | select(.tag_name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+-rc[0-9]+$"))) | first | .tag_name')

          # Compare the versions and choose the newest that matches the requirements
          if [[ "$TAG_TYPE" == "beta" || -z "$TAG_TYPE" ]]; then
            # For beta or dev builds (indicated by the absence of a tag), use the latest version available
            LATEST_VERSION=$(printf "%s\n%s\n%s\n" "$LATEST_RELEASE" "$LATEST_BETA" "$LATEST_RC" | sed '/-/!s/$/_/' | sort -V | sed 's/_$//' | tail -n 1)
          elif [[ "$TAG_TYPE" == "rc" ]]; then
            # For RC builds, use the latest RC or full release if it's newer
            LATEST_VERSION=$(printf "%s\n%s\n" "$LATEST_RELEASE" "$LATEST_RC" | sed '/-/!s/$/_/' | sort -V | sed 's/_$//' | tail -n 1)
          else
            # For full releases, use the latest full release
            LATEST_VERSION="$LATEST_RELEASE"
          fi
          echo "LATEST_VERSION=$LATEST_VERSION" >> "$GITHUB_ENV"

      - name: Get latest bladebit plotter
        shell: bash
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Download and extract the chosen version
          mkdir "$GITHUB_WORKSPACE"/bladebit
          cd "$GITHUB_WORKSPACE"/bladebit
          ASSETS=$(gh release view "$LATEST_VERSION" --repo Chia-Network/bladebit --json assets -q '.assets[].name')
              if ! echo "$ASSETS" | grep -q 'bladebit.*-${{ matrix.os.bladebit-suffix }}'; then
                LATEST_VERSION=v2.0.1
              fi
          gh release download -R Chia-Network/bladebit "$LATEST_VERSION" -p 'bladebit*-${{ matrix.os.bladebit-suffix }}'
          ls *.tar.gz | xargs -I{} bash -c 'tar -xzf {} && rm {}'
          ls bladebit* | xargs -I{} chmod +x {}
          cd "$OLDPWD"

      - uses: ./.github/actions/install
        with:
          python-version: ${{ matrix.python-version }}
          development: true
          constraints-file-artifact-name: constraints-file-${{ matrix.os.arch-artifact-name }}

      - uses: chia-network/actions/activate-venv@main

      - name: Setup Node 18.x
        uses: actions/setup-node@v4
        with:
          node-version: "18.x"

      - name: Prepare GUI cache
        id: gui-ref
        run: |
          gui_ref=$(git submodule status chia-blockchain-gui | sed -e 's/^ //g' -e 's/ chia-blockchain-gui.*$//g')
          echo "${gui_ref}"
          echo "GUI_REF=${gui_ref}" >> "$GITHUB_OUTPUT"
          echo "rm -rf ./chia-blockchain-gui"
          rm -rf ./chia-blockchain-gui

      - name: Cache GUI
        uses: actions/cache@v4
        id: cache-gui
        with:
          path: ./chia-blockchain-gui
          key: ${{ runner.os }}-${{ matrix.os.name }}-chia-blockchain-gui-${{ steps.gui-ref.outputs.GUI_REF }}

      - if: steps.cache-gui.outputs.cache-hit != 'true'
        name: Build GUI
        continue-on-error: false
        run: |
          cd ./build_scripts
          sh build_macos-1-gui.sh

      - name: Build MacOS DMG
        env:
          NOTARIZE: ${{ steps.check_secrets.outputs.HAS_APPLE_SECRET }}
          APPLE_NOTARIZE_USERNAME: "${{ secrets.APPLE_NOTARIZE_USERNAME }}"
          APPLE_NOTARIZE_PASSWORD: "${{ secrets.APPLE_NOTARIZE_PASSWORD }}"
          APPLE_TEAM_ID: "${{ secrets.APPLE_TEAM_ID }}"
          APPLE_DEV_ID_APP: "${{ secrets.APPLE_DEV_ID_APP }}"
          APPLE_DEV_ID_APP_PASS: "${{ secrets.APPLE_DEV_ID_APP_PASS }}"
        run: |
          cd ./build_scripts
          sh build_macos-2-installer.sh

      - name: Upload MacOS artifacts
        uses: actions/upload-artifact@v4
        with:
          name: chia-installers-macos-dmg-${{ matrix.os.arch-artifact-name }}
          path: build_scripts/final_installer/

      - name: Remove working files to exclude from cache
        run: |
          rm -rf ./chia-blockchain-gui/packages/gui/daemon

      # We want to delete this no matter what happened in the previous steps (failures, success, etc)
      - name: Delete signing keychain
        if: always()
        run: security delete-keychain signing_temp.keychain || true

  publish:
    name: 📦 Publish Installers
    uses: ./.github/workflows/reflow-publish-installer.yml
    with:
      concurrency-name: macos
      chia-installer-version: ${{ needs.version.outputs.chia-installer-version }}
      chia-dev-version: ${{ needs.version.outputs.chia-dev-version }}
      configuration: ${{ toJSON( matrix.configuration ) }}
    secrets: inherit
    needs:
      - version
      - build
    strategy:
      fail-fast: false
      matrix:
        configuration:
          - python-version: ["3.10"]
            os:
              - matrix: macos
                file-type:
                  name: DMG
                  extension: dmg
                glue-name: macos
                artifact-platform-name: macos
                file-arch-name:
                  arm: m1
                  intel: intel
                file-suffix:
                  arm: "-arm64"
                  intel: ""
                names:
                  gui:
                    file: Chia-{0}{3}.dmg
                    dev-file: Chia-{1}{3}.dmg
                    latest-dev-file: Chia-{3}_latest_dev.dmg
            mode:
              - name: GUI
                matrix: gui
                glue-name: gui
              - name: CLI
                matrix: cli
                glue-name: cli
            arch:
              - name: ARM64
                matrix: arm
                artifact-name: arm
                glue-name: arm
              - name: Intel
                matrix: intel
                artifact-name: intel
                glue-name: intel
            exclude:
              - os:
                  matrix: macos
                mode:
                  matrix: cli

  test:
    name: Test ${{ matrix.os.name }} ${{ matrix.arch.name }}
    runs-on: ${{ matrix.os.runs-on[matrix.arch.matrix] }}
    needs:
      - version
      - build
    strategy:
      fail-fast: false
      matrix:
        os:
          - name: 12
            matrix: 12
            runs-on:
              intel: macos-12
          - name: 13
            matrix: 13
            runs-on:
              intel: macos-13
          - name: 14
            matrix: 14
            runs-on:
              arm: macos-14
        arch:
          - name: ARM64
            matrix: arm
            artifact-name: arm
          - name: Intel
            matrix: intel
            artifact-name: intel
        exclude:
          - os:
              matrix: 12
            arch:
              matrix: arm
          - os:
              matrix: 13
            arch:
              matrix: arm
          - os:
              matrix: 14
            arch:
              matrix: intel

    steps:
      - uses: Chia-Network/actions/clean-workspace@main

      - name: Download packages
        uses: actions/download-artifact@v4
        id: download
        with:
          name: chia-installers-macos-dmg-${{ matrix.arch.artifact-name }}
          path: packages

      - name: Mount .dmg
        env:
          PACKAGE_PATH: artifacts/
        run: |
          ls -l "${{ steps.download.outputs.download-path }}"
          hdiutil attach "${{ steps.download.outputs.download-path }}"/Chia-*.dmg

      - name: List .dmg contents
        run: |
          find "/Volumes/Chia "*

      - name: Test for homebrew rpath
        if: matrix.arch.name == 'ARM64'
        run: |
          ! otool -l "/Volumes/Chia "*/Chia.app/Contents/Resources/app.asar.unpacked/daemon/_internal/lib-dynload/_ssl.*darwin.so | grep /opt/homebrew/lib

      - name: Run chia dev installers test
        run: |
          "/Volumes/Chia "*"/Chia.app/Contents/Resources/app.asar.unpacked/daemon/chia" dev installers test --expected-chia-version "${{ needs.version.outputs.chia-installer-version }}"

      - name: Detach .dmg
        if: always()
        run: |
          hdiutil detach -force "/Volumes/Chia "*
