name: GKI Kernel Build

on:
  workflow_call:
    inputs:
      version:
        required: true
        type: string
        description: >
          Output directory of gki,
          for example: android12-5.10
      version_name:
        required: true
        type: string
        description: >
          With SUBLEVEL of kernel,
          for example: android12-5.10.66
      tag:
        required: true
        type: string
        description: >
          Part of branch name of common kernel manifest,
          for example: android12-5.10-2021-11
      os_patch_level:
        required: false
        type: string
        description: >
          Patch level of common kernel manifest,
          for example: 2021-11
        default: 2022-05
      patch_path:
        required: false
        type: string
        description: >
          Directory name of .github/patches/<patch_path>
          for example: 5.10
      use_cache:
        required: false
        type: boolean
        default: true
      embed_ksud:
        required: false
        type: string
        default: ksud-aarch64-linux-android
        description: >
          Artifact name of prebuilt ksud to be embedded
          for example: ksud-aarch64-linux-android
      debug:
        required: false
        type: boolean
        default: false
      build_lkm:
        required: false
        type: boolean
        default: false
    secrets:
      BOOT_SIGN_KEY:
        required: false
      CHAT_ID:
        required: false
      BOT_TOKEN:
        required: false
      MESSAGE_THREAD_ID:
        required: false

jobs:
  build:
    name: Build ${{ inputs.version_name }}
    runs-on: ubuntu-latest
    env:
      CCACHE_COMPILERCHECK: "%compiler% -dumpmachine; %compiler% -dumpversion"
      CCACHE_NOHASHDIR: "true"
      CCACHE_HARDLINK: "true"
    steps:
      - name: Maximize build space
        uses: easimon/maximize-build-space@master
        with:
          root-reserve-mb: 8192
          temp-reserve-mb: 2048
          remove-dotnet: 'true'
          remove-android: 'true'
          remove-haskell: 'true'
          remove-codeql: 'true'

      - uses: actions/checkout@v4
        with:
          path: KernelSU
          fetch-depth: 0

      - name: Setup need_upload
        id: need_upload
        run: |
          if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
            echo "UPLOAD=true" >> $GITHUB_OUTPUT
          else
            echo "UPLOAD=false" >> $GITHUB_OUTPUT
          fi

      - name: Setup kernel source
        run: |
          echo "Free space:"
          df -h
          cd $GITHUB_WORKSPACE
          sudo apt-get install repo -y
          mkdir android-kernel && cd android-kernel
          repo init --depth=1 --u https://android.googlesource.com/kernel/manifest -b common-${{ inputs.tag }} --repo-rev=v2.16
          REMOTE_BRANCH=$(git ls-remote https://android.googlesource.com/kernel/common ${{ inputs.tag }})
          DEFAULT_MANIFEST_PATH=.repo/manifests/default.xml
          if grep -q deprecated <<< $REMOTE_BRANCH; then
            echo "Found deprecated branch: ${{ inputs.tag }}"
            sed -i 's/"${{ inputs.tag }}"/"deprecated\/${{ inputs.tag }}"/g' $DEFAULT_MANIFEST_PATH
            cat $DEFAULT_MANIFEST_PATH
          fi
          repo --version
          repo --trace sync -c -j$(nproc --all) --no-tags
          df -h

      - name: Setup KernelSU
        env:
          PATCH_PATH: ${{ inputs.patch_path }}
          IS_DEBUG_KERNEL: ${{ inputs.debug }}
        run: |
          cd $GITHUB_WORKSPACE/android-kernel
          echo "[+] KernelSU setup"
          GKI_ROOT=$(pwd)
          echo "[+] GKI_ROOT: $GKI_ROOT"
          echo "[+] Copy KernelSU driver to $GKI_ROOT/common/drivers"
          ln -sf $GITHUB_WORKSPACE/KernelSU/kernel $GKI_ROOT/common/drivers/kernelsu
          echo "[+] Add KernelSU driver to Makefile"
          DRIVER_MAKEFILE=$GKI_ROOT/common/drivers/Makefile
          DRIVER_KCONFIG=$GKI_ROOT/common/drivers/Kconfig
          grep -q "kernelsu" "$DRIVER_MAKEFILE" || printf "\nobj-\$(CONFIG_KSU) += kernelsu/\n" >> "$DRIVER_MAKEFILE"
          grep -q "kernelsu" "$DRIVER_KCONFIG" || sed -i "/endmenu/i\\source \"drivers/kernelsu/Kconfig\"" "$DRIVER_KCONFIG"
          echo "[+] Apply KernelSU patches"
          cd $GKI_ROOT/common/ && git apply $GITHUB_WORKSPACE/KernelSU/.github/patches/$PATCH_PATH/*.patch || echo "[-] No patch found"

          if [ "$IS_DEBUG_KERNEL" = "true" ]; then
            echo "[+] Enable debug features for kernel"
            printf "\nccflags-y += -DCONFIG_KSU_DEBUG\n" >> $GITHUB_WORKSPACE/KernelSU/kernel/Makefile
          fi
          repo status
          echo "[+] KernelSU setup done."

      - name: Symbol magic
        run: |
          echo "[+] Export all symbol from abi_gki_aarch64.xml"
          COMMON_ROOT=$GITHUB_WORKSPACE/android-kernel/common
          KSU_ROOT=$GITHUB_WORKSPACE/KernelSU
          ABI_XML=$COMMON_ROOT/android/abi_gki_aarch64.xml
          SYMBOL_LIST=$COMMON_ROOT/android/abi_gki_aarch64
          # python3 $KSU_ROOT/scripts/abi_gki_all.py $ABI_XML > $SYMBOL_LIST
          echo "[+] Add KernelSU symbols"
          cat $KSU_ROOT/kernel/export_symbol.txt | awk '{sub("[ \t]+","");print "  "$0}' >> $SYMBOL_LIST

      - name: Setup ccache
        if: inputs.use_cache == true
        uses: hendrikmuhs/ccache-action@v1
        with:
          key: gki-kernel-aarch64-${{ inputs.version_name }}
          max-size: 2G
          save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}

      - name: Setup for LKM
        if: ${{ inputs.build_lkm == true }}
        working-directory: android-kernel
        run: |
          pip install ast-grep-cli
          sudo apt-get install llvm-15 -y
          ast-grep -U -p '$$$ check_exports($$$) {$$$}' -r '' common/scripts/mod/modpost.c
          ast-grep -U -p 'check_exports($$$);' -r '' common/scripts/mod/modpost.c
          sed -i '/config KSU/,/help/{s/default y/default m/}' common/drivers/kernelsu/Kconfig
          echo "drivers/kernelsu/kernelsu.ko" >> common/android/gki_aarch64_modules

          # bazel build, android14-5.15, android14-6.1 use bazel
          if [ ! -e build/build.sh ]; then
            sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' build/kernel/*.sh || echo "No unknown symbol scripts found"
            if [ -e common/modules.bzl ]; then
              sed -i 's/_COMMON_GKI_MODULES_LIST = \[/_COMMON_GKI_MODULES_LIST = \[ "drivers\/kernelsu\/kernelsu.ko",/g' common/modules.bzl
            fi
          else
            TARGET_FILE="build/kernel/build.sh"
            if [ ! -e "$TARGET_FILE" ]; then
              TARGET_FILE="build/build.sh"
            fi
            sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' $TARGET_FILE || echo "No unknown symbol in $TARGET_FILE"
            sed -i 's/if ! diff -u "\${KERNEL_DIR}\/\${MODULES_ORDER}" "\${OUT_DIR}\/modules\.order"; then/if false; then/g' $TARGET_FILE
            sed -i 's@${ROOT_DIR}/build/abi/compare_to_symbol_list@echo@g' $TARGET_FILE
            sed -i 's/needs unknown symbol/Dont abort when unknown symbol/g' build/kernel/*.sh || echo "No unknown symbol scripts found"
          fi

      - name: Make working directory clean to avoid dirty
        working-directory: android-kernel
        run: |
          rm common/android/abi_gki_protected_exports_* || echo "No protected exports!"
          git config --global user.email "bot@kernelsu.org"
          git config --global user.name "KernelSUBot"
          cd common/ && git add -A && git commit -a -m "Add KernelSU"
          repo status

      - name: Build Kernel/LKM
        working-directory: android-kernel
        run: |
          if [ ! -z ${{ vars.EXPECTED_SIZE }} ] && [ ! -z ${{ vars.EXPECTED_HASH }} ]; then
            export KSU_EXPECTED_SIZE=${{ vars.EXPECTED_SIZE }}
            export KSU_EXPECTED_HASH=${{ vars.EXPECTED_HASH }}
          fi
          if [ -e build/build.sh ]; then
            LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh CC="/usr/bin/ccache clang"
          else
            tools/bazel run --disk_cache=/home/runner/.cache/bazel --config=fast --config=stamp --lto=thin //common:kernel_aarch64_dist -- --dist_dir=dist
          fi

      - name: Prepare artifacts
        id: prepareArtifacts
        run: |
          OUTDIR=android-kernel/out/${{ inputs.version }}/dist
          if [ ! -e $OUTDIR ]; then
            OUTDIR=android-kernel/dist
          fi
          mkdir output
          if [ "${{ inputs.build_lkm}}" = "true" ]; then 
            llvm-strip-15 -d $OUTDIR/kernelsu.ko
            mv $OUTDIR/kernelsu.ko ./output/${{ inputs.version }}_kernelsu.ko
          else
            cp $OUTDIR/Image ./output/
            cp $OUTDIR/Image.lz4 ./output/
            git clone https://github.com/Kernel-SU/AnyKernel3
            rm -rf ./AnyKernel3/.git
            cp $OUTDIR/Image ./AnyKernel3/
          fi

      - name: Upload Image and Image.gz
        uses: actions/upload-artifact@v4
        if: ${{ inputs.build_lkm == false }}
        with:
          name: Image-${{ inputs.version_name }}_${{ inputs.os_patch_level }}
          path: ./output/*

      - name: Upload AnyKernel3
        if: ${{ inputs.build_lkm == false }}
        uses: actions/upload-artifact@v4
        with:
          name: AnyKernel3-${{ inputs.version_name }}_${{ inputs.os_patch_level }}
          path: ./AnyKernel3/*

      - name: Upload LKM
        uses: actions/upload-artifact@v4
        if: ${{ inputs.build_lkm == true }}
        with:
          name: ${{ inputs.version }}-lkm
          path: ./output/*_kernelsu.ko