name: citra-build

on:
  push:
    branches: [ "*" ]
    tags: [ "*" ]
  pull_request:
    branches: [ master ]

permissions:
  id-token: write
  contents: read
  attestations: write

jobs:
  source:
    if: ${{ !github.head_ref }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
      - name: Pack
        run: ./.ci/source.sh
      - name: Generate SBOM
        if: ${{ github.ref_type == 'tag' }}
        uses: anchore/sbom-action@v0
        with:
          path: ./
          format: spdx-json
          output-file: artifacts/source.spdx.json
          upload-artifact: false
      - name: Upload
        uses: actions/upload-artifact@v4
        with:
          name: source
          path: artifacts/
      - name: Attest artifacts
        if: ${{ github.ref_type == 'tag' }}
        uses: actions/attest@v4
        with:
          subject-path: |
            artifacts/*.tar.xz
          sbom-path: artifacts/source.spdx.json

  linux-x86_64:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        target: ["appimage", "appimage-wayland", "gcc-nopch"]
    container:
      image: opensauce04/azahar-build-environment:latest
      options: -u 1001
    env:
      CCACHE_DIR: ${{ github.workspace }}/.ccache
      CCACHE_COMPILERCHECK: content
      CCACHE_SLOPPINESS: time_macros
      OS: linux
      TARGET: ${{ matrix.target }}
      SHOULD_RUN: ${{ (matrix.target != 'appimage-wayland' || github.ref_type == 'tag') }}
      CACHE_ENABLED: ${{ github.ref_type != 'tag' }}
    steps:
      - uses: actions/checkout@v4
        if: ${{ env.SHOULD_RUN == 'true' }}
        with:
          submodules: recursive
      - name: Set up cache
        if: ${{ env.SHOULD_RUN == 'true' && env.CACHE_ENABLED == 'true' }}
        uses: actions/cache@v4
        with:
          path: ${{ env.CCACHE_DIR }}
          key: ${{ github.job }}-${{ matrix.target }}-${{ github.sha }}
          restore-keys: |
            ${{ github.job }}-${{ matrix.target }}-
      - name: Build
        if: ${{ env.SHOULD_RUN == 'true' }}
        run: ./.ci/linux.sh
      - name: Move AppImage to artifacts directory
        if: ${{ contains(matrix.target, 'appimage') && env.SHOULD_RUN == 'true' }}
        run: |
          mkdir -p artifacts
          mv build/bundle/*.AppImage artifacts/
      - name: Rename AppImage
        if: ${{ matrix.target == 'appimage-wayland' && env.SHOULD_RUN == 'true' }}
        run: |
          mv artifacts/azahar.AppImage artifacts/azahar-wayland.AppImage
      - name: Generate SBOM
        if: ${{ contains(matrix.target, 'appimage') && github.ref_type == 'tag' && env.SHOULD_RUN == 'true' }}
        uses: anchore/sbom-action@v0
        with:
          path: build/
          format: spdx-json
          output-file: artifacts/linux-x86_64-${{ matrix.target }}.spdx.json
          upload-artifact: false
      - name: Upload
        if: ${{ contains(matrix.target, 'appimage') && env.SHOULD_RUN == 'true' }}
        uses: actions/upload-artifact@v4
        with:
          name: ${{ github.job }}-${{ matrix.target }}
          path: artifacts/
      - name: Attest artifacts
        if: ${{ contains(matrix.target, 'appimage') && github.ref_type == 'tag' && env.SHOULD_RUN == 'true' }}
        uses: actions/attest@v4
        with:
          subject-path: |
            artifacts/*.AppImage
          sbom-path: artifacts/linux-x86_64-${{ matrix.target }}.spdx.json

  linux-arm64:
    runs-on: ubuntu-24.04-arm
    strategy:
      fail-fast: false
      matrix:
        target: ["clang", "gcc-nopch"]
    container:
      image: opensauce04/azahar-build-environment:latest
      options: -u 1001
    env:
      CCACHE_DIR: ${{ github.workspace }}/.ccache
      CCACHE_COMPILERCHECK: content
      CCACHE_SLOPPINESS: time_macros
      OS: linux
      TARGET: ${{ matrix.target }}
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
      - name: Set up cache
        uses: actions/cache@v4
        with:
          path: ${{ env.CCACHE_DIR }}
          key: ${{ github.job }}-${{ matrix.target }}-${{ github.sha }}
          restore-keys: |
            ${{ github.job }}-${{ matrix.target }}-
      - name: Build
        run: ./.ci/linux.sh

  macos:
    runs-on: 'macos-26'
    env:
      CCACHE_DIR: ${{ github.workspace }}/.ccache
      CCACHE_COMPILERCHECK: content
      CCACHE_SLOPPINESS: time_macros
      CACHE_ENABLED: ${{ github.ref_type != 'tag' }}
      OS: macos
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
      - name: Set up cache
        if: ${{ env.CACHE_ENABLED == 'true' }}
        uses: actions/cache@v4
        with:
          path: ${{ env.CCACHE_DIR }}
          key: ${{ runner.os }}-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-
      - name: Install tools
        run: brew install ccache ninja spirv-tools
      - name: Build (x86_64)
        run: BUILD_ARCH=x86_64 ./.ci/macos.sh
      - name: Build (arm64)
        run: BUILD_ARCH=arm64 ./.ci/macos.sh
      - name: Create universal app
        run: ./.ci/macos-universal.sh
      - name: Prepare for packing
        run: |
          mkdir build/bundle
          cp -r build/x86_64/bundle build/bundle/x86_64
          cp -r build/arm64/bundle build/bundle/arm64
          cp -r build/universal/bundle build/bundle/universal
      - name: Pack
        env:
          PACK_INDIVIDUALLY: 1
        run: ./.ci/pack.sh
      - name: Generate SBOM
        if: ${{ github.ref_type == 'tag' }}
        uses: anchore/sbom-action@v0
        with:
          path: build/
          format: spdx-json
          output-file: artifacts/macos.spdx.json
          upload-artifact: false
      - name: Upload
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.OS }}
          path: artifacts/
      - name: Attest artifacts
        if: ${{ github.ref_type == 'tag' }}
        uses: actions/attest@v4
        with:
          subject-path: |
            artifacts/*.zip
          sbom-path: artifacts/macos.spdx.json

  windows:
    runs-on: windows-2022
    strategy:
      fail-fast: false
      matrix:
        target: ["msvc", "msys2"]
    defaults:
      run:
        shell: ${{ (matrix.target == 'msys2' && 'msys2') || 'bash' }} {0}
    env:
      CCACHE_DIR: ${{ github.workspace }}/.ccache
      CCACHE_COMPILERCHECK: content
      CCACHE_SLOPPINESS: time_macros
      CACHE_ENABLED: ${{ github.ref_type != 'tag' }}
      OS: windows
      TARGET: ${{ matrix.target }}
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
      - name: Set up cache
        if: ${{ env.CACHE_ENABLED == 'true' }}
        uses: actions/cache@v4
        with:
          path: ${{ env.CCACHE_DIR }}
          key: ${{ runner.os }}-${{ matrix.target }}-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-${{ matrix.target }}-
      - name: Set up MSVC
        if: ${{ matrix.target == 'msvc' }}
        uses: ilammy/msvc-dev-cmd@v1
      - name: Install extra tools (MSVC)
        if: ${{ matrix.target == 'msvc' }}
        run: choco install ccache ninja ptime wget
      - name: Install vulkan-sdk (MSVC)
        if: ${{ matrix.target == 'msvc' }}
        run: |
          wget https://sdk.lunarg.com/sdk/download/1.4.304.1/windows/VulkanSDK-1.4.304.1-Installer.exe -O D:/a/_temp/vulkan.exe
          D:/a/_temp/vulkan.exe --accept-licenses --default-answer --confirm-command install
      - name: Set up MSYS2
        if: ${{ matrix.target == 'msys2' }}
        uses: msys2/setup-msys2@v2
        with:
          msystem: clang64
          update: true
          install: git make p7zip
          pacboy: >-
            toolchain:p ccache:p cmake:p ninja:p spirv-tools:p
            qt6-base:p qt6-multimedia:p qt6-multimedia-wmf:p qt6-tools:p qt6-translations:p
      - name: Install extra tools (MSYS2)
        if: ${{ matrix.target == 'msys2' }}
        uses: crazy-max/ghaction-chocolatey@v3
        with:
          args: install ptime wget
      - name: Install NSIS
        if: ${{ github.ref_type == 'tag' }}
        run: |
          wget https://download.sourceforge.net/project/nsis/NSIS%203/3.11/nsis-3.11-setup.exe -O D:/a/_temp/nsis-setup.exe
          ptime D:/a/_temp/nsis-setup.exe /S
        shell: pwsh
      - name: Disable line ending translation
        run: git config --global core.autocrlf input
      - name: Build
        run: ./.ci/windows.sh
      - name: Generate installer
        if: ${{ github.ref_type == 'tag' }}
        run: |
          cd src\installer
          "C:\Program Files (x86)\NSIS\makensis.exe" /DPRODUCT_VARIANT=${{ matrix.target }} /DPRODUCT_VERSION=${{ github.ref_name }} citra.nsi
          mkdir ..\..\artifacts 2> NUL
          move /y *.exe ..\..\artifacts\
        shell: cmd
      - name: Pack
        run: ./.ci/pack.sh
      - name: Generate SBOM
        if: ${{ github.ref_type == 'tag' }}
        uses: anchore/sbom-action@v0
        with:
          path: build/
          format: spdx-json
          output-file: artifacts/windows-${{ matrix.target }}.spdx.json
          upload-artifact: false
      - name: Upload
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.OS }}-${{ env.TARGET }}
          path: artifacts/
      - name: Attest artifacts
        if: ${{ github.ref_type == 'tag' }}
        uses: actions/attest@v4
        with:
          subject-path: |
            artifacts/*.zip
            artifacts/*.exe
          sbom-path: artifacts/windows-${{ matrix.target }}.spdx.json

  android:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        target: ["vanilla", "googleplay"]
    env:
      CCACHE_DIR: ${{ github.workspace }}/.ccache
      CCACHE_COMPILERCHECK: content
      CCACHE_SLOPPINESS: time_macros
      CACHE_ENABLED: ${{ github.ref_type != 'tag' }}
      OS: android
      TARGET: ${{ matrix.target }}
      SHOULD_RUN: ${{ (matrix.target == 'vanilla' || github.ref_type == 'tag') }}
    steps:
      - uses: actions/checkout@v4
        if: ${{ env.SHOULD_RUN == 'true' }}
        with:
          submodules: recursive
      - name: Set up cache
        if: ${{ env.SHOULD_RUN == 'true' && env.CACHE_ENABLED == 'true' }}
        uses: actions/cache@v4
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
            ${{ env.CCACHE_DIR }}
          key: ${{ runner.os }}-${{ env.OS }}-${{ matrix.target }}-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-${{ env.OS }}-${{ matrix.target }}-
      - name: Set tag name
        if: ${{ env.SHOULD_RUN == 'true' }}
        run: |
          if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then
              echo "GIT_TAG_NAME=$GITHUB_REF_NAME" >> $GITHUB_ENV
          fi
          echo $GIT_TAG_NAME
      - name: Install tools
        if: ${{ env.SHOULD_RUN == 'true' }}
        run: |
          sudo apt-get update -y
          sudo apt-get install ccache apksigner -y
      - name: Update Android SDK CMake version
        if: ${{ env.SHOULD_RUN == 'true' }}
        run: |
          echo "y" | ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager "cmake;3.30.3"
      - name: Build
        if: ${{ env.SHOULD_RUN == 'true' }}
        run: JAVA_HOME=$JAVA_HOME_17_X64 ./.ci/android.sh
        env:
          ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }}
          ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
          ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
      - name: Pack
        if: ${{ env.SHOULD_RUN == 'true' }}
        run: ../../../.ci/pack.sh
        working-directory: src/android/app
        env:
          UNPACKED: 1
      - name: Generate SBOM
        if: ${{ github.ref_type == 'tag' }}
        uses: anchore/sbom-action@v0
        with:
          path: src/android
          format: spdx-json
          output-file: src/android/app/artifacts/android-${{ matrix.target }}.spdx.json
          upload-artifact: false
      - name: Upload
        if: ${{ env.SHOULD_RUN == 'true' }}
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.OS }}-${{ env.TARGET }}
          path: src/android/app/artifacts/
      - name: Attest artifacts
        if: ${{ github.ref_type == 'tag' }}
        uses: actions/attest@v4
        with:
          subject-path: |
            src/android/app/artifacts/*.apk
            src/android/app/artifacts/*.aab
          sbom-path: src/android/app/artifacts/android-${{ matrix.target }}.spdx.json

  docker:
    runs-on: ubuntu-latest
    container:
      image: docker:dind
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
      - name: Install tools
        run: apk add bash
      - name: Fix git ownership
        run: git config --global --add safe.directory .
      - name: Build Docker image
        run: ./.ci/docker.sh
      - name: Move Docker image to artifacts directory
        run: |
          mkdir -p artifacts
          mv build/*.dockerimage artifacts/
      - name: Generate SBOM
        if: ${{ github.ref_type == 'tag' }}
        uses: anchore/sbom-action@v0
        with:
          image: ${{ env.DOCKER_IMAGE_PATH }}
          format: spdx-json
          output-file: artifacts/docker-room.spdx.json
          upload-artifact: false
      - name: Upload
        uses: actions/upload-artifact@v4
        with:
          name: docker
          path: artifacts/
      - name: Attest artifacts
        if: ${{ github.ref_type == 'tag' }}
        uses: actions/attest@v4
        with:
          subject-path: |
            artifacts/*.dockerimage
          sbom-path: artifacts/docker-room.spdx.json
