name: Release

on:
  push:
    tags:
      - '[0-9]+.[0-9]+.[0-9]+'
  workflow_dispatch:

env:
  CARGO_TERM_COLOR: always

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v6.0.2

      - name: Install system dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            openssl \
            pkg-config \
            libxml2-dev \
            libsqlite3-dev \
            llvm \
            clang

      - name: Setup Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy

      - name: Cache cargo registry
        uses: actions/cache@v5.0.3
        with:
          path: ~/.cargo/registry
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-registry-

      - name: Cache cargo index
        uses: actions/cache@v5.0.3
        with:
          path: ~/.cargo/git
          key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-git-

      - name: Cache cargo build
        uses: actions/cache@v5.0.3
        with:
          path: target
          key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-build-target-

      - name: Run cargo fmt
        run: cargo fmt --check

      - name: Run clippy
        run: cargo clippy --all-targets --all-features -- -D warnings

  test:
    name: Test
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - name: Checkout code
        uses: actions/checkout@v6.0.2

      - name: Install system dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            openssl \
            pkg-config \
            libxml2-dev \
            libsqlite3-dev \
            llvm \
            clang

      - name: Setup Rust toolchain
        uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo registry
        uses: actions/cache@v5.0.3
        with:
          path: ~/.cargo/registry
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-registry-

      - name: Cache cargo index
        uses: actions/cache@v5.0.3
        with:
          path: ~/.cargo/git
          key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-git-

      - name: Cache cargo build
        uses: actions/cache@v5.0.3
        with:
          path: target
          key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-build-target-

      - name: Run cargo test
        run: cargo test --all-features

  build_musl:
    name: Build MUSL targets
    needs: [lint, test]
    strategy:
      matrix:
        include:
          - docker-tag: x86_64-musl
            target: x86_64-unknown-linux-musl
          - docker-tag: aarch64-musl
            target: aarch64-unknown-linux-musl
          - docker-tag: armv7-musleabihf
            target: armv7-unknown-linux-musleabihf
    runs-on: ubuntu-latest
    container: ghcr.io/blackdex/rust-musl:${{ matrix.docker-tag }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v6.0.2
      - name: Build
        run: |
          cargo build --release
      - name: Extract tag name
        id: tag
        run: echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

      - name: Create package directory
        run: |
          mkdir -p package/eilmeldung
          cp target/${{ matrix.target }}/release/eilmeldung package/eilmeldung/
          cp -r examples package/eilmeldung/

      - name: Create tarball
        run: |
          cd package
          tar -czf eilmeldung-${{ matrix.target }}-${{ steps.tag.outputs.TAG_NAME }}.tar.gz eilmeldung/

      - name: Upload artifact
        uses: actions/upload-artifact@v7.0.0
        with:
          name: eilmeldung-${{ matrix.target }}-${{ steps.tag.outputs.TAG_NAME }}
          path: package/eilmeldung-${{ matrix.target }}-${{ steps.tag.outputs.TAG_NAME }}.tar.gz


  build_macos:
    name: Build ${{ matrix.target }}
    runs-on: ${{ matrix.os}}
    needs: [lint, test]
    strategy:
      matrix:
        include:
          - os: macos-latest
            target: x86_64-apple-darwin
          - os: macos-latest
            target: aarch64-apple-darwin
    steps:
      - name: Checkout code
        uses: actions/checkout@v6.0.2

      - name: Install system dependencies (Ubuntu Linux)
        if: ${{ runner.os == 'Linux' }}
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            openssl \
            pkg-config \
            libxml2-dev \
            libsqlite3-dev \
            llvm \
            clang

      - name: Install system dependencies (macOS)
        if: ${{ runner.os == 'macOS' }}
        run: |
          brew install libxml2

      - name: Setup Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target  }}

      - name: Cache cargo registry
        uses: actions/cache@v5.0.3
        with:
          path: ~/.cargo/registry
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-registry-

      - name: Cache cargo index
        uses: actions/cache@v5.0.3
        with:
          path: ~/.cargo/git
          key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-git-

      - name: Cache cargo build
        uses: actions/cache@v5.0.3
        with:
          path: target
          key: ${{ runner.os }}-cargo-build-target-release-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-build-target-release-

      - name: Build release binary
        run: cargo build --release --target ${{ matrix.target  }}
        env:
          PKG_CONFIG_PATH: ${{ matrix.target == 'x86_64-apple-darwin' && '/usr/local/opt/libxml2/lib/pkgconfig:/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/pkgconfig' || (runner.os == 'macOS' && '/opt/homebrew/opt/libxml2/lib/pkgconfig' || '') }}
          PKG_CONFIG_ALLOW_CROSS: ${{ runner.os == 'macOS' && '1' || '' }}
          XML2_CONFIG: ${{ matrix.target == 'x86_64-apple-darwin' && '/Library/Developer/CommandLineTools/usr/bin/xml2-config' || '' }}

      - name: Extract tag name
        id: tag
        run: echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

      - name: Create package directory
        run: |
          mkdir -p package/eilmeldung
          cp target/${{ matrix.target }}/release/eilmeldung package/eilmeldung/
          cp -r examples package/eilmeldung/

      - name: Create tarball
        run: |
          cd package
          tar -czf eilmeldung-${{ matrix.target }}-${{ steps.tag.outputs.TAG_NAME }}.tar.gz eilmeldung/

      - name: Upload artifact
        uses: actions/upload-artifact@v7.0.0
        with:
          name: eilmeldung-${{ matrix.target }}-${{ steps.tag.outputs.TAG_NAME }}
          path: package/eilmeldung-${{ matrix.target }}-${{ steps.tag.outputs.TAG_NAME }}.tar.gz


  build_windows:
    name: Build x86_64-pc-windows-msvc
    runs-on: windows-latest
    needs: [lint, test]
    steps:
      - name: Checkout code
        uses: actions/checkout@v6.0.2

      - name: Install vcpkg dependencies
        run: vcpkg install libxml2:x64-windows-static
        shell: pwsh

      - name: Setup Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: x86_64-pc-windows-msvc

      - name: Cache cargo registry
        uses: actions/cache@v5.0.3
        with:
          path: ~\.cargo\registry
          key: windows-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: windows-cargo-registry-

      - name: Cache cargo index
        uses: actions/cache@v5.0.3
        with:
          path: ~\.cargo\git
          key: windows-cargo-git-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: windows-cargo-git-

      - name: Extract tag name
        id: tag
        run: echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
        shell: bash

      - name: Build release binary
        run: cargo build --release --target x86_64-pc-windows-msvc
        env:
          RUSTFLAGS: "-C target-feature=+crt-static"
          VCPKG_ROOT: C:\vcpkg
          VCPKGRS_DYNAMIC: "0"
          PKG_CONFIG_PATH: C:\vcpkg\installed\x64-windows-static\lib\pkgconfig
          CMAKE_TOOLCHAIN_FILE: C:\vcpkg\scripts\buildsystems\vcpkg.cmake
          VCPKG_TARGET_TRIPLET: x64-windows-static
          OPENSSL_SRC_PERL: C:\Strawberry\perl\bin\perl.exe

      - name: Create package directory
        run: |
          mkdir -p package/eilmeldung
          cp target/x86_64-pc-windows-msvc/release/eilmeldung.exe package/eilmeldung/
          cp -r examples package/eilmeldung/
        shell: bash

      - name: Create archive
        run: |
          cd package
          tar -czf eilmeldung-x86_64-pc-windows-msvc-${{ steps.tag.outputs.TAG_NAME }}.tar.gz eilmeldung/
        shell: bash

      - name: Upload artifact
        uses: actions/upload-artifact@v7.0.0
        with:
          name: eilmeldung-x86_64-pc-windows-msvc-${{ steps.tag.outputs.TAG_NAME }}
          path: package/eilmeldung-x86_64-pc-windows-msvc-${{ steps.tag.outputs.TAG_NAME }}.tar.gz


  release-crates-io:
    name: Release on crates.io
    runs-on: ubuntu-latest
    needs: [build_macos, build_musl, build_windows]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6.0.2

      - name: Install system dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            openssl \
            pkg-config \
            libxml2-dev \
            libsqlite3-dev \
            llvm \
            clang

      - name: Setup Rust toolchain
        uses: dtolnay/rust-toolchain@stable

      - name: Publish
        run: cargo publish
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

  release-github:
    name: Create GitHub Release
    runs-on: ubuntu-latest
    needs: [build_macos, build_musl, build_windows]
    permissions:
      contents: write
    steps:
      - name: Checkout code
        uses: actions/checkout@v6.0.2

      - name: Extract tag name
        id: tag
        run: echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

      - name: Extract release notes from CHANGELOG
        id: changelog
        run: |
          VERSION=${{ steps.tag.outputs.TAG_NAME }}
          {
            echo 'NOTES<<EOF'
            sed -n "/^# ${VERSION}/,/^# [0-9]/p" CHANGELOG.md | sed '$d'
            echo EOF
          } >> $GITHUB_OUTPUT


      - name: Download artifacts
        uses: actions/download-artifact@v4
        with:
          path: ./artifacts

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          tag_name: ${{ steps.tag.outputs.TAG_NAME }}
          name: Release ${{ steps.tag.outputs.TAG_NAME }}
          body: ${{ steps.changelog.outputs.NOTES }}
          draft: false
          prerelease: false
          files: |
            ./artifacts/**/eilmeldung-*.tar.gz

  hashes-bump:
      name: Updating Hashes (nix, homebrew and scoop)
      runs-on: ubuntu-latest
      needs: release-github
      permissions:
        contents: write
      environment: ${{ inputs.environment }}
      steps:
      - name: Extract tag name
        id: tag
        run: echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
      - name: Checkout code
        uses: actions/checkout@v6.0.2
        with:
          persist-credentials: true            
          ref: "main"
          ssh-key: ${{ secrets.GIT_DEPLOY_KEY }}

      - name: Install Nix
        uses: cachix/install-nix-action@v27

      - name: Compute source hash
        id: hash
        run: |
          URL="https://github.com/christo-auer/eilmeldung/archive/refs/tags/${{ steps.tag.outputs.TAG_NAME }}.tar.gz"
          RAW=$(nix-prefetch-url --type sha256 --unpack "$URL")
          HASH=$(nix hash convert --hash-algo sha256 --to sri "$RAW")
          echo "HASH=$HASH" >> $GITHUB_OUTPUT

      - name: Update hash in flake.nix
        run: |


      - name: Update hashes, commit and push
        run: |
          ./HomebrewFormula/update-sha.sh ${{ steps.tag.outputs.TAG_NAME }}
          ./ScoopBucket/update-sha.sh ${{ steps.tag.outputs.TAG_NAME }}
          sed -i 's|hash = "sha256-.*";|hash = "${{ steps.hash.outputs.HASH }}";|' flake.nix
          git config user.email "${{ vars.GIT_USER_EMAIL }}"
          git config user.name "${{ vars.GIT_USER_NAME }}"
          git add ./HomebrewFormula/eilmeldung.rb ./ScoopBucket/eilmeldung.json flake.nix
          git commit -m "chore: update SHA256 values"
          git push origin main

  aur-publish:
    name: Publish ${{ matrix.package }} to AUR
    runs-on: ubuntu-latest
    container: archlinux:latest
    needs: release-github
    permissions:
      contents: read
    strategy:
      matrix:
        package: [eilmeldung, eilmeldung-bin]
    steps:
      - name: Extract tag name
        id: tag
        run: echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

      - name: Install required packages
        run: |
          pacman -Syu --noconfirm
          pacman -S --noconfirm git openssh base-devel namcap pacman-contrib

      - name: Setup SSH for AUR
        run: |
          mkdir -p /root/.ssh
          chmod 700 /root/.ssh
          echo "${{ secrets.AUR_DEPLOY_KEY }}" > /root/.ssh/aur
          chmod 600 /root/.ssh/aur
          ssh-keyscan -H aur.archlinux.org >> /root/.ssh/known_hosts
          chmod 644 /root/.ssh/known_hosts
          cat > /root/.ssh/config <<'EOF'
          Host aur.archlinux.org
            IdentityFile /root/.ssh/aur
            User aur
          EOF
          chmod 600 /root/.ssh/config
          echo "SSH config:"
          cat /root/.ssh/config
          echo "Known hosts for AUR:"
          grep aur /root/.ssh/known_hosts || echo "No AUR entry found!"

      - name: Clone AUR repository
        run: |
          git clone ssh://aur@aur.archlinux.org/${{ matrix.package }}.git aur-pkg
          cd aur-pkg
          git config user.email "${{ vars.GIT_USER_EMAIL }}"
          git config user.name "${{ vars.GIT_USER_NAME }}"

      - name: Update PKGBUILD version and checksums
        run: |
          cd aur-pkg
          sed -i "s/^pkgver=.*/pkgver=${{ steps.tag.outputs.TAG_NAME }}/" PKGBUILD
          sed -i "s/^pkgrel=.*/pkgrel=1/" PKGBUILD
          # Create a temporary user for updpkgsums (refuses to run as root)
          useradd -m builder
          chown -R builder:builder .
          su builder -c "updpkgsums"
          echo "Updated PKGBUILD:"
          cat PKGBUILD

      - name: Generate .SRCINFO
        run: |
          cd aur-pkg

          su builder -c "makepkg --printsrcinfo > .SRCINFO"

      - name: Validate with namcap
        run: |
          cd aur-pkg
          namcap PKGBUILD || true

      - name: Commit and push to AUR
        run: |
          # revert ownership back to root (its builder now)
          chown root:root -R aur-pkg
          cd aur-pkg
          git add PKGBUILD .SRCINFO
          git commit -m "chore: update to version ${{ steps.tag.outputs.TAG_NAME }}"
          git push origin master
