###############################################################################
# Forgejo Actions - build, sign, and push the KAMOS Gaming OS image
#
# Configured for: cgi.medsys.cloud/mkm1971/kamos
# Runner labels:  ubuntu-latest / ubuntu-24.04 / ubuntu-22.04 (Forgejo runner v0.4.1)
#
# Prereqs in your Forgejo repo:
#   1. Container Registry feature enabled on cgi.medsys.cloud.
#   2. The runner host must be x86_64 (Bazzite NVIDIA is x86_64 only).
#   3. Repository secrets at /mkm1971/kamos/settings/actions/secrets:
#        - SIGNING_SECRET     contents of cosign.key (NOT the .pub)
#        - REGISTRY_USER      mkm1971
#        - REGISTRY_TOKEN     Forgejo access token with `package` write scope
###############################################################################

name: build-image

# DISABLED for now — the Forgejo runner sandbox blocks unshare(CLONE_NEWUSER)
# which all container build tools require. See ./kamos-build.sh for the
# replacement: a local Mac-based build script that pushes to this same
# Forgejo registry. Re-enable this workflow once the runner config is updated
# to allow privileged containers (container.privileged: true in act_runner
# config.yaml).
on:
  workflow_dispatch:
  # push:
  #   branches: [main]
  # pull_request:
  #   branches: [main]
  # schedule:
  #   - cron: "0 6 * * 1"

env:
  IMAGE_NAME: kamos
  IMAGE_TAGS: "stable latest"
  # Override this in your Forgejo repo's variables to point at your instance.
  REGISTRY: ${{ vars.REGISTRY || 'cgi.medsys.cloud' }}
  REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
  REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}

jobs:
  build:
    name: Build & push (${{ matrix.platform }})
    # Matches your runner labels: ubuntu-latest / ubuntu-24.04 / ubuntu-22.04
    # Assumes the runner host is x86_64 - if it's actually Apple Silicon, the
    # build will hit "exec format error" and we'll need to add binfmt qemu setup.
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    strategy:
      fail-fast: false
      matrix:
        platform: [linux/amd64]

    steps:
      # Manual checkout that bypasses the runner's broken internal URL.
      # The runner's `instance` is configured as http://forgejo:3000 which it
      # cannot resolve, so actions/checkout@v4 fails. We clone from the
      # public URL directly using REGISTRY_TOKEN for auth.
      - name: Checkout (manual workaround for runner internal URL)
        shell: bash
        env:
          TOKEN: ${{ secrets.REGISTRY_TOKEN }}
          REPO:  ${{ gitea.repository }}
          SHA:   ${{ gitea.sha }}
        run: |
          set -eo pipefail
          # Don't echo the token-bearing URL into logs
          set +x
          REMOTE="https://mkm1971:${TOKEN}@cgi.medsys.cloud/${REPO}.git"
          git init -q .
          git remote add origin "$REMOTE"
          git fetch --depth=1 origin "${SHA:-main}"
          git checkout -q FETCH_HEAD
          # Scrub the credential out of the remote so later steps can't leak it
          git remote set-url origin "https://cgi.medsys.cloud/${REPO}.git"
          set -x
          git log --oneline -1

      - name: Compute tags
        id: tags
        shell: bash
        run: |
          DATE_TAG="$(date +%Y%m%d)"
          SHA_TAG="${GITHUB_SHA::7}"
          {
            echo "date_tag=${DATE_TAG}"
            echo "sha_tag=${SHA_TAG}"
            echo "image_ref=${REGISTRY}/${{ gitea.repository_owner }}/${IMAGE_NAME}"
          } >> "$GITHUB_OUTPUT"

      - name: Install build tooling
        shell: bash
        env:
          COSIGN_VERSION: v2.4.1
        run: |
          set -euxo pipefail
          # podman, buildah, skopeo, jq come from Ubuntu repos.
          sudo apt-get update -y
          sudo apt-get install -y podman buildah skopeo jq curl ca-certificates
          # cosign is NOT in apt - install the official binary from sigstore.
          sudo curl -fsSL \
            "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-linux-amd64" \
            -o /usr/local/bin/cosign
          sudo chmod +x /usr/local/bin/cosign
          # Verify everything is callable.
          podman --version
          buildah --version
          skopeo --version
          cosign version
          jq --version

      # Build with buildah + vfs + chroot isolation. This combo avoids:
      #   - user namespaces (which need newuidmap and aren't always allowed)
      #   - overlay mounts (which need mount propagation)
      #   - clone() with CLONE_NEW* flags (which seccomp may block)
      # Run with sudo so we already have full caps and don't need to unshare.
      - name: Build image
        id: build
        shell: bash
        env:
          IMAGE_REF: ${{ steps.tags.outputs.image_ref }}
          DATE_TAG: ${{ steps.tags.outputs.date_tag }}
          SHA_TAG:  ${{ steps.tags.outputs.sha_tag }}
          BUILDAH_ISOLATION: chroot
          STORAGE_DRIVER: vfs
        run: |
          set -euxo pipefail
          sudo BUILDAH_ISOLATION=chroot STORAGE_DRIVER=vfs buildah \
            --storage-driver=vfs \
            bud \
            --isolation=chroot \
            --platform=${{ matrix.platform }} \
            --pull-always \
            --tag "${IMAGE_REF}:${DATE_TAG}" \
            --tag "${IMAGE_REF}:${SHA_TAG}" \
            $(for t in $IMAGE_TAGS; do echo --tag "${IMAGE_REF}:${t}"; done) \
            .

      - name: Login to Forgejo container registry
        if: github.event_name != 'pull_request'
        shell: bash
        run: |
          echo "${REGISTRY_TOKEN}" | sudo buildah --storage-driver=vfs login \
            --username "${REGISTRY_USER}" \
            --password-stdin \
            "${REGISTRY}"

      - name: Push image
        if: github.event_name != 'pull_request'
        shell: bash
        env:
          IMAGE_REF: ${{ steps.tags.outputs.image_ref }}
          DATE_TAG:  ${{ steps.tags.outputs.date_tag }}
          SHA_TAG:   ${{ steps.tags.outputs.sha_tag }}
        run: |
          set -euxo pipefail
          for tag in $DATE_TAG $SHA_TAG $IMAGE_TAGS; do
            sudo buildah --storage-driver=vfs push "${IMAGE_REF}:${tag}"
          done

      - name: Sign image with cosign
        if: github.event_name != 'pull_request'
        shell: bash
        env:
          COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
          COSIGN_PASSWORD: ""
          IMAGE_REF: ${{ steps.tags.outputs.image_ref }}
        run: |
          set -euxo pipefail
          for tag in $IMAGE_TAGS; do
            # skopeo inspect against private registry needs creds
            DIGEST=$(skopeo inspect \
              --creds "${REGISTRY_USER}:${REGISTRY_TOKEN}" \
              --format '{{.Digest}}' \
              "docker://${IMAGE_REF}:${tag}")
            cosign sign --yes --key env://COSIGN_PRIVATE_KEY "${IMAGE_REF}@${DIGEST}"
          done

      - name: Summary
        shell: bash
        env:
          IMAGE_REF: ${{ steps.tags.outputs.image_ref }}
        run: |
          {
            echo "### Built image"
            echo ""
            echo "\`${IMAGE_REF}\` with tags: ${IMAGE_TAGS}"
            echo ""
            echo "Switch a target machine to this image with:"
            echo ""
            echo "\`\`\`"
            echo "sudo bootc switch ${IMAGE_REF}:stable"
            echo "\`\`\`"
          } >> "$GITHUB_STEP_SUMMARY"
