name: Build & test x86_64

on:
  workflow_call:
    inputs:
      flavor:
        required: true
        type: string
      version:
        required: true
        type: string

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }}-${{ inputs.flavor }}-x86_64
  cancel-in-progress: true

jobs:
  build-os:
    permissions:
      contents: read
    runs-on: ubuntu-24.04
    env:
      FLAVOR: ${{ inputs.flavor }}
      ARCH: x86_64
      VERSION: ${{ inputs.version }} 
    steps:
      - uses: actions/checkout@v4
        with:
          ref: "${{ github.event.pull_request.head.sha }}"
      - run: |
          git fetch --prune --unshallow
      - name: Check cache for OS image
        id: cache-os
        uses: actions/cache/restore@v4
        env:
          cache-name: os-build-x86_64-${{ inputs.flavor }}-${{ github.event_name }}
          lookup-only: true
        with:
          path: /tmp/os.tar
          key: ${{ env.cache-name }}-${{ inputs.version }}
      - if: ${{ steps.cache-os.outputs.cache-hit != 'true' }}
        name: Pull images
        uses: ./.github/actions/fetchimages
        with:
          os: 'false'
          version: ${{ inputs.version }}
      - if: ${{ steps.cache-os.outputs.cache-hit != 'true' }}
        name: Build OS
        run: |
          make ARCH=${{ env.ARCH }} build-os-save
          mv build/elemental-${{ inputs.flavor }}*.tar /tmp/os.tar 
      - if: ${{ steps.cache-os.outputs.cache-hit != 'true' }}
        name: Save OS image in cache
        id: save-os
        uses: actions/cache/save@v4
        env:
          cache-name: os-build-x86_64-${{ inputs.flavor }}-${{ github.event_name }}
        with:
          path: /tmp/os.tar
          key: ${{ env.cache-name }}-${{ inputs.version }}

  build-iso:
    permissions:
      contents: read
    needs: 
      - build-os
    runs-on: ubuntu-24.04
    env:
      FLAVOR: ${{ inputs.flavor }}
      ARCH: x86_64
      VERSION: ${{ inputs.version }}
    steps:
      - uses: actions/checkout@v4
        with:
          ref: "${{ github.event.pull_request.head.sha }}"
      - run: |
          git fetch --prune --unshallow
      - name: Cached ISO
        id: cache-iso
        uses: actions/cache/restore@v4
        env:
          cache-name: iso-build-x86_64-${{ inputs.flavor }}-${{ github.event_name }}
          lookup-only: true
        with:
          path: /tmp/*.iso
          key: ${{ env.cache-name }}-${{ inputs.version }}
      - if: ${{ steps.cache-iso.outputs.cache-hit != 'true' }}
        name: Pull images
        uses: ./.github/actions/fetchimages
        with:
          flavor: ${{ inputs.flavor }}
          version: ${{ inputs.version }}
      - if: ${{ steps.cache-iso.outputs.cache-hit != 'true' }}
        name: Build ISO
        run: |
          make build-iso
          sudo mv build/elemental-${{ env.FLAVOR }}.${{ env.ARCH}}.iso /tmp/
      - if: ${{ steps.cache-iso.outputs.cache-hit != 'true' }}
        name: Save ISO
        id: save-iso
        uses: actions/cache/save@v4
        env:
          cache-name: iso-build-x86_64-${{ inputs.flavor }}-${{ github.event_name }}
        with:
          path: /tmp/*.iso
          key: ${{ env.cache-name }}-${{ inputs.version }}

  build-disk:
    permissions:
      contents: read
    needs:
      - build-os
    runs-on: ubuntu-24.04
    env:
      FLAVOR: ${{ inputs.flavor }}
      ARCH: x86_64
      VERSION: ${{ inputs.version }}
    steps:
      - uses: actions/checkout@v4
        with:
          ref: "${{ github.event.pull_request.head.sha }}"
      - run: |
          git fetch --prune --unshallow
      - name: Checks cached Disk
        uses: actions/cache/restore@v4
        id: cache-disk
        env:
          cache-name: disk-build-x86_64-${{ inputs.flavor }}-${{ github.event_name }}
        with:
          path: /tmp/*.qcow2
          key: ${{ env.cache-name }}-${{ inputs.version }}
          lookup-only: true
      - if: ${{ steps.cache-disk.outputs.cache-hit != 'true' }}
        name: Cleanup worker
        run: |
          sudo rm -rf /usr/local/lib/android # will release about 10 GB if you don't need Android
          sudo rm -rf /usr/share/dotnet # will release about 20GB if you don't need .NET
          sudo df -h
      - if: ${{ steps.cache-disk.outputs.cache-hit != 'true' }}
        name: Pull images
        uses: ./.github/actions/fetchimages
        with:
          flavor: ${{ inputs.flavor }}
          version: ${{ inputs.version }}
      - if: ${{ steps.cache-disk.outputs.cache-hit != 'true' }}
        name: Install to disk
        run: |
          sudo apt-get update && sudo apt-get install -y --no-install-recommends qemu-utils coreutils
          sudo -E make ARCH=${{ env.ARCH }} build-disk
          sudo mv build/elemental-${{ env.FLAVOR }}.${{ env.ARCH}}.qcow2 /tmp/
      - if: ${{ steps.cache-disk.outputs.cache-hit != 'true' }}
        name: Save cached disk
        id: save-disk
        uses: actions/cache/save@v4
        env:
          cache-name: disk-build-x86_64-${{ inputs.flavor }}-${{ github.event_name }}
        with:
          path: /tmp/*.qcow2
          key: ${{ env.cache-name }}-${{ inputs.version }}

  detect:
    permissions:
      contents: read
    runs-on: ubuntu-24.04
    outputs:
      tests: ${{ steps.detect.outputs.tests }}
    steps:
      - id: detect
        env:
          FLAVOR: ${{ inputs.flavor }}
        run: |
          if [ "${FLAVOR}" == green ]; then
            echo "tests=['test-upgrade', 'test-downgrade', 'test-recovery', 'test-fallback', 'test-fsck', 'test-grubfallback']" >> $GITHUB_OUTPUT
          else
            echo "tests=['test-active']" >> $GITHUB_OUTPUT
          fi

  tests-matrix:
    permissions:
      contents: read
    needs:
      - build-disk
      - detect
    runs-on: ubuntu-24.04
    env:
      FLAVOR: ${{ inputs.flavor }}
      ARCH: x86_64
      COS_TIMEOUT: 1600
      VERSION: ${{ inputs.version }}
    strategy:
      matrix:
        test: ${{ fromJson(needs.detect.outputs.tests) }}
      fail-fast: false
    steps:
      - uses: actions/checkout@v4
        with:
          ref: "${{ github.event.pull_request.head.sha }}"
      - name: Install Go
        uses: actions/setup-go@v5
        with:
          go-version-file: go.mod
      - run: |
          git fetch --prune --unshallow
      - if: ${{ matrix.test == 'test-upgrade' }}
        name: Pull images
        uses: ./.github/actions/fetchimages
        with:
          flavor: ${{ inputs.flavor }}
          version: ${{ inputs.version }}
      - if: ${{ matrix.test != 'test-upgrade' }}
        name: Cached Disk
        id: cache-disk
        uses: actions/cache/restore@v4
        env:
          cache-name: disk-build-x86_64-${{ inputs.flavor }}-${{ github.event_name }}
        with:
          path: /tmp/*.qcow2
          key: ${{ env.cache-name }}-${{ inputs.version }}
          fail-on-cache-miss: true
      - name: Enable KVM group perms
        run: |
          sudo apt-get update
          sudo apt-get install qemu-utils ovmf qemu-system-x86
          echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
          sudo udevadm control --reload-rules
          sudo udevadm trigger --name-match=kvm
      - name: Run ${{ matrix.test }}
        run: |
          make DISK=/tmp/elemental-${{ env.FLAVOR }}.${{ env.ARCH}}.qcow2 ELMNTL_TARGETARCH=${{ env.ARCH }} ELMNTL_FIRMWARE=/usr/share/OVMF/OVMF_CODE_4M.fd ${{ matrix.test }}
      - name: Upload serial console for ${{ matrix.test }}
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: serial-${{ env.ARCH }}-${{ env.FLAVOR }}-${{ matrix.test }}.log
          path: tests/serial.log
          if-no-files-found: error
          overwrite: true
      - name: Upload qemu stdout for ${{ matrix.test }}
        uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: vmstdout-${{ env.ARCH }}-${{ env.FLAVOR }}-${{ matrix.test }}.log
          path: tests/vmstdout
          if-no-files-found: error
          overwrite: true
      - name: Stop test VM
        if: always()
        run: |
          make test-clean

  test-installer:
    permissions:
      contents: read
    needs:
      - build-iso
      - detect
    runs-on: ubuntu-24.04
    env:
      FLAVOR: ${{ inputs.flavor }}
      ARCH: x86_64
      COS_TIMEOUT: 1600
      VERSION: ${{ inputs.version }}
    steps:
      - uses: actions/checkout@v4
        with:
          ref: "${{ github.event.pull_request.head.sha }}"
      - name: Install Go
        uses: actions/setup-go@v5
        with:
          go-version-file: go.mod
      - run: |
          git fetch --prune --unshallow
      - name: Cached ISO
        id: cache-iso
        uses: actions/cache/restore@v4
        env:
          cache-name: iso-build-x86_64-${{ inputs.flavor }}-${{ github.event_name }}
        with:
          path: /tmp/*.iso
          key: ${{ env.cache-name }}-${{ inputs.version }}
          fail-on-cache-miss: true
      - name: Enable KVM group perms
        run: |
          sudo apt-get update
          sudo apt-get install qemu-utils ovmf qemu-system-x86
          echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
          sudo udevadm control --reload-rules
          sudo udevadm trigger --name-match=kvm
      - name: Run installer test
        run: |
          make ISO=/tmp/elemental-${{ env.FLAVOR }}.${{ env.ARCH}}.iso ELMNTL_TARGETARCH=${{ env.ARCH }} ELMNTL_FIRMWARE=/usr/share/OVMF/OVMF_CODE_4M.fd test-installer
      - name: Upload serial console for installer tests
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: serial-${{ env.ARCH }}-${{ env.FLAVOR }}-installer.log
          path: tests/serial.log
          if-no-files-found: error
          overwrite: true
      - name: Upload qemu stdout for installer tests
        uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: vmstdout-${{ env.ARCH }}-${{ env.FLAVOR }}-installer.log
          path: tests/vmstdout
          if-no-files-found: error
          overwrite: true
      - name: Stop test VM
        if: always()
        run: |
          make test-clean
