on:
  workflow_call:
    inputs:
      deb-src-artifact-id:
        required: true
        type: string
      runs-on:
        required: true
        type: string
      machine-arch:
        required: true
        type: string
      build-arch:
        required: true
        type: string
      host-arch:
        required: true
        type: string
      dist-name:
        required: true
        type: string
      dist-version:
        required: true
        type: string
    secrets:
      GPG_SECRET_SUBKEYS:
      GPG_SIGNING_SUBKEY_FINGERPRINT:

jobs:
  linux:
    runs-on: ${{ inputs.runs-on }}
    env:
      CONTAINER_DISTRO: trixie
    permissions:
      id-token: write
      contents: read
      attestations: write
    steps:
      - name: Configure baseline system
        timeout-minutes: 1
        shell: sudo sh "{0}"
        run: |
          set -xe
          mount -t tmpfs tmpfs ${{ github.workspace }}
          echo "set man-db/auto-update false" | debconf-communicate
          dpkg-reconfigure man-db
          mkdir -p /etc/apt/apt.conf.d
          mkdir -p /etc/dpkg/dpkg.cfg.d
          tee /etc/apt/apt.conf.d/99gh > /dev/null <<EOT
          APT::ExtractTemplates::TempDir "/tmp/apt/temp";
          Acquire::Retries "10";
          APT::Install-Recommends "false";
          APT::Install-Suggests "false";
          APT::Get::Assume-Yes "true";
          APT::Get::Fix-Missing "true";
          EOT
          tee /etc/dpkg/dpkg.cfg.d/99gh > /dev/null <<EOT
          force-unsafe-io
          force-confdef
          EOT
          rm -rf /var/lib/apt/lists/*
          rm -rf /etc/apt/sources.list*
          if [ "${{ inputs.machine-arch }}" = "amd64" ];
          then
          MIRROR="http://archive.ubuntu.com/ubuntu"
          else
          MIRROR="http://ports.ubuntu.com/ubuntu-ports"
          fi
          tee /etc/apt/sources.list > /dev/null <<EOT
          deb $MIRROR noble main universe
          EOT
          apt update
          apt install eatmydata
          eatmydata apt install \
            podman \
            qemu-user-static \
          ;
          apt clean
      - name: Start the container
        timeout-minutes: 1
        shell: sudo eatmydata sh "{0}"
        run: |
          set -xe
          export IMAGE=debian:${{ env.CONTAINER_DISTRO }}-slim
          podman pull ${IMAGE}
          podman run \
            --name container \
            --image-volume=tmpfs \
            --tmpfs=/run \
            --tmpfs=/tmp \
            --tmpfs=/var/tmp \
            --volume=/home/runner:/home/runner \
            --volume=${{ github.workspace }}:${{ github.workspace }} \
            --privileged \
            --cap-add=SYS_ADMIN \
            --security-opt=apparmor:unconfined \
            --interactive \
            --tty \
            --detach \
            ${IMAGE} \
            /usr/bin/sh \
          ;
      - name: Install necessary packages
        timeout-minutes: 1
        shell: sudo podman exec --interactive --tty container sh "{0}"
        run: |
          set -xe
          mkdir -p /etc/apt/apt.conf.d
          mkdir -p /etc/dpkg/dpkg.cfg.d
          tee /etc/apt/apt.conf.d/99gh > /dev/null <<EOT
          APT::ExtractTemplates::TempDir "/tmp/apt/temp";
          Acquire::Retries "10";
          APT::Install-Recommends "false";
          APT::Install-Suggests "false";
          APT::Get::Assume-Yes "true";
          APT::Get::Fix-Missing "true";
          EOT
          tee /etc/dpkg/dpkg.cfg.d/99gh > /dev/null <<EOT
          force-unsafe-io
          force-confdef
          EOT
          rm -rf /var/lib/apt/lists/*
          rm -rf /etc/apt/sources.list*
          tee /etc/apt/sources.list > /dev/null <<EOT
          deb http://deb.debian.org/debian ${{ env.CONTAINER_DISTRO }} main
          deb http://deb.debian.org/debian ${{ env.CONTAINER_DISTRO }}-updates main
          deb http://deb.debian.org/debian ${{ env.CONTAINER_DISTRO }}-backports main
          EOT
          apt update
          apt install eatmydata
          eatmydata apt full-upgrade
          eatmydata apt install \
            ${{ inputs.dist-name }}-keyring \
            arch-test \
            autopkgtest \
            curl \
            devscripts \
            dosfstools \
            e2fsprogs \
            fakemachine \
            fdisk \
            gnupg \
            iproute2 \
            ipxe-qemu \
            libarchive13 \
            mmdebstrap \
            mtools \
            ovmf \
            qemu-efi-aarch64 \
            qemu-kvm \
            qemu-utils \
            sbuild \
            sudo \
            systemd-boot-efi \
            tar \
            uidmap \
            xz-utils \
            zerofree \
            zip \
          ;
          apt clean
          USER=`whoami`
          sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
      - name: Import/Configure GPG
        timeout-minutes: 1
        id: gpg
        if: github.event_name != 'pull_request'
        shell: sudo podman exec --interactive --tty container eatmydata sh "{0}"
        run: |
          set -xe
          gpg --import <<EOT
          ${{ secrets.GPG_SECRET_SUBKEYS }}
          EOT
          gpg \
            --output /etc/apt/trusted.gpg.d/apt.bcachefs.org.asc \
            --armor \
            --export \
            ${{ secrets.GPG_SIGNING_SUBKEY_FINGERPRINT }} \
          ;
          rm -f ~/.gnupg/trustedkeys.gpg
          gpg \
            --no-default-keyring \
            --keyring ~/.gnupg/trustedkeys.gpg \
            --import \
            /etc/apt/trusted.gpg.d/apt.bcachefs.org.asc \
          ;
          tee -a ~/.gnupg/gpg.conf > /dev/null <<EOT
          default-key ${{ secrets.GPG_SIGNING_SUBKEY_FINGERPRINT }}
          trusted-key ${{ secrets.GPG_SIGNING_SUBKEY_FINGERPRINT }}
          EOT
          tee -a ~/.gbp.conf > /dev/null <<EOT
          [buildpackage]
          sign-tags = True
          keyid = ${{ secrets.GPG_SIGNING_SUBKEY_FINGERPRINT }}
          EOT
          tee -a ~/.devscripts > /dev/null <<EOT
          DEBSIGN_KEYID=${{ secrets.GPG_SIGNING_SUBKEY_FINGERPRINT }}
          EOT
          tee -a ~/.sbuildrc > /dev/null <<EOT
          \$key_id = '${{ secrets.GPG_SIGNING_SUBKEY_FINGERPRINT }}';
          \$dpkg_buildpackage_user_options = [
            '--sign-keyid=${{ secrets.GPG_SIGNING_SUBKEY_FINGERPRINT }}',
            '--force-sign'
          ];
          EOT
      - name: Configure sbuild
        timeout-minutes: 1
        shell: sudo podman exec --interactive --tty container eatmydata sh "{0}"
        run: |
          set -xe
          BUILD_DIR="${{ github.workspace }}/deb-bin/${{ inputs.dist-version }}/${{ inputs.host-arch }}"
          echo "BUILD_DIR=$(echo ${BUILD_DIR})" >> ~/.env
          mkdir -p "$BUILD_DIR"
          tee -a ~/.sbuildrc > /dev/null <<EOT
          \$verbose = 1;
          \$build_dir = '$BUILD_DIR';
          \$distribution = '${{ inputs.dist-version }}';
          \$build_arch = '${{ inputs.build-arch }}';
          \$host_arch = '${{ inputs.host-arch }}';
          \$chroot_mode = 'unshare';
          \$unshare_tmpdir_template = '/tmp/tmp.sbuild.XXXXXXXXXX';
          \$run_lintian = 1;
          \$run_piuparts = 0;
          \$run_autopkgtest = 0;
          push @{\$unshare_mmdebstrap_extra_args}, "*", [
            '--include=eatmydata',
            '--variant=apt'
          ];
          EOT
          if [ "${{ inputs.dist-name }}" = "debian" ];
          then
          tee -a ~/.sbuildrc > /dev/null <<EOT
          \$external_commands = {
            'chroot-setup-commands' => [
              "export LD_PRELOAD=/usr/lib/$(dpkg-architecture -a "${{ inputs.build-arch }}" -q DEB_HOST_MULTIARCH)/libeatmydata.so"
            ]
          };
          \$build_environment = {
            "LD_PRELOAD" =>
              "/usr/lib/$(dpkg-architecture -a "${{ inputs.build-arch }}" -q DEB_HOST_MULTIARCH)/libeatmydata.so"
          };
          \$environment_filter = [
            Dpkg::BuildInfo::get_build_env_allowed(),
            '^LD_PRELOAD$'
          ];
          push @{\$unshare_mmdebstrap_extra_args}, "*", [
            '--hook-dir=/usr/share/mmdebstrap/hooks/eatmydata'
          ];
          EOT
          fi
          if [ "${{ inputs.dist-name }}" = "debian" ];
          then
          MIRROR="http://deb.debian.org/debian"
          fi
          if [ "${{ inputs.dist-name }}" = "debian" ];
          then
          KEYRING="/usr/share/keyrings/debian-keyring.gpg"
          elif [ "${{ inputs.dist-name }}" = "ubuntu" ];
          then
          KEYRING="/usr/share/keyrings/ubuntu-archive-keyring.gpg"
          else
          exit 1
          fi
          echo "MIRROR=$(echo ${MIRROR})" >> ~/.env
          if [ "${{ inputs.dist-name }}" = "debian" ];
          then
          tee -a ~/.sbuildrc > /dev/null <<EOT
          push @{\$unshare_mmdebstrap_extra_args}, "*", [
            '$MIRROR',
            '--keyring=$KEYRING',
            '--components=main'
          ];
          EOT
          fi
          if [ "${{ inputs.dist-name }}" = "debian" ] && [ "${{ inputs.dist-version }}" != "unstable" ];
          then
          tee -a ~/.sbuildrc > /dev/null <<EOT
          \$extra_repositories = [
            'deb $MIRROR ${{ inputs.dist-version }}-updates main',
            'deb $MIRROR ${{ inputs.dist-version }}-backports main'
          ];
          EOT
          fi
          if [ "${{ inputs.dist-name }}" = "ubuntu" ];
          then
          MIRROR="http://archive.ubuntu.com/ubuntu"
          tee -a ~/.sbuildrc > /dev/null <<EOT
          push @{\$unshare_mmdebstrap_extra_args}, "*", [
            '--keyring=$KEYRING',
            '--components=main,universe',
            'deb [arch=amd64] $MIRROR ${{ inputs.dist-version }} main universe',
            'deb [arch=amd64] $MIRROR ${{ inputs.dist-version }}-updates main universe',
            'deb [arch=amd64] $MIRROR ${{ inputs.dist-version }}-security main universe',
            'deb [arch=amd64] $MIRROR ${{ inputs.dist-version }}-backports main universe',
          ];
          EOT
          fi
          if [ "${{ inputs.dist-name }}" = "ubuntu" ] && [ "${{ inputs.host-arch }}" != "amd64" ];
          then
          MIRROR_PORTS="http://ports.ubuntu.com/ubuntu-ports"
          tee -a ~/.sbuildrc > /dev/null <<EOT
          push @{\$unshare_mmdebstrap_extra_args}, "*", [
            'deb [arch=${{ inputs.host-arch }}] $MIRROR_PORTS ${{ inputs.dist-version }} main universe',
            'deb [arch=${{ inputs.host-arch }}] $MIRROR_PORTS ${{ inputs.dist-version }}-updates main universe',
            'deb [arch=${{ inputs.host-arch }}] $MIRROR_PORTS ${{ inputs.dist-version }}-security main universe',
            'deb [arch=${{ inputs.host-arch }}] $MIRROR_PORTS ${{ inputs.dist-version }}-backports main universe',
          ];
          EOT
          fi
      - name: Ensure that the download directory does not exist
        timeout-minutes: 1
        run: |
          set -xe
          rm -rf "${{ github.workspace }}/deb-src"
      - name: Download source-only .deb to be built
        timeout-minutes: 1
        uses: actions/download-artifact@v5
        with:
          artifact-ids: ${{ inputs.deb-src-artifact-id }}
          path: deb-src
      - name: Check attestation of all incoming artifact archives
        timeout-minutes: 1
        if: github.event_name != 'pull_request'
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          set -xe
          cd "${{ github.workspace }}/deb-src"
          find . -type f -print0 | xargs --null -I'{}' sh -c "                 \
            echo '::group::Attestation check for {}' &&                        \
            (                                                                  \
              gh attestation verify                                            \
                {}                                                             \
                --repo        ${{ github.repository }}                         \
                --signer-repo ${{ github.repository }}                         \
                --source-digest ${{ github.sha }}                              \
                --signer-digest ${{ github.sha }}                              \
              ||                                                               \
              (                                                                \
                echo '::error file={}::NOT ATTESTED!' &&                       \
                echo '::endgroup::' &&                                         \
                exit 1                                                         \
              )                                                                \
            ) &&                                                               \
            echo 'ok.' &&                                                      \
            echo '::endgroup::'                                                \
          "
      - name: Unpack the downloaded tarball
        timeout-minutes: 1
        shell: sudo podman exec --interactive --tty container eatmydata sh "{0}"
        run: |
          set -xe
          cd "${{ github.workspace }}/deb-src"
          tar -xf "${{ github.workspace }}/deb-src/artifact-src.tar"
          rm "${{ github.workspace }}/deb-src/artifact-src.tar"
      - name: Ensure that all incoming source artifacts are signed
        timeout-minutes: 1
        if: steps.gpg.conclusion != 'skipped'
        shell: sudo podman exec --interactive --tty container eatmydata sh "{0}"
        run: |
          set -xe
          cd "${{ github.workspace }}/deb-src"
          find . -type f -not -iname '*.sig' -print0 | xargs --null -I'{}' sh -c "                     \
            echo '::group::Signature check for {}' &&                                                  \
            (                                                                                          \
              gpg --verbose --no-default-keyring --keyring ~/.gnupg/trustedkeys.gpg --verify {}     || \
              gpg --verbose --no-default-keyring --keyring ~/.gnupg/trustedkeys.gpg --verify {}.sig || \
              (                                                                                        \
                echo '::error file={}::NOT SIGNED!' &&                                                 \
                echo '::endgroup::' &&                                                                 \
                exit 1                                                                                 \
              )                                                                                        \
            ) &&                                                                                       \
            echo 'ok.' &&                                                                              \
            echo '::endgroup::'                                                                        \
          "
      - name: Build the package
        timeout-minutes: 60
        shell: sudo podman exec --interactive --tty container eatmydata sh "{0}"
        run: |
          set -xe
          cd "${{ github.workspace }}/deb-bin"
          if [ "${{ inputs.dist-name }}" = "ubuntu" ];
          then
          export DEB_BUILD_OPTIONS=noautodbgsym
          fi
          echo '::group::Building the package'
          sbuild \
            --verbose \
            --arch-any \
            --arch-all \
            "${{ github.workspace }}/deb-src/"*.dsc \
          ;
          echo '::endgroup::'
      - name: Ensure that all binary artifacts are signed, or sign them
        timeout-minutes: 1
        if: steps.gpg.conclusion != 'skipped'
        shell: sudo podman exec --interactive --tty container eatmydata sh "{0}"
        run: |
          set -xe
          cd "${{ github.workspace }}/deb-bin"
          find . -type f -not -iname '*.sig' -print0 | xargs --null -I'{}' sh -c "                     \
            echo '::group::Signing {}' &&                                                              \
            (                                                                                          \
              gpg --verbose --no-default-keyring --keyring ~/.gnupg/trustedkeys.gpg --verify {}     || \
              gpg --verbose --no-default-keyring --keyring ~/.gnupg/trustedkeys.gpg --verify {}.sig || \
              gpg --verbose --detach-sign {}                                                           \
            ) &&                                                                                       \
            echo '::endgroup::'                                                                        \
          "
      - name: Archive build artifacts
        timeout-minutes: 1
        shell: sudo podman exec --interactive --tty container eatmydata sh "{0}"
        run: |
          set -xe
          cd "${{ github.workspace }}/deb-bin"
          tar -cf "${{ github.workspace }}/deb-bin/artifact-bin-${{ inputs.dist-version }}-${{ inputs.host-arch }}.tar" *
      - name: Attest build artifact
        timeout-minutes: 1
        if: github.event_name != 'pull_request'
        uses: actions/attest-build-provenance@v3
        with:
          subject-path: '${{ github.workspace }}/deb-bin'
      - name: Upload build artifact archive
        timeout-minutes: 1
        id: deb-bin-upload
        uses: actions/upload-artifact@v4
        with:
          name: artifact-bin-${{ inputs.dist-version }}-${{ inputs.host-arch }}.tar
          path: '${{ github.workspace }}/deb-bin/artifact-bin-${{ inputs.dist-version }}-${{ inputs.host-arch }}.tar'
          if-no-files-found: error
          compression-level: 0
      - name: Attest uploaded build artifact
        timeout-minutes: 1
        if: github.event_name != 'pull_request'
        uses: actions/attest-build-provenance@v3
        with:
          subject-name: artifact-bin-${{ inputs.dist-version }}-${{ inputs.host-arch }}.tar.zip
          subject-digest: sha256:${{ steps.deb-bin-upload.outputs.artifact-digest }}
      - name: Build Qemu image for autopkgtest
        timeout-minutes: 2
        id: qemu-image
        if: inputs.dist-name == 'debian' && inputs.dist-version != 'trixie' && inputs.machine-arch == 'amd64' && inputs.build-arch == inputs.machine-arch && inputs.host-arch == inputs.build-arch
        shell: sudo podman exec --interactive --tty container eatmydata sh "{0}"
        run: |
          set -xe
          . ~/.env
          IMAGE="/tmp/autopkgtest-qemu-image.qcow2"
          echo "IMAGE=$(echo ${IMAGE})" >> ~/.env
          mmdebstrap-autopkgtest-build-qemu --boot=efi --mirror "$MIRROR" "${{ inputs.dist-version }}" "$IMAGE"
      - name: Run autopkgtest
        timeout-minutes: 10
        if: steps.qemu-image.conclusion != 'skipped'
        shell: sudo podman exec --interactive --tty container eatmydata sh "{0}"
        run: |
          set -xe
          . ~/.env
          if [ "${{ inputs.machine-arch }}" = "amd64" ];
          then
          QEMU_OPTIONS="-enable-kvm -cpu host"
          elif [ "${{ inputs.machine-arch }}" = "arm64" ];
          then
          QEMU_OPTIONS="-machine virt -cpu cortex-a710 -accel tcg"
          else
          exit 1
          fi
          autopkgtest \
            --no-built-binaries \
            --setup-commands "apt update && apt install openssl" \
            --apt-upgrade \
            "${{ github.workspace }}/deb-src"/*.dsc \
            "$BUILD_DIR"/*.changes \
            -- \
            autopkgtest-virt-qemu \
            --cpus=$(nproc --all) \
            --qemu-options="$QEMU_OPTIONS" \
            --boot=efi \
            "$IMAGE" \
          ;
