---
name: Build

on:
  push:
    branches:
      - master
      - "bugfix-release/*"
      - "release/*"
  pull_request:
  workflow_dispatch:
    inputs:
      buildType:
        description: "Build type"
        required: true
        type: choice
        default: "auto"
        options:
          - auto
          - nightly
          - stable
  merge_group:

concurrency:
  group: build-${{ github.ref }}
  cancel-in-progress: true

env:
  C2_ENABLE_LTO: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/bugfix-release/') || startsWith(github.ref, 'refs/heads/release/') }}
  CHATTERINO_REQUIRE_CLEAN_GIT: On
  CHATTERINO_BUILD_TYPE: ${{ case(inputs.buildType != '', inputs.buildType, 'auto') }}
  CONAN_VERSION: 2.28.1

jobs:
  build-ubuntu-docker:
    # Our Ubuntu builds are built using Docker images that have been pre-published.
    # This speeds up builds for us since we do some pre-building of packages that takes a long time
    # However, this means if you need to add a dependency to the build, you'll need to do that
    # in the https://github.com/Chatterino/docker repository first.
    name: "Build Ubuntu in Docker"
    runs-on: ubuntu-latest
    container: ${{ matrix.container }}
    strategy:
      matrix:
        include:
          - os: ubuntu-22.04
            container: ghcr.io/chatterino/chatterino2-build-ubuntu-22.04:latest
            force-lto: false
            skip-artifact: false
            skip-crashpad: false
            build-deb: true
            plugins: true
          - os: ubuntu-24.04
            container: ghcr.io/chatterino/chatterino2-build-ubuntu-24.04:latest
            force-lto: false
            skip-artifact: false
            skip-crashpad: false
            build-deb: true
            plugins: true
          - os: ubuntu-24.04
            container: ghcr.io/chatterino/chatterino2-build-ubuntu-24.04:latest
            force-lto: false
            skip-artifact: false
            skip-crashpad: false
            build-deb: false
            plugins: false
          - os: ubuntu-26.04
            container: ghcr.io/chatterino/chatterino2-build-ubuntu-26.04:latest
            force-lto: false
            skip-artifact: false
            skip-crashpad: false
            build-deb: true
            plugins: true
    env:
      C2_ENABLE_LTO: ${{ matrix.force-lto }}
      C2_ENABLE_CRASHPAD: ${{ matrix.skip-crashpad == false }}

    steps:
      - uses: actions/checkout@v7
        with:
          submodules: recursive
          fetch-depth: 0 # allows for tags access

      - name: Fix git permission error
        run: |
          git config --global --add safe.directory '*'

      - name: Determine build type
        id: build-type
        shell: bash
        run: |
          if [ "${CHATTERINO_BUILD_TYPE}" = "auto" ]; then
            if git describe --exact-match --match 'v*'; then
              echo "Auto - found release tag format"
              echo "NIGHTLY_BUILD=Off" >> "$GITHUB_OUTPUT"
            else
              echo "Auto - did not find release tag format"
              echo "NIGHTLY_BUILD=On" >> "$GITHUB_OUTPUT"
            fi
          elif [ "${CHATTERINO_BUILD_TYPE}" = "nightly" ]; then
            echo "Override to nightly"
            echo "NIGHTLY_BUILD=On" >> "$GITHUB_OUTPUT"
          elif [ "${CHATTERINO_BUILD_TYPE}" = "stable" ]; then
            echo "Override to stable"
            echo "NIGHTLY_BUILD=Off" >> "$GITHUB_OUTPUT"
          else
            echo "Error: no build type variable set"
            exit 1
          fi

      - name: Build
        run: |
          mkdir build
          cd build
          CXXFLAGS=-fno-sized-deallocation cmake \
            -DCMAKE_INSTALL_PREFIX=appdir/usr/ \
            -DCMAKE_BUILD_TYPE=Release \
            -DPAJLADA_SETTINGS_USE_BOOST_FILESYSTEM=On \
            -DUSE_PRECOMPILED_HEADERS=OFF \
            -DCMAKE_EXPORT_COMPILE_COMMANDS=On \
            -DCHATTERINO_LTO="$C2_ENABLE_LTO" \
            -DCMAKE_PREFIX_PATH="$Qt6_DIR/lib/cmake" \
            -DCHATTERINO_STATIC_QT_BUILD=On \
            -DCHATTERINO_NIGHTLY_BUILD=${{ steps.build-type.outputs.NIGHTLY_BUILD }} \
            -DFORCE_JSON_GENERATION=Off \
            -DCHATTERINO_PLUGINS=${{ case(matrix.plugins, 'On', 'Off') }} \
            ..
          make -j"$(nproc)"

      - name: Package - .deb (Ubuntu)
        if: matrix.build-deb
        run: |
          cd build
          sh ./../.CI/CreateUbuntuDeb.sh

      - name: Upload artifact - .deb (Ubuntu)
        if: matrix.build-deb
        uses: actions/upload-artifact@v7
        with:
          name: Chatterino-${{ matrix.os }}.deb
          path: build/Chatterino-${{ matrix.os }}-x86_64.deb

  build:
    name: "Build ${{ matrix.os }}, Qt ${{ matrix.qt-version }} (LTO:${{ matrix.force-lto }}, crashpad:${{ case(matrix.skip-crashpad, 'off', 'on') }})"
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          # macOS
          - os: macos-26
            qt-version: 6.11.1
            force-lto: false
            skip-artifact: false
            skip-crashpad: false
          # Windows
          - os: windows-latest
            qt-version: 6.8.3
            force-lto: false
            skip-artifact: false
            skip-crashpad: false

      fail-fast: false
    env:
      C2_ENABLE_LTO: ${{ matrix.force-lto }}
      C2_ENABLE_CRASHPAD: ${{ matrix.skip-crashpad == false }}

    steps:
      - uses: actions/checkout@v7
        with:
          submodules: recursive
          fetch-depth: 0 # allows for tags access

      - name: Determine build type
        id: build-type
        shell: bash
        run: |
          if [ "${CHATTERINO_BUILD_TYPE}" = "auto" ]; then
            if git describe --exact-match --match 'v*'; then
              echo "Auto - found release tag format"
              echo "NIGHTLY_BUILD=Off" >> "$GITHUB_OUTPUT"
            else
              echo "Auto - did not find release tag format"
              echo "NIGHTLY_BUILD=On" >> "$GITHUB_OUTPUT"
            fi
          elif [ "${CHATTERINO_BUILD_TYPE}" = "nightly" ]; then
            echo "Override to nightly"
            echo "NIGHTLY_BUILD=On" >> "$GITHUB_OUTPUT"
          elif [ "${CHATTERINO_BUILD_TYPE}" = "stable" ]; then
            echo "Override to stable"
            echo "NIGHTLY_BUILD=Off" >> "$GITHUB_OUTPUT"
          else
            echo "Error: no build type variable set"
            exit 1
          fi

      - name: Install Qt6
        if: startsWith(matrix.qt-version, '6.')
        uses: jurplel/install-qt-action@v4.3.1
        with:
          cache: true
          cache-key-prefix: ${{ runner.os }}-QtCache-${{ matrix.qt-version }}-v2
          modules: qtimageformats
          version: ${{ matrix.qt-version }}

      # WINDOWS
      - name: Enable Developer Command Prompt (Windows)
        if: startsWith(matrix.os, 'windows')
        uses: Chatterino/msvc-dev-cmd@v2.0.7

      - name: Setup sccache (Windows)
        # sccache v0.7.4
        uses: hendrikmuhs/ccache-action@v1.2.23
        if: startsWith(matrix.os, 'windows')
        with:
          variant: sccache
          # only save on on the default (master) branch
          save: ${{ github.event_name == 'push' }}
          key: sccache-build-${{ matrix.os }}-${{ matrix.qt-version }}-${{ matrix.skip-crashpad }}
          restore-keys: |
            sccache-build-${{ matrix.os }}-${{ matrix.qt-version }}

      - name: Cache conan packages (Windows)
        if: startsWith(matrix.os, 'windows')
        uses: actions/cache@v6
        with:
          key: ${{ runner.os }}-conan-user-${{ hashFiles('**/conanfile.py') }}-QT6
          path: ~/.conan2/

      - name: Install Conan (Windows)
        if: startsWith(matrix.os, 'windows')
        run: |
          python3 -c "import site; import sys; print(f'{site.USER_BASE}\\Python{sys.version_info.major}{sys.version_info.minor}\\Scripts')" >> "$GITHUB_PATH"
          pip3 install --user "conan==${{ env.CONAN_VERSION }}"
        shell: powershell

      - name: Setup Conan (Windows)
        if: startsWith(matrix.os, 'windows')
        run: |
          conan --version
          conan profile detect -f
        shell: powershell

      - name: Install dependencies (Windows)
        if: startsWith(matrix.os, 'windows')
        run: |
          mkdir build
          cd build
          conan install .. `
              -s build_type=RelWithDebInfo `
              -c tools.cmake.cmaketoolchain:generator="NMake Makefiles" `
              -b missing `
              --output-folder=. `
              -o with_openssl3="True"
        shell: powershell

      - name: Build (Windows)
        if: startsWith(matrix.os, 'windows')
        shell: pwsh
        run: |
          cd build
          cmake `
              -G"NMake Makefiles" `
              -DCMAKE_BUILD_TYPE=RelWithDebInfo `
              -DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake" `
              -DUSE_PRECOMPILED_HEADERS=ON `
              -DBUILD_WITH_CRASHPAD="$Env:C2_ENABLE_CRASHPAD" `
              -DCHATTERINO_LTO="$Env:C2_ENABLE_LTO" `
              -DCHATTERINO_NIGHTLY_BUILD="${{ steps.build-type.outputs.NIGHTLY_BUILD }}" `
              -DFORCE_JSON_GENERATION=Off `
              -DCHATTERINO_SPELLCHECK=On `
              ..
          set cl=/MP
          nmake /S /NOLOGO

      - name: Build crashpad (Windows)
        if: startsWith(matrix.os, 'windows') && !matrix.skip-crashpad
        shell: pwsh
        run: |
          cd build
          set cl=/MP
          nmake /S /NOLOGO chatterino-crash-handler
          mkdir Chatterino2/crashpad
          cp bin/crashpad/crashpad-handler.exe Chatterino2/crashpad/crashpad-handler.exe
          7z a bin/chatterino-Qt-${{ matrix.qt-version }}.pdb.7z bin/chatterino.pdb

      - name: Prepare build dir (windows)
        if: startsWith(matrix.os, 'windows')
        run: |
          cd build
          windeployqt bin/chatterino.exe --release --no-compiler-runtime --no-translations --no-opengl-sw --force-openssl --dir Chatterino2/
          cp bin/chatterino.exe Chatterino2/
          ..\.CI\deploy-crt.ps1 Chatterino2

      - name: Package (windows)
        if: startsWith(matrix.os, 'windows')
        working-directory: build
        run: |
          7z a chatterino-windows-x86-64-Qt-${{ matrix.qt-version }}.zip Chatterino2/

      - name: Upload artifact (Windows - binary)
        if: startsWith(matrix.os, 'windows') && !matrix.skip-artifact
        uses: actions/upload-artifact@v7
        with:
          name: chatterino-windows-x86-64-Qt-${{ matrix.qt-version }}.zip
          path: build/chatterino-windows-x86-64-Qt-${{ matrix.qt-version }}.zip

      - name: Upload artifact (Windows - symbols)
        if: startsWith(matrix.os, 'windows') && !matrix.skip-artifact
        uses: actions/upload-artifact@v7
        with:
          name: chatterino-windows-x86-64-Qt-${{ matrix.qt-version }}-symbols.pdb.7z
          path: build/bin/chatterino-Qt-${{ matrix.qt-version }}.pdb.7z

      - name: Clean Conan cache
        if: startsWith(matrix.os, 'windows')
        run: conan cache clean --source --build --download "*"
        shell: bash

      # MACOS
      - name: Install dependencies (MacOS)
        if: startsWith(matrix.os, 'macos')
        run: |
          # brew install openssl rapidjson p7zip create-dmg cmake tree boost hunspell
          brew install openssl rapidjson p7zip create-dmg tree boost hunspell
        shell: bash

      - name: Build (MacOS)
        if: startsWith(matrix.os, 'macos')
        run: |
          mkdir build
          cd build
          cmake \
              -DCMAKE_BUILD_TYPE=Release \
              -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 \
              -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl \
              -DUSE_PRECOMPILED_HEADERS=OFF \
              -DCHATTERINO_LTO="$C2_ENABLE_LTO" \
              -DFORCE_JSON_GENERATION=Off \
              -DCHATTERINO_NIGHTLY_BUILD=${{ steps.build-type.outputs.NIGHTLY_BUILD }} \
              -DCHATTERINO_SPELLCHECK=On \
              ..
          make -j"$(sysctl -n hw.logicalcpu)"
        shell: bash

      - name: Package (MacOS)
        if: startsWith(matrix.os, 'macos')
        env:
          OUTPUT_DMG_PATH: chatterino-macos-Qt-${{ matrix.qt-version}}.dmg
        run: |
          ls -la
          pwd
          ls -la build || true
          cd build
          ./../.CI/MacDeploy.sh
          ./../.CI/CreateDMG.sh
        shell: bash

      - name: Upload artifact (MacOS)
        if: startsWith(matrix.os, 'macos')
        uses: actions/upload-artifact@v7
        with:
          name: chatterino-macos-Qt-${{ matrix.qt-version }}.dmg
          path: build/chatterino-macos-Qt-${{ matrix.qt-version }}.dmg

  create-release:
    needs: [build-ubuntu-docker, build]
    runs-on: ubuntu-latest
    if: (github.event_name == 'push' && github.ref == 'refs/heads/master')

    steps:
      - uses: actions/checkout@v7
        with:
          fetch-depth: 0 # allows for tags access

      - uses: actions/download-artifact@v8
        name: Download artifacts
        with:
          path: release-artifacts/
          merge-multiple: true

      - name: Copy flatpakref
        run: |
          cp .CI/chatterino-nightly.flatpakref release-artifacts/
        shell: bash

      - name: Remove macOS artifacts
        run: |
          rm -f release-artifacts/*macos*.dmg
        shell: bash

      - name: Setup Python
        uses: actions/setup-python@v7
        with:
          python-version: "3.12"

      - name: Format changes
        id: format-changes
        run: |
          delimiter=$(openssl rand -hex 32)
          {
            echo "changelog<<$delimiter"
            python3 ./.CI/format-recent-changes.py
            echo $delimiter
          } >> "$GITHUB_OUTPUT"
        shell: bash

      - name: Create release
        uses: ncipollo/release-action@v1.21.0
        with:
          replacesArtifacts: true
          allowUpdates: true
          artifactErrorsFailBuild: true
          artifacts: "release-artifacts/*"
          body: ${{ steps.format-changes.outputs.changelog }}
          prerelease: true
          name: Nightly Release
          tag: nightly-build

      - name: Update nightly-build tag
        run: |
          git tag -f nightly-build
          git push -f origin nightly-build
        shell: bash
