name: Build / Fedora RPM

concurrency:
  group: "build-fedora-${{ github.ref }}"
  cancel-in-progress: true

on:
  push:
    tags:
      - "v*.*.*"
    # paths:
    #   - 'pkg/fedora/**'
    #   - 'src/**'
    #   - 'Cargo.toml'
    #   - 'Cargo.lock'
    #   - '.forgejo/workflows/build-fedora.yml'
  workflow_dispatch:
  schedule:
    - cron: '30 0 * * *'

jobs:
  build:
    runs-on: fedora-latest
    steps:
      - name: Detect Fedora version
        id: fedora
        run: |
          VERSION=$(rpm -E %fedora)
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "Fedora version: $VERSION"

      - name: Checkout repository with full history
        uses: https://code.forgejo.org/actions/checkout@v5
        with:
          fetch-depth: 0


      - name: Cache DNF packages
        uses: https://code.forgejo.org/actions/cache@v4
        with:
          path: |
            /var/cache/dnf
            /var/cache/yum
          key: dnf-fedora${{ steps.fedora.outputs.version }}-${{ hashFiles('pkg/fedora/continuwuity.spec.rpkg') }}-v1
          restore-keys: |
            dnf-fedora${{ steps.fedora.outputs.version }}-

      - name: Cache Cargo registry
        uses: https://code.forgejo.org/actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
          key: cargo-fedora${{ steps.fedora.outputs.version }}-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            cargo-fedora${{ steps.fedora.outputs.version }}-

      - name: Cache Rust build dependencies
        uses: https://code.forgejo.org/actions/cache@v4
        with:
          path: |
            ~/rpmbuild/BUILD/*/target/release/deps
            ~/rpmbuild/BUILD/*/target/release/build
            ~/rpmbuild/BUILD/*/target/release/.fingerprint
            ~/rpmbuild/BUILD/*/target/release/incremental
          key: rust-deps-fedora${{ steps.fedora.outputs.version }}-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            rust-deps-fedora${{ steps.fedora.outputs.version }}-

      - name: Setup sccache
        uses: https://git.tomfos.tr/tom/sccache-action@v1

      - name: Configure sccache environment
        run: |
          echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV
          echo "CMAKE_C_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV
          echo "CMAKE_CXX_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV
          echo "SCCACHE_CACHE_SIZE=10G" >> $GITHUB_ENV
          # Aggressive GC since cache restores don't increment counter
          echo "CARGO_INCREMENTAL_GC_TRIGGER=5" >> $GITHUB_ENV

      - name: Install base RPM tools
        run: |
          dnf install -y --setopt=keepcache=1 \
            fedora-packager \
            python3-pip \
            rpm-sign \
            rpkg \
            wget

      - name: Setup build environment and build SRPM
        run: |
          git config --global --add safe.directory "$GITHUB_WORKSPACE"
          git config --global user.email "ci@continuwuity.org"
          git config --global user.name "Continuwuity"

          rpmdev-setuptree

          cd "$GITHUB_WORKSPACE"

          # Determine release suffix and version based on ref type and branch
          if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
            # Tags get clean version numbers for stable releases
            RELEASE_SUFFIX=""
            TAG_NAME="${{ github.ref_name }}"
            # Extract version from tag (remove v prefix if present)
            TAG_VERSION=$(echo "$TAG_NAME" | sed 's/^v//')

            # Create spec file with tag version
            sed -e "s/^Version:.*$/Version:        $TAG_VERSION/" \
                -e "s/^Release:.*$/Release:        1%{?dist}/" \
                pkg/fedora/continuwuity.spec.rpkg > continuwuity.spec.rpkg
          elif [ "${{ github.ref_name }}" = "main" ]; then
            # Main branch gets .dev suffix
            RELEASE_SUFFIX=".dev"

            # Replace the Release line to include our suffix
            sed "s/^Release:.*$/Release:        1${RELEASE_SUFFIX}%{?dist}/" \
              pkg/fedora/continuwuity.spec.rpkg > continuwuity.spec.rpkg
          else
            # Other branches get sanitized branch name as suffix
            SAFE_BRANCH=$(echo "${{ github.ref_name }}" | sed 's/[^a-zA-Z0-9]/_/g' | cut -c1-20)
            RELEASE_SUFFIX=".${SAFE_BRANCH}"

            # Replace the Release line to include our suffix
            sed "s/^Release:.*$/Release:        1${RELEASE_SUFFIX}%{?dist}/" \
              pkg/fedora/continuwuity.spec.rpkg > continuwuity.spec.rpkg
          fi

          rpkg srpm --outdir "$HOME/rpmbuild/SRPMS"

          ls -la $HOME/rpmbuild/SRPMS/


      - name: Install build dependencies from SRPM
        run: |
          SRPM=$(find "$HOME/rpmbuild/SRPMS" -name "*.src.rpm" | head -1)

          if [ -z "$SRPM" ]; then
            echo "Error: No SRPM file found"
            exit 1
          fi

          echo "Installing build dependencies from: $(basename $SRPM)"
          dnf builddep -y "$SRPM"

      - name: Build RPM from SRPM
        run: |
          SRPM=$(find "$HOME/rpmbuild/SRPMS" -name "*.src.rpm" | head -1)

          if [ -z "$SRPM" ]; then
            echo "Error: No SRPM file found"
            exit 1
          fi

          echo "Building from SRPM: $SRPM"

          rpmbuild --rebuild "$SRPM" \
            --define "_topdir $HOME/rpmbuild" \
            --define "_sourcedir $GITHUB_WORKSPACE" \
            --nocheck  # Skip %check section to avoid test dependencies


      - name: Test RPM installation
        run: |
          # Find the main binary RPM (exclude debug and source RPMs)
          RPM=$(find "$HOME/rpmbuild/RPMS" -name "continuwuity-*.rpm" \
            ! -name "*debuginfo*" \
            ! -name "*debugsource*" \
            ! -name "*.src.rpm" | head -1)

          if [ -z "$RPM" ]; then
            echo "Error: No binary RPM file found"
            exit 1
          fi

          echo "Testing installation of: $RPM"

          # Dry run first
          rpm -qpi "$RPM"
          echo ""
          rpm -qpl "$RPM"

          # Actually install it
          dnf install -y "$RPM"

          # Verify installation
          rpm -qa | grep continuwuity

          # Check that the binary exists
          [ -f /usr/bin/conduwuit ] && echo "✅ Binary installed successfully"
          [ -f /usr/lib/systemd/system/conduwuit.service ] && echo "✅ Systemd service installed"
          [ -f /etc/conduwuit/conduwuit.toml ] && echo "✅ Config file installed"

      - name: List built packages
        run: |
          echo "Binary RPMs:"
          find "$HOME/rpmbuild/RPMS" -name "*.rpm" -type f -exec ls -la {} \;

          echo ""
          echo "Source RPMs:"
          find "$HOME/rpmbuild/SRPMS" -name "*.rpm" -type f -exec ls -la {} \;

      - name: Collect artifacts
        run: |
          mkdir -p artifacts

          find "$HOME/rpmbuild/RPMS" -name "*.rpm" -type f -exec cp {} artifacts/ \;
          find "$HOME/rpmbuild/SRPMS" -name "*.rpm" -type f -exec cp {} artifacts/ \;

          cd artifacts
          echo "Build Information:" > BUILD_INFO.txt
          echo "==================" >> BUILD_INFO.txt
          echo "Git commit: ${{ github.sha }}" >> BUILD_INFO.txt
          echo "Git branch: ${{ github.ref_name }}" >> BUILD_INFO.txt
          echo "Build date: $(date -u +%Y-%m-%d_%H:%M:%S_UTC)" >> BUILD_INFO.txt
          echo "" >> BUILD_INFO.txt
          echo "Package contents:" >> BUILD_INFO.txt
          echo "-----------------" >> BUILD_INFO.txt
          for rpm in *.rpm; do
            echo "" >> BUILD_INFO.txt
            echo "File: $rpm" >> BUILD_INFO.txt
            rpm -qpi "$rpm" 2>/dev/null | grep -E "^(Name|Version|Release|Architecture|Size)" >> BUILD_INFO.txt
          done

          ls -la

      - name: Upload binary RPM artifact
        run: |
          # Find the main binary RPM (exclude debug and source RPMs)
          BIN_RPM=$(find artifacts -name "continuwuity-*.rpm" \
            ! -name "*debuginfo*" \
            ! -name "*debugsource*" \
            ! -name "*.src.rpm" \
            -type f)

          mkdir -p upload-bin
          cp $BIN_RPM upload-bin/

      - name: Upload binary RPM
        uses: https://code.forgejo.org/actions/upload-artifact@v3
        with:
          name: continuwuity
          path: upload-bin/

      - name: Upload debug RPM artifact
        uses: https://code.forgejo.org/actions/upload-artifact@v3
        with:
          name: continuwuity-debug
          path: artifacts/*debuginfo*.rpm

      - name: Publish to RPM Package Registry
        if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' }}
        run: |
          # Find the main binary RPM (exclude debug and source RPMs)
          RPM=$(find artifacts -name "continuwuity-*.rpm" \
            ! -name "*debuginfo*" \
            ! -name "*debugsource*" \
            ! -name "*.src.rpm" \
            -type f | head -1)

          if [ -z "$RPM" ]; then
            echo "No binary RPM found to publish"
            exit 0
          fi

          RPM_BASENAME=$(basename "$RPM")
          echo "Publishing: $RPM_BASENAME"

          # Determine the group based on ref type and branch
          if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
            GROUP="stable"
            # For tags, extract the tag name for version info
            TAG_NAME="${{ github.ref_name }}"
          elif [ "${{ github.ref_name }}" = "main" ]; then
            GROUP="dev"
          else
            # Use sanitized branch name as group for feature branches
            GROUP=$(echo "${{ github.ref_name }}" | sed 's/[^a-zA-Z0-9]/-/g' | tr '[:upper:]' '[:lower:]' | cut -c1-30)
          fi

          PACKAGE_INFO=$(rpm -qpi "$RPM" 2>/dev/null)
          PACKAGE_NAME=$(echo "$PACKAGE_INFO" | grep "^Name" | awk '{print $3}')
          PACKAGE_VERSION=$(echo "$PACKAGE_INFO" | grep "^Version" | awk '{print $3}')
          PACKAGE_RELEASE=$(echo "$PACKAGE_INFO" | grep "^Release" | awk '{print $3}')
          PACKAGE_ARCH=$(echo "$PACKAGE_INFO" | grep "^Architecture" | awk '{print $2}')

          # Full version includes release
          FULL_VERSION="${PACKAGE_VERSION}-${PACKAGE_RELEASE}"

          # Forgejo's RPM registry cannot overwrite existing packages, so we must delete first
          # 404 is OK if package doesn't exist yet
          echo "Removing any existing package: $PACKAGE_NAME-$FULL_VERSION.$PACKAGE_ARCH"
          RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \
            -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
            "https://forgejo.ellis.link/api/packages/continuwuation/rpm/$GROUP/package/$PACKAGE_NAME/$FULL_VERSION/$PACKAGE_ARCH")
          HTTP_CODE=$(echo "$RESPONSE" | tail -n1)

          if [ "$HTTP_CODE" != "204" ] && [ "$HTTP_CODE" != "404" ]; then
            echo "ERROR: Failed to delete package (HTTP $HTTP_CODE)"
            echo "$RESPONSE" | head -n -1
            exit 1
          fi

          curl --fail-with-body \
            -X PUT \
            -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
            -H "Content-Type: application/x-rpm" \
            -T "$RPM" \
            "https://forgejo.ellis.link/api/packages/continuwuation/rpm/$GROUP/upload?sign=true"

          echo ""
          echo "✅ Published binary RPM to: https://forgejo.ellis.link/continuwuation/-/packages/rpm/continuwuity/"
          echo "Group: $GROUP"

          # Upload debug RPMs to separate group
          DEBUG_RPMS=$(find artifacts -name "*debuginfo*.rpm")
          if [ -n "$DEBUG_RPMS" ]; then
            echo ""
            echo "Publishing debug RPMs to group: ${GROUP}-debug"

            for DEBUG_RPM in $DEBUG_RPMS; do
              echo "Publishing: $(basename "$DEBUG_RPM")"

              DEBUG_INFO=$(rpm -qpi "$DEBUG_RPM" 2>/dev/null)
              DEBUG_NAME=$(echo "$DEBUG_INFO" | grep "^Name" | awk '{print $3}')
              DEBUG_VERSION=$(echo "$DEBUG_INFO" | grep "^Version" | awk '{print $3}')
              DEBUG_RELEASE=$(echo "$DEBUG_INFO" | grep "^Release" | awk '{print $3}')
              DEBUG_ARCH=$(echo "$DEBUG_INFO" | grep "^Architecture" | awk '{print $2}')
              DEBUG_FULL_VERSION="${DEBUG_VERSION}-${DEBUG_RELEASE}"

              # Must delete existing package first (Forgejo limitation)
              RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \
                -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
                "https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-debug/package/$DEBUG_NAME/$DEBUG_FULL_VERSION/$DEBUG_ARCH")
              HTTP_CODE=$(echo "$RESPONSE" | tail -n1)

              if [ "$HTTP_CODE" != "204" ] && [ "$HTTP_CODE" != "404" ]; then
                echo "ERROR: Failed to delete debug package (HTTP $HTTP_CODE)"
                echo "$RESPONSE" | head -n -1
                exit 1
              fi

              curl --fail-with-body \
                -X PUT \
                -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
                -H "Content-Type: application/x-rpm" \
                -T "$DEBUG_RPM" \
                "https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-debug/upload?sign=true"
            done

            echo "✅ Published debug RPMs to group: ${GROUP}-debug"
          fi

          # Also upload the SRPM to separate group
          SRPM=$(find artifacts -name "*.src.rpm" | head -1)
          if [ -n "$SRPM" ]; then
            echo ""
            echo "Publishing source RPM: $(basename "$SRPM")"
            echo "Publishing to group: ${GROUP}-src"

            SRPM_INFO=$(rpm -qpi "$SRPM" 2>/dev/null)
            SRPM_NAME=$(echo "$SRPM_INFO" | grep "^Name" | awk '{print $3}')
            SRPM_VERSION=$(echo "$SRPM_INFO" | grep "^Version" | awk '{print $3}')
            SRPM_RELEASE=$(echo "$SRPM_INFO" | grep "^Release" | awk '{print $3}')
            SRPM_FULL_VERSION="${SRPM_VERSION}-${SRPM_RELEASE}"

            # Must delete existing SRPM first (Forgejo limitation)
            echo "Removing any existing SRPM: $SRPM_NAME-$SRPM_FULL_VERSION.src"
            RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \
              -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
              "https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-src/package/$SRPM_NAME/$SRPM_FULL_VERSION/src")
            HTTP_CODE=$(echo "$RESPONSE" | tail -n1)

            if [ "$HTTP_CODE" != "204" ] && [ "$HTTP_CODE" != "404" ]; then
              echo "ERROR: Failed to delete SRPM (HTTP $HTTP_CODE)"
              echo "$RESPONSE" | head -n -1
              exit 1
            fi

            curl --fail-with-body \
              -X PUT \
              -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
              -H "Content-Type: application/x-rpm" \
              -T "$SRPM" \
              "https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-src/upload?sign=true"

            echo "✅ Published source RPM to group: ${GROUP}-src"
          fi
